diff --git a/Assets/roots.pem b/Assets/roots.pem index 5dbd1ae6e..be598710d 100644 --- a/Assets/roots.pem +++ b/Assets/roots.pem @@ -329,36 +329,6 @@ OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- -# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association -# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association -# Label: "Visa eCommerce Root" -# Serial: 25952180776285836048024890241505565794 -# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 -# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 -# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- - # Issuer: CN=AAA Certificate Services O=Comodo CA Limited # Subject: CN=AAA Certificate Services O=Comodo CA Limited # Label: "Comodo AAA Services root" @@ -3734,169 +3704,6 @@ lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- -# Issuer: CN=Certplus Root CA G1 O=Certplus -# Subject: CN=Certplus Root CA G1 O=Certplus -# Label: "Certplus Root CA G1" -# Serial: 1491911565779898356709731176965615564637713 -# MD5 Fingerprint: 7f:09:9c:f7:d9:b9:5c:69:69:56:d5:37:3e:14:0d:42 -# SHA1 Fingerprint: 22:fd:d0:b7:fd:a2:4e:0d:ac:49:2c:a0:ac:a6:7b:6a:1f:e3:f7:66 -# SHA256 Fingerprint: 15:2a:40:2b:fc:df:2c:d5:48:05:4d:22:75:b3:9c:7f:ca:3e:c0:97:80:78:b0:f0:ea:76:e5:61:a6:c7:43:3e ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a -iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt -6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP -0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f -6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE -EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN -1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc -h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT -mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV -4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO -WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud -DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd -Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq -hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh -66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 -/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS -S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j -2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R -Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr -RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy -6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV -V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 -g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl -++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= ------END CERTIFICATE----- - -# Issuer: CN=Certplus Root CA G2 O=Certplus -# Subject: CN=Certplus Root CA G2 O=Certplus -# Label: "Certplus Root CA G2" -# Serial: 1492087096131536844209563509228951875861589 -# MD5 Fingerprint: a7:ee:c4:78:2d:1b:ee:2d:b9:29:ce:d6:a7:96:32:31 -# SHA1 Fingerprint: 4f:65:8e:1f:e9:06:d8:28:02:e9:54:47:41:c9:54:25:5d:69:cc:1a -# SHA256 Fingerprint: 6c:c0:50:41:e6:44:5e:74:69:6c:4c:fb:c9:f8:0f:54:3b:7e:ab:bb:44:b4:ce:6f:78:7c:6a:99:71:c4:2f:17 ------BEGIN CERTIFICATE----- -MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat -93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x -Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj -FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG -SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch -p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal -U5ORGpOucGpnutee5WEaXw== ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G1 O=OpenTrust -# Subject: CN=OpenTrust Root CA G1 O=OpenTrust -# Label: "OpenTrust Root CA G1" -# Serial: 1492036577811947013770400127034825178844775 -# MD5 Fingerprint: 76:00:cc:81:29:cd:55:5e:88:6a:7a:2e:f7:4d:39:da -# SHA1 Fingerprint: 79:91:e8:34:f7:e2:ee:dd:08:95:01:52:e9:55:2d:14:e9:58:d5:7e -# SHA256 Fingerprint: 56:c7:71:28:d9:8c:18:d9:1b:4c:fd:ff:bc:25:ee:91:03:d4:75:8e:a2:ab:ad:82:6a:90:f3:45:7d:46:0e:b4 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b -wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX -/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 -77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP -uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx -p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx -Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 -TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W -G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw -vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY -EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 -2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw -DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E -PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf -gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS -FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 -V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P -XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I -i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t -TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 -09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky -Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ -AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj -1oxx ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G2 O=OpenTrust -# Subject: CN=OpenTrust Root CA G2 O=OpenTrust -# Label: "OpenTrust Root CA G2" -# Serial: 1492012448042702096986875987676935573415441 -# MD5 Fingerprint: 57:24:b6:59:24:6b:ae:c8:fe:1c:0c:20:f2:c0:4e:eb -# SHA1 Fingerprint: 79:5f:88:60:c5:ab:7c:3d:92:e6:cb:f4:8d:e1:45:cd:11:ef:60:0b -# SHA256 Fingerprint: 27:99:58:29:fe:6a:75:15:c1:bf:e8:48:f9:c4:76:1d:b1:6c:22:59:29:25:7b:f4:0d:08:94:f2:9e:a8:ba:f2 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh -/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e -CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 -1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE -FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS -gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X -G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy -YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH -vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 -t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ -gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 -5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w -DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz -Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 -nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT -RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT -wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 -t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa -TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 -o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU -3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA -iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f -WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM -S1IK ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G3 O=OpenTrust -# Subject: CN=OpenTrust Root CA G3 O=OpenTrust -# Label: "OpenTrust Root CA G3" -# Serial: 1492104908271485653071219941864171170455615 -# MD5 Fingerprint: 21:37:b4:17:16:92:7b:67:46:70:a9:96:d7:a8:13:24 -# SHA1 Fingerprint: 6e:26:64:f3:56:bf:34:55:bf:d1:93:3f:7c:01:de:d8:13:da:8a:a6 -# SHA256 Fingerprint: b7:c3:62:31:70:6e:81:07:8c:36:7c:b8:96:19:8f:1e:32:08:dd:92:69:49:dd:8f:57:09:a4:10:f7:5b:62:92 ------BEGIN CERTIFICATE----- -MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx -CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U -cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow -QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl -blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm -3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d -oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 -DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK -BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q -j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx -4nxp5V2a+EEfOzmTk51V6s2N8fvB ------END CERTIFICATE----- - # Issuer: CN=ISRG Root X1 O=Internet Security Research Group # Subject: CN=ISRG Root X1 O=Internet Security Research Group # Label: "ISRG Root X1" @@ -4440,3 +4247,308 @@ MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== -----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Label: "GlobalSign Root CA - R6" +# Serial: 1417766617973444989252670301619537 +# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae +# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 +# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GC CA" +# Serial: 44084345621038548146064804565436152554 +# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 +# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 +# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R1 O=Google Trust Services LLC +# Subject: CN=GTS Root R1 O=Google Trust Services LLC +# Label: "GTS Root R1" +# Serial: 146587175971765017618439757810265552097 +# MD5 Fingerprint: 82:1a:ef:d4:d2:4a:f2:9f:e2:3d:97:06:14:70:72:85 +# SHA1 Fingerprint: e1:c9:50:e6:ef:22:f8:4c:56:45:72:8b:92:20:60:d7:d5:a7:a3:e8 +# SHA256 Fingerprint: 2a:57:54:71:e3:13:40:bc:21:58:1c:bd:2c:f1:3e:15:84:63:20:3e:ce:94:bc:f9:d3:cc:19:6b:f0:9a:54:72 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX +mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 +zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P +fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc +vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 +Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp +zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO +Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW +k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ +DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF +lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW +Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z +XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR +gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 +d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv +J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg +DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM ++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy +F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 +SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws +E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R2 O=Google Trust Services LLC +# Subject: CN=GTS Root R2 O=Google Trust Services LLC +# Label: "GTS Root R2" +# Serial: 146587176055767053814479386953112547951 +# MD5 Fingerprint: 44:ed:9a:0e:a4:09:3b:00:f2:ae:4c:a3:c6:61:b0:8b +# SHA1 Fingerprint: d2:73:96:2a:2a:5e:39:9f:73:3f:e1:c7:1e:64:3f:03:38:34:fc:4d +# SHA256 Fingerprint: c4:5d:7b:b0:8e:6d:67:e6:2e:42:35:11:0b:56:4e:5f:78:fd:92:ef:05:8c:84:0a:ea:4e:64:55:d7:58:5c:60 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg +GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu +XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd +re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu +PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 +mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K +8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj +x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR +nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 +kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok +twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp +8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT +z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA +pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb +pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB +R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R +RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk +0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC +5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF +izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn +yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R3 O=Google Trust Services LLC +# Subject: CN=GTS Root R3 O=Google Trust Services LLC +# Label: "GTS Root R3" +# Serial: 146587176140553309517047991083707763997 +# MD5 Fingerprint: 1a:79:5b:6b:04:52:9c:5d:c7:74:33:1b:25:9a:f9:25 +# SHA1 Fingerprint: 30:d4:24:6f:07:ff:db:91:89:8a:0b:e9:49:66:11:eb:8c:5e:46:e5 +# SHA256 Fingerprint: 15:d5:b8:77:46:19:ea:7d:54:ce:1c:a6:d0:b0:c4:03:e0:37:a9:17:f1:31:e8:a0:4e:1e:6b:7a:71:ba:bc:e5 +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A +DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk +fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA +njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R4 O=Google Trust Services LLC +# Subject: CN=GTS Root R4 O=Google Trust Services LLC +# Label: "GTS Root R4" +# Serial: 146587176229350439916519468929765261721 +# MD5 Fingerprint: 5d:b6:6a:c4:60:17:24:6a:1a:99:a8:4b:ee:5e:b4:26 +# SHA1 Fingerprint: 2a:1d:60:27:d9:4a:b1:0a:1c:4d:91:5c:cd:33:a0:cb:3e:2d:54:cb +# SHA256 Fingerprint: 71:cc:a5:39:1f:9e:79:4b:04:80:25:30:b3:63:e1:21:da:8a:30:43:bb:26:66:2f:ea:4d:ca:7f:c9:51:a4:bd +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l +xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 +CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx +sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Global G2 Root O=UniTrust +# Subject: CN=UCA Global G2 Root O=UniTrust +# Label: "UCA Global G2 Root" +# Serial: 124779693093741543919145257850076631279 +# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 +# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a +# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Extended Validation Root O=UniTrust +# Subject: CN=UCA Extended Validation Root O=UniTrust +# Label: "UCA Extended Validation Root" +# Serial: 106100277556486529736699587978573607008 +# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 +# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a +# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- + +# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Label: "Certigna Root CA" +# Serial: 269714418870597844693661054334862075617 +# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 +# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 +# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- diff --git a/Package.resolved b/Package.resolved index e4ffab0d7..06ea6eb7d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "98434c1f1d687ff5a24d2cabfbd19b5c7d2d7a2f", - "version": "1.13.0" + "revision": "29a9f2aca71c8afb07e291336f1789337ce235dd", + "version": "1.13.2" } }, { @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/apple/swift-protobuf.git", "state": { "branch": null, - "revision": "ab98c52b5166593ad1ae0df246463266df151cfa", - "version": "1.3.1" + "revision": "6520fb185db88c0774a929acea1f7d5981a30d3a", + "version": "1.4.0" } } ] diff --git a/Sources/BoringSSL/crypto/asn1/a_int.c b/Sources/BoringSSL/crypto/asn1/a_int.c index 8a4edd691..dd74550be 100644 --- a/Sources/BoringSSL/crypto/asn1/a_int.c +++ b/Sources/BoringSSL/crypto/asn1/a_int.c @@ -347,40 +347,45 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) { - int j, k; - unsigned int i; - unsigned char buf[sizeof(long) + 1]; - long d; - - a->type = V_ASN1_INTEGER; - if (a->length < (int)(sizeof(long) + 1)) { - if (a->data != NULL) - OPENSSL_free(a->data); - if ((a->data = - (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL) - OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1); + if (v >= 0) { + return ASN1_INTEGER_set_uint64(a, (uint64_t) v); } - if (a->data == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (0); + + if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) { + return 0; } - d = v; - if (d < 0) { - d = -d; - a->type = V_ASN1_NEG_INTEGER; + + a->type = V_ASN1_NEG_INTEGER; + return 1; +} + +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v) +{ + uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t)); + if (newdata == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; } - for (i = 0; i < sizeof(long); i++) { - if (d == 0) + OPENSSL_free(out->data); + out->data = newdata; + v = CRYPTO_bswap8(v); + memcpy(out->data, &v, sizeof(v)); + + out->type = V_ASN1_INTEGER; + + size_t leading_zeros; + for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1; + leading_zeros++) { + if (out->data[leading_zeros] != 0) { break; - buf[i] = (int)d & 0xff; - d >>= 8; + } } - j = 0; - for (k = i - 1; k >= 0; k--) - a->data[j++] = buf[k]; - a->length = j; - return (1); + + out->length = sizeof(uint64_t) - leading_zeros; + OPENSSL_memmove(out->data, out->data + leading_zeros, out->length); + + return 1; } long ASN1_INTEGER_get(const ASN1_INTEGER *a) diff --git a/Sources/BoringSSL/crypto/asn1/a_mbstr.c b/Sources/BoringSSL/crypto/asn1/a_mbstr.c index 30fff82a7..a2789ed1e 100644 --- a/Sources/BoringSSL/crypto/asn1/a_mbstr.c +++ b/Sources/BoringSSL/crypto/asn1/a_mbstr.c @@ -61,17 +61,19 @@ #include #include +#include "asn1_locl.h" + static int traverse_string(const unsigned char *p, int len, int inform, - int (*rfunc) (unsigned long value, void *in), + int (*rfunc) (uint32_t value, void *in), void *arg); -static int in_utf8(unsigned long value, void *arg); -static int out_utf8(unsigned long value, void *arg); -static int type_str(unsigned long value, void *arg); -static int cpy_asc(unsigned long value, void *arg); -static int cpy_bmp(unsigned long value, void *arg); -static int cpy_univ(unsigned long value, void *arg); -static int cpy_utf8(unsigned long value, void *arg); -static int is_printable(unsigned long value); +static int in_utf8(uint32_t value, void *arg); +static int out_utf8(uint32_t value, void *arg); +static int type_str(uint32_t value, void *arg); +static int cpy_asc(uint32_t value, void *arg); +static int cpy_bmp(uint32_t value, void *arg); +static int cpy_univ(uint32_t value, void *arg); +static int cpy_utf8(uint32_t value, void *arg); +static int is_printable(uint32_t value); /* * These functions take a string in UTF8, ASCII or multibyte form and a mask @@ -100,7 +102,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, unsigned char *p; int nchar; char strbuf[32]; - int (*cpyfunc) (unsigned long, void *) = NULL; + int (*cpyfunc) (uint32_t, void *) = NULL; if (len == -1) len = strlen((const char *)in); if (!mask) @@ -253,10 +255,10 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, */ static int traverse_string(const unsigned char *p, int len, int inform, - int (*rfunc) (unsigned long value, void *in), + int (*rfunc) (uint32_t value, void *in), void *arg) { - unsigned long value; + uint32_t value; int ret; while (len) { if (inform == MBSTRING_ASC) { @@ -267,8 +269,8 @@ static int traverse_string(const unsigned char *p, int len, int inform, value |= *p++; len -= 2; } else if (inform == MBSTRING_UNIV) { - value = ((unsigned long)*p++) << 24; - value |= ((unsigned long)*p++) << 16; + value = ((uint32_t)*p++) << 24; + value |= ((uint32_t)*p++) << 16; value |= *p++ << 8; value |= *p++; len -= 4; @@ -292,7 +294,7 @@ static int traverse_string(const unsigned char *p, int len, int inform, /* Just count number of characters */ -static int in_utf8(unsigned long value, void *arg) +static int in_utf8(uint32_t value, void *arg) { int *nchar; nchar = arg; @@ -302,7 +304,7 @@ static int in_utf8(unsigned long value, void *arg) /* Determine size of output as a UTF8 String */ -static int out_utf8(unsigned long value, void *arg) +static int out_utf8(uint32_t value, void *arg) { int *outlen; outlen = arg; @@ -315,7 +317,7 @@ static int out_utf8(unsigned long value, void *arg) * "mask". */ -static int type_str(unsigned long value, void *arg) +static int type_str(uint32_t value, void *arg) { unsigned long types; types = *((unsigned long *)arg); @@ -335,7 +337,7 @@ static int type_str(unsigned long value, void *arg) /* Copy one byte per character ASCII like strings */ -static int cpy_asc(unsigned long value, void *arg) +static int cpy_asc(uint32_t value, void *arg) { unsigned char **p, *q; p = arg; @@ -347,7 +349,7 @@ static int cpy_asc(unsigned long value, void *arg) /* Copy two byte per character BMPStrings */ -static int cpy_bmp(unsigned long value, void *arg) +static int cpy_bmp(uint32_t value, void *arg) { unsigned char **p, *q; p = arg; @@ -360,7 +362,7 @@ static int cpy_bmp(unsigned long value, void *arg) /* Copy four byte per character UniversalStrings */ -static int cpy_univ(unsigned long value, void *arg) +static int cpy_univ(uint32_t value, void *arg) { unsigned char **p, *q; p = arg; @@ -375,7 +377,7 @@ static int cpy_univ(unsigned long value, void *arg) /* Copy to a UTF8String */ -static int cpy_utf8(unsigned long value, void *arg) +static int cpy_utf8(uint32_t value, void *arg) { unsigned char **p; int ret; @@ -387,7 +389,7 @@ static int cpy_utf8(unsigned long value, void *arg) } /* Return 1 if the character is permitted in a PrintableString */ -static int is_printable(unsigned long value) +static int is_printable(uint32_t value) { int ch; if (value > 0x7f) diff --git a/Sources/BoringSSL/crypto/asn1/a_utf8.c b/Sources/BoringSSL/crypto/asn1/a_utf8.c index 170276866..119ccf92c 100644 --- a/Sources/BoringSSL/crypto/asn1/a_utf8.c +++ b/Sources/BoringSSL/crypto/asn1/a_utf8.c @@ -59,6 +59,8 @@ #include #include +#include "asn1_locl.h" + /* UTF8 utilities */ /* @@ -70,10 +72,10 @@ * incorrectly (not minimal length). */ -int UTF8_getc(const unsigned char *str, int len, unsigned long *val) +int UTF8_getc(const unsigned char *str, int len, uint32_t *val) { const unsigned char *p; - unsigned long value; + uint32_t value; int ret; if (len <= 0) return 0; @@ -112,7 +114,7 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val) || ((p[2] & 0xc0) != 0x80) || ((p[3] & 0xc0) != 0x80)) return -3; - value = ((unsigned long)(*p++ & 0x7)) << 18; + value = ((uint32_t)(*p++ & 0x7)) << 18; value |= (*p++ & 0x3f) << 12; value |= (*p++ & 0x3f) << 6; value |= *p++ & 0x3f; @@ -127,9 +129,9 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val) || ((p[3] & 0xc0) != 0x80) || ((p[4] & 0xc0) != 0x80)) return -3; - value = ((unsigned long)(*p++ & 0x3)) << 24; - value |= ((unsigned long)(*p++ & 0x3f)) << 18; - value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value = ((uint32_t)(*p++ & 0x3)) << 24; + value |= ((uint32_t)(*p++ & 0x3f)) << 18; + value |= ((uint32_t)(*p++ & 0x3f)) << 12; value |= (*p++ & 0x3f) << 6; value |= *p++ & 0x3f; if (value < 0x200000) @@ -144,10 +146,10 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val) || ((p[4] & 0xc0) != 0x80) || ((p[5] & 0xc0) != 0x80)) return -3; - value = ((unsigned long)(*p++ & 0x1)) << 30; - value |= ((unsigned long)(*p++ & 0x3f)) << 24; - value |= ((unsigned long)(*p++ & 0x3f)) << 18; - value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value = ((uint32_t)(*p++ & 0x1)) << 30; + value |= ((uint32_t)(*p++ & 0x3f)) << 24; + value |= ((uint32_t)(*p++ & 0x3f)) << 18; + value |= ((uint32_t)(*p++ & 0x3f)) << 12; value |= (*p++ & 0x3f) << 6; value |= *p++ & 0x3f; if (value < 0x4000000) @@ -167,7 +169,7 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val) * most 6 characters. */ -int UTF8_putc(unsigned char *str, int len, unsigned long value) +int UTF8_putc(unsigned char *str, int len, uint32_t value) { if (!str) len = 6; /* Maximum we will need */ diff --git a/Sources/BoringSSL/crypto/asn1/asn1_locl.h b/Sources/BoringSSL/crypto/asn1/asn1_locl.h index 10a832cd5..8cef2463a 100644 --- a/Sources/BoringSSL/crypto/asn1/asn1_locl.h +++ b/Sources/BoringSSL/crypto/asn1/asn1_locl.h @@ -93,6 +93,9 @@ int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); +int UTF8_getc(const unsigned char *str, int len, uint32_t *val); +int UTF8_putc(unsigned char *str, int len, uint32_t value); + #if defined(__cplusplus) } /* extern C */ diff --git a/Sources/BoringSSL/crypto/asn1/tasn_dec.c b/Sources/BoringSSL/crypto/asn1/tasn_dec.c index 2f5f132a5..32aba0bda 100644 --- a/Sources/BoringSSL/crypto/asn1/tasn_dec.c +++ b/Sources/BoringSSL/crypto/asn1/tasn_dec.c @@ -66,6 +66,14 @@ #include "../internal.h" +/* + * Constructed types with a recursive definition (such as can be found in PKCS7) + * could eventually exceed the stack given malicious input with excessive + * recursion. Therefore we limit the stack depth. This is the maximum number of + * recursive invocations of asn1_item_embed_d2i(). + */ +#define ASN1_MAX_CONSTRUCTED_NEST 30 + static int asn1_check_eoc(const unsigned char **in, long len); static int asn1_find_end(const unsigned char **in, long len, char inf); @@ -82,11 +90,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx); + ASN1_TLC *ctx, int depth); static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx); + ASN1_TLC *ctx, int depth); static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, @@ -153,9 +161,9 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, * tag mismatch return -1 to handle OPTIONAL */ -int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx) +static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx, int depth) { const ASN1_TEMPLATE *tt, *errtt = NULL; const ASN1_COMPAT_FUNCS *cf; @@ -188,6 +196,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, len = INT_MAX/2; } + if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_TOO_DEEP); + goto err; + } + switch (it->itype) { case ASN1_ITYPE_PRIMITIVE: if (it->templates) { @@ -203,7 +216,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, goto err; } return asn1_template_ex_d2i(pval, in, len, - it->templates, opt, ctx); + it->templates, opt, ctx, depth); } return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt, ctx); @@ -326,7 +339,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, /* * We mark field as OPTIONAL so its absence can be recognised. */ - ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth); /* If field not present, try the next one */ if (ret == -1) continue; @@ -444,7 +457,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, * attempt to read in field, allowing each to be OPTIONAL */ - ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx, + depth); if (!ret) { errtt = seqtt; goto err; @@ -514,6 +528,13 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, return 0; } +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); +} + /* * Templates are handled with two separate functions. One handles any * EXPLICIT tag and the other handles the rest. @@ -522,7 +543,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx) + ASN1_TLC *ctx, int depth) { int flags, aclass; int ret; @@ -556,7 +577,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, return 0; } /* We've found the field so it can't be OPTIONAL now */ - ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); if (!ret) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); return 0; @@ -579,7 +600,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, } } } else - return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth); *in = p; return 1; @@ -592,7 +613,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx) + ASN1_TLC *ctx, int depth) { int flags, aclass; int ret; @@ -661,8 +682,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, break; } skfield = NULL; - if (!ASN1_item_ex_d2i(&skfield, &p, len, - ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { + if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), + -1, 0, 0, ctx, depth)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); goto err; } @@ -679,9 +700,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, } } else if (flags & ASN1_TFLG_IMPTAG) { /* IMPLICIT tagging */ - ret = ASN1_item_ex_d2i(val, &p, len, - ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, - ctx); + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, + aclass, opt, ctx, depth); if (!ret) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); goto err; @@ -689,8 +709,9 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, return -1; } else { /* Nothing special */ - ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), - -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), + -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx, + depth); if (!ret) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); goto err; diff --git a/Sources/BoringSSL/crypto/bio/fd.c b/Sources/BoringSSL/crypto/bio/fd.c index ea5bfd8cc..fed5228ff 100644 --- a/Sources/BoringSSL/crypto/bio/fd.c +++ b/Sources/BoringSSL/crypto/bio/fd.c @@ -73,6 +73,7 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) #include #include "internal.h" +#include "../internal.h" static int bio_fd_non_fatal_error(int err) { diff --git a/Sources/BoringSSL/crypto/bio/file.c b/Sources/BoringSSL/crypto/bio/file.c index 278be1880..f61dbe4fe 100644 --- a/Sources/BoringSSL/crypto/bio/file.c +++ b/Sources/BoringSSL/crypto/bio/file.c @@ -81,6 +81,8 @@ #include #include +#include "../internal.h" + #define BIO_FP_READ 0x02 #define BIO_FP_WRITE 0x04 diff --git a/Sources/BoringSSL/crypto/bn_extra/convert.c b/Sources/BoringSSL/crypto/bn_extra/convert.c index 6f3a062ad..c70ff8b5b 100644 --- a/Sources/BoringSSL/crypto/bn_extra/convert.c +++ b/Sources/BoringSSL/crypto/bn_extra/convert.c @@ -77,8 +77,9 @@ int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) { static const char hextable[] = "0123456789abcdef"; char *BN_bn2hex(const BIGNUM *bn) { + int width = bn_minimal_width(bn); char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ + - bn->top * BN_BYTES * 2 + 1 /* trailing NUL */); + width * BN_BYTES * 2 + 1 /* trailing NUL */); if (buf == NULL) { OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); return NULL; @@ -94,7 +95,7 @@ char *BN_bn2hex(const BIGNUM *bn) { } int z = 0; - for (int i = bn->top - 1; i >= 0; i--) { + for (int i = width - 1; i >= 0; i--) { for (int j = BN_BITS2 - 8; j >= 0; j -= 8) { // strip leading zeros int v = ((int)(bn->d[i] >> (long)j)) & 0xff; @@ -153,7 +154,7 @@ static int decode_hex(BIGNUM *bn, const char *in, int in_len) { in_len -= todo; } assert(i <= bn->dmax); - bn->top = i; + bn->width = i; return 1; } @@ -222,7 +223,7 @@ static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_ goto err; } - bn_correct_top(ret); + bn_set_minimal_width(ret); if (!BN_is_zero(ret)) { ret->neg = neg; } @@ -347,7 +348,7 @@ int BN_print(BIO *bp, const BIGNUM *a) { goto end; } - for (i = a->top - 1; i >= 0; i--) { + for (i = bn_minimal_width(a) - 1; i >= 0; i--) { for (j = BN_BITS2 - 4; j >= 0; j -= 4) { // strip leading zeros v = ((int)(a->d[i] >> (long)j)) & 0x0f; diff --git a/Sources/BoringSSL/crypto/bytestring/ber.c b/Sources/BoringSSL/crypto/bytestring/ber.c index 4dc94f6f7..bb5e17c42 100644 --- a/Sources/BoringSSL/crypto/bytestring/ber.c +++ b/Sources/BoringSSL/crypto/bytestring/ber.c @@ -29,10 +29,7 @@ static const unsigned kMaxDepth = 2048; // is_string_type returns one if |tag| is a string type and zero otherwise. It // ignores the constructed bit. static int is_string_type(unsigned tag) { - if ((tag & 0xc0) != 0) { - return 0; - } - switch (tag & 0x1f) { + switch (tag & ~CBS_ASN1_CONSTRUCTED) { case CBS_ASN1_BITSTRING: case CBS_ASN1_OCTETSTRING: case CBS_ASN1_UTF8STRING: diff --git a/Sources/BoringSSL/crypto/bytestring/cbb.c b/Sources/BoringSSL/crypto/bytestring/cbb.c index 2853509cb..38e9a83a3 100644 --- a/Sources/BoringSSL/crypto/bytestring/cbb.c +++ b/Sources/BoringSSL/crypto/bytestring/cbb.c @@ -18,6 +18,7 @@ #include #include +#include #include #include "../internal.h" @@ -332,9 +333,9 @@ int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) { // add_base128_integer encodes |v| as a big-endian base-128 integer where the // high bit of each byte indicates where there is more data. This is the // encoding used in DER for both high tag number form and OID components. -static int add_base128_integer(CBB *cbb, uint32_t v) { +static int add_base128_integer(CBB *cbb, uint64_t v) { unsigned len_len = 0; - unsigned copy = v; + uint64_t copy = v; while (copy > 0) { len_len++; copy >>= 7; @@ -356,17 +357,20 @@ static int add_base128_integer(CBB *cbb, uint32_t v) { } int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) { - if (tag > 0xff || - (tag & 0x1f) == 0x1f) { - // Long form identifier octets are not supported. Further, all current valid - // tag serializations are 8 bits. - cbb->base->error = 1; + if (!CBB_flush(cbb)) { return 0; } - if (!CBB_flush(cbb) || - // |tag|'s representation matches the DER encoding. - !CBB_add_u8(cbb, (uint8_t)tag)) { + // Split the tag into leading bits and tag number. + uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0; + unsigned tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK; + if (tag_number >= 0x1f) { + // Set all the bits in the tag number to signal high tag number form. + if (!CBB_add_u8(cbb, tag_bits | 0x1f) || + !add_base128_integer(cbb, tag_number)) { + return 0; + } + } else if (!CBB_add_u8(cbb, tag_bits | tag_number)) { return 0; } @@ -501,11 +505,33 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { return CBB_flush(cbb); } +int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child, data, data_len) || + !CBB_flush(cbb)) { + return 0; + } + + return 1; +} + +int CBB_add_asn1_bool(CBB *cbb, int value) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_BOOLEAN) || + !CBB_add_u8(&child, value != 0 ? 0xff : 0) || + !CBB_flush(cbb)) { + return 0; + } + + return 1; +} + // parse_dotted_decimal parses one decimal component from |cbs|, where |cbs| is // an OID literal, e.g., "1.2.840.113554.4.1.72585". It consumes both the // component and the dot, so |cbs| may be passed into the function again for the // next value. -static int parse_dotted_decimal(CBS *cbs, uint32_t *out) { +static int parse_dotted_decimal(CBS *cbs, uint64_t *out) { *out = 0; int seen_digit = 0; for (;;) { @@ -521,8 +547,8 @@ static int parse_dotted_decimal(CBS *cbs, uint32_t *out) { // Forbid stray leading zeros. (seen_digit && *out == 0) || // Check for overflow. - *out > UINT32_MAX / 10 || - *out * 10 > UINT32_MAX - (u - '0')) { + *out > UINT64_MAX / 10 || + *out * 10 > UINT64_MAX - (u - '0')) { return 0; } *out = *out * 10 + (u - '0'); @@ -541,7 +567,7 @@ int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) { CBS_init(&cbs, (const uint8_t *)text, len); // OIDs must have at least two components. - uint32_t a, b; + uint64_t a, b; if (!parse_dotted_decimal(&cbs, &a) || !parse_dotted_decimal(&cbs, &b)) { return 0; @@ -551,8 +577,8 @@ int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) { // 0, 1, or 2 and that, when it is 0 or 1, |b| is at most 39. if (a > 2 || (a < 2 && b > 39) || - b > UINT32_MAX - 80 || - !add_base128_integer(cbb, 40 * a + b)) { + b > UINT64_MAX - 80 || + !add_base128_integer(cbb, 40u * a + b)) { return 0; } @@ -566,3 +592,77 @@ int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) { return 1; } + +static int compare_set_of_element(const void *a_ptr, const void *b_ptr) { + // See X.690, section 11.6 for the ordering. They are sorted in ascending + // order by their DER encoding. + const CBS *a = a_ptr, *b = b_ptr; + size_t a_len = CBS_len(a), b_len = CBS_len(b); + size_t min_len = a_len < b_len ? a_len : b_len; + int ret = OPENSSL_memcmp(CBS_data(a), CBS_data(b), min_len); + if (ret != 0) { + return ret; + } + if (a_len == b_len) { + return 0; + } + // If one is a prefix of the other, the shorter one sorts first. (This is not + // actually reachable. No DER encoding is a prefix of another DER encoding.) + return a_len < b_len ? -1 : 1; +} + +int CBB_flush_asn1_set_of(CBB *cbb) { + if (!CBB_flush(cbb)) { + return 0; + } + + CBS cbs; + size_t num_children = 0; + CBS_init(&cbs, CBB_data(cbb), CBB_len(cbb)); + while (CBS_len(&cbs) != 0) { + if (!CBS_get_any_asn1_element(&cbs, NULL, NULL, NULL)) { + return 0; + } + num_children++; + } + + if (num_children < 2) { + return 1; // Nothing to do. This is the common case for X.509. + } + if (num_children > ((size_t)-1) / sizeof(CBS)) { + return 0; // Overflow. + } + + // Parse out the children and sort. We alias them into a copy of so they + // remain valid as we rewrite |cbb|. + int ret = 0; + size_t buf_len = CBB_len(cbb); + uint8_t *buf = BUF_memdup(CBB_data(cbb), buf_len); + CBS *children = OPENSSL_malloc(num_children * sizeof(CBS)); + if (buf == NULL || children == NULL) { + goto err; + } + CBS_init(&cbs, buf, buf_len); + for (size_t i = 0; i < num_children; i++) { + if (!CBS_get_any_asn1_element(&cbs, &children[i], NULL, NULL)) { + goto err; + } + } + qsort(children, num_children, sizeof(CBS), compare_set_of_element); + + // Rewind |cbb| and write the contents back in the new order. + cbb->base->len = cbb->offset + cbb->pending_len_len; + for (size_t i = 0; i < num_children; i++) { + if (!CBB_add_bytes(cbb, CBS_data(&children[i]), CBS_len(&children[i]))) { + goto err; + } + } + assert(CBB_len(cbb) == buf_len); + + ret = 1; + +err: + OPENSSL_free(buf); + OPENSSL_free(children); + return ret; +} diff --git a/Sources/BoringSSL/crypto/bytestring/cbs.c b/Sources/BoringSSL/crypto/bytestring/cbs.c index ec495d210..458af3809 100644 --- a/Sources/BoringSSL/crypto/bytestring/cbs.c +++ b/Sources/BoringSSL/crypto/bytestring/cbs.c @@ -12,11 +12,16 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif + #include #include #include #include +#include #include #include "internal.h" @@ -175,18 +180,36 @@ int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) { return cbs_get_length_prefixed(cbs, out, 3); } -static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, - size_t *out_header_len, int ber_ok) { - uint8_t tag, length_byte; - CBS header = *cbs; - CBS throwaway; +// parse_base128_integer reads a big-endian base-128 integer from |cbs| and sets +// |*out| to the result. This is the encoding used in DER for both high tag +// number form and OID components. +static int parse_base128_integer(CBS *cbs, uint64_t *out) { + uint64_t v = 0; + uint8_t b; + do { + if (!CBS_get_u8(cbs, &b)) { + return 0; + } + if ((v >> (64 - 7)) != 0) { + // The value is too large. + return 0; + } + if (v == 0 && b == 0x80) { + // The value must be minimally encoded. + return 0; + } + v = (v << 7) | (b & 0x7f); - if (out == NULL) { - out = &throwaway; - } + // Values end at an octet with the high bit cleared. + } while (b & 0x80); + + *out = v; + return 1; +} - if (!CBS_get_u8(&header, &tag) || - !CBS_get_u8(&header, &length_byte)) { +static int parse_asn1_tag(CBS *cbs, unsigned *out) { + uint8_t tag_byte; + if (!CBS_get_u8(cbs, &tag_byte)) { return 0; } @@ -197,22 +220,58 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, // allotted bits), then the tag is more than one byte long and the // continuation bytes contain the tag number. This parser only supports tag // numbers less than 31 (and thus single-byte tags). - if ((tag & 0x1f) == 0x1f) { - return 0; + unsigned tag = ((unsigned)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT; + unsigned tag_number = tag_byte & 0x1f; + if (tag_number == 0x1f) { + uint64_t v; + if (!parse_base128_integer(cbs, &v) || + // Check the tag number is within our supported bounds. + v > CBS_ASN1_TAG_NUMBER_MASK || + // Small tag numbers should have used low tag number form. + v < 0x1f) { + return 0; + } + tag_number = (unsigned)v; } + tag |= tag_number; + + *out = tag; + return 1; +} + +static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len, int ber_ok) { + CBS header = *cbs; + CBS throwaway; + + if (out == NULL) { + out = &throwaway; + } + + unsigned tag; + if (!parse_asn1_tag(&header, &tag)) { + return 0; + } if (out_tag != NULL) { *out_tag = tag; } + uint8_t length_byte; + if (!CBS_get_u8(&header, &length_byte)) { + return 0; + } + + size_t header_len = CBS_len(cbs) - CBS_len(&header); + size_t len; // The format for the length encoding is specified in ITU-T X.690 section // 8.1.3. if ((length_byte & 0x80) == 0) { // Short form length. - len = ((size_t) length_byte) + 2; + len = ((size_t) length_byte) + header_len; if (out_header_len != NULL) { - *out_header_len = 2; + *out_header_len = header_len; } } else { // The high bit indicate that this is the long form, while the next 7 bits @@ -224,9 +283,9 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) { // indefinite length if (out_header_len != NULL) { - *out_header_len = 2; + *out_header_len = header_len; } - return CBS_get_bytes(cbs, out, 2); + return CBS_get_bytes(cbs, out, header_len); } // ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be @@ -249,13 +308,13 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, return 0; } len = len32; - if (len + 2 + num_bytes < len) { + if (len + header_len + num_bytes < len) { // Overflow. return 0; } - len += 2 + num_bytes; + len += header_len + num_bytes; if (out_header_len != NULL) { - *out_header_len = 2 + num_bytes; + *out_header_len = header_len + num_bytes; } } @@ -323,7 +382,10 @@ int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) { if (CBS_len(cbs) < 1) { return 0; } - return CBS_data(cbs)[0] == tag_value; + + CBS copy = *cbs; + unsigned actual_tag; + return parse_asn1_tag(©, &actual_tag) && tag_value == actual_tag; } int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) { @@ -363,6 +425,22 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) { return 1; } +int CBS_get_asn1_bool(CBS *cbs, int *out) { + CBS bytes; + if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) || + CBS_len(&bytes) != 1) { + return 0; + } + + const uint8_t value = *CBS_data(&bytes); + if (value != 0 && value != 0xff) { + return 0; + } + + *out = !!value; + return 1; +} + int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) { int present = 0; @@ -388,6 +466,7 @@ int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, return 0; } if (present) { + assert(out); if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || CBS_len(&child) != 0) { return 0; @@ -485,3 +564,55 @@ int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) { return byte_num < CBS_len(cbs) && (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0; } + +static int add_decimal(CBB *out, uint64_t v) { + char buf[DECIMAL_SIZE(uint64_t) + 1]; + BIO_snprintf(buf, sizeof(buf), "%" PRIu64, v); + return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf)); +} + +char *CBS_asn1_oid_to_text(const CBS *cbs) { + CBB cbb; + if (!CBB_init(&cbb, 32)) { + goto err; + } + + CBS copy = *cbs; + // The first component is 40 * value1 + value2, where value1 is 0, 1, or 2. + uint64_t v; + if (!parse_base128_integer(©, &v)) { + goto err; + } + + if (v >= 80) { + if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) || + !add_decimal(&cbb, v - 80)) { + goto err; + } + } else if (!add_decimal(&cbb, v / 40) || + !CBB_add_u8(&cbb, '.') || + !add_decimal(&cbb, v % 40)) { + goto err; + } + + while (CBS_len(©) != 0) { + if (!parse_base128_integer(©, &v) || + !CBB_add_u8(&cbb, '.') || + !add_decimal(&cbb, v)) { + goto err; + } + } + + uint8_t *txt; + size_t txt_len; + if (!CBB_add_u8(&cbb, '\0') || + !CBB_finish(&cbb, &txt, &txt_len)) { + goto err; + } + + return (char *)txt; + +err: + CBB_cleanup(&cbb); + return NULL; +} diff --git a/Sources/BoringSSL/crypto/cipher_extra/e_aesccm.c b/Sources/BoringSSL/crypto/cipher_extra/e_aesccm.c new file mode 100644 index 000000000..87f16dc6a --- /dev/null +++ b/Sources/BoringSSL/crypto/cipher_extra/e_aesccm.c @@ -0,0 +1,203 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include + +#include "../fipsmodule/cipher/internal.h" + + +#define EVP_AEAD_AES_CCM_MAX_TAG_LEN 16 + +struct aead_aes_ccm_ctx { + union { + double align; + AES_KEY ks; + } ks; + CCM128_CONTEXT ccm; +}; + +static int aead_aes_ccm_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, unsigned M, + unsigned L) { + assert(M == EVP_AEAD_max_overhead(ctx->aead)); + assert(M == EVP_AEAD_max_tag_len(ctx->aead)); + assert(15 - L == EVP_AEAD_nonce_length(ctx->aead)); + + if (key_len != EVP_AEAD_key_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; // EVP_AEAD_CTX_init should catch this. + } + + if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) { + tag_len = M; + } + + if (tag_len != M) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE); + return 0; + } + + struct aead_aes_ccm_ctx *ccm_ctx = + OPENSSL_malloc(sizeof(struct aead_aes_ccm_ctx)); + if (ccm_ctx == NULL) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + + block128_f block; + ctr128_f ctr = aes_ctr_set_key(&ccm_ctx->ks.ks, NULL, &block, key, key_len); + ctx->tag_len = tag_len; + if (!CRYPTO_ccm128_init(&ccm_ctx->ccm, &ccm_ctx->ks.ks, block, ctr, M, L)) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_INTERNAL_ERROR); + OPENSSL_free(ccm_ctx); + return 0; + } + + ctx->aead_state = ccm_ctx; + return 1; +} + +static void aead_aes_ccm_cleanup(EVP_AEAD_CTX *ctx) { + OPENSSL_free(ctx->aead_state); +} + +static int aead_aes_ccm_seal_scatter( + const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag, + size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce, + size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in, + size_t extra_in_len, const uint8_t *ad, size_t ad_len) { + const struct aead_aes_ccm_ctx *ccm_ctx = ctx->aead_state; + + if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_tag_len < ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); + return 0; + } + + if (!CRYPTO_ccm128_encrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, out_tag, + ctx->tag_len, nonce, nonce_len, in, in_len, ad, + ad_len)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + *out_tag_len = ctx->tag_len; + return 1; +} + +static int aead_aes_ccm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *in_tag, size_t in_tag_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_ccm_ctx *ccm_ctx = ctx->aead_state; + + if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); + return 0; + } + + if (in_tag_len != ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + uint8_t tag[EVP_AEAD_AES_CCM_MAX_TAG_LEN]; + assert(ctx->tag_len <= EVP_AEAD_AES_CCM_MAX_TAG_LEN); + if (!CRYPTO_ccm128_decrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, tag, + ctx->tag_len, nonce, nonce_len, in, in_len, ad, + ad_len)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + return 1; +} + +static int aead_aes_ccm_bluetooth_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + return aead_aes_ccm_init(ctx, key, key_len, tag_len, 4, 2); +} + +static const EVP_AEAD aead_aes_128_ccm_bluetooth = { + 16, // key length (AES-128) + 13, // nonce length + 4, // overhead + 4, // max tag length + 0, // seal_scatter_supports_extra_in + + aead_aes_ccm_bluetooth_init, + NULL /* init_with_direction */, + aead_aes_ccm_cleanup, + NULL /* open */, + aead_aes_ccm_seal_scatter, + aead_aes_ccm_open_gather, + NULL /* get_iv */, + NULL /* tag_len */, +}; + +const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth(void) { + return &aead_aes_128_ccm_bluetooth; +} + +static int aead_aes_ccm_bluetooth_8_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + return aead_aes_ccm_init(ctx, key, key_len, tag_len, 8, 2); +} + +static const EVP_AEAD aead_aes_128_ccm_bluetooth_8 = { + 16, // key length (AES-128) + 13, // nonce length + 8, // overhead + 8, // max tag length + 0, // seal_scatter_supports_extra_in + + aead_aes_ccm_bluetooth_8_init, + NULL /* init_with_direction */, + aead_aes_ccm_cleanup, + NULL /* open */, + aead_aes_ccm_seal_scatter, + aead_aes_ccm_open_gather, + NULL /* get_iv */, + NULL /* tag_len */, +}; + +const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth_8(void) { + return &aead_aes_128_ccm_bluetooth_8; +} diff --git a/Sources/BoringSSL/crypto/cipher_extra/e_rc2.c b/Sources/BoringSSL/crypto/cipher_extra/e_rc2.c index 0b2caf555..221a9c923 100644 --- a/Sources/BoringSSL/crypto/cipher_extra/e_rc2.c +++ b/Sources/BoringSSL/crypto/cipher_extra/e_rc2.c @@ -57,6 +57,8 @@ #include #include +#include "../internal.h" + #define c2l(c, l) \ do { \ diff --git a/Sources/BoringSSL/crypto/cipher_extra/e_tls.c b/Sources/BoringSSL/crypto/cipher_extra/e_tls.c index 72754c0f1..bba22be53 100644 --- a/Sources/BoringSSL/crypto/cipher_extra/e_tls.c +++ b/Sources/BoringSSL/crypto/cipher_extra/e_tls.c @@ -191,8 +191,7 @@ static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, // block from encrypting the input and split the result between |out| and // |out_tag|. Then feed the rest. - const size_t early_mac_len = - (block_size - (in_len % block_size) % block_size); + const size_t early_mac_len = (block_size - (in_len % block_size)) % block_size; if (early_mac_len != 0) { assert(len + block_size - early_mac_len == in_len); uint8_t buf[EVP_MAX_BLOCK_LENGTH]; diff --git a/Sources/BoringSSL/crypto/cpu-aarch64-fuchsia.c b/Sources/BoringSSL/crypto/cpu-aarch64-fuchsia.c new file mode 100644 index 000000000..98303a033 --- /dev/null +++ b/Sources/BoringSSL/crypto/cpu-aarch64-fuchsia.c @@ -0,0 +1,55 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if defined(OPENSSL_AARCH64) && defined(OPENSSL_FUCHSIA) && \ + !defined(OPENSSL_STATIC_ARMCAP) + +#include +#include +#include + +#include + +#include "internal.h" + +extern uint32_t OPENSSL_armcap_P; + +void OPENSSL_cpuid_setup(void) { + uint32_t hwcap; + zx_status_t rc = zx_system_get_features(ZX_FEATURE_KIND_CPU, &hwcap); + if (rc != ZX_OK || (hwcap & ZX_ARM64_FEATURE_ISA_ASIMD) == 0) { + // Matching OpenSSL, if NEON/ASIMD is missing, don't report other features + // either. + return; + } + + OPENSSL_armcap_P |= ARMV7_NEON; + + if (hwcap & ZX_ARM64_FEATURE_ISA_AES) { + OPENSSL_armcap_P |= ARMV8_AES; + } + if (hwcap & ZX_ARM64_FEATURE_ISA_PMULL) { + OPENSSL_armcap_P |= ARMV8_PMULL; + } + if (hwcap & ZX_ARM64_FEATURE_ISA_SHA1) { + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (hwcap & ZX_ARM64_FEATURE_ISA_SHA2) { + OPENSSL_armcap_P |= ARMV8_SHA256; + } +} + +#endif // OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP diff --git a/Sources/BoringSSL/crypto/cpu-aarch64-linux.c b/Sources/BoringSSL/crypto/cpu-aarch64-linux.c index f9fa6c5c5..0184dd4ff 100644 --- a/Sources/BoringSSL/crypto/cpu-aarch64-linux.c +++ b/Sources/BoringSSL/crypto/cpu-aarch64-linux.c @@ -14,7 +14,8 @@ #include -#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP) +#if defined(OPENSSL_AARCH64) && defined(OPENSSL_LINUX) && \ + !defined(OPENSSL_STATIC_ARMCAP) #include diff --git a/Sources/BoringSSL/crypto/curve25519/x25519-x86_64.c b/Sources/BoringSSL/crypto/curve25519/x25519-x86_64.c deleted file mode 100644 index 41db0bddc..000000000 --- a/Sources/BoringSSL/crypto/curve25519/x25519-x86_64.c +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2015, Google Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -// This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP -// 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as -// public domain but this file has the ISC license just to keep licencing -// simple. -// -// The field functions are shared by Ed25519 and X25519 where possible. - -#include - -#include - -#include "../internal.h" -#include "../../third_party/fiat/internal.h" - - -#if defined(BORINGSSL_X25519_X86_64) - -typedef struct { uint64_t v[5]; } fe25519; - -// These functions are defined in asm/x25519-x86_64.S -void x25519_x86_64_work_cswap(fe25519 *, uint64_t); -void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b); -void x25519_x86_64_square(fe25519 *out, const fe25519 *a); -void x25519_x86_64_freeze(fe25519 *); -void x25519_x86_64_ladderstep(fe25519 *work); - -static void fe25519_setint(fe25519 *r, unsigned v) { - r->v[0] = v; - r->v[1] = 0; - r->v[2] = 0; - r->v[3] = 0; - r->v[4] = 0; -} - -// Assumes input x being reduced below 2^255 -static void fe25519_pack(unsigned char r[32], const fe25519 *x) { - fe25519 t; - t = *x; - x25519_x86_64_freeze(&t); - - r[0] = (uint8_t)(t.v[0] & 0xff); - r[1] = (uint8_t)((t.v[0] >> 8) & 0xff); - r[2] = (uint8_t)((t.v[0] >> 16) & 0xff); - r[3] = (uint8_t)((t.v[0] >> 24) & 0xff); - r[4] = (uint8_t)((t.v[0] >> 32) & 0xff); - r[5] = (uint8_t)((t.v[0] >> 40) & 0xff); - r[6] = (uint8_t)((t.v[0] >> 48)); - - r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8); - r[7] = (uint8_t)((t.v[1] >> 5) & 0xff); - r[8] = (uint8_t)((t.v[1] >> 13) & 0xff); - r[9] = (uint8_t)((t.v[1] >> 21) & 0xff); - r[10] = (uint8_t)((t.v[1] >> 29) & 0xff); - r[11] = (uint8_t)((t.v[1] >> 37) & 0xff); - r[12] = (uint8_t)((t.v[1] >> 45)); - - r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0); - r[13] = (uint8_t)((t.v[2] >> 2) & 0xff); - r[14] = (uint8_t)((t.v[2] >> 10) & 0xff); - r[15] = (uint8_t)((t.v[2] >> 18) & 0xff); - r[16] = (uint8_t)((t.v[2] >> 26) & 0xff); - r[17] = (uint8_t)((t.v[2] >> 34) & 0xff); - r[18] = (uint8_t)((t.v[2] >> 42) & 0xff); - r[19] = (uint8_t)((t.v[2] >> 50)); - - r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe); - r[20] = (uint8_t)((t.v[3] >> 7) & 0xff); - r[21] = (uint8_t)((t.v[3] >> 15) & 0xff); - r[22] = (uint8_t)((t.v[3] >> 23) & 0xff); - r[23] = (uint8_t)((t.v[3] >> 31) & 0xff); - r[24] = (uint8_t)((t.v[3] >> 39) & 0xff); - r[25] = (uint8_t)((t.v[3] >> 47)); - - r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0); - r[26] = (uint8_t)((t.v[4] >> 4) & 0xff); - r[27] = (uint8_t)((t.v[4] >> 12) & 0xff); - r[28] = (uint8_t)((t.v[4] >> 20) & 0xff); - r[29] = (uint8_t)((t.v[4] >> 28) & 0xff); - r[30] = (uint8_t)((t.v[4] >> 36) & 0xff); - r[31] = (uint8_t)((t.v[4] >> 44)); -} - -static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) { - r->v[0] = x[0]; - r->v[0] += (uint64_t)x[1] << 8; - r->v[0] += (uint64_t)x[2] << 16; - r->v[0] += (uint64_t)x[3] << 24; - r->v[0] += (uint64_t)x[4] << 32; - r->v[0] += (uint64_t)x[5] << 40; - r->v[0] += ((uint64_t)x[6] & 7) << 48; - - r->v[1] = x[6] >> 3; - r->v[1] += (uint64_t)x[7] << 5; - r->v[1] += (uint64_t)x[8] << 13; - r->v[1] += (uint64_t)x[9] << 21; - r->v[1] += (uint64_t)x[10] << 29; - r->v[1] += (uint64_t)x[11] << 37; - r->v[1] += ((uint64_t)x[12] & 63) << 45; - - r->v[2] = x[12] >> 6; - r->v[2] += (uint64_t)x[13] << 2; - r->v[2] += (uint64_t)x[14] << 10; - r->v[2] += (uint64_t)x[15] << 18; - r->v[2] += (uint64_t)x[16] << 26; - r->v[2] += (uint64_t)x[17] << 34; - r->v[2] += (uint64_t)x[18] << 42; - r->v[2] += ((uint64_t)x[19] & 1) << 50; - - r->v[3] = x[19] >> 1; - r->v[3] += (uint64_t)x[20] << 7; - r->v[3] += (uint64_t)x[21] << 15; - r->v[3] += (uint64_t)x[22] << 23; - r->v[3] += (uint64_t)x[23] << 31; - r->v[3] += (uint64_t)x[24] << 39; - r->v[3] += ((uint64_t)x[25] & 15) << 47; - - r->v[4] = x[25] >> 4; - r->v[4] += (uint64_t)x[26] << 4; - r->v[4] += (uint64_t)x[27] << 12; - r->v[4] += (uint64_t)x[28] << 20; - r->v[4] += (uint64_t)x[29] << 28; - r->v[4] += (uint64_t)x[30] << 36; - r->v[4] += ((uint64_t)x[31] & 127) << 44; -} - -static void fe25519_invert(fe25519 *r, const fe25519 *x) { - fe25519 z2; - fe25519 z9; - fe25519 z11; - fe25519 z2_5_0; - fe25519 z2_10_0; - fe25519 z2_20_0; - fe25519 z2_50_0; - fe25519 z2_100_0; - fe25519 t; - int i; - - /* 2 */ x25519_x86_64_square(&z2, x); - /* 4 */ x25519_x86_64_square(&t, &z2); - /* 8 */ x25519_x86_64_square(&t, &t); - /* 9 */ x25519_x86_64_mul(&z9, &t, x); - /* 11 */ x25519_x86_64_mul(&z11, &z9, &z2); - /* 22 */ x25519_x86_64_square(&t, &z11); - /* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9); - - /* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0); - /* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); } - /* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0); - - /* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0); - /* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); } - /* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0); - - /* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0); - /* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); } - /* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0); - - /* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t); - /* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); } - /* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0); - - /* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0); - /* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); } - /* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0); - - /* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0); - /* 2^200 - 2^100 */ for (i = 1; i < 100; i++) { - x25519_x86_64_square(&t, &t); - } - /* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0); - - /* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t); - /* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); } - /* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0); - - /* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t); - /* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t); - /* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t); - - /* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t); - - /* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t); - /* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11); -} - -static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) { - fe25519 work[5]; - - work[0] = *xr; - fe25519_setint(work + 1, 1); - fe25519_setint(work + 2, 0); - work[3] = *xr; - fe25519_setint(work + 4, 1); - - int i, j; - uint8_t prevbit = 0; - - j = 6; - for (i = 31; i >= 0; i--) { - while (j >= 0) { - const uint8_t bit = 1 & (s[i] >> j); - const uint64_t swap = bit ^ prevbit; - prevbit = bit; - x25519_x86_64_work_cswap(work + 1, swap); - x25519_x86_64_ladderstep(work); - j -= 1; - } - j = 7; - } - - *xr = work[1]; - *zr = work[2]; -} - -void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32], - const uint8_t point[32]) { - uint8_t e[32]; - OPENSSL_memcpy(e, scalar, sizeof(e)); - - e[0] &= 248; - e[31] &= 127; - e[31] |= 64; - - fe25519 t; - fe25519 z; - fe25519_unpack(&t, point); - mladder(&t, &z, e); - fe25519_invert(&z, &z); - x25519_x86_64_mul(&t, &t, &z); - fe25519_pack(out, &t); -} - -#endif // BORINGSSL_X25519_X86_64 diff --git a/Sources/BoringSSL/crypto/dsa/dsa.c b/Sources/BoringSSL/crypto/dsa/dsa.c index f3d4f859d..b97806b84 100644 --- a/Sources/BoringSSL/crypto/dsa/dsa.c +++ b/Sources/BoringSSL/crypto/dsa/dsa.c @@ -239,11 +239,6 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in, } BN_CTX_start(ctx); - mont = BN_MONT_CTX_new(); - if (mont == NULL) { - goto err; - } - r0 = BN_CTX_get(ctx); g = BN_CTX_get(ctx); W = BN_CTX_get(ctx); @@ -401,8 +396,9 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in, goto err; } - if (!BN_set_word(test, h) || - !BN_MONT_CTX_set(mont, p, ctx)) { + mont = BN_MONT_CTX_new_for_modulus(p, ctx); + if (mont == NULL || + !BN_set_word(test, h)) { goto err; } @@ -839,7 +835,7 @@ int DSA_size(const DSA *dsa) { static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, BIGNUM **out_r) { BN_CTX *ctx; - BIGNUM k, kq, *kinv = NULL, *r = NULL; + BIGNUM k, *kinv = NULL, *r = NULL; int ret = 0; if (!dsa->p || !dsa->q || !dsa->g) { @@ -848,7 +844,6 @@ static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, } BN_init(&k); - BN_init(&kq); ctx = ctx_in; if (ctx == NULL) { @@ -859,54 +854,22 @@ static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, } r = BN_new(); - if (r == NULL) { - goto err; - } - - // Get random k - if (!BN_rand_range_ex(&k, 1, dsa->q)) { - goto err; - } - - if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + kinv = BN_new(); + if (r == NULL || kinv == NULL || + // Get random k + !BN_rand_range_ex(&k, 1, dsa->q) || + !BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p, ctx) || !BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_q, (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->q, - ctx)) { - goto err; - } - - // Compute r = (g^k mod p) mod q - if (!BN_copy(&kq, &k)) { - goto err; - } - - // We do not want timing information to leak the length of k, - // so we compute g^k using an equivalent exponent of fixed length. - // - // (This is a kludge that we need because the BN_mod_exp_mont() - // does not let us specify the desired timing behaviour.) - - if (!BN_add(&kq, &kq, dsa->q)) { - goto err; - } - if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) { - goto err; - } - - if (!BN_mod_exp_mont_consttime(r, dsa->g, &kq, dsa->p, ctx, - dsa->method_mont_p)) { - goto err; - } - if (!BN_mod(r, r, dsa->q, ctx)) { - goto err; - } - - // Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little - // Theorem. - kinv = BN_new(); - if (kinv == NULL || + ctx) || + // Compute r = (g^k mod p) mod q + !BN_mod_exp_mont_consttime(r, dsa->g, &k, dsa->p, ctx, + dsa->method_mont_p) || + !BN_mod(r, r, dsa->q, ctx) || + // Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little + // Theorem. !bn_mod_inverse_prime(kinv, &k, dsa->q, ctx, dsa->method_mont_q)) { goto err; } @@ -930,7 +893,6 @@ static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, BN_CTX_free(ctx); } BN_clear_free(&k); - BN_clear_free(&kq); BN_clear_free(kinv); return ret; } diff --git a/Sources/BoringSSL/crypto/ec_extra/ec_asn1.c b/Sources/BoringSSL/crypto/ec_extra/ec_asn1.c index c125af2b4..bde6d0b31 100644 --- a/Sources/BoringSSL/crypto/ec_extra/ec_asn1.c +++ b/Sources/BoringSSL/crypto/ec_extra/ec_asn1.c @@ -86,6 +86,7 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { // Parse the optional parameters field. EC_GROUP *inner_group = NULL; EC_KEY *ret = NULL; + BIGNUM *priv_key = NULL; if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) { // Per SEC 1, as an alternative to omitting it, one is allowed to specify // this field and put in a NULL to mean inheriting this value. This was @@ -126,15 +127,10 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { // Although RFC 5915 specifies the length of the key, OpenSSL historically // got this wrong, so accept any length. See upstream's // 30cd4ff294252c4b6a4b69cbef6a5b4117705d22. - ret->priv_key = - BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL); + priv_key = BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL); ret->pub_key = EC_POINT_new(group); - if (ret->priv_key == NULL || ret->pub_key == NULL) { - goto err; - } - - if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(group)) >= 0) { - OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + if (priv_key == NULL || ret->pub_key == NULL || + !EC_KEY_set_private_key(ret, priv_key)) { goto err; } @@ -163,7 +159,8 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01); } else { // Compute the public key instead. - if (!EC_POINT_mul(group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) { + if (!ec_point_mul_scalar(group, ret->pub_key, &ret->priv_key->scalar, NULL, + NULL, NULL)) { goto err; } // Remember the original private-key-only encoding. @@ -181,11 +178,13 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { goto err; } + BN_free(priv_key); EC_GROUP_free(inner_group); return ret; err: EC_KEY_free(ret); + BN_free(priv_key); EC_GROUP_free(inner_group); return NULL; } @@ -203,7 +202,7 @@ int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key, !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) || !BN_bn2cbb_padded(&private_key, BN_num_bytes(EC_GROUP_get0_order(key->group)), - key->priv_key)) { + EC_KEY_get0_private_key(key))) { OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); return 0; } diff --git a/Sources/BoringSSL/crypto/ecdh/ecdh.c b/Sources/BoringSSL/crypto/ecdh/ecdh.c index f38de2f1f..7634ba590 100644 --- a/Sources/BoringSSL/crypto/ecdh/ecdh.c +++ b/Sources/BoringSSL/crypto/ecdh/ecdh.c @@ -74,6 +74,7 @@ #include #include +#include "../fipsmodule/ec/internal.h" #include "../internal.h" @@ -81,11 +82,11 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *priv_key, void *(*kdf)(const void *in, size_t inlen, void *out, size_t *outlen)) { - const BIGNUM *const priv = EC_KEY_get0_private_key(priv_key); - if (priv == NULL) { + if (priv_key->priv_key == NULL) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); return -1; } + const EC_SCALAR *const priv = &priv_key->priv_key->scalar; BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { @@ -104,7 +105,7 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, goto err; } - if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv, ctx)) { + if (!ec_point_mul_scalar(group, tmp, NULL, pub_key, priv, ctx)) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/add.c b/Sources/BoringSSL/crypto/fipsmodule/bn/add.c index 201c526d1..38a845062 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/add.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/add.c @@ -100,61 +100,38 @@ int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { return ret; } -int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { - int max, min, dif; - BN_ULONG *ap, *bp, *rp, carry, t1, t2; - const BIGNUM *tmp; - - if (a->top < b->top) { - tmp = a; +int bn_uadd_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + // Widths are public, so we normalize to make |a| the larger one. + if (a->width < b->width) { + const BIGNUM *tmp = a; a = b; b = tmp; } - max = a->top; - min = b->top; - dif = max - min; + int max = a->width; + int min = b->width; if (!bn_wexpand(r, max + 1)) { return 0; } - - r->top = max; - - ap = a->d; - bp = b->d; - rp = r->d; - - carry = bn_add_words(rp, ap, bp, min); - rp += min; - ap += min; - bp += min; - - if (carry) { - while (dif) { - dif--; - t1 = *(ap++); - t2 = t1 + 1; - *(rp++) = t2; - if (t2) { - carry = 0; - break; - } - } - if (carry) { - // carry != 0 => dif == 0 - *rp = 1; - r->top++; - } + r->width = max + 1; + + BN_ULONG carry = bn_add_words(r->d, a->d, b->d, min); + for (int i = min; i < max; i++) { + // |r| and |a| may alias, so use a temporary. + BN_ULONG tmp = carry + a->d[i]; + carry = tmp < a->d[i]; + r->d[i] = tmp; } - if (dif && rp != ap) { - while (dif--) { - // copy remaining words if ap != rp - *(rp++) = *(ap++); - } - } + r->d[max] = carry; + return 1; +} - r->neg = 0; +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + if (!bn_uadd_consttime(r, a, b)) { + return 0; + } + bn_set_minimal_width(r); return 1; } @@ -182,16 +159,16 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) { return i; } - for (i = 0; w != 0 && i < a->top; i++) { + for (i = 0; w != 0 && i < a->width; i++) { a->d[i] = l = a->d[i] + w; w = (w > l) ? 1 : 0; } - if (w && i == a->top) { - if (!bn_wexpand(a, a->top + 1)) { + if (w && i == a->width) { + if (!bn_wexpand(a, a->width + 1)) { return 0; } - a->top++; + a->width++; a->d[i] = w; } @@ -199,7 +176,6 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) { } int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { - int max; int add = 0, neg = 0; const BIGNUM *tmp; @@ -232,13 +208,6 @@ int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { return 1; } - // We are actually doing a - b :-) - - max = (a->top > b->top) ? a->top : b->top; - if (!bn_wexpand(r, max)) { - return 0; - } - if (BN_ucmp(a, b) < 0) { if (!BN_usub(r, b, a)) { return 0; @@ -254,69 +223,45 @@ int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { return 1; } -int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { - int max, min, dif; - register BN_ULONG t1, t2, *ap, *bp, *rp; - int i, carry; - - max = a->top; - min = b->top; - dif = max - min; - - if (dif < 0) // hmm... should not be happening - { - OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3); - return 0; +int bn_usub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + // |b| may have more words than |a| given non-minimal inputs, but all words + // beyond |a->width| must then be zero. + int b_width = b->width; + if (b_width > a->width) { + if (!bn_fits_in_words(b, a->width)) { + OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3); + return 0; + } + b_width = a->width; } - if (!bn_wexpand(r, max)) { + if (!bn_wexpand(r, a->width)) { return 0; } - ap = a->d; - bp = b->d; - rp = r->d; - - carry = 0; - for (i = min; i != 0; i--) { - t1 = *(ap++); - t2 = *(bp++); - if (carry) { - carry = (t1 <= t2); - t1 -= t2 + 1; - } else { - carry = (t1 < t2); - t1 -= t2; - } - *(rp++) = t1; + BN_ULONG borrow = bn_sub_words(r->d, a->d, b->d, b_width); + for (int i = b_width; i < a->width; i++) { + // |r| and |a| may alias, so use a temporary. + BN_ULONG tmp = a->d[i]; + r->d[i] = a->d[i] - borrow; + borrow = tmp < r->d[i]; } - if (carry) // subtracted - { - if (!dif) { - // error: a < b - return 0; - } - - while (dif) { - dif--; - t1 = *(ap++); - t2 = t1 - 1; - *(rp++) = t2; - if (t1) { - break; - } - } - } - - if (dif > 0 && rp != ap) { - OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif); + if (borrow) { + OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3); + return 0; } - r->top = max; + r->width = a->width; r->neg = 0; - bn_correct_top(r); + return 1; +} +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + if (!bn_usub_consttime(r, a, b)) { + return 0; + } + bn_set_minimal_width(r); return 1; } @@ -345,7 +290,7 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) { return i; } - if ((a->top == 1) && (a->d[0] < w)) { + if ((bn_minimal_width(a) == 1) && (a->d[0] < w)) { a->d[0] = w - a->d[0]; a->neg = 1; return 1; @@ -363,8 +308,8 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) { } } - if ((a->d[i] == 0) && (i == (a->top - 1))) { - a->top--; + if ((a->d[i] == 0) && (i == (a->width - 1))) { + a->width--; } return 1; diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/bn.c b/Sources/BoringSSL/crypto/fipsmodule/bn/bn.c index 4ed6ab056..c020d9640 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/bn.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/bn.c @@ -148,13 +148,13 @@ BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) { return dest; } - if (!bn_wexpand(dest, src->top)) { + if (!bn_wexpand(dest, src->width)) { return NULL; } - OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top); + OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->width); - dest->top = src->top; + dest->width = src->width; dest->neg = src->neg; return dest; } @@ -164,14 +164,14 @@ void BN_clear(BIGNUM *bn) { OPENSSL_memset(bn->d, 0, bn->dmax * sizeof(bn->d[0])); } - bn->top = 0; + bn->width = 0; bn->neg = 0; } DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one) { static const BN_ULONG kOneLimbs[1] = { 1 }; out->d = (BN_ULONG*) kOneLimbs; - out->top = 1; + out->width = 1; out->dmax = 1; out->neg = 0; out->flags = BN_FLG_STATIC_DATA; @@ -180,61 +180,65 @@ DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one) { // BN_num_bits_word returns the minimum number of bits needed to represent the // value in |l|. unsigned BN_num_bits_word(BN_ULONG l) { - static const unsigned char bits[256] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; - -#if defined(OPENSSL_64_BIT) - if (l & 0xffffffff00000000L) { - if (l & 0xffff000000000000L) { - if (l & 0xff00000000000000L) { - return (bits[(int)(l >> 56)] + 56); - } else { - return (bits[(int)(l >> 48)] + 48); - } - } else { - if (l & 0x0000ff0000000000L) { - return (bits[(int)(l >> 40)] + 40); - } else { - return (bits[(int)(l >> 32)] + 32); - } - } - } else + // |BN_num_bits| is often called on RSA prime factors. These have public bit + // lengths, but all bits beyond the high bit are secret, so count bits in + // constant time. + BN_ULONG x, mask; + int bits = (l != 0); + +#if BN_BITS2 > 32 + // Look at the upper half of |x|. |x| is at most 64 bits long. + x = l >> 32; + // Set |mask| to all ones if |x| (the top 32 bits of |l|) is non-zero and all + // all zeros otherwise. + mask = 0u - x; + mask = (0u - (mask >> (BN_BITS2 - 1))); + // If |x| is non-zero, the lower half is included in the bit count in full, + // and we count the upper half. Otherwise, we count the lower half. + bits += 32 & mask; + l ^= (x ^ l) & mask; // |l| is |x| if |mask| and remains |l| otherwise. #endif - { - if (l & 0xffff0000L) { - if (l & 0xff000000L) { - return (bits[(int)(l >> 24L)] + 24); - } else { - return (bits[(int)(l >> 16L)] + 16); - } - } else { - if (l & 0xff00L) { - return (bits[(int)(l >> 8)] + 8); - } else { - return (bits[(int)(l)]); - } - } - } + + // The remaining blocks are analogous iterations at lower powers of two. + x = l >> 16; + mask = 0u - x; + mask = (0u - (mask >> (BN_BITS2 - 1))); + bits += 16 & mask; + l ^= (x ^ l) & mask; + + x = l >> 8; + mask = 0u - x; + mask = (0u - (mask >> (BN_BITS2 - 1))); + bits += 8 & mask; + l ^= (x ^ l) & mask; + + x = l >> 4; + mask = 0u - x; + mask = (0u - (mask >> (BN_BITS2 - 1))); + bits += 4 & mask; + l ^= (x ^ l) & mask; + + x = l >> 2; + mask = 0u - x; + mask = (0u - (mask >> (BN_BITS2 - 1))); + bits += 2 & mask; + l ^= (x ^ l) & mask; + + x = l >> 1; + mask = 0u - x; + mask = (0u - (mask >> (BN_BITS2 - 1))); + bits += 1 & mask; + + return bits; } unsigned BN_num_bits(const BIGNUM *bn) { - const int max = bn->top - 1; - - if (BN_is_zero(bn)) { + const int width = bn_minimal_width(bn); + if (width == 0) { return 0; } - return max*BN_BITS2 + BN_num_bits_word(bn->d[max]); + return (width - 1) * BN_BITS2 + BN_num_bits_word(bn->d[width - 1]); } unsigned BN_num_bytes(const BIGNUM *bn) { @@ -242,7 +246,7 @@ unsigned BN_num_bytes(const BIGNUM *bn) { } void BN_zero(BIGNUM *bn) { - bn->top = bn->neg = 0; + bn->width = bn->neg = 0; } int BN_one(BIGNUM *bn) { @@ -261,7 +265,7 @@ int BN_set_word(BIGNUM *bn, BN_ULONG value) { bn->neg = 0; bn->d[0] = value; - bn->top = 1; + bn->width = 1; return 1; } @@ -280,7 +284,7 @@ int BN_set_u64(BIGNUM *bn, uint64_t value) { bn->neg = 0; bn->d[0] = (BN_ULONG)value; bn->d[1] = (BN_ULONG)(value >> 32); - bn->top = 2; + bn->width = 2; return 1; #else #error "BN_BITS2 must be 32 or 64." @@ -293,12 +297,40 @@ int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { } OPENSSL_memmove(bn->d, words, num * sizeof(BN_ULONG)); // |bn_wexpand| verified that |num| isn't too large. - bn->top = (int)num; - bn_correct_top(bn); + bn->width = (int)num; bn->neg = 0; return 1; } +int bn_fits_in_words(const BIGNUM *bn, size_t num) { + // All words beyond |num| must be zero. + BN_ULONG mask = 0; + for (size_t i = num; i < (size_t)bn->width; i++) { + mask |= bn->d[i]; + } + return mask == 0; +} + +int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn) { + if (bn->neg) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + size_t width = (size_t)bn->width; + if (width > num) { + if (!bn_fits_in_words(bn, num)) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return 0; + } + width = num; + } + + OPENSSL_memset(out, 0, sizeof(BN_ULONG) * num); + OPENSSL_memcpy(out, bn->d, sizeof(BN_ULONG) * width); + return 1; +} + int BN_is_negative(const BIGNUM *bn) { return bn->neg != 0; } @@ -334,7 +366,7 @@ int bn_wexpand(BIGNUM *bn, size_t words) { return 0; } - OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top); + OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->width); OPENSSL_free(bn->d); bn->d = a; @@ -351,20 +383,46 @@ int bn_expand(BIGNUM *bn, size_t bits) { return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2); } -void bn_correct_top(BIGNUM *bn) { - BN_ULONG *ftl; - int tmp_top = bn->top; - - if (tmp_top > 0) { - for (ftl = &(bn->d[tmp_top - 1]); tmp_top > 0; tmp_top--) { - if (*(ftl--)) { - break; - } +int bn_resize_words(BIGNUM *bn, size_t words) { + if ((size_t)bn->width <= words) { + if (!bn_wexpand(bn, words)) { + return 0; } - bn->top = tmp_top; + OPENSSL_memset(bn->d + bn->width, 0, + (words - bn->width) * sizeof(BN_ULONG)); + bn->width = words; + return 1; + } + + // All words beyond the new width must be zero. + if (!bn_fits_in_words(bn, words)) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return 0; } + bn->width = words; + return 1; +} + +void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a, + const BN_ULONG *b, size_t num) { + for (size_t i = 0; i < num; i++) { + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), + crypto_word_t_too_small); + r[i] = constant_time_select_w(mask, a[i], b[i]); + } +} + +int bn_minimal_width(const BIGNUM *bn) { + int ret = bn->width; + while (ret > 0 && bn->d[ret - 1] == 0) { + ret--; + } + return ret; +} - if (bn->top == 0) { +void bn_set_minimal_width(BIGNUM *bn) { + bn->width = bn_minimal_width(bn); + if (bn->width == 0) { bn->neg = 0; } } diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/bytes.c b/Sources/BoringSSL/crypto/fipsmodule/bn/bytes.c index 328d56e74..56241e3b9 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/bytes.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/bytes.c @@ -77,7 +77,7 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { } if (len == 0) { - ret->top = 0; + ret->width = 0; return ret; } @@ -93,7 +93,7 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { // |bn_wexpand| must check bounds on |num_words| to write it into // |ret->dmax|. assert(num_words <= INT_MAX); - ret->top = (int)num_words; + ret->width = (int)num_words; ret->neg = 0; while (len--) { @@ -105,9 +105,6 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { } } - // need to call this due to clear byte at top if avoiding having the top bit - // set (-ve number) - bn_correct_top(ret); return ret; } @@ -123,7 +120,7 @@ BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) { } if (len == 0) { - ret->top = 0; + ret->width = 0; ret->neg = 0; return ret; } @@ -134,7 +131,7 @@ BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) { BN_free(bn); return NULL; } - ret->top = num_words; + ret->width = num_words; // Make sure the top bytes will be zeroed. ret->d[num_words - 1] = 0; @@ -142,8 +139,6 @@ BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) { // We only support little-endian platforms, so we can simply memcpy the // internal representation. OPENSSL_memcpy(ret->d, in, len); - - bn_correct_top(ret); return ret; } @@ -159,88 +154,54 @@ size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) { return n; } +static int fits_in_bytes(const uint8_t *bytes, size_t num_bytes, size_t len) { + uint8_t mask = 0; + for (size_t i = len; i < num_bytes; i++) { + mask |= bytes[i]; + } + return mask == 0; +} + int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) { - // If we don't have enough space, fail out. - size_t num_bytes = BN_num_bytes(in); + const uint8_t *bytes = (const uint8_t *)in->d; + size_t num_bytes = in->width * BN_BYTES; if (len < num_bytes) { - return 0; + if (!fits_in_bytes(bytes, num_bytes, len)) { + return 0; + } + num_bytes = len; } // We only support little-endian platforms, so we can simply memcpy into the // internal representation. - OPENSSL_memcpy(out, in->d, num_bytes); - + OPENSSL_memcpy(out, bytes, num_bytes); // Pad out the rest of the buffer with zeroes. OPENSSL_memset(out + num_bytes, 0, len - num_bytes); - return 1; } -// constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its -// behavior is undefined if |v| takes any other value. -static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) { - BN_ULONG mask = v; - mask--; - - return (~mask & x) | (mask & y); -} - -// constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y| -// must not have their MSBs set. -static int constant_time_le_size_t(size_t x, size_t y) { - return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1; -} - -// read_word_padded returns the |i|'th word of |in|, if it is not out of -// bounds. Otherwise, it returns 0. It does so without branches on the size of -// |in|, however it necessarily does not have the same memory access pattern. If -// the access would be out of bounds, it reads the last word of |in|. |in| must -// not be zero. -static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) { - // Read |in->d[i]| if valid. Otherwise, read the last word. - BN_ULONG l = in->d[constant_time_select_ulong( - constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)]; - - // Clamp to zero if above |d->top|. - return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l); -} - int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) { - // Special case for |in| = 0. Just branch as the probability is negligible. - if (BN_is_zero(in)) { - OPENSSL_memset(out, 0, len); - return 1; - } - - // Check if the integer is too big. This case can exit early in non-constant - // time. - if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) { - return 0; - } - if ((len % BN_BYTES) != 0) { - BN_ULONG l = read_word_padded(in, len / BN_BYTES); - if (l >> (8 * (len % BN_BYTES)) != 0) { + const uint8_t *bytes = (const uint8_t *)in->d; + size_t num_bytes = in->width * BN_BYTES; + if (len < num_bytes) { + if (!fits_in_bytes(bytes, num_bytes, len)) { return 0; } + num_bytes = len; } - // Write the bytes out one by one. Serialization is done without branching on - // the bits of |in| or on |in->top|, but if the routine would otherwise read - // out of bounds, the memory access pattern can't be fixed. However, for an - // RSA key of size a multiple of the word size, the probability of BN_BYTES - // leading zero octets is low. - // - // See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. - size_t i = len; - while (i--) { - BN_ULONG l = read_word_padded(in, i / BN_BYTES); - *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff; + // We only support little-endian platforms, so we can simply write the buffer + // in reverse. + for (size_t i = 0; i < num_bytes; i++) { + out[len - i - 1] = bytes[i]; } + // Pad out the rest of the buffer with zeroes. + OPENSSL_memset(out, 0, len - num_bytes); return 1; } BN_ULONG BN_get_word(const BIGNUM *bn) { - switch (bn->top) { + switch (bn_minimal_width(bn)) { case 0: return 0; case 1: @@ -251,7 +212,7 @@ BN_ULONG BN_get_word(const BIGNUM *bn) { } int BN_get_u64(const BIGNUM *bn, uint64_t *out) { - switch (bn->top) { + switch (bn_minimal_width(bn)) { case 0: *out = 0; return 1; diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/cmp.c b/Sources/BoringSSL/crypto/fipsmodule/bn/cmp.c index acc017ff6..692adb5af 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/cmp.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/cmp.c @@ -63,33 +63,43 @@ #include "../../internal.h" -int BN_ucmp(const BIGNUM *a, const BIGNUM *b) { - int i; - BN_ULONG t1, t2, *ap, *bp; - - i = a->top - b->top; - if (i != 0) { - return i; +static int bn_cmp_words_consttime(const BN_ULONG *a, size_t a_len, + const BN_ULONG *b, size_t b_len) { + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), + crypto_word_t_too_small); + int ret = 0; + // Process the common words in little-endian order. + size_t min = a_len < b_len ? a_len : b_len; + for (size_t i = 0; i < min; i++) { + crypto_word_t eq = constant_time_eq_w(a[i], b[i]); + crypto_word_t lt = constant_time_lt_w(a[i], b[i]); + ret = + constant_time_select_int(eq, ret, constant_time_select_int(lt, -1, 1)); } - ap = a->d; - bp = b->d; - for (i = a->top - 1; i >= 0; i--) { - t1 = ap[i]; - t2 = bp[i]; - if (t1 != t2) { - return (t1 > t2) ? 1 : -1; + // If |a| or |b| has non-zero words beyond |min|, they take precedence. + if (a_len < b_len) { + crypto_word_t mask = 0; + for (size_t i = a_len; i < b_len; i++) { + mask |= b[i]; + } + ret = constant_time_select_int(constant_time_is_zero_w(mask), ret, -1); + } else if (b_len < a_len) { + crypto_word_t mask = 0; + for (size_t i = b_len; i < a_len; i++) { + mask |= a[i]; } + ret = constant_time_select_int(constant_time_is_zero_w(mask), ret, 1); } - return 0; + return ret; } -int BN_cmp(const BIGNUM *a, const BIGNUM *b) { - int i; - int gt, lt; - BN_ULONG t1, t2; +int BN_ucmp(const BIGNUM *a, const BIGNUM *b) { + return bn_cmp_words_consttime(a->d, a->width, b->d, b->width); +} +int BN_cmp(const BIGNUM *a, const BIGNUM *b) { if ((a == NULL) || (b == NULL)) { if (a != NULL) { return -1; @@ -100,104 +110,32 @@ int BN_cmp(const BIGNUM *a, const BIGNUM *b) { } } + // We do not attempt to process the sign bit in constant time. Negative + // |BIGNUM|s should never occur in crypto, only calculators. if (a->neg != b->neg) { if (a->neg) { return -1; } return 1; } - if (a->neg == 0) { - gt = 1; - lt = -1; - } else { - gt = -1; - lt = 1; - } - - if (a->top > b->top) { - return gt; - } - if (a->top < b->top) { - return lt; - } - - for (i = a->top - 1; i >= 0; i--) { - t1 = a->d[i]; - t2 = b->d[i]; - if (t1 > t2) { - return gt; - } if (t1 < t2) { - return lt; - } - } - - return 0; -} - -int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) { - int i; - BN_ULONG aa, bb; - - aa = a[n - 1]; - bb = b[n - 1]; - if (aa != bb) { - return (aa > bb) ? 1 : -1; - } - - for (i = n - 2; i >= 0; i--) { - aa = a[i]; - bb = b[i]; - if (aa != bb) { - return (aa > bb) ? 1 : -1; - } - } - return 0; -} - -int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) { - int n, i; - n = cl - 1; - - if (dl < 0) { - for (i = dl; i < 0; i++) { - if (b[n - i] != 0) { - return -1; // a < b - } - } - } - if (dl > 0) { - for (i = dl; i > 0; i--) { - if (a[n + i] != 0) { - return 1; // a > b - } - } - } - return bn_cmp_words(a, b, cl); + int ret = BN_ucmp(a, b); + return a->neg ? -ret : ret; } int bn_less_than_words(const BN_ULONG *a, const BN_ULONG *b, size_t len) { - OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), - crypto_word_t_too_small); - int ret = 0; - // Process the words in little-endian order. - for (size_t i = 0; i < len; i++) { - crypto_word_t eq = constant_time_eq_w(a[i], b[i]); - crypto_word_t lt = constant_time_lt_w(a[i], b[i]); - ret = constant_time_select_int(eq, ret, constant_time_select_int(lt, 1, 0)); - } - return ret; + return bn_cmp_words_consttime(a, len, b, len) < 0; } int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) { - switch (bn->top) { - case 1: - return bn->d[0] == w; - case 0: - return w == 0; - default: - return 0; + if (bn->width == 0) { + return w == 0; + } + BN_ULONG mask = bn->d[0] ^ w; + for (int i = 1; i < bn->width; i++) { + mask |= bn->d[i]; } + return mask == 0; } int BN_cmp_word(const BIGNUM *a, BN_ULONG b) { @@ -205,14 +143,14 @@ int BN_cmp_word(const BIGNUM *a, BN_ULONG b) { BN_init(&b_bn); b_bn.d = &b; - b_bn.top = b > 0; + b_bn.width = b > 0; b_bn.dmax = 1; b_bn.flags = BN_FLG_STATIC_DATA; return BN_cmp(a, &b_bn); } int BN_is_zero(const BIGNUM *bn) { - return bn->top == 0; + return bn_fits_in_words(bn, 0); } int BN_is_one(const BIGNUM *bn) { @@ -224,31 +162,39 @@ int BN_is_word(const BIGNUM *bn, BN_ULONG w) { } int BN_is_odd(const BIGNUM *bn) { - return bn->top > 0 && (bn->d[0] & 1) == 1; + return bn->width > 0 && (bn->d[0] & 1) == 1; } int BN_is_pow2(const BIGNUM *bn) { - if (bn->top == 0 || bn->neg) { + int width = bn_minimal_width(bn); + if (width == 0 || bn->neg) { return 0; } - for (int i = 0; i < bn->top - 1; i++) { + for (int i = 0; i < width - 1; i++) { if (bn->d[i] != 0) { return 0; } } - return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1)); + return 0 == (bn->d[width-1] & (bn->d[width-1] - 1)); } int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) { - if (a->top != b->top) { - return 0; - } - - int limbs_are_equal = - CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0; - - return constant_time_select_int(constant_time_eq_int(a->neg, b->neg), - limbs_are_equal, 0); + BN_ULONG mask = 0; + // If |a| or |b| has more words than the other, all those words must be zero. + for (int i = a->width; i < b->width; i++) { + mask |= b->d[i]; + } + for (int i = b->width; i < a->width; i++) { + mask |= a->d[i]; + } + // Common words must match. + int min = a->width < b->width ? a->width : b->width; + for (int i = 0; i < min; i++) { + mask |= (a->d[i] ^ b->d[i]); + } + // The sign bit must match. + mask |= (a->neg ^ b->neg); + return mask == 0; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/div.c b/Sources/BoringSSL/crypto/fipsmodule/bn/div.c index c92eab365..2a3bcdde8 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/div.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/div.c @@ -155,18 +155,18 @@ static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out, // // These issues aren't specific to x86 and x86_64, so it might be worthwhile // to add more assembly language implementations. -#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__) - __asm__ volatile ( - "divl %4" - : "=a"(*quotient_out), "=d"(*rem_out) - : "a"(n1), "d"(n0), "rm"(d0) - : "cc" ); -#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__) - __asm__ volatile ( - "divq %4" - : "=a"(*quotient_out), "=d"(*rem_out) - : "a"(n1), "d"(n0), "rm"(d0) - : "cc" ); +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && \ + (defined(__GNUC__) || defined(__clang__)) + __asm__ volatile("divl %4" + : "=a"(*quotient_out), "=d"(*rem_out) + : "a"(n1), "d"(n0), "rm"(d0) + : "cc"); +#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + (defined(__GNUC__) || defined(__clang__)) + __asm__ volatile("divq %4" + : "=a"(*quotient_out), "=d"(*rem_out) + : "a"(n1), "d"(n0), "rm"(d0) + : "cc"); #else #if defined(BN_ULLONG) BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1; @@ -202,10 +202,16 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, BN_ULONG d0, d1; int num_n, div_n; - // Invalid zero-padding would have particularly bad consequences - // so don't just rely on bn_check_top() here - if ((numerator->top > 0 && numerator->d[numerator->top - 1] == 0) || - (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) { + // This function relies on the historical minimal-width |BIGNUM| invariant. + // It is already not constant-time (constant-time reductions should use + // Montgomery logic), so we shrink all inputs and intermediate values to + // retain the previous behavior. + + // Invalid zero-padding would have particularly bad consequences. + int numerator_width = bn_minimal_width(numerator); + int divisor_width = bn_minimal_width(divisor); + if ((numerator_width > 0 && numerator->d[numerator_width - 1] == 0) || + (divisor_width > 0 && divisor->d[divisor_width - 1] == 0)) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_INITIALIZED); return 0; } @@ -234,46 +240,48 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, if (!BN_lshift(sdiv, divisor, norm_shift)) { goto err; } + bn_set_minimal_width(sdiv); sdiv->neg = 0; norm_shift += BN_BITS2; if (!BN_lshift(snum, numerator, norm_shift)) { goto err; } + bn_set_minimal_width(snum); snum->neg = 0; // Since we don't want to have special-case logic for the case where snum is // larger than sdiv, we pad snum with enough zeroes without changing its // value. - if (snum->top <= sdiv->top + 1) { - if (!bn_wexpand(snum, sdiv->top + 2)) { + if (snum->width <= sdiv->width + 1) { + if (!bn_wexpand(snum, sdiv->width + 2)) { goto err; } - for (int i = snum->top; i < sdiv->top + 2; i++) { + for (int i = snum->width; i < sdiv->width + 2; i++) { snum->d[i] = 0; } - snum->top = sdiv->top + 2; + snum->width = sdiv->width + 2; } else { - if (!bn_wexpand(snum, snum->top + 1)) { + if (!bn_wexpand(snum, snum->width + 1)) { goto err; } - snum->d[snum->top] = 0; - snum->top++; + snum->d[snum->width] = 0; + snum->width++; } - div_n = sdiv->top; - num_n = snum->top; + div_n = sdiv->width; + num_n = snum->width; loop = num_n - div_n; // Lets setup a 'window' into snum // This is the part that corresponds to the current // 'area' being divided wnum.neg = 0; wnum.d = &(snum->d[loop]); - wnum.top = div_n; - // only needed when BN_ucmp messes up the values between top and max + wnum.width = div_n; + // only needed when BN_ucmp messes up the values between width and max wnum.dmax = snum->dmax - loop; // so we don't step out of bounds // Get the top 2 words of sdiv - // div_n=sdiv->top; + // div_n=sdiv->width; d0 = sdiv->d[div_n - 1]; d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; @@ -285,7 +293,7 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, if (!bn_wexpand(res, loop + 1)) { goto err; } - res->top = loop - 1; + res->width = loop - 1; resp = &(res->d[loop - 1]); // space for temp @@ -293,9 +301,9 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, goto err; } - // if res->top == 0 then clear the neg value otherwise decrease + // if res->width == 0 then clear the neg value otherwise decrease // the resp pointer - if (res->top == 0) { + if (res->width == 0) { res->neg = 0; } else { resp--; @@ -371,7 +379,7 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, *resp = q; } - bn_correct_top(snum); + bn_set_minimal_width(snum); if (rem != NULL) { // Keep a copy of the neg flag in numerator because if |rem| == |numerator| @@ -385,7 +393,7 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator, } } - bn_correct_top(res); + bn_set_minimal_width(res); BN_CTX_end(ctx); return 1; @@ -406,6 +414,164 @@ int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) { return (d->neg ? BN_sub : BN_add)(r, r, d); } +// bn_mod_sub_words sets |r| to |a| - |b| (mod |m|), using |tmp| as scratch +// space. Each array is |num| words long. |a| and |b| must be < |m|. Any pair of +// |r|, |a|, and |b| may alias. +static void bn_mod_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + const BN_ULONG *m, BN_ULONG *tmp, size_t num) { + // r = a - b + BN_ULONG borrow = bn_sub_words(r, a, b, num); + // tmp = a - b + m + bn_add_words(tmp, r, m, num); + bn_select_words(r, 0 - borrow, tmp /* r < 0 */, r /* r >= 0 */, num); +} + +// bn_mod_add_words sets |r| to |a| + |b| (mod |m|), using |tmp| as scratch +// space. Each array is |num| words long. |a| and |b| must be < |m|. Any pair of +// |r|, |a|, and |b| may alias. +static void bn_mod_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + const BN_ULONG *m, BN_ULONG *tmp, size_t num) { + // tmp = a + b. Note the result fits in |num|+1 words. We store the extra word + // in |carry|. + BN_ULONG carry = bn_add_words(tmp, a, b, num); + // r = a + b - m. We use |bn_sub_words| to perform the bulk of the + // subtraction, and then apply the borrow to |carry|. + carry -= bn_sub_words(r, tmp, m, num); + // |a| and |b| were both fully-reduced, so we know: + // + // 0 + 0 - m <= r < m + m - m + // -m <= r < m + // + // If 0 <= |r| < |m|, |r| fits in |num| words and |carry| is zero. We then + // wish to select |r| as the answer. Otherwise -m <= r < 0 and we wish to + // return |r| + |m|, or |tmp|. |carry| must then be -1 or all ones. In both + // cases, |carry| is a suitable input to |bn_select_words|. + // + // Although |carry| may be one if |bn_add_words| returns one and + // |bn_sub_words| returns zero, this would give |r| > |m|, which violates are + // input assumptions. + assert(carry == 0 || carry == (BN_ULONG)-1); + bn_select_words(r, carry, tmp /* r < 0 */, r /* r >= 0 */, num); +} + +int bn_div_consttime(BIGNUM *quotient, BIGNUM *remainder, + const BIGNUM *numerator, const BIGNUM *divisor, + BN_CTX *ctx) { + if (BN_is_negative(numerator) || BN_is_negative(divisor)) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + if (BN_is_zero(divisor)) { + OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); + return 0; + } + + // This function implements long division in binary. It is not very efficient, + // but it is simple, easy to make constant-time, and performant enough for RSA + // key generation. + + int ret = 0; + BN_CTX_start(ctx); + BIGNUM *q = quotient, *r = remainder; + if (quotient == NULL || quotient == numerator || quotient == divisor) { + q = BN_CTX_get(ctx); + } + if (remainder == NULL || remainder == numerator || remainder == divisor) { + r = BN_CTX_get(ctx); + } + BIGNUM *tmp = BN_CTX_get(ctx); + if (q == NULL || r == NULL || tmp == NULL || + !bn_wexpand(q, numerator->width) || + !bn_wexpand(r, divisor->width) || + !bn_wexpand(tmp, divisor->width)) { + goto err; + } + + OPENSSL_memset(q->d, 0, numerator->width * sizeof(BN_ULONG)); + q->width = numerator->width; + q->neg = 0; + + OPENSSL_memset(r->d, 0, divisor->width * sizeof(BN_ULONG)); + r->width = divisor->width; + r->neg = 0; + + // Incorporate |numerator| into |r|, one bit at a time, reducing after each + // step. At the start of each loop iteration, |r| < |divisor| + for (int i = numerator->width - 1; i >= 0; i--) { + for (int bit = BN_BITS2 - 1; bit >= 0; bit--) { + // Incorporate the next bit of the numerator, by computing + // r = 2*r or 2*r + 1. Note the result fits in one more word. We store the + // extra word in |carry|. + BN_ULONG carry = bn_add_words(r->d, r->d, r->d, divisor->width); + r->d[0] |= (numerator->d[i] >> bit) & 1; + // tmp = r - divisor. We use |bn_sub_words| to perform the bulk of the + // subtraction, and then apply the borrow to |carry|. + carry -= bn_sub_words(tmp->d, r->d, divisor->d, divisor->width); + // |r| was previously fully-reduced, so we know: + // + // 2*0 - divisor <= tmp <= 2*(divisor-1) + 1 - divisor + // -divisor <= tmp < divisor + // + // If 0 <= |tmp| < |divisor|, |tmp| fits in |divisor->width| and |carry| + // is zero. We then wish to select |tmp|. Otherwise, + // -|divisor| <= |tmp| < 0 and we wish to select |tmp| + |divisor|, which + // is |r|. |carry| must then be -1 (all ones). In both cases, |carry| is a + // suitable input to |bn_select_words|. + // + // Although |carry| may be one if |bn_add_words| returns one and + // |bn_sub_words| returns zero, this would give |r| > |d|, which violates + // the loop invariant. + bn_select_words(r->d, carry, r->d /* tmp < 0 */, tmp->d /* tmp >= 0 */, + divisor->width); + // The corresponding bit of the quotient is set iff we needed to subtract. + q->d[i] |= (~carry & 1) << bit; + } + } + + if ((quotient != NULL && !BN_copy(quotient, q)) || + (remainder != NULL && !BN_copy(remainder, r))) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +static BIGNUM *bn_scratch_space_from_ctx(size_t width, BN_CTX *ctx) { + BIGNUM *ret = BN_CTX_get(ctx); + if (ret == NULL || + !bn_wexpand(ret, width)) { + return NULL; + } + ret->neg = 0; + ret->width = width; + return ret; +} + +// bn_resized_from_ctx returns |bn| with width at least |width| or NULL on +// error. This is so it may be used with low-level "words" functions. If +// necessary, it allocates a new |BIGNUM| with a lifetime of the current scope +// in |ctx|, so the caller does not need to explicitly free it. |bn| must fit in +// |width| words. +static const BIGNUM *bn_resized_from_ctx(const BIGNUM *bn, size_t width, + BN_CTX *ctx) { + if ((size_t)bn->width >= width) { + // Any excess words must be zero. + assert(bn_fits_in_words(bn, width)); + return bn; + } + BIGNUM *ret = bn_scratch_space_from_ctx(width, ctx); + if (ret == NULL || + !BN_copy(ret, bn) || + !bn_resize_words(ret, width)) { + return NULL; + } + return ret; +} + int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) { if (!BN_add(r, a, b)) { @@ -416,13 +582,27 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m) { - if (!BN_uadd(r, a, b)) { - return 0; - } - if (BN_ucmp(r, m) >= 0) { - return BN_usub(r, r, m); + BN_CTX *ctx = BN_CTX_new(); + int ok = ctx != NULL && + bn_mod_add_consttime(r, a, b, m, ctx); + BN_CTX_free(ctx); + return ok; +} + +int bn_mod_add_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx) { + BN_CTX_start(ctx); + a = bn_resized_from_ctx(a, m->width, ctx); + b = bn_resized_from_ctx(b, m->width, ctx); + BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx); + int ok = a != NULL && b != NULL && tmp != NULL && + bn_wexpand(r, m->width); + if (ok) { + bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width); + r->width = m->width; } - return 1; + BN_CTX_end(ctx); + return ok; } int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, @@ -433,17 +613,29 @@ int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, return BN_nnmod(r, r, m, ctx); } -// BN_mod_sub variant that may be used if both a and b are non-negative -// and less than m +int bn_mod_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx) { + BN_CTX_start(ctx); + a = bn_resized_from_ctx(a, m->width, ctx); + b = bn_resized_from_ctx(b, m->width, ctx); + BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx); + int ok = a != NULL && b != NULL && tmp != NULL && + bn_wexpand(r, m->width); + if (ok) { + bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width); + r->width = m->width; + } + BN_CTX_end(ctx); + return ok; +} + int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m) { - if (!BN_sub(r, a, b)) { - return 0; - } - if (r->neg) { - return BN_add(r, r, m); - } - return 1; + BN_CTX *ctx = BN_CTX_new(); + int ok = ctx != NULL && + bn_mod_sub_consttime(r, a, b, m, ctx); + BN_CTX_free(ctx); + return ok; } int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, @@ -504,58 +696,33 @@ int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, abs_m->neg = 0; } - ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m)); + ret = bn_mod_lshift_consttime(r, r, n, (abs_m ? abs_m : m), ctx); BN_free(abs_m); return ret; } -int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) { - if (r != a) { - if (BN_copy(r, a) == NULL) { - return 0; - } +int bn_mod_lshift_consttime(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx) { + if (!BN_copy(r, a)) { + return 0; } - - while (n > 0) { - int max_shift; - - // 0 < r < m - max_shift = BN_num_bits(m) - BN_num_bits(r); - // max_shift >= 0 - - if (max_shift < 0) { - OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED); + for (int i = 0; i < n; i++) { + if (!bn_mod_lshift1_consttime(r, r, m, ctx)) { return 0; } - - if (max_shift > n) { - max_shift = n; - } - - if (max_shift) { - if (!BN_lshift(r, r, max_shift)) { - return 0; - } - n -= max_shift; - } else { - if (!BN_lshift1(r, r)) { - return 0; - } - --n; - } - - // BN_num_bits(r) <= BN_num_bits(m) - if (BN_cmp(r, m) >= 0) { - if (!BN_sub(r, r, m)) { - return 0; - } - } } - return 1; } +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) { + BN_CTX *ctx = BN_CTX_new(); + int ok = ctx != NULL && + bn_mod_lshift_consttime(r, a, n, m, ctx); + BN_CTX_free(ctx); + return ok; +} + int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { if (!BN_lshift1(r, a)) { return 0; @@ -564,15 +731,17 @@ int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { return BN_nnmod(r, r, m, ctx); } -int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) { - if (!BN_lshift1(r, a)) { - return 0; - } - if (BN_cmp(r, m) >= 0) { - return BN_sub(r, r, m); - } +int bn_mod_lshift1_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, + BN_CTX *ctx) { + return bn_mod_add_consttime(r, a, a, m, ctx); +} - return 1; +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) { + BN_CTX *ctx = BN_CTX_new(); + int ok = ctx != NULL && + bn_mod_lshift1_consttime(r, a, m, ctx); + BN_CTX_free(ctx); + return ok; } BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { @@ -584,7 +753,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { return (BN_ULONG) - 1; } - if (a->top == 0) { + if (a->width == 0) { return 0; } @@ -595,7 +764,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { return (BN_ULONG) - 1; } - for (i = a->top - 1; i >= 0; i--) { + for (i = a->width - 1; i >= 0; i--) { BN_ULONG l = a->d[i]; BN_ULONG d; BN_ULONG unused_rem; @@ -604,20 +773,13 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { a->d[i] = d; } - if ((a->top > 0) && (a->d[a->top - 1] == 0)) { - a->top--; - } - - if (a->top == 0) { - a->neg = 0; - } - + bn_set_minimal_width(a); ret >>= j; return ret; } BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { -#ifndef BN_ULLONG +#ifndef BN_CAN_DIVIDE_ULLONG BN_ULONG ret = 0; #else BN_ULLONG ret = 0; @@ -628,9 +790,9 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { return (BN_ULONG) -1; } -#ifndef BN_ULLONG - // If |w| is too long and we don't have |BN_ULLONG| then we need to fall back - // to using |BN_div_word|. +#ifndef BN_CAN_DIVIDE_ULLONG + // If |w| is too long and we don't have |BN_ULLONG| division then we need to + // fall back to using |BN_div_word|. if (w > ((BN_ULONG)1 << BN_BITS4)) { BIGNUM *tmp = BN_dup(a); if (tmp == NULL) { @@ -642,8 +804,8 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { } #endif - for (i = a->top - 1; i >= 0; i--) { -#ifndef BN_ULLONG + for (i = a->width - 1; i >= 0; i--) { +#ifndef BN_CAN_DIVIDE_ULLONG ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w; ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w; #else @@ -654,7 +816,7 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { } int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) { - if (e == 0 || a->top == 0) { + if (e == 0 || a->width == 0) { BN_zero(r); return 1; } @@ -662,7 +824,7 @@ int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) { size_t num_words = 1 + ((e - 1) / BN_BITS2); // If |a| definitely has less than |e| bits, just BN_copy. - if ((size_t) a->top < num_words) { + if ((size_t) a->width < num_words) { return BN_copy(r, a) != NULL; } @@ -683,8 +845,8 @@ int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) { // Fill in the remaining fields of |r|. r->neg = a->neg; - r->top = (int) num_words; - bn_correct_top(r); + r->width = (int) num_words; + bn_set_minimal_width(r); return 1; } @@ -706,27 +868,27 @@ int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) { } // Clear the upper words of |r|. - OPENSSL_memset(&r->d[r->top], 0, (num_words - r->top) * BN_BYTES); + OPENSSL_memset(&r->d[r->width], 0, (num_words - r->width) * BN_BYTES); // Set parameters of |r|. r->neg = 0; - r->top = (int) num_words; + r->width = (int) num_words; // Now, invert every word. The idea here is that we want to compute 2^e-|x|, // which is actually equivalent to the twos-complement representation of |x| // in |e| bits, which is -x = ~x + 1. - for (int i = 0; i < r->top; i++) { + for (int i = 0; i < r->width; i++) { r->d[i] = ~r->d[i]; } // If our exponent doesn't span the top word, we have to mask the rest. size_t top_word_exponent = e % BN_BITS2; if (top_word_exponent != 0) { - r->d[r->top - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1; + r->d[r->width - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1; } - // Keep the correct_top invariant for BN_add. - bn_correct_top(r); + // Keep the minimal-width invariant for |BIGNUM|. + bn_set_minimal_width(r); // Finally, add one, for the reason described above. return BN_add(r, r, BN_value_one()); diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/exponentiation.c b/Sources/BoringSSL/crypto/fipsmodule/bn/exponentiation.c index a5cb7dab2..c85c00b1b 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/exponentiation.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/exponentiation.c @@ -622,8 +622,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // Allocate a montgomery context if it was not supplied by the caller. if (mont == NULL) { - new_mont = BN_MONT_CTX_new(); - if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + new_mont = BN_MONT_CTX_new_for_modulus(m, ctx); + if (new_mont == NULL) { goto err; } mont = new_mont; @@ -666,22 +666,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, } } - // Set |r| to one in Montgomery form. If the high bit of |m| is set, |m| is - // close to R and we subtract rather than perform Montgomery reduction. - if (m->d[m->top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { - if (!bn_wexpand(r, m->top)) { - goto err; - } - // r = 2^(top*BN_BITS2) - m - r->d[0] = 0 - m->d[0]; - for (int i = 1; i < m->top; i++) { - r->d[i] = ~m->d[i]; - } - r->top = m->top; - // The upper words will be zero if the corresponding words of |m| were - // 0xfff[...], so call |bn_correct_top|. - bn_correct_top(r); - } else if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) { + if (!bn_one_to_montgomery(r, mont, ctx)) { goto err; } @@ -746,8 +731,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, int bn_mod_exp_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_ULONG *p, size_t num_p, const BN_MONT_CTX *mont) { - const BN_ULONG *n = mont->N.d; - size_t num_n = mont->N.top; + size_t num_n = mont->N.width; if (num_n != num_a || num_n != num_r || num_n > BN_SMALL_MAX_WORDS) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; @@ -793,16 +777,7 @@ int bn_mod_exp_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, } } - // Set |r| to one in Montgomery form. If the high bit of |m| is set, |m| is - // close to R and we subtract rather than perform Montgomery reduction. - if (n[num_n - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { - // r = 2^(top*BN_BITS2) - m - r[0] = 0 - n[0]; - for (size_t i = 1; i < num_n; i++) { - r[i] = ~n[i]; - } - } else if (!bn_from_montgomery_small(r, num_r, mont->RR.d, mont->RR.top, - mont)) { + if (!bn_one_to_montgomery_small(r, num_r, mont)) { goto err; } @@ -866,7 +841,7 @@ int bn_mod_inverse_prime_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_MONT_CTX *mont) { const BN_ULONG *p = mont->N.d; - size_t num_p = mont->N.top; + size_t num_p = mont->N.width; if (num_p > BN_SMALL_MAX_WORDS || num_p == 0) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; @@ -901,8 +876,8 @@ static void copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, const int width = 1 << window; BN_ULONG *table = (BN_ULONG *) buf; - if (top > b->top) { - top = b->top; // this works because 'buf' is explicitly zeroed + if (top > b->width) { + top = b->width; // this works because 'buf' is explicitly zeroed } for (i = 0, j = idx; i < top; i++, j += width) { @@ -955,8 +930,7 @@ static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx, } } - b->top = top; - bn_correct_top(b); + b->width = top; return 1; } @@ -1006,8 +980,7 @@ static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx, int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont) { - int i, bits, ret = 0, window, wvalue; - int top; + int i, ret = 0, window, wvalue; BN_MONT_CTX *new_mont = NULL; int numPowers; @@ -1022,9 +995,10 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, return 0; } - top = m->top; - - bits = BN_num_bits(p); + // Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak + // whether the top bits are zero. + int max_bits = p->width * BN_BITS2; + int bits = max_bits; if (bits == 0) { // x**0 mod 1 is still zero. if (BN_is_one(m)) { @@ -1036,13 +1010,17 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // Allocate a montgomery context if it was not supplied by the caller. if (mont == NULL) { - new_mont = BN_MONT_CTX_new(); - if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + new_mont = BN_MONT_CTX_new_for_modulus(m, ctx); + if (new_mont == NULL) { goto err; } mont = new_mont; } + // Use the width in |mont->N|, rather than the copy in |m|. The assembly + // implementation assumes it can use |top| to size R. + int top = mont->N.width; + if (a->neg || BN_ucmp(a, m) >= 0) { new_a = BN_new(); if (new_a == NULL || @@ -1056,15 +1034,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // If the size of the operands allow it, perform the optimized // RSAZ exponentiation. For further information see // crypto/bn/rsaz_exp.c and accompanying assembly modules. - if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) && + if ((16 == a->width) && (16 == p->width) && (BN_num_bits(m) == 1024) && rsaz_avx2_eligible()) { if (!bn_wexpand(rr, 16)) { goto err; } RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, mont->n0[0]); - rr->top = 16; + rr->width = 16; rr->neg = 0; - bn_correct_top(rr); ret = 1; goto err; } @@ -1110,21 +1087,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // lay down tmp and am right after powers table tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers); am.d = tmp.d + top; - tmp.top = am.top = 0; + tmp.width = am.width = 0; tmp.dmax = am.dmax = top; tmp.neg = am.neg = 0; tmp.flags = am.flags = BN_FLG_STATIC_DATA; -// prepare a^0 in Montgomery domain -// by Shay Gueron's suggestion - if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { - // 2^(top*BN_BITS2) - m - tmp.d[0] = 0 - m->d[0]; - for (i = 1; i < top; i++) { - tmp.d[i] = ~m->d[i]; - } - tmp.top = top; - } else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) { + if (!bn_one_to_montgomery(&tmp, mont, ctx)) { goto err; } @@ -1148,10 +1116,10 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // BN_to_montgomery can contaminate words above .top // [in BN_DEBUG[_DEBUG] build]... - for (i = am.top; i < top; i++) { + for (i = am.width; i < top; i++) { am.d[i] = 0; } - for (i = tmp.top; i < top; i++) { + for (i = tmp.width; i < top; i++) { tmp.d[i] = 0; } @@ -1161,7 +1129,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, } bn_scatter5(tmp.d, top, powerbuf, 0); - bn_scatter5(am.d, am.top, powerbuf, 1); + bn_scatter5(am.d, am.width, powerbuf, 1); bn_mul_mont(tmp.d, am.d, am.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, 2); @@ -1217,7 +1185,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, } } else { const uint8_t *p_bytes = (const uint8_t *)p->d; - int max_bits = p->top * BN_BITS2; assert(bits < max_bits); // |p = 0| has been handled as a special case, so |max_bits| is at least // one word. @@ -1229,7 +1196,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // here is the top bit, inclusive. if (bits - 4 >= max_bits - 8) { // Read five bits from |bits-4| through |bits|, inclusive. - wvalue = p_bytes[p->top * BN_BYTES - 1]; + wvalue = p_bytes[p->width * BN_BYTES - 1]; wvalue >>= (bits - 4) & 7; wvalue &= 0x1f; bits -= 5; @@ -1248,8 +1215,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, } ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top); - tmp.top = top; - bn_correct_top(&tmp); + tmp.width = top; if (ret) { if (!BN_copy(rr, &tmp)) { ret = 0; @@ -1363,8 +1329,8 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1, // Allocate a montgomery context if it was not supplied by the caller. if (mont == NULL) { - new_mont = BN_MONT_CTX_new(); - if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + new_mont = BN_MONT_CTX_new_for_modulus(m, ctx); + if (new_mont == NULL) { goto err; } mont = new_mont; diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/gcd.c b/Sources/BoringSSL/crypto/fipsmodule/bn/gcd.c index 850d44672..7868b4078 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/gcd.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/gcd.c @@ -114,121 +114,310 @@ #include "internal.h" -static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) { - BIGNUM *t; - int shifts = 0; - // 0 <= b <= a - while (!BN_is_zero(b)) { - // 0 < b <= a +static BN_ULONG word_is_odd_mask(BN_ULONG a) { return (BN_ULONG)0 - (a & 1); } - if (BN_is_odd(a)) { - if (BN_is_odd(b)) { - if (!BN_sub(a, a, b)) { - goto err; - } - if (!BN_rshift1(a, a)) { - goto err; - } - if (BN_cmp(a, b) < 0) { - t = a; - a = b; - b = t; - } - } else { - // a odd - b even - if (!BN_rshift1(b, b)) { - goto err; - } - if (BN_cmp(a, b) < 0) { - t = a; - a = b; - b = t; - } - } - } else { - // a is even - if (BN_is_odd(b)) { - if (!BN_rshift1(a, a)) { - goto err; - } - if (BN_cmp(a, b) < 0) { - t = a; - a = b; - b = t; - } - } else { - // a even - b even - if (!BN_rshift1(a, a)) { - goto err; - } - if (!BN_rshift1(b, b)) { - goto err; - } - shifts++; - } - } - // 0 <= b <= a +static void maybe_rshift1_words(BN_ULONG *a, BN_ULONG mask, BN_ULONG *tmp, + size_t num) { + bn_rshift1_words(tmp, a, num); + bn_select_words(a, mask, tmp, a, num); +} + +static void maybe_rshift1_words_carry(BN_ULONG *a, BN_ULONG carry, + BN_ULONG mask, BN_ULONG *tmp, + size_t num) { + maybe_rshift1_words(a, mask, tmp, num); + if (num != 0) { + carry &= mask; + a[num - 1] |= carry << (BN_BITS2-1); + } +} + +static BN_ULONG maybe_add_words(BN_ULONG *a, BN_ULONG mask, const BN_ULONG *b, + BN_ULONG *tmp, size_t num) { + BN_ULONG carry = bn_add_words(tmp, a, b, num); + bn_select_words(a, mask, tmp, a, num); + return carry & mask; +} + +static int bn_gcd_consttime(BIGNUM *r, unsigned *out_shift, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) { + size_t width = x->width > y->width ? x->width : y->width; + if (width == 0) { + *out_shift = 0; + BN_zero(r); + return 1; } - if (shifts) { - if (!BN_lshift(a, a, shifts)) { - goto err; - } + // This is a constant-time implementation of Stein's algorithm (binary GCD). + int ret = 0; + BN_CTX_start(ctx); + BIGNUM *u = BN_CTX_get(ctx); + BIGNUM *v = BN_CTX_get(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); + if (u == NULL || v == NULL || tmp == NULL || + !BN_copy(u, x) || + !BN_copy(v, y) || + !bn_resize_words(u, width) || + !bn_resize_words(v, width) || + !bn_resize_words(tmp, width)) { + goto err; + } + + // Each loop iteration halves at least one of |u| and |v|. Thus we need at + // most the combined bit width of inputs for at least one value to be zero. + unsigned x_bits = x->width * BN_BITS2, y_bits = y->width * BN_BITS2; + unsigned num_iters = x_bits + y_bits; + if (num_iters < x_bits) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + goto err; } - return a; + unsigned shift = 0; + for (unsigned i = 0; i < num_iters; i++) { + BN_ULONG both_odd = word_is_odd_mask(u->d[0]) & word_is_odd_mask(v->d[0]); + + // If both |u| and |v| are odd, subtract the smaller from the larger. + BN_ULONG u_less_than_v = + (BN_ULONG)0 - bn_sub_words(tmp->d, u->d, v->d, width); + bn_select_words(u->d, both_odd & ~u_less_than_v, tmp->d, u->d, width); + bn_sub_words(tmp->d, v->d, u->d, width); + bn_select_words(v->d, both_odd & u_less_than_v, tmp->d, v->d, width); + + // At least one of |u| and |v| is now even. + BN_ULONG u_is_odd = word_is_odd_mask(u->d[0]); + BN_ULONG v_is_odd = word_is_odd_mask(v->d[0]); + assert(!(u_is_odd & v_is_odd)); + + // If both are even, the final GCD gains a factor of two. + shift += 1 & (~u_is_odd & ~v_is_odd); + + // Halve any which are even. + maybe_rshift1_words(u->d, ~u_is_odd, tmp->d, width); + maybe_rshift1_words(v->d, ~v_is_odd, tmp->d, width); + } + + // One of |u| or |v| is zero at this point. The algorithm usually makes |u| + // zero, unless |y| was already zero on input. Fix this by combining the + // values. + assert(BN_is_zero(u) || BN_is_zero(v)); + for (size_t i = 0; i < width; i++) { + v->d[i] |= u->d[i]; + } + + *out_shift = shift; + ret = bn_set_words(r, v->d, width); err: - return NULL; + BN_CTX_end(ctx); + return ret; } -int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) { - BIGNUM *a, *b, *t; +int BN_gcd(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { + unsigned shift; + return bn_gcd_consttime(r, &shift, x, y, ctx) && + BN_lshift(r, r, shift); +} + +int bn_is_relatively_prime(int *out_relatively_prime, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) { int ret = 0; + BN_CTX_start(ctx); + unsigned shift; + BIGNUM *gcd = BN_CTX_get(ctx); + if (gcd == NULL || + !bn_gcd_consttime(gcd, &shift, x, y, ctx)) { + goto err; + } + + // Check that 2^|shift| * |gcd| is one. + if (gcd->width == 0) { + *out_relatively_prime = 0; + } else { + BN_ULONG mask = shift | (gcd->d[0] ^ 1); + for (int i = 1; i < gcd->width; i++) { + mask |= gcd->d[i]; + } + *out_relatively_prime = mask == 0; + } + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} +int bn_lcm_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { BN_CTX_start(ctx); - a = BN_CTX_get(ctx); - b = BN_CTX_get(ctx); + unsigned shift; + BIGNUM *gcd = BN_CTX_get(ctx); + int ret = gcd != NULL && + bn_mul_consttime(r, a, b, ctx) && + bn_gcd_consttime(gcd, &shift, a, b, ctx) && + bn_div_consttime(r, NULL, r, gcd, ctx) && + bn_rshift_secret_shift(r, r, shift, ctx); + BN_CTX_end(ctx); + return ret; +} - if (a == NULL || b == NULL) { - goto err; +int bn_mod_inverse_consttime(BIGNUM *r, int *out_no_inverse, const BIGNUM *a, + const BIGNUM *n, BN_CTX *ctx) { + *out_no_inverse = 0; + if (BN_is_negative(a) || BN_ucmp(a, n) >= 0) { + OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED); + return 0; } - if (BN_copy(a, in_a) == NULL) { - goto err; + if (BN_is_zero(a)) { + if (BN_is_one(n)) { + BN_zero(r); + return 1; + } + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); + return 0; } - if (BN_copy(b, in_b) == NULL) { - goto err; + + // This is a constant-time implementation of the extended binary GCD + // algorithm. It is adapted from the Handbook of Applied Cryptography, section + // 14.4.3, algorithm 14.51, and modified to bound coefficients and avoid + // negative numbers. + // + // For more details and proof of correctness, see + // https://github.com/mit-plv/fiat-crypto/pull/333. In particular, see |step| + // and |mod_inverse_consttime| for the algorithm in Gallina and see + // |mod_inverse_consttime_spec| for the correctness result. + + if (!BN_is_odd(a) && !BN_is_odd(n)) { + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); + return 0; } - a->neg = 0; - b->neg = 0; + // This function exists to compute the RSA private exponent, where |a| is one + // word. We'll thus use |a_width| when available. + size_t n_width = n->width, a_width = a->width; + if (a_width > n_width) { + a_width = n_width; + } - if (BN_cmp(a, b) < 0) { - t = a; - a = b; - b = t; + int ret = 0; + BN_CTX_start(ctx); + BIGNUM *u = BN_CTX_get(ctx); + BIGNUM *v = BN_CTX_get(ctx); + BIGNUM *A = BN_CTX_get(ctx); + BIGNUM *B = BN_CTX_get(ctx); + BIGNUM *C = BN_CTX_get(ctx); + BIGNUM *D = BN_CTX_get(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); + BIGNUM *tmp2 = BN_CTX_get(ctx); + if (u == NULL || v == NULL || A == NULL || B == NULL || C == NULL || + D == NULL || tmp == NULL || tmp2 == NULL || + !BN_copy(u, a) || + !BN_copy(v, n) || + !BN_one(A) || + !BN_one(D) || + // For convenience, size |u| and |v| equivalently. + !bn_resize_words(u, n_width) || + !bn_resize_words(v, n_width) || + // |A| and |C| are bounded by |m|. + !bn_resize_words(A, n_width) || + !bn_resize_words(C, n_width) || + // |B| and |D| are bounded by |a|. + !bn_resize_words(B, a_width) || + !bn_resize_words(D, a_width) || + // |tmp| and |tmp2| may be used at either size. + !bn_resize_words(tmp, n_width) || + !bn_resize_words(tmp2, n_width)) { + goto err; } - t = euclid(a, b); - if (t == NULL) { + + // Each loop iteration halves at least one of |u| and |v|. Thus we need at + // most the combined bit width of inputs for at least one value to be zero. + unsigned a_bits = a_width * BN_BITS2, n_bits = n_width * BN_BITS2; + unsigned num_iters = a_bits + n_bits; + if (num_iters < a_bits) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); goto err; } - if (BN_copy(r, t) == NULL) { + // Before and after each loop iteration, the following hold: + // + // u = A*a - B*n + // v = D*n - C*a + // 0 < u <= a + // 0 <= v <= n + // 0 <= A < n + // 0 <= B <= a + // 0 <= C < n + // 0 <= D <= a + // + // After each loop iteration, u and v only get smaller, and at least one of + // them shrinks by at least a factor of two. + for (unsigned i = 0; i < num_iters; i++) { + BN_ULONG both_odd = word_is_odd_mask(u->d[0]) & word_is_odd_mask(v->d[0]); + + // If both |u| and |v| are odd, subtract the smaller from the larger. + BN_ULONG v_less_than_u = + (BN_ULONG)0 - bn_sub_words(tmp->d, v->d, u->d, n_width); + bn_select_words(v->d, both_odd & ~v_less_than_u, tmp->d, v->d, n_width); + bn_sub_words(tmp->d, u->d, v->d, n_width); + bn_select_words(u->d, both_odd & v_less_than_u, tmp->d, u->d, n_width); + + // If we updated one of the values, update the corresponding coefficient. + BN_ULONG carry = bn_add_words(tmp->d, A->d, C->d, n_width); + carry -= bn_sub_words(tmp2->d, tmp->d, n->d, n_width); + bn_select_words(tmp->d, carry, tmp->d, tmp2->d, n_width); + bn_select_words(A->d, both_odd & v_less_than_u, tmp->d, A->d, n_width); + bn_select_words(C->d, both_odd & ~v_less_than_u, tmp->d, C->d, n_width); + + bn_add_words(tmp->d, B->d, D->d, a_width); + bn_sub_words(tmp2->d, tmp->d, a->d, a_width); + bn_select_words(tmp->d, carry, tmp->d, tmp2->d, a_width); + bn_select_words(B->d, both_odd & v_less_than_u, tmp->d, B->d, a_width); + bn_select_words(D->d, both_odd & ~v_less_than_u, tmp->d, D->d, a_width); + + // Our loop invariants hold at this point. Additionally, exactly one of |u| + // and |v| is now even. + BN_ULONG u_is_even = ~word_is_odd_mask(u->d[0]); + BN_ULONG v_is_even = ~word_is_odd_mask(v->d[0]); + assert(u_is_even != v_is_even); + + // Halve the even one and adjust the corresponding coefficient. + maybe_rshift1_words(u->d, u_is_even, tmp->d, n_width); + BN_ULONG A_or_B_is_odd = + word_is_odd_mask(A->d[0]) | word_is_odd_mask(B->d[0]); + BN_ULONG A_carry = + maybe_add_words(A->d, A_or_B_is_odd & u_is_even, n->d, tmp->d, n_width); + BN_ULONG B_carry = + maybe_add_words(B->d, A_or_B_is_odd & u_is_even, a->d, tmp->d, a_width); + maybe_rshift1_words_carry(A->d, A_carry, u_is_even, tmp->d, n_width); + maybe_rshift1_words_carry(B->d, B_carry, u_is_even, tmp->d, a_width); + + maybe_rshift1_words(v->d, v_is_even, tmp->d, n_width); + BN_ULONG C_or_D_is_odd = + word_is_odd_mask(C->d[0]) | word_is_odd_mask(D->d[0]); + BN_ULONG C_carry = + maybe_add_words(C->d, C_or_D_is_odd & v_is_even, n->d, tmp->d, n_width); + BN_ULONG D_carry = + maybe_add_words(D->d, C_or_D_is_odd & v_is_even, a->d, tmp->d, a_width); + maybe_rshift1_words_carry(C->d, C_carry, v_is_even, tmp->d, n_width); + maybe_rshift1_words_carry(D->d, D_carry, v_is_even, tmp->d, a_width); + } + + assert(BN_is_zero(v)); + if (!BN_is_one(u)) { + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); goto err; } - ret = 1; + + ret = BN_copy(r, A) != NULL; err: BN_CTX_end(ctx); return ret; } -// solves ax == 1 (mod n) -static int bn_mod_inverse_general(BIGNUM *out, int *out_no_inverse, - const BIGNUM *a, const BIGNUM *n, - BN_CTX *ctx); - int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { *out_no_inverse = 0; @@ -423,7 +612,7 @@ BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n, int no_inverse; if (!BN_is_odd(n)) { - if (!bn_mod_inverse_general(out, &no_inverse, a, n, ctx)) { + if (!bn_mod_inverse_consttime(out, &no_inverse, a, n, ctx)) { goto err; } } else if (!BN_mod_inverse_odd(out, &no_inverse, a, n, ctx)) { @@ -469,139 +658,6 @@ int BN_mod_inverse_blinded(BIGNUM *out, int *out_no_inverse, const BIGNUM *a, return ret; } -// bn_mod_inverse_general is the general inversion algorithm that works for -// both even and odd |n|. It was specifically designed to contain fewer -// branches that may leak sensitive information; see "New Branch Prediction -// Vulnerabilities in OpenSSL and Necessary Software Countermeasures" by -// Onur Acıçmez, Shay Gueron, and Jean-Pierre Seifert. -static int bn_mod_inverse_general(BIGNUM *out, int *out_no_inverse, - const BIGNUM *a, const BIGNUM *n, - BN_CTX *ctx) { - BIGNUM *A, *B, *X, *Y, *M, *D, *T; - int ret = 0; - int sign; - - *out_no_inverse = 0; - - BN_CTX_start(ctx); - A = BN_CTX_get(ctx); - B = BN_CTX_get(ctx); - X = BN_CTX_get(ctx); - D = BN_CTX_get(ctx); - M = BN_CTX_get(ctx); - Y = BN_CTX_get(ctx); - T = BN_CTX_get(ctx); - if (T == NULL) { - goto err; - } - - BIGNUM *R = out; - - BN_zero(Y); - if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) { - goto err; - } - A->neg = 0; - - sign = -1; - // From B = a mod |n|, A = |n| it follows that - // - // 0 <= B < A, - // -sign*X*a == B (mod |n|), - // sign*Y*a == A (mod |n|). - - while (!BN_is_zero(B)) { - BIGNUM *tmp; - - // 0 < B < A, - // (*) -sign*X*a == B (mod |n|), - // sign*Y*a == A (mod |n|) - - // (D, M) := (A/B, A%B) ... - if (!BN_div(D, M, A, B, ctx)) { - goto err; - } - - // Now - // A = D*B + M; - // thus we have - // (**) sign*Y*a == D*B + M (mod |n|). - - tmp = A; // keep the BIGNUM object, the value does not matter - - // (A, B) := (B, A mod B) ... - A = B; - B = M; - // ... so we have 0 <= B < A again - - // Since the former M is now B and the former B is now A, - // (**) translates into - // sign*Y*a == D*A + B (mod |n|), - // i.e. - // sign*Y*a - D*A == B (mod |n|). - // Similarly, (*) translates into - // -sign*X*a == A (mod |n|). - // - // Thus, - // sign*Y*a + D*sign*X*a == B (mod |n|), - // i.e. - // sign*(Y + D*X)*a == B (mod |n|). - // - // So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at - // -sign*X*a == B (mod |n|), - // sign*Y*a == A (mod |n|). - // Note that X and Y stay non-negative all the time. - - if (!BN_mul(tmp, D, X, ctx)) { - goto err; - } - if (!BN_add(tmp, tmp, Y)) { - goto err; - } - - M = Y; // keep the BIGNUM object, the value does not matter - Y = X; - X = tmp; - sign = -sign; - } - - if (!BN_is_one(A)) { - *out_no_inverse = 1; - OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); - goto err; - } - - // The while loop (Euclid's algorithm) ends when - // A == gcd(a,n); - // we have - // sign*Y*a == A (mod |n|), - // where Y is non-negative. - - if (sign < 0) { - if (!BN_sub(Y, n, Y)) { - goto err; - } - } - // Now Y*a == A (mod |n|). - - // Y*a == 1 (mod |n|) - if (!Y->neg && BN_ucmp(Y, n) < 0) { - if (!BN_copy(R, Y)) { - goto err; - } - } else { - if (!BN_nnmod(R, Y, n, ctx)) { - goto err; - } - } - - ret = 1; - -err: - BN_CTX_end(ctx); - return ret; -} - int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx, const BN_MONT_CTX *mont_p) { BN_CTX_start(ctx); diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/generic.c b/Sources/BoringSSL/crypto/fipsmodule/bn/generic.c index a39a033c1..ee80a3ce7 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/generic.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/generic.c @@ -64,7 +64,8 @@ // This file has two other implementations: x86 assembly language in // asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. #if defined(OPENSSL_NO_ASM) || \ - !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__))) + !(defined(OPENSSL_X86) || \ + (defined(OPENSSL_X86_64) && (defined(__GNUC__) || defined(__clang__)))) #ifdef BN_ULLONG #define mul_add(r, a, w, c) \ diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/internal.h b/Sources/BoringSSL/crypto/fipsmodule/bn/internal.h index 75efbfab9..a8ad129d0 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/internal.h +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/internal.h @@ -140,9 +140,12 @@ extern "C" { #if defined(OPENSSL_64_BIT) -#if !defined(_MSC_VER) +#if defined(BORINGSSL_HAS_UINT128) // MSVC doesn't support two-word integers on 64-bit. #define BN_ULLONG uint128_t +#if defined(BORINGSSL_CAN_DIVIDE_UINT128) +#define BN_CAN_DIVIDE_ULLONG +#endif #endif #define BN_BITS2 64 @@ -160,6 +163,7 @@ extern "C" { #elif defined(OPENSSL_32_BIT) #define BN_ULLONG uint64_t +#define BN_CAN_DIVIDE_ULLONG #define BN_BITS2 32 #define BN_BYTES 4 #define BN_BITS4 16 @@ -193,9 +197,13 @@ extern "C" { #define Hw(t) ((BN_ULONG)((t) >> BN_BITS2)) #endif -// bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or -// until |top| is zero. If |bn| is zero, |bn->neg| is set to zero. -void bn_correct_top(BIGNUM *bn); +// bn_minimal_width returns the minimal value of |bn->top| which fits the +// value of |bn|. +int bn_minimal_width(const BIGNUM *bn); + +// bn_set_minimal_width sets |bn->width| to |bn_minimal_width(bn)|. If |bn| is +// zero, |bn->neg| is set to zero. +void bn_set_minimal_width(BIGNUM *bn); // bn_wexpand ensures that |bn| has at least |words| works of space without // altering its value. It returns one on success or zero on allocation @@ -206,10 +214,27 @@ int bn_wexpand(BIGNUM *bn, size_t words); // than a number of words. int bn_expand(BIGNUM *bn, size_t bits); +// bn_resize_words adjusts |bn->top| to be |words|. It returns one on success +// and zero on allocation error or if |bn|'s value is too large. +OPENSSL_EXPORT int bn_resize_words(BIGNUM *bn, size_t words); + +// bn_select_words sets |r| to |a| if |mask| is all ones or |b| if |mask| is +// all zeros. +void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a, + const BN_ULONG *b, size_t num); + // bn_set_words sets |bn| to the value encoded in the |num| words in |words|, // least significant word first. int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num); +// bn_fits_in_words returns one if |bn| may be represented in |num| words, plus +// a sign bit, and zero otherwise. +int bn_fits_in_words(const BIGNUM *bn, size_t num); + +// bn_copy_words copies the value of |bn| to |out| and returns one if the value +// is representable in |num| words. Otherwise, it returns zero. +int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn); + // bn_mul_add_words multiples |ap| by |w|, adds the result to |rp|, and places // the result in |rp|. |ap| and |rp| must both be |num| words long. It returns // the carry word of the operation. |ap| and |rp| may be equal but otherwise may @@ -255,25 +280,13 @@ void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[4]); // bn_sqr_comba4 sets |r| to |a|^2. void bn_sqr_comba4(BN_ULONG r[8], const BN_ULONG a[4]); -// bn_cmp_words returns a value less than, equal to or greater than zero if -// the, length |n|, array |a| is less than, equal to or greater than |b|. -int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n); - -// bn_cmp_words returns a value less than, equal to or greater than zero if the -// array |a| is less than, equal to or greater than |b|. The arrays can be of -// different lengths: |cl| gives the minimum of the two lengths and |dl| gives -// the length of |a| minus the length of |b|. -int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); - // bn_less_than_words returns one if |a| < |b| and zero otherwise, where |a| // and |b| both are |len| words long. It runs in constant time. int bn_less_than_words(const BN_ULONG *a, const BN_ULONG *b, size_t len); // bn_in_range_words returns one if |min_inclusive| <= |a| < |max_exclusive|, -// where |a| and |max_exclusive| both are |len| words long. This function leaks -// which of [0, min_inclusive), [min_inclusive, max_exclusive), and -// [max_exclusive, 2^(BN_BITS2*len)) contains |a|, but otherwise the value of -// |a| is secret. +// where |a| and |max_exclusive| both are |len| words long. |a| and +// |max_exclusive| are treated as secret. int bn_in_range_words(const BN_ULONG *a, BN_ULONG min_inclusive, const BN_ULONG *max_exclusive, size_t len); @@ -288,11 +301,38 @@ int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive, const BN_ULONG *max_exclusive, size_t len, const uint8_t additional_data[32]); +// bn_range_secret_range behaves like |BN_rand_range_ex|, but treats +// |max_exclusive| as secret. Because of this constraint, the distribution of +// values returned is more complex. +// +// Rather than repeatedly generating values until one is in range, which would +// leak information, it generates one value. If the value is in range, it sets +// |*out_is_uniform| to one. Otherwise, it sets |*out_is_uniform| to zero, +// fixing up the value to force it in range. +// +// The subset of calls to |bn_rand_secret_range| which set |*out_is_uniform| to +// one are uniformly distributed in the target range. Calls overall are not. +// This function is intended for use in situations where the extra values are +// still usable and where the number of iterations needed to reach the target +// number of uniform outputs may be blinded for negligible probabilities of +// timing leaks. +// +// Although this function treats |max_exclusive| as secret, it treats the number +// of bits in |max_exclusive| as public. +int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive, + const BIGNUM *max_exclusive); + int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num); uint64_t bn_mont_n0(const BIGNUM *n); -int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n); + +// bn_mod_exp_base_2_consttime calculates r = 2**p (mod n). |p| must be larger +// than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and +// odd. |p| and the bit width of |n| are assumed public, but |n| is otherwise +// treated as secret. +int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n, + BN_CTX *ctx); #if defined(OPENSSL_X86_64) && defined(_MSC_VER) #define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high))) @@ -302,6 +342,127 @@ int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n); #error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform." #endif +// bn_jacobi returns the Jacobi symbol of |a| and |b| (which is -1, 0 or 1), or +// -2 on error. +int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + +// bn_is_bit_set_words returns one if bit |bit| is set in |a| and zero +// otherwise. +int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit); + +// bn_one_to_montgomery sets |r| to one in Montgomery form. It returns one on +// success and zero on error. This function treats the bit width of the modulus +// as public. +int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx); + +// bn_less_than_montgomery_R returns one if |bn| is less than the Montgomery R +// value for |mont| and zero otherwise. +int bn_less_than_montgomery_R(const BIGNUM *bn, const BN_MONT_CTX *mont); + +// bn_mod_u16_consttime returns |bn| mod |d|, ignoring |bn|'s sign bit. It runs +// in time independent of the value of |bn|, but it treats |d| as public. +OPENSSL_EXPORT uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d); + +// bn_odd_number_is_obviously_composite returns one if |bn| is divisible by one +// of the first several odd primes and zero otherwise. +int bn_odd_number_is_obviously_composite(const BIGNUM *bn); + +// bn_rshift1_words sets |r| to |a| >> 1, where both arrays are |num| bits wide. +void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num); + +// bn_rshift_secret_shift behaves like |BN_rshift| but runs in time independent +// of both |a| and |n|. +OPENSSL_EXPORT int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a, + unsigned n, BN_CTX *ctx); + + +// Constant-time non-modular arithmetic. +// +// The following functions implement non-modular arithmetic in constant-time +// and pessimally set |r->width| to the largest possible word size. +// +// Note this means that, e.g., repeatedly multiplying by one will cause widths +// to increase without bound. The corresponding public API functions minimize +// their outputs to avoid regressing calculator consumers. + +// bn_uadd_consttime behaves like |BN_uadd|, but it pessimally sets +// |r->width| = |a->width| + |b->width| + 1. +int bn_uadd_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +// bn_usub_consttime behaves like |BN_usub|, but it pessimally sets +// |r->width| = |a->width|. +int bn_usub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +// bn_abs_sub_consttime sets |r| to the absolute value of |a| - |b|, treating +// both inputs as secret. It returns one on success and zero on error. +OPENSSL_EXPORT int bn_abs_sub_consttime(BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +// bn_mul_consttime behaves like |BN_mul|, but it rejects negative inputs and +// pessimally sets |r->width| to |a->width| + |b->width|, to avoid leaking +// information about |a| and |b|. +int bn_mul_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + +// bn_sqrt_consttime behaves like |BN_sqrt|, but it pessimally sets |r->width| +// to 2*|a->width|, to avoid leaking information about |a| and |b|. +int bn_sqr_consttime(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); + +// bn_div_consttime behaves like |BN_div|, but it rejects negative inputs and +// treats both inputs, including their magnitudes, as secret. It is, as a +// result, much slower than |BN_div| and should only be used for rare operations +// where Montgomery reduction is not available. +// +// Note that |quotient->width| will be set pessimally to |numerator->width|. +OPENSSL_EXPORT int bn_div_consttime(BIGNUM *quotient, BIGNUM *remainder, + const BIGNUM *numerator, + const BIGNUM *divisor, BN_CTX *ctx); + +// bn_is_relatively_prime checks whether GCD(|x|, |y|) is one. On success, it +// returns one and sets |*out_relatively_prime| to one if the GCD was one and +// zero otherwise. On error, it returns zero. +OPENSSL_EXPORT int bn_is_relatively_prime(int *out_relatively_prime, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); + +// bn_lcm_consttime sets |r| to LCM(|a|, |b|). It returns one and success and +// zero on error. |a| and |b| are both treated as secret. +OPENSSL_EXPORT int bn_lcm_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx); + + +// Constant-time modular arithmetic. +// +// The following functions implement basic constant-time modular arithmetic. + +// bn_mod_add_consttime acts like |BN_mod_add_quick| but takes a |BN_CTX|. +int bn_mod_add_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +// bn_mod_sub_consttime acts like |BN_mod_sub_quick| but takes a |BN_CTX|. +int bn_mod_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +// bn_mod_lshift1_consttime acts like |BN_mod_lshift1_quick| but takes a +// |BN_CTX|. +int bn_mod_lshift1_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, + BN_CTX *ctx); + +// bn_mod_lshift_consttime acts like |BN_mod_lshift_quick| but takes a |BN_CTX|. +int bn_mod_lshift_consttime(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx); + +// bn_mod_inverse_consttime sets |r| to |a|^-1, mod |n|. |a| must be non- +// negative and less than |n|. It returns one on success and zero on error. On +// failure, if the failure was caused by |a| having no inverse mod |n| then +// |*out_no_inverse| will be set to one; otherwise it will be set to zero. +// +// This function treats both |a| and |n| as secret, provided they are both non- +// zero and the inverse exists. It should only be used for even moduli where +// none of the less general implementations are applicable. +OPENSSL_EXPORT int bn_mod_inverse_consttime(BIGNUM *r, int *out_no_inverse, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + // bn_mod_inverse_prime sets |out| to the modular inverse of |a| modulo |p|, // computed with Fermat's Little Theorem. It returns one on success and zero on // error. If |mont_p| is NULL, one will be computed temporarily. @@ -314,14 +475,6 @@ int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p, int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx, const BN_MONT_CTX *mont_p); -// bn_jacobi returns the Jacobi symbol of |a| and |b| (which is -1, 0 or 1), or -// -2 on error. -int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); - -// bn_is_bit_set_words returns one if bit |bit| is set in |a| and zero -// otherwise. -int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit); - // Low-level operations for small numbers. // @@ -368,6 +521,13 @@ int bn_to_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_MONT_CTX *mont); +// bn_one_to_montgomery_small sets |r| to one in Montgomery form. It returns one +// on success and zero on error. |num_r| must be the length of the modulus, +// which is |mont->N.top|. This function treats the bit width of the modulus as +// public. +int bn_one_to_montgomery_small(BN_ULONG *r, size_t num_r, + const BN_MONT_CTX *mont); + // bn_mod_mul_montgomery_small sets |r| to |a| * |b| mod |mont->N|. Both inputs // and outputs are in the Montgomery domain. |num_r| must be the length of the // modulus, which is |mont->N.top|. This function returns one on success and diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/jacobi.c b/Sources/BoringSSL/crypto/fipsmodule/bn/jacobi.c index 9c909bb22..d1a9d506a 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/jacobi.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/jacobi.c @@ -58,7 +58,7 @@ // least significant word -#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) +#define BN_lsw(n) (((n)->width == 0) ? (BN_ULONG) 0 : (n)->d[0]) int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { // In 'tab', only odd-indexed entries are relevant: diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery.c b/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery.c index e8505dae0..d6e2ad55b 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery.c @@ -126,10 +126,6 @@ #define OPENSSL_BN_ASM_MONT #endif -static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, - const BN_MONT_CTX *mont, BN_CTX *ctx); - BN_MONT_CTX *BN_MONT_CTX_new(void) { BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX)); @@ -193,6 +189,10 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR); return 0; } + // |mont->N| is always stored minimally. Computing RR efficiently leaks the + // size of the modulus. While the modulus may be private in RSA (one of the + // primes), their sizes are public, so this is fine. + bn_set_minimal_width(&mont->N); // Find n0 such that n0 * N == -1 (mod r). // @@ -200,7 +200,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { // others, we could use a shorter R value and use faster |BN_ULONG|-based // math instead of |uint64_t|-based math, which would be double-precision. // However, currently only the assembler files know which is which. - uint64_t n0 = bn_mont_n0(mod); + uint64_t n0 = bn_mont_n0(&mont->N); mont->n0[0] = (BN_ULONG)n0; #if BN_MONT_CTX_N0_LIMBS == 2 mont->n0[1] = (BN_ULONG)(n0 >> BN_BITS2); @@ -208,19 +208,34 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { mont->n0[1] = 0; #endif + BN_CTX *new_ctx = NULL; + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + return 0; + } + ctx = new_ctx; + } + // Save RR = R**2 (mod N). R is the smallest power of 2**BN_BITS2 such that R // > mod. Even though the assembly on some 32-bit platforms works with 64-bit // values, using |BN_BITS2| here, rather than |BN_MONT_CTX_N0_LIMBS * // BN_BITS2|, is correct because R**2 will still be a multiple of the latter // as |BN_MONT_CTX_N0_LIMBS| is either one or two. - // - // XXX: This is not constant time with respect to |mont->N|, but it should be. - unsigned lgBigR = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; - if (!bn_mod_exp_base_2_vartime(&mont->RR, lgBigR * 2, &mont->N)) { - return 0; - } + unsigned lgBigR = mont->N.width * BN_BITS2; + int ok = bn_mod_exp_base_2_consttime(&mont->RR, lgBigR * 2, &mont->N, ctx); + BN_CTX_free(new_ctx); + return ok; +} - return 1; +BN_MONT_CTX *BN_MONT_CTX_new_for_modulus(const BIGNUM *mod, BN_CTX *ctx) { + BN_MONT_CTX *mont = BN_MONT_CTX_new(); + if (mont == NULL || + !BN_MONT_CTX_set(mont, mod, ctx)) { + BN_MONT_CTX_free(mont); + return NULL; + } + return mont; } int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock, @@ -234,25 +249,12 @@ int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock, } CRYPTO_MUTEX_lock_write(lock); - ctx = *pmont; - if (ctx) { - goto out; + if (*pmont == NULL) { + *pmont = BN_MONT_CTX_new_for_modulus(mod, bn_ctx); } - - ctx = BN_MONT_CTX_new(); - if (ctx == NULL) { - goto out; - } - if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) { - BN_MONT_CTX_free(ctx); - ctx = NULL; - goto out; - } - *pmont = ctx; - -out: + const int ok = *pmont != NULL; CRYPTO_MUTEX_unlock_write(lock); - return ctx != NULL; + return ok; } int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont, @@ -263,7 +265,7 @@ int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont, static int bn_from_montgomery_in_place(BN_ULONG *r, size_t num_r, BN_ULONG *a, size_t num_a, const BN_MONT_CTX *mont) { const BN_ULONG *n = mont->N.d; - size_t num_n = mont->N.top; + size_t num_n = mont->N.width; if (num_r != num_n || num_a != 2 * num_n) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; @@ -304,32 +306,26 @@ static int bn_from_montgomery_in_place(BN_ULONG *r, size_t num_r, BN_ULONG *a, static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont) { - const BIGNUM *n = &mont->N; - if (n->top == 0) { - ret->top = 0; - return 1; - } - - int max = (2 * n->top); // carry is stored separately - if (!bn_wexpand(r, max) || - !bn_wexpand(ret, n->top)) { + if (r->neg) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); return 0; } - // Clear the top words of |r|. - if (max > r->top) { - OPENSSL_memset(r->d + r->top, 0, (max - r->top) * sizeof(BN_ULONG)); + + const BIGNUM *n = &mont->N; + if (n->width == 0) { + ret->width = 0; + return 1; } - r->top = max; - ret->top = n->top; - if (!bn_from_montgomery_in_place(ret->d, ret->top, r->d, r->top, mont)) { + int max = 2 * n->width; // carry is stored separately + if (!bn_resize_words(r, max) || + !bn_wexpand(ret, n->width)) { return 0; } - ret->neg = r->neg; - bn_correct_top(r); - bn_correct_top(ret); - return 1; + ret->width = n->width; + ret->neg = 0; + return bn_from_montgomery_in_place(ret->d, ret->width, r->d, r->width, mont); } int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont, @@ -352,35 +348,24 @@ int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont, return ret; } -int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, - const BN_MONT_CTX *mont, BN_CTX *ctx) { -#if !defined(OPENSSL_BN_ASM_MONT) - return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx); -#else - int num = mont->N.top; - - // |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. - if (num < (128 / BN_BITS2) || - a->top != num || - b->top != num) { - return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx); - } - - if (!bn_wexpand(r, num)) { - return 0; - } - if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { - // The check above ensures this won't happen. - assert(0); - OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR); - return 0; +int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx) { + // If the high bit of |n| is set, R = 2^(width*BN_BITS2) < 2 * |n|, so we + // compute R - |n| rather than perform Montgomery reduction. + const BIGNUM *n = &mont->N; + if (n->width > 0 && (n->d[n->width - 1] >> (BN_BITS2 - 1)) != 0) { + if (!bn_wexpand(r, n->width)) { + return 0; + } + r->d[0] = 0 - n->d[0]; + for (int i = 1; i < n->width; i++) { + r->d[i] = ~n->d[i]; + } + r->width = n->width; + r->neg = 0; + return 1; } - r->neg = a->neg ^ b->neg; - r->top = num; - bn_correct_top(r); - return 1; -#endif + return BN_from_montgomery(r, &mont->RR, mont, ctx); } static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a, @@ -396,11 +381,11 @@ static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a, } if (a == b) { - if (!BN_sqr(tmp, a, ctx)) { + if (!bn_sqr_consttime(tmp, a, ctx)) { goto err; } } else { - if (!BN_mul(tmp, a, b, ctx)) { + if (!bn_mul_consttime(tmp, a, b, ctx)) { goto err; } } @@ -417,15 +402,51 @@ static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a, return ret; } +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + if (a->neg || b->neg) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + +#if defined(OPENSSL_BN_ASM_MONT) + // |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. + int num = mont->N.width; + if (num >= (128 / BN_BITS2) && + a->width == num && + b->width == num) { + if (!bn_wexpand(r, num)) { + return 0; + } + if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { + // The check above ensures this won't happen. + assert(0); + OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR); + return 0; + } + r->neg = 0; + r->width = num; + return 1; + } +#endif + + return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx); +} + +int bn_less_than_montgomery_R(const BIGNUM *bn, const BN_MONT_CTX *mont) { + return !BN_is_negative(bn) && + bn_fits_in_words(bn, mont->N.width); +} + int bn_to_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_MONT_CTX *mont) { return bn_mod_mul_montgomery_small(r, num_r, a, num_a, mont->RR.d, - mont->RR.top, mont); + mont->RR.width, mont); } int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_MONT_CTX *mont) { - size_t num_n = mont->N.top; + size_t num_n = mont->N.width; if (num_a > 2 * num_n || num_r != num_n || num_n > BN_SMALL_MAX_WORDS) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; @@ -439,10 +460,32 @@ int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, return ret; } +int bn_one_to_montgomery_small(BN_ULONG *r, size_t num_r, + const BN_MONT_CTX *mont) { + const BN_ULONG *n = mont->N.d; + size_t num_n = mont->N.width; + if (num_n == 0 || num_r != num_n) { + OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + // If the high bit of |n| is set, R = 2^(num_n*BN_BITS2) < 2 * |n|, so we + // compute R - |n| rather than perform Montgomery reduction. + if (num_n > 0 && (n[num_n - 1] >> (BN_BITS2 - 1)) != 0) { + r[0] = 0 - n[0]; + for (size_t i = 1; i < num_n; i++) { + r[i] = ~n[i]; + } + return 1; + } + + return bn_from_montgomery_small(r, num_r, mont->RR.d, mont->RR.width, mont); +} + int bn_mod_mul_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_ULONG *b, size_t num_b, const BN_MONT_CTX *mont) { - size_t num_n = mont->N.top; + size_t num_n = mont->N.width; if (num_r != num_n || num_a + num_b > 2 * num_n || num_n > BN_SMALL_MAX_WORDS) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery_inv.c b/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery_inv.c index c3c788ab1..a920ca41d 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery_inv.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/montgomery_inv.c @@ -71,7 +71,7 @@ uint64_t bn_mont_n0(const BIGNUM *n) { // |BN_MONT_CTX_N0_LIMBS| limbs of |n|. uint64_t n_mod_r = n->d[0]; #if BN_MONT_CTX_N0_LIMBS == 2 - if (n->top > 1) { + if (n->width > 1) { n_mod_r |= (uint64_t)n->d[1] << BN_BITS2; } #endif @@ -159,10 +159,8 @@ static uint64_t bn_neg_inv_mod_r_u64(uint64_t n) { return v; } -// bn_mod_exp_base_2_vartime calculates r = 2**p (mod n). |p| must be larger -// than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and -// odd. -int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n) { +int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n, + BN_CTX *ctx) { assert(!BN_is_zero(n)); assert(!BN_is_negative(n)); assert(BN_is_odd(n)); @@ -171,37 +169,17 @@ int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n) { unsigned n_bits = BN_num_bits(n); assert(n_bits != 0); + assert(p > n_bits); if (n_bits == 1) { return 1; } - // Set |r| to the smallest power of two larger than |n|. - assert(p > n_bits); - if (!BN_set_bit(r, n_bits)) { - return 0; - } - - // Unconditionally reduce |r|. - assert(BN_cmp(r, n) > 0); - if (!BN_usub(r, r, n)) { + // Set |r| to the larger power of two smaller than |n|, then shift with + // reductions the rest of the way. + if (!BN_set_bit(r, n_bits - 1) || + !bn_mod_lshift_consttime(r, r, p - (n_bits - 1), n, ctx)) { return 0; } - assert(BN_cmp(r, n) < 0); - - for (unsigned i = n_bits; i < p; ++i) { - // This is like |BN_mod_lshift1_quick| except using |BN_usub|. - // - // TODO: Replace this with the use of a constant-time variant of - // |BN_mod_lshift1_quick|. - if (!BN_lshift1(r, r)) { - return 0; - } - if (BN_cmp(r, n) >= 0) { - if (!BN_usub(r, r, n)) { - return 0; - } - } - } return 1; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/mul.c b/Sources/BoringSSL/crypto/fipsmodule/bn/mul.c index b93f5587a..4a0711d89 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/mul.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/mul.c @@ -61,6 +61,7 @@ #include #include +#include #include "internal.h" #include "../../internal.h" @@ -70,6 +71,13 @@ #define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL +static void bn_abs_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + size_t num, BN_ULONG *tmp) { + BN_ULONG borrow = bn_sub_words(tmp, a, b, num); + bn_sub_words(r, b, a, num); + bn_select_words(r, 0 - borrow, r /* tmp < 0 */, tmp /* tmp >= 0 */, num); +} + static void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, size_t na, const BN_ULONG *b, size_t nb) { if (na < nb) { @@ -279,25 +287,61 @@ BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); #endif +// bn_abs_sub_part_words computes |r| = |a| - |b|, storing the absolute value +// and returning a mask of all ones if the result was negative and all zeros if +// the result was positive. |cl| and |dl| follow the |bn_sub_part_words| calling +// convention. +// +// TODO(davidben): Make this take |size_t|. The |cl| + |dl| calling convention +// is confusing. The trouble is 32-bit x86 implements |bn_sub_part_words| in +// assembly, but we can probably just delete it? +static BN_ULONG bn_abs_sub_part_words(BN_ULONG *r, const BN_ULONG *a, + const BN_ULONG *b, int cl, int dl, + BN_ULONG *tmp) { + BN_ULONG borrow = bn_sub_part_words(tmp, a, b, cl, dl); + bn_sub_part_words(r, b, a, cl, -dl); + int r_len = cl + (dl < 0 ? -dl : dl); + borrow = 0 - borrow; + bn_select_words(r, borrow, r /* tmp < 0 */, tmp /* tmp >= 0 */, r_len); + return borrow; +} + +int bn_abs_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { + int cl = a->width < b->width ? a->width : b->width; + int dl = a->width - b->width; + int r_len = a->width < b->width ? b->width : a->width; + BN_CTX_start(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); + int ok = tmp != NULL && + bn_wexpand(r, r_len) && + bn_wexpand(tmp, r_len); + if (ok) { + bn_abs_sub_part_words(r->d, a->d, b->d, cl, dl, tmp->d); + r->width = r_len; + } + BN_CTX_end(ctx); + return ok; +} + // Karatsuba recursive multiplication algorithm // (cf. Knuth, The Art of Computer Programming, Vol. 2) -// r is 2*n2 words in size, -// a and b are both n2 words in size. -// n2 must be a power of 2. -// We multiply and return the result. -// t must be 2*n2 words in size -// We calculate -// a[0]*b[0] -// a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) -// a[1]*b[1] -// dnX may not be positive, but n2/2+dnX has to be +// bn_mul_recursive sets |r| to |a| * |b|, using |t| as scratch space. |r| has +// length 2*|n2|, |a| has length |n2| + |dna|, |b| has length |n2| + |dnb|, and +// |t| has length 4*|n2|. |n2| must be a power of two. Finally, we must have +// -|BN_MUL_RECURSIVE_SIZE_NORMAL|/2 <= |dna| <= 0 and +// -|BN_MUL_RECURSIVE_SIZE_NORMAL|/2 <= |dnb| <= 0. +// +// TODO(davidben): Simplify and |size_t| the calling convention around lengths +// here. static void bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2, int dna, int dnb, BN_ULONG *t) { - int n = n2 / 2, c1, c2; - int tna = n + dna, tnb = n + dnb; - unsigned int neg, zero; - BN_ULONG ln, lo, *p; + // |n2| is a power of two. + assert(n2 != 0 && (n2 & (n2 - 1)) == 0); + // Check |dna| and |dnb| are in range. + assert(-BN_MUL_RECURSIVE_SIZE_NORMAL/2 <= dna && dna <= 0); + assert(-BN_MUL_RECURSIVE_SIZE_NORMAL/2 <= dnb && dnb <= 0); // Only call bn_mul_comba 8 if n2 == 8 and the // two arrays are complete [steve] @@ -309,276 +353,212 @@ static void bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, // Else do normal multiply if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { bn_mul_normal(r, a, n2 + dna, b, n2 + dnb); - if ((dna + dnb) < 0) { + if (dna + dnb < 0) { OPENSSL_memset(&r[2 * n2 + dna + dnb], 0, sizeof(BN_ULONG) * -(dna + dnb)); } return; } - // r=(a[0]-a[1])*(b[1]-b[0]) - c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); - c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); - zero = neg = 0; - switch (c1 * 3 + c2) { - case -4: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); // - - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); // - - break; - case -3: - zero = 1; - break; - case -2: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); // - - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); // + - neg = 1; - break; - case -1: - case 0: - case 1: - zero = 1; - break; - case 2: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); // + - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); // - - neg = 1; - break; - case 3: - zero = 1; - break; - case 4: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); - break; - } - + // Split |a| and |b| into a0,a1 and b0,b1, where a0 and b0 have size |n|. + // Split |t| into t0,t1,t2,t3, each of size |n|, with the remaining 4*|n| used + // for recursive calls. + // Split |r| into r0,r1,r2,r3. We must contribute a0*b0 to r0,r1, a0*a1+b0*b1 + // to r1,r2, and a1*b1 to r2,r3. The middle term we will compute as: + // + // a0*a1 + b0*b1 = (a0 - a1)*(b1 - b0) + a1*b1 + a0*b0 + // + // Note that we know |n| >= |BN_MUL_RECURSIVE_SIZE_NORMAL|/2 above, so + // |tna| and |tnb| are non-negative. + int n = n2 / 2, tna = n + dna, tnb = n + dnb; + + // t0 = a0 - a1 and t1 = b1 - b0. The result will be multiplied, so we XOR + // their sign masks, giving the sign of (a0 - a1)*(b1 - b0). t0 and t1 + // themselves store the absolute value. + BN_ULONG neg = bn_abs_sub_part_words(t, a, &a[n], tna, n - tna, &t[n2]); + neg ^= bn_abs_sub_part_words(&t[n], &b[n], b, tnb, tnb - n, &t[n2]); + + // Compute: + // t2,t3 = t0 * t1 = |(a0 - a1)*(b1 - b0)| + // r0,r1 = a0 * b0 + // r2,r3 = a1 * b1 if (n == 4 && dna == 0 && dnb == 0) { - // XXX: bn_mul_comba4 could take extra args to do this well - if (!zero) { - bn_mul_comba4(&(t[n2]), t, &(t[n])); - } else { - OPENSSL_memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG)); - } + bn_mul_comba4(&t[n2], t, &t[n]); bn_mul_comba4(r, a, b); - bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); + bn_mul_comba4(&r[n2], &a[n], &b[n]); } else if (n == 8 && dna == 0 && dnb == 0) { - // XXX: bn_mul_comba8 could take extra args to do this well - if (!zero) { - bn_mul_comba8(&(t[n2]), t, &(t[n])); - } else { - OPENSSL_memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG)); - } + bn_mul_comba8(&t[n2], t, &t[n]); bn_mul_comba8(r, a, b); - bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); + bn_mul_comba8(&r[n2], &a[n], &b[n]); } else { - p = &(t[n2 * 2]); - if (!zero) { - bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); - } else { - OPENSSL_memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG)); - } + BN_ULONG *p = &t[n2 * 2]; + bn_mul_recursive(&t[n2], t, &t[n], n, 0, 0, p); bn_mul_recursive(r, a, b, n, 0, 0, p); - bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p); + bn_mul_recursive(&r[n2], &a[n], &b[n], n, dna, dnb, p); } - // t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign - // r[10] holds (a[0]*b[0]) - // r[32] holds (b[1]*b[1]) + // t0,t1,c = r0,r1 + r2,r3 = a0*b0 + a1*b1 + BN_ULONG c = bn_add_words(t, r, &r[n2], n2); - c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + // t2,t3,c = t0,t1,c + neg*t2,t3 = (a0 - a1)*(b1 - b0) + a1*b1 + a0*b0. + // The second term is stored as the absolute value, so we do this with a + // constant-time select. + BN_ULONG c_neg = c - bn_sub_words(&t[n2 * 2], t, &t[n2], n2); + BN_ULONG c_pos = c + bn_add_words(&t[n2], t, &t[n2], n2); + bn_select_words(&t[n2], neg, &t[n2 * 2], &t[n2], n2); + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), + crypto_word_t_too_small); + c = constant_time_select_w(neg, c_neg, c_pos); - if (neg) { - // if t[32] is negative - c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); - } else { - // Might have a carry - c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); - } - - // t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) - // r[10] holds (a[0]*b[0]) - // r[32] holds (b[1]*b[1]) - // c1 holds the carry bits - c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); - if (c1) { - p = &(r[n + n2]); - lo = *p; - ln = lo + c1; - *p = ln; - - // The overflow will stop before we over write - // words we should not overwrite - if (ln < (BN_ULONG)c1) { - do { - p++; - lo = *p; - ln = lo + 1; - *p = ln; - } while (ln == 0); - } + // We now have our three components. Add them together. + // r1,r2,c = r1,r2 + t2,t3,c + c += bn_add_words(&r[n], &r[n], &t[n2], n2); + + // Propagate the carry bit to the end. + for (int i = n + n2; i < n2 + n2; i++) { + BN_ULONG old = r[i]; + r[i] = old + c; + c = r[i] < old; } + + // The product should fit without carries. + assert(c == 0); } -// n+tn is the word length -// t needs to be n*4 is size, as does r -// tnX may not be negative but less than n +// bn_mul_part_recursive sets |r| to |a| * |b|, using |t| as scratch space. |r| +// has length 4*|n|, |a| has length |n| + |tna|, |b| has length |n| + |tnb|, and +// |t| has length 8*|n|. |n| must be a power of two. Additionally, we must have +// 0 <= tna < n and 0 <= tnb < n, and |tna| and |tnb| must differ by at most +// one. +// +// TODO(davidben): Make this take |size_t| and perhaps the actual lengths of |a| +// and |b|. static void bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n, int tna, int tnb, BN_ULONG *t) { - int i, j, n2 = n * 2; - int c1, c2, neg; - BN_ULONG ln, lo, *p; - + // |n| is a power of two. + assert(n != 0 && (n & (n - 1)) == 0); + // Check |tna| and |tnb| are in range. + assert(0 <= tna && tna < n); + assert(0 <= tnb && tnb < n); + assert(-1 <= tna - tnb && tna - tnb <= 1); + + int n2 = n * 2; if (n < 8) { bn_mul_normal(r, a, n + tna, b, n + tnb); + OPENSSL_memset(r + n2 + tna + tnb, 0, n2 - tna - tnb); return; } - // r=(a[0]-a[1])*(b[1]-b[0]) - c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); - c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); - neg = 0; - switch (c1 * 3 + c2) { - case -4: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); // - - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); // - - break; - case -3: - // break; - case -2: - bn_sub_part_words(t, &(a[n]), a, tna, tna - n); // - - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); // + - neg = 1; - break; - case -1: - case 0: - case 1: - // break; - case 2: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); // + - bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); // - - neg = 1; - break; - case 3: - // break; - case 4: - bn_sub_part_words(t, a, &(a[n]), tna, n - tna); - bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); - break; - } - + // Split |a| and |b| into a0,a1 and b0,b1, where a0 and b0 have size |n|. |a1| + // and |b1| have size |tna| and |tnb|, respectively. + // Split |t| into t0,t1,t2,t3, each of size |n|, with the remaining 4*|n| used + // for recursive calls. + // Split |r| into r0,r1,r2,r3. We must contribute a0*b0 to r0,r1, a0*a1+b0*b1 + // to r1,r2, and a1*b1 to r2,r3. The middle term we will compute as: + // + // a0*a1 + b0*b1 = (a0 - a1)*(b1 - b0) + a1*b1 + a0*b0 + + // t0 = a0 - a1 and t1 = b1 - b0. The result will be multiplied, so we XOR + // their sign masks, giving the sign of (a0 - a1)*(b1 - b0). t0 and t1 + // themselves store the absolute value. + BN_ULONG neg = bn_abs_sub_part_words(t, a, &a[n], tna, n - tna, &t[n2]); + neg ^= bn_abs_sub_part_words(&t[n], &b[n], b, tnb, tnb - n, &t[n2]); + + // Compute: + // t2,t3 = t0 * t1 = |(a0 - a1)*(b1 - b0)| + // r0,r1 = a0 * b0 + // r2,r3 = a1 * b1 if (n == 8) { - bn_mul_comba8(&(t[n2]), t, &(t[n])); + bn_mul_comba8(&t[n2], t, &t[n]); bn_mul_comba8(r, a, b); - bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); - OPENSSL_memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb)); + + bn_mul_normal(&r[n2], &a[n], tna, &b[n], tnb); + // |bn_mul_normal| only writes |tna| + |tna| words. Zero the rest. + OPENSSL_memset(&r[n2 + tna + tnb], 0, sizeof(BN_ULONG) * (n2 - tna - tnb)); } else { - p = &(t[n2 * 2]); - bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + BN_ULONG *p = &t[n2 * 2]; + bn_mul_recursive(&t[n2], t, &t[n], n, 0, 0, p); bn_mul_recursive(r, a, b, n, 0, 0, p); - i = n / 2; - // If there is only a bottom half to the number, - // just do it - if (tna > tnb) { - j = tna - i; - } else { - j = tnb - i; - } - if (j == 0) { - bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p); - OPENSSL_memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2)); - } else if (j > 0) { - // eg, n == 16, i == 8 and tn == 11 - bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p); - OPENSSL_memset(&(r[n2 + tna + tnb]), 0, - sizeof(BN_ULONG) * (n2 - tna - tnb)); + OPENSSL_memset(&r[n2], 0, sizeof(BN_ULONG) * n2); + if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL && + tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(&r[n2], &a[n], tna, &b[n], tnb); } else { - // (j < 0) eg, n == 16, i == 8 and tn == 5 - OPENSSL_memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2); - if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL && - tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { - bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); - } else { - for (;;) { - i /= 2; - // these simplified conditions work - // exclusively because difference - // between tna and tnb is 1 or 0 - if (i < tna || i < tnb) { - bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, - tnb - i, p); - break; - } else if (i == tna || i == tnb) { - bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, - p); - break; - } + int i = n; + for (;;) { + i /= 2; + if (i < tna || i < tnb) { + // E.g., n == 16, i == 8 and tna == 11. |tna| and |tnb| are within one + // of each other, so if |tna| is larger and tna > i, then we know + // tnb >= i, and this call is valid. + bn_mul_part_recursive(&r[n2], &a[n], &b[n], i, tna - i, tnb - i, p); + break; } + if (i == tna || i == tnb) { + // If there is only a bottom half to the number, just do it. We know + // the larger of |tna - i| and |tnb - i| is zero. The other is zero or + // -1 by because of |tna| and |tnb| differ by at most one. + bn_mul_recursive(&r[n2], &a[n], &b[n], i, tna - i, tnb - i, p); + break; + } + + // This loop will eventually terminate when |i| falls below + // |BN_MUL_RECURSIVE_SIZE_NORMAL| because we know one of |tna| and |tnb| + // exceeds that. } } } - // t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign - // r[10] holds (a[0]*b[0]) - // r[32] holds (b[1]*b[1]) + // t0,t1,c = r0,r1 + r2,r3 = a0*b0 + a1*b1 + BN_ULONG c = bn_add_words(t, r, &r[n2], n2); - c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + // t2,t3,c = t0,t1,c + neg*t2,t3 = (a0 - a1)*(b1 - b0) + a1*b1 + a0*b0. + // The second term is stored as the absolute value, so we do this with a + // constant-time select. + BN_ULONG c_neg = c - bn_sub_words(&t[n2 * 2], t, &t[n2], n2); + BN_ULONG c_pos = c + bn_add_words(&t[n2], t, &t[n2], n2); + bn_select_words(&t[n2], neg, &t[n2 * 2], &t[n2], n2); + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), + crypto_word_t_too_small); + c = constant_time_select_w(neg, c_neg, c_pos); - if (neg) { - // if t[32] is negative - c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); - } else { - // Might have a carry - c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); - } - - // t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) - // r[10] holds (a[0]*b[0]) - // r[32] holds (b[1]*b[1]) - // c1 holds the carry bits - c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); - if (c1) { - p = &(r[n + n2]); - lo = *p; - ln = lo + c1; - *p = ln; - - // The overflow will stop before we over write - // words we should not overwrite - if (ln < (BN_ULONG)c1) { - do { - p++; - lo = *p; - ln = lo + 1; - *p = ln; - } while (ln == 0); - } - } -} + // We now have our three components. Add them together. + // r1,r2,c = r1,r2 + t2,t3,c + c += bn_add_words(&r[n], &r[n], &t[n2], n2); -int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { - int ret = 0; - int top, al, bl; - BIGNUM *rr; - int i; - BIGNUM *t = NULL; - int j = 0, k; + // Propagate the carry bit to the end. + for (int i = n + n2; i < n2 + n2; i++) { + BN_ULONG old = r[i]; + r[i] = old + c; + c = r[i] < old; + } - al = a->top; - bl = b->top; + // The product should fit without carries. + assert(c == 0); +} - if ((al == 0) || (bl == 0)) { +// bn_mul_impl implements |BN_mul| and |bn_mul_consttime|. Note this function +// breaks |BIGNUM| invariants and may return a negative zero. This is handled by +// the callers. +static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { + int al = a->width; + int bl = b->width; + if (al == 0 || bl == 0) { BN_zero(r); return 1; } - top = al + bl; + int ret = 0; + BIGNUM *rr; BN_CTX_start(ctx); - if ((r == a) || (r == b)) { - if ((rr = BN_CTX_get(ctx)) == NULL) { + if (r == a || r == b) { + rr = BN_CTX_get(ctx); + if (r == NULL) { goto err; } } else { @@ -586,55 +566,55 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { } rr->neg = a->neg ^ b->neg; - i = al - bl; + int i = al - bl; if (i == 0) { if (al == 8) { if (!bn_wexpand(rr, 16)) { goto err; } - rr->top = 16; + rr->width = 16; bn_mul_comba8(rr->d, a->d, b->d); goto end; } } + int top = al + bl; static const int kMulNormalSize = 16; if (al >= kMulNormalSize && bl >= kMulNormalSize) { - if (i >= -1 && i <= 1) { - /* Find out the power of two lower or equal - to the longest of the two numbers */ + if (-1 <= i && i <= 1) { + // Find the larger power of two less than or equal to the larger length. + int j; if (i >= 0) { j = BN_num_bits_word((BN_ULONG)al); - } - if (i == -1) { + } else { j = BN_num_bits_word((BN_ULONG)bl); } j = 1 << (j - 1); assert(j <= al || j <= bl); - k = j + j; - t = BN_CTX_get(ctx); + BIGNUM *t = BN_CTX_get(ctx); if (t == NULL) { goto err; } if (al > j || bl > j) { - if (!bn_wexpand(t, k * 4)) { - goto err; - } - if (!bn_wexpand(rr, k * 4)) { + // We know |al| and |bl| are at most one from each other, so if al > j, + // bl >= j, and vice versa. Thus we can use |bn_mul_part_recursive|. + assert(al >= j && bl >= j); + if (!bn_wexpand(t, j * 8) || + !bn_wexpand(rr, j * 4)) { goto err; } bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } else { - // al <= j || bl <= j - if (!bn_wexpand(t, k * 2)) { - goto err; - } - if (!bn_wexpand(rr, k * 2)) { + // al <= j && bl <= j. Additionally, we know j <= al or j <= bl, so one + // of al - j or bl - j is zero. The other, by the bound on |i| above, is + // zero or -1. Thus, we can use |bn_mul_recursive|. + if (!bn_wexpand(t, j * 4) || + !bn_wexpand(rr, j * 2)) { goto err; } bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); } - rr->top = top; + rr->width = top; goto end; } } @@ -642,11 +622,10 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { if (!bn_wexpand(rr, top)) { goto err; } - rr->top = top; + rr->width = top; bn_mul_normal(rr->d, a->d, al, b->d, bl); end: - bn_correct_top(rr); if (r != rr && !BN_copy(r, rr)) { goto err; } @@ -657,6 +636,26 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { return ret; } +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { + if (!bn_mul_impl(r, a, b, ctx)) { + return 0; + } + + // This additionally fixes any negative zeros created by |bn_mul_impl|. + bn_set_minimal_width(r); + return 1; +} + +int bn_mul_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { + // Prevent negative zeros. + if (a->neg || b->neg) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + return bn_mul_impl(r, a, b, ctx); +} + int bn_mul_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a, const BN_ULONG *b, size_t num_b) { if (num_r != num_a + num_b) { @@ -711,25 +710,19 @@ static void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, size_t n, bn_add_words(r, r, tmp, max); } -// r is 2*n words in size, -// a and b are both n words in size. (There's not actually a 'b' here ...) -// n must be a power of 2. -// We multiply and return the result. -// t must be 2*n words in size -// We calculate -// a[0]*b[0] -// a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) -// a[1]*b[1] -static void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, +// bn_sqr_recursive sets |r| to |a|^2, using |t| as scratch space. |r| has +// length 2*|n2|, |a| has length |n2|, and |t| has length 4*|n2|. |n2| must be +// a power of two. +static void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, size_t n2, BN_ULONG *t) { - int n = n2 / 2; - int zero, c1; - BN_ULONG ln, lo, *p; + // |n2| is a power of two. + assert(n2 != 0 && (n2 & (n2 - 1)) == 0); if (n2 == 4) { bn_sqr_comba4(r, a); return; - } else if (n2 == 8) { + } + if (n2 == 8) { bn_sqr_comba8(r, a); return; } @@ -737,63 +730,48 @@ static void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, bn_sqr_normal(r, a, n2, t); return; } - // r=(a[0]-a[1])*(a[1]-a[0]) - c1 = bn_cmp_words(a, &(a[n]), n); - zero = 0; - if (c1 > 0) { - bn_sub_words(t, a, &(a[n]), n); - } else if (c1 < 0) { - bn_sub_words(t, &(a[n]), a, n); - } else { - zero = 1; - } - // The result will always be negative unless it is zero - p = &(t[n2 * 2]); + // Split |a| into a0,a1, each of size |n|. + // Split |t| into t0,t1,t2,t3, each of size |n|, with the remaining 4*|n| used + // for recursive calls. + // Split |r| into r0,r1,r2,r3. We must contribute a0^2 to r0,r1, 2*a0*a1 to + // r1,r2, and a1^2 to r2,r3. + size_t n = n2 / 2; + BN_ULONG *t_recursive = &t[n2 * 2]; - if (!zero) { - bn_sqr_recursive(&(t[n2]), t, n, p); - } else { - OPENSSL_memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG)); - } - bn_sqr_recursive(r, a, n, p); - bn_sqr_recursive(&(r[n2]), &(a[n]), n, p); - - // t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero - // r[10] holds (a[0]*b[0]) - // r[32] holds (b[1]*b[1]) - - c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); - - // t[32] is negative - c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); - - // t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) - // r[10] holds (a[0]*a[0]) - // r[32] holds (a[1]*a[1]) - // c1 holds the carry bits - c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); - if (c1) { - p = &(r[n + n2]); - lo = *p; - ln = lo + c1; - *p = ln; - - // The overflow will stop before we over write - // words we should not overwrite - if (ln < (BN_ULONG)c1) { - do { - p++; - lo = *p; - ln = lo + 1; - *p = ln; - } while (ln == 0); - } + // t0 = |a0 - a1|. + bn_abs_sub_words(t, a, &a[n], n, &t[n]); + // t2,t3 = t0^2 = |a0 - a1|^2 = a0^2 - 2*a0*a1 + a1^2 + bn_sqr_recursive(&t[n2], t, n, t_recursive); + + // r0,r1 = a0^2 + bn_sqr_recursive(r, a, n, t_recursive); + + // r2,r3 = a1^2 + bn_sqr_recursive(&r[n2], &a[n], n, t_recursive); + + // t0,t1,c = r0,r1 + r2,r3 = a0^2 + a1^2 + BN_ULONG c = bn_add_words(t, r, &r[n2], n2); + // t2,t3,c = t0,t1,c - t2,t3 = 2*a0*a1 + c -= bn_sub_words(&t[n2], t, &t[n2], n2); + + // We now have our three components. Add them together. + // r1,r2,c = r1,r2 + t2,t3,c + c += bn_add_words(&r[n], &r[n], &t[n2], n2); + + // Propagate the carry bit to the end. + for (size_t i = n + n2; i < n2 + n2; i++) { + BN_ULONG old = r[i]; + r[i] = old + c; + c = r[i] < old; } + + // The square should fit without carries. + assert(c == 0); } int BN_mul_word(BIGNUM *bn, BN_ULONG w) { - if (!bn->top) { + if (!bn->width) { return 1; } @@ -802,37 +780,34 @@ int BN_mul_word(BIGNUM *bn, BN_ULONG w) { return 1; } - BN_ULONG ll = bn_mul_words(bn->d, bn->d, bn->top, w); + BN_ULONG ll = bn_mul_words(bn->d, bn->d, bn->width, w); if (ll) { - if (!bn_wexpand(bn, bn->top + 1)) { + if (!bn_wexpand(bn, bn->width + 1)) { return 0; } - bn->d[bn->top++] = ll; + bn->d[bn->width++] = ll; } return 1; } -int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { - int max, al; - int ret = 0; - BIGNUM *tmp, *rr; - - al = a->top; +int bn_sqr_consttime(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { + int al = a->width; if (al <= 0) { - r->top = 0; + r->width = 0; r->neg = 0; return 1; } + int ret = 0; BN_CTX_start(ctx); - rr = (a != r) ? r : BN_CTX_get(ctx); - tmp = BN_CTX_get(ctx); + BIGNUM *rr = (a != r) ? r : BN_CTX_get(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); if (!rr || !tmp) { goto err; } - max = 2 * al; // Non-zero (from above) + int max = 2 * al; // Non-zero (from above) if (!bn_wexpand(rr, max)) { goto err; } @@ -846,13 +821,9 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2]; bn_sqr_normal(rr->d, a->d, al, t); } else { - int j, k; - - j = BN_num_bits_word((BN_ULONG)al); - j = 1 << (j - 1); - k = j + j; - if (al == j) { - if (!bn_wexpand(tmp, k * 2)) { + // If |al| is a power of two, we can use |bn_sqr_recursive|. + if (al != 0 && (al & (al - 1)) == 0) { + if (!bn_wexpand(tmp, al * 4)) { goto err; } bn_sqr_recursive(rr->d, a->d, al, tmp->d); @@ -866,13 +837,7 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { } rr->neg = 0; - // If the most-significant half of the top word of 'a' is zero, then - // the square of 'a' will max-1 words. - if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l)) { - rr->top = max - 1; - } else { - rr->top = max; - } + rr->width = max; if (rr != r && !BN_copy(r, rr)) { goto err; @@ -884,6 +849,15 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { return ret; } +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { + if (!bn_sqr_consttime(r, a, ctx)) { + return 0; + } + + bn_set_minimal_width(r); + return 1; +} + int bn_sqr_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a) { if (num_r != 2 * num_a || num_a > BN_SMALL_MAX_WORDS) { OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/prime.c b/Sources/BoringSSL/crypto/fipsmodule/bn/prime.c index 691d0cba5..35b1034df 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/prime.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/prime.c @@ -112,6 +112,8 @@ #include #include "internal.h" +#include "../../internal.h" + // The quick sieve algorithm approach to weeding out primes is Philip // Zimmermann's, as implemented in PGP. I have had a read of his comments and @@ -341,6 +343,67 @@ static int BN_prime_checks_for_size(int bits) { return 28; } +// BN_PRIME_CHECKS_BLINDED is the iteration count for blinding the constant-time +// primality test. See |BN_primality_test| for details. This number is selected +// so that, for a candidate N-bit RSA prime, picking |BN_PRIME_CHECKS_BLINDED| +// random N-bit numbers will have at least |BN_prime_checks_for_size(N)| values +// in range with high probability. +// +// The following Python script computes the blinding factor needed for the +// corresponding iteration count. +/* +import math + +# We choose candidate RSA primes between sqrt(2)/2 * 2^N and 2^N and select +# witnesses by generating random N-bit numbers. Thus the probability of +# selecting one in range is at least sqrt(2)/2. +p = math.sqrt(2) / 2 + +# Target around 2^-8 probability of the blinding being insufficient given that +# key generation is a one-time, noisy operation. +epsilon = 2**-8 + +def choose(a, b): + r = 1 + for i in xrange(b): + r *= a - i + r /= (i + 1) + return r + +def failure_rate(min_uniform, iterations): + """ Returns the probability that, for |iterations| candidate witnesses, fewer + than |min_uniform| of them will be uniform. """ + prob = 0.0 + for i in xrange(min_uniform): + prob += (choose(iterations, i) * + p**i * (1-p)**(iterations - i)) + return prob + +for min_uniform in (3, 4, 5, 6, 8, 13, 19, 28): + # Find the smallest number of iterations under the target failure rate. + iterations = min_uniform + while True: + prob = failure_rate(min_uniform, iterations) + if prob < epsilon: + print min_uniform, iterations, prob + break + iterations += 1 + +Output: + 3 9 0.00368894873911 + 4 11 0.00363319494662 + 5 13 0.00336215573898 + 6 15 0.00300145783158 + 8 19 0.00225214119331 + 13 27 0.00385610026955 + 19 38 0.0021410539126 + 28 52 0.00325405801769 + +16 iterations suffices for 400-bit primes and larger (6 uniform samples needed), +which is already well below the minimum acceptable key size for RSA. +*/ +#define BN_PRIME_CHECKS_BLINDED 16 + static int probable_prime(BIGNUM *rnd, int bits); static int probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); @@ -461,81 +524,291 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, return found; } -int BN_primality_test(int *is_probably_prime, const BIGNUM *candidate, - int checks, BN_CTX *ctx, int do_trial_division, - BN_GENCB *cb) { - switch (BN_is_prime_fasttest_ex(candidate, checks, ctx, do_trial_division, cb)) { - case 1: - *is_probably_prime = 1; - return 1; - case 0: - *is_probably_prime = 0; +// The following functions use a Barrett reduction variant to avoid leaking the +// numerator. See http://ridiculousfish.com/blog/posts/labor-of-division-episode-i.html +// +// We use 32-bit numerator and 16-bit divisor for simplicity. This allows +// computing |m| and |q| without architecture-specific code. + +// mod_u16 returns |n| mod |d|. |p| and |m| are the "magic numbers" for |d| (see +// reference). For proof of correctness in Coq, see +// https://github.com/davidben/fiat-crypto/blob/barrett/src/Arithmetic/BarrettReduction/RidiculousFish.v +// Note the Coq version of |mod_u16| additionally includes the computation of +// |p| and |m| from |bn_mod_u16_consttime| below. +static uint16_t mod_u16(uint32_t n, uint16_t d, uint32_t p, uint32_t m) { + // Compute floor(n/d) per steps 3 through 5. + uint32_t q = ((uint64_t)m * n) >> 32; + // Note there is a typo in the reference. We right-shift by one, not two. + uint32_t t = ((n - q) >> 1) + q; + t = t >> (p - 1); + + // Multiply and subtract to get the remainder. + n -= d * t; + assert(n < d); + return n; +} + +// shift_and_add_mod_u16 returns |r| * 2^32 + |a| mod |d|. |p| and |m| are the +// "magic numbers" for |d| (see reference). +static uint16_t shift_and_add_mod_u16(uint16_t r, uint32_t a, uint16_t d, + uint32_t p, uint32_t m) { + // Incorporate |a| in two 16-bit chunks. + uint32_t t = r; + t <<= 16; + t |= a >> 16; + t = mod_u16(t, d, p, m); + + t <<= 16; + t |= a & 0xffff; + t = mod_u16(t, d, p, m); + return t; +} + +uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d) { + if (d <= 1) { + return 0; + } + + // Compute the "magic numbers" for |d|. See steps 1 and 2. + // This computes p = ceil(log_2(d)). + uint32_t p = BN_num_bits_word(d - 1); + // This operation is not constant-time, but |p| and |d| are public values. + // Note that |p| is at most 16, so the computation fits in |uint64_t|. + assert(p <= 16); + uint32_t m = ((UINT64_C(1) << (32 + p)) + d - 1) / d; + + uint16_t ret = 0; + for (int i = bn->width - 1; i >= 0; i--) { +#if BN_BITS2 == 32 + ret = shift_and_add_mod_u16(ret, bn->d[i], d, p, m); +#elif BN_BITS2 == 64 + ret = shift_and_add_mod_u16(ret, bn->d[i] >> 32, d, p, m); + ret = shift_and_add_mod_u16(ret, bn->d[i] & 0xffffffff, d, p, m); +#else +#error "Unknown BN_ULONG size" +#endif + } + return ret; +} + +static int bn_trial_division(uint16_t *out, const BIGNUM *bn) { + for (int i = 1; i < NUMPRIMES; i++) { + if (bn_mod_u16_consttime(bn, primes[i]) == 0) { + *out = primes[i]; return 1; - default: - *is_probably_prime = 0; - return 0; + } } + return 0; } -int BN_is_prime_ex(const BIGNUM *candidate, int checks, BN_CTX *ctx, BN_GENCB *cb) { - return BN_is_prime_fasttest_ex(candidate, checks, ctx, 0, cb); +int bn_odd_number_is_obviously_composite(const BIGNUM *bn) { + uint16_t prime; + return bn_trial_division(&prime, bn) && !BN_is_word(bn, prime); } -int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx, - int do_trial_division, BN_GENCB *cb) { - if (BN_cmp(a, BN_value_one()) <= 0) { - return 0; +int BN_primality_test(int *is_probably_prime, const BIGNUM *w, + int iterations, BN_CTX *ctx, int do_trial_division, + BN_GENCB *cb) { + *is_probably_prime = 0; + + // To support RSA key generation, this function should treat |w| as secret if + // it is a large prime. Composite numbers are discarded, so they may return + // early. + + if (BN_cmp(w, BN_value_one()) <= 0) { + return 1; } - // first look for small factors - if (!BN_is_odd(a)) { - // a is even => a is prime if and only if a == 2 - return BN_is_word(a, 2); + if (!BN_is_odd(w)) { + // The only even prime is two. + *is_probably_prime = BN_is_word(w, 2); + return 1; } - // Enhanced Miller-Rabin does not work for three. - if (BN_is_word(a, 3)) { + // Miller-Rabin does not work for three. + if (BN_is_word(w, 3)) { + *is_probably_prime = 1; return 1; } if (do_trial_division) { - for (int i = 1; i < NUMPRIMES; i++) { - BN_ULONG mod = BN_mod_word(a, primes[i]); - if (mod == (BN_ULONG)-1) { - return -1; - } - if (mod == 0) { - return BN_is_word(a, primes[i]); - } + // Perform additional trial division checks to discard small primes. + uint16_t prime; + if (bn_trial_division(&prime, w)) { + *is_probably_prime = BN_is_word(w, prime); + return 1; } - if (!BN_GENCB_call(cb, 1, -1)) { - return -1; + return 0; } } - int ret = -1; - BN_CTX *ctx_allocated = NULL; - if (ctx == NULL) { - ctx_allocated = BN_CTX_new(); - if (ctx_allocated == NULL) { - return -1; - } - ctx = ctx_allocated; + if (iterations == BN_prime_checks) { + iterations = BN_prime_checks_for_size(BN_num_bits(w)); } - enum bn_primality_result_t result; - if (!BN_enhanced_miller_rabin_primality_test(&result, a, checks, ctx, cb)) { + // See C.3.1 from FIPS 186-4. + int ret = 0; + BN_MONT_CTX *mont = NULL; + BN_CTX_start(ctx); + BIGNUM *w1 = BN_CTX_get(ctx); + if (w1 == NULL || + !bn_usub_consttime(w1, w, BN_value_one())) { goto err; } - ret = (result == bn_probably_prime); + // Write w1 as m * 2^a (Steps 1 and 2). + int w_len = BN_num_bits(w); + int a = BN_count_low_zero_bits(w1); + BIGNUM *m = BN_CTX_get(ctx); + if (m == NULL || + !bn_rshift_secret_shift(m, w1, a, ctx)) { + goto err; + } + + // Montgomery setup for computations mod w. Additionally, compute 1 and w - 1 + // in the Montgomery domain for later comparisons. + BIGNUM *b = BN_CTX_get(ctx); + BIGNUM *z = BN_CTX_get(ctx); + BIGNUM *one_mont = BN_CTX_get(ctx); + BIGNUM *w1_mont = BN_CTX_get(ctx); + mont = BN_MONT_CTX_new_for_modulus(w, ctx); + if (b == NULL || z == NULL || one_mont == NULL || w1_mont == NULL || + mont == NULL || + !bn_one_to_montgomery(one_mont, mont, ctx) || + // w - 1 is -1 mod w, so we can compute it in the Montgomery domain, -R, + // with a subtraction. (|one_mont| cannot be zero.) + !bn_usub_consttime(w1_mont, w, one_mont)) { + goto err; + } + + // The following loop performs in inner iteration of the Miller-Rabin + // Primality test (Step 4). + // + // The algorithm as specified in FIPS 186-4 leaks information on |w|, the RSA + // private key. Instead, we run through each iteration unconditionally, + // performing modular multiplications, masking off any effects to behave + // equivalently to the specified algorithm. + // + // We also blind the number of values of |b| we try. Steps 4.1–4.2 say to + // discard out-of-range values. To avoid leaking information on |w|, we use + // |bn_rand_secret_range| which, rather than discarding bad values, adjusts + // them to be in range. Though not uniformly selected, these adjusted values + // are still usable as Rabin-Miller checks. + // + // Rabin-Miller is already probabilistic, so we could reach the desired + // confidence levels by just suitably increasing the iteration count. However, + // to align with FIPS 186-4, we use a more pessimal analysis: we do not count + // the non-uniform values towards the iteration count. As a result, this + // function is more complex and has more timing risk than necessary. + // + // We count both total iterations and uniform ones and iterate until we've + // reached at least |BN_PRIME_CHECKS_BLINDED| and |iterations|, respectively. + // If the latter is large enough, it will be the limiting factor with high + // probability and we won't leak information. + // + // Note this blinding does not impact most calls when picking primes because + // composites are rejected early. Only the two secret primes see extra work. + + crypto_word_t uniform_iterations = 0; + // Using |constant_time_lt_w| seems to prevent the compiler from optimizing + // this into two jumps. + for (int i = 1; (i <= BN_PRIME_CHECKS_BLINDED) | + constant_time_lt_w(uniform_iterations, iterations); + i++) { + int is_uniform; + if (// Step 4.1-4.2 + !bn_rand_secret_range(b, &is_uniform, 2, w1) || + // Step 4.3 + !BN_mod_exp_mont_consttime(z, b, m, w, ctx, mont)) { + goto err; + } + uniform_iterations += is_uniform; + + // loop_done is all ones if the loop has completed and all zeros otherwise. + crypto_word_t loop_done = 0; + // next_iteration is all ones if we should continue to the next iteration + // (|b| is not a composite witness for |w|). This is equivalent to going to + // step 4.7 in the original algorithm. + crypto_word_t next_iteration = 0; + + // Step 4.4. If z = 1 or z = w-1, mask off the loop and continue to the next + // iteration (go to step 4.7). + loop_done = BN_equal_consttime(z, BN_value_one()) | + BN_equal_consttime(z, w1); + loop_done = 0 - loop_done; // Make it all zeros or all ones. + next_iteration = loop_done; // Go to step 4.7 if |loop_done|. + + // Step 4.5. We use Montgomery-encoding for better performance and to avoid + // timing leaks. + if (!BN_to_montgomery(z, z, mont, ctx)) { + goto err; + } + + // To avoid leaking |a|, we run the loop to |w_len| and mask off all + // iterations once |j| = |a|. + for (int j = 1; j < w_len; j++) { + loop_done |= constant_time_eq_int(j, a); + + // Step 4.5.1. + if (!BN_mod_mul_montgomery(z, z, z, mont, ctx)) { + goto err; + } + + // Step 4.5.2. If z = w-1 and the loop is not done, run through the next + // iteration. + crypto_word_t z_is_w1_mont = BN_equal_consttime(z, w1_mont) & ~loop_done; + z_is_w1_mont = 0 - z_is_w1_mont; // Make it all zeros or all ones. + loop_done |= z_is_w1_mont; + next_iteration |= z_is_w1_mont; // Go to step 4.7 if |z_is_w1_mont|. + + // Step 4.5.3. If z = 1 and the loop is not done, w is composite and we + // may exit in variable time. + if (BN_equal_consttime(z, one_mont) & ~loop_done) { + assert(!next_iteration); + break; + } + } + + if (!next_iteration) { + // Step 4.6. We did not see z = w-1 before z = 1, so w must be composite. + // (For any prime, the value of z immediately preceding 1 must be -1. + // There are no non-trivial square roots of 1 modulo a prime.) + *is_probably_prime = 0; + ret = 1; + goto err; + } + + // Step 4.7 + if (!BN_GENCB_call(cb, 1, i)) { + goto err; + } + } + + assert(uniform_iterations >= (crypto_word_t)iterations); + *is_probably_prime = 1; + ret = 1; err: - BN_CTX_free(ctx_allocated); + BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); return ret; } +int BN_is_prime_ex(const BIGNUM *candidate, int checks, BN_CTX *ctx, BN_GENCB *cb) { + return BN_is_prime_fasttest_ex(candidate, checks, ctx, 0, cb); +} + +int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb) { + int is_probably_prime; + if (!BN_primality_test(&is_probably_prime, a, checks, ctx, do_trial_division, + cb)) { + return -1; + } + return is_probably_prime; +} + int BN_enhanced_miller_rabin_primality_test( enum bn_primality_result_t *out_result, const BIGNUM *w, int iterations, BN_CTX *ctx, BN_GENCB *cb) { @@ -585,10 +858,9 @@ int BN_enhanced_miller_rabin_primality_test( goto err; } - // Montgomery setup for computations mod A - mont = BN_MONT_CTX_new(); - if (mont == NULL || - !BN_MONT_CTX_set(mont, w, ctx)) { + // Montgomery setup for computations mod w + mont = BN_MONT_CTX_new_for_modulus(w, ctx); + if (mont == NULL) { goto err; } @@ -690,11 +962,7 @@ static int probable_prime(BIGNUM *rnd, int bits) { // we now have a random number 'rnd' to test. for (i = 1; i < NUMPRIMES; i++) { - BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); - if (mod == (BN_ULONG)-1) { - return 0; - } - mods[i] = (uint16_t)mod; + mods[i] = bn_mod_u16_consttime(rnd, primes[i]); } // If bits is so small that it fits into a single word then we // additionally don't want to exceed that many bits. @@ -794,11 +1062,7 @@ static int probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, loop: for (i = 1; i < NUMPRIMES; i++) { // check that rnd is a prime - BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); - if (mod == (BN_ULONG)-1) { - goto err; - } - if (mod <= 1) { + if (bn_mod_u16_consttime(rnd, primes[i]) <= 1) { if (!BN_add(rnd, rnd, add)) { goto err; } @@ -870,12 +1134,8 @@ static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd, // check that p and q are prime // check that for p and q // gcd(p-1,primes) == 1 (except for 2) - BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]); - BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]); - if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) { - goto err; - } - if (pmod == 0 || qmod == 0) { + if (bn_mod_u16_consttime(p, primes[i]) == 0 || + bn_mod_u16_consttime(q, primes[i]) == 0) { if (!BN_add(p, p, padd)) { goto err; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/random.c b/Sources/BoringSSL/crypto/fipsmodule/bn/random.c index 61499af47..5922df416 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/random.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/random.c @@ -120,8 +120,6 @@ #include "../rand/internal.h" -static const uint8_t kDefaultAdditionalData[32] = {0}; - int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) { uint8_t *buf = NULL; int ret = 0, bit, bytes, mask; @@ -194,15 +192,16 @@ int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) { return BN_rand(rnd, bits, top, bottom); } -// bn_less_than_word returns one if the number represented by |len| words at |a| -// is less than |b| and zero otherwise. It performs this computation in time -// independent of the value of |a|. |b| is assumed public. -static int bn_less_than_word(const BN_ULONG *a, size_t len, BN_ULONG b) { +// bn_less_than_word_mask returns a mask of all ones if the number represented +// by |len| words at |a| is less than |b| and zero otherwise. It performs this +// computation in time independent of the value of |a|. |b| is assumed public. +static crypto_word_t bn_less_than_word_mask(const BN_ULONG *a, size_t len, + BN_ULONG b) { if (b == 0) { - return 0; + return CONSTTIME_FALSE_W; } if (len == 0) { - return 1; + return CONSTTIME_TRUE_W; } // |a| < |b| iff a[1..len-1] are all zero and a[0] < b. @@ -215,25 +214,19 @@ static int bn_less_than_word(const BN_ULONG *a, size_t len, BN_ULONG b) { // |mask| is now zero iff a[1..len-1] are all zero. mask = constant_time_is_zero_w(mask); mask &= constant_time_lt_w(a[0], b); - return constant_time_select_int(mask, 1, 0); + return mask; } int bn_in_range_words(const BN_ULONG *a, BN_ULONG min_inclusive, const BN_ULONG *max_exclusive, size_t len) { - return bn_less_than_words(a, max_exclusive, len) && - !bn_less_than_word(a, len, min_inclusive); + crypto_word_t mask = ~bn_less_than_word_mask(a, len, min_inclusive); + return mask & bn_less_than_words(a, max_exclusive, len); } -int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive, - const BN_ULONG *max_exclusive, size_t len, - const uint8_t additional_data[32]) { - // This function implements the equivalent of steps 4 through 7 of FIPS 186-4 - // appendices B.4.2 and B.5.2. When called in those contexts, |max_exclusive| - // is n and |min_inclusive| is one. - - // Compute the bit length of |max_exclusive| (step 1), in terms of a number of - // |words| worth of entropy to fill and a mask of bits to clear in the top - // word. +static int bn_range_to_mask(size_t *out_words, BN_ULONG *out_mask, + size_t min_inclusive, const BN_ULONG *max_exclusive, + size_t len) { + // The magnitude of |max_exclusive| is assumed public. size_t words = len; while (words > 0 && max_exclusive[words - 1] == 0) { words--; @@ -254,6 +247,27 @@ int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive, mask |= mask >> 32; #endif + *out_words = words; + *out_mask = mask; + return 1; +} + +int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive, + const BN_ULONG *max_exclusive, size_t len, + const uint8_t additional_data[32]) { + // This function implements the equivalent of steps 4 through 7 of FIPS 186-4 + // appendices B.4.2 and B.5.2. When called in those contexts, |max_exclusive| + // is n and |min_inclusive| is one. + + // Compute the bit length of |max_exclusive| (step 1), in terms of a number of + // |words| worth of entropy to fill and a mask of bits to clear in the top + // word. + size_t words; + BN_ULONG mask; + if (!bn_range_to_mask(&words, &mask, min_inclusive, max_exclusive, len)) { + return 0; + } + // Fill any unused words with zero. OPENSSL_memset(out + words, 0, (len - words) * sizeof(BN_ULONG)); @@ -278,15 +292,53 @@ int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive, int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive, const BIGNUM *max_exclusive) { - if (!bn_wexpand(r, max_exclusive->top) || + static const uint8_t kDefaultAdditionalData[32] = {0}; + if (!bn_wexpand(r, max_exclusive->width) || !bn_rand_range_words(r->d, min_inclusive, max_exclusive->d, - max_exclusive->top, kDefaultAdditionalData)) { + max_exclusive->width, kDefaultAdditionalData)) { return 0; } r->neg = 0; - r->top = max_exclusive->top; - bn_correct_top(r); + r->width = max_exclusive->width; + return 1; +} + +int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive, + const BIGNUM *max_exclusive) { + size_t words; + BN_ULONG mask; + if (!bn_range_to_mask(&words, &mask, min_inclusive, max_exclusive->d, + max_exclusive->width) || + !bn_wexpand(r, words)) { + return 0; + } + + assert(words > 0); + assert(mask != 0); + // The range must be large enough for bit tricks to fix invalid values. + if (words == 1 && min_inclusive > mask >> 1) { + OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE); + return 0; + } + + // Select a uniform random number with num_bits(max_exclusive) bits. + RAND_bytes((uint8_t *)r->d, words * sizeof(BN_ULONG)); + r->d[words - 1] &= mask; + + // Check, in constant-time, if the value is in range. + *out_is_uniform = + bn_in_range_words(r->d, min_inclusive, max_exclusive->d, words); + crypto_word_t in_range = *out_is_uniform; + in_range = 0 - in_range; + + // If the value is not in range, force it to be in range. + r->d[0] |= constant_time_select_w(in_range, 0, min_inclusive); + r->d[words - 1] &= constant_time_select_w(in_range, BN_MASK2, mask >> 1); + assert(bn_in_range_words(r->d, min_inclusive, max_exclusive->d, words)); + + r->neg = 0; + r->width = words; return 1; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.c b/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.c index d0090a663..97c58bad6 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.c @@ -1,44 +1,16 @@ -/***************************************************************************** -* * -* Copyright (c) 2012, Intel Corporation * -* * -* All rights reserved. * -* * -* Redistribution and use in source and binary forms, with or without * -* modification, are permitted provided that the following conditions are * -* met: * -* * -* * Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* * Redistributions in binary form must reproduce the above copyright * -* notice, this list of conditions and the following disclaimer in the * -* documentation and/or other materials provided with the * -* distribution. * -* * -* * Neither the name of the Intel Corporation nor the names of its * -* contributors may be used to endorse or promote products derived from * -* this software without specific prior written permission. * -* * -* * -* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY * -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * -* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR * -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * -* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * -* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * -* * -****************************************************************************** -* Developers and authors: * -* Shay Gueron (1, 2), and Vlad Krasnov (1) * -* (1) Intel Corporation, Israel Development Center, Haifa, Israel * -* (2) University of Haifa, Israel * -*****************************************************************************/ +/* + * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2012, Intel Corporation. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + */ #include @@ -51,204 +23,209 @@ #include "../../internal.h" -/* - * See crypto/bn/asm/rsaz-avx2.pl for further details. - */ -void rsaz_1024_norm2red_avx2(void *red,const void *norm); -void rsaz_1024_mul_avx2(void *ret,const void *a,const void *b,const void *n,BN_ULONG k); -void rsaz_1024_sqr_avx2(void *ret,const void *a,const void *n,BN_ULONG k,int cnt); -void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i); -void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i); -void rsaz_1024_red2norm_avx2(void *norm,const void *red); - -alignas(64) static const BN_ULONG one[40] = - {1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -alignas(64) static const BN_ULONG two80[40] = - {0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +// See crypto/bn/asm/rsaz-avx2.pl for further details. +void rsaz_1024_norm2red_avx2(void *red, const void *norm); +void rsaz_1024_mul_avx2(void *ret, const void *a, const void *b, const void *n, + BN_ULONG k); +void rsaz_1024_sqr_avx2(void *ret, const void *a, const void *n, BN_ULONG k, + int cnt); +void rsaz_1024_scatter5_avx2(void *tbl, const void *val, int i); +void rsaz_1024_gather5_avx2(void *val, const void *tbl, int i); +void rsaz_1024_red2norm_avx2(void *norm, const void *red); + +// one is 1 in RSAZ's representation. +alignas(64) static const BN_ULONG one[40] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +// two80 is 2^80 in RSAZ's representation. Note RSAZ uses base 2^29, so this is +// 2^(29*2 + 22) = 2^80, not 2^(64*2 + 22). +alignas(64) static const BN_ULONG two80[40] = { + 0, 0, 1 << 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16], const BN_ULONG base_norm[16], const BN_ULONG exponent[16], - const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0) -{ - alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */ - unsigned char *a_inv, *m, *result, - *table_s = storage + (320 * 3), - *R2 = table_s; /* borrow */ - int index; - int wvalue; - - if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) { - result = storage; - a_inv = storage + 320; - m = storage + (320 * 2); /* should not cross page */ - } else { - m = storage; /* should not cross page */ - result = storage + 320; - a_inv = storage + (320 * 2); - } - - rsaz_1024_norm2red_avx2(m, m_norm); - rsaz_1024_norm2red_avx2(a_inv, base_norm); - rsaz_1024_norm2red_avx2(R2, RR); - - rsaz_1024_mul_avx2(R2, R2, R2, m, k0); - rsaz_1024_mul_avx2(R2, R2, two80, m, k0); - - /* table[0] = 1 */ - rsaz_1024_mul_avx2(result, R2, one, m, k0); - /* table[1] = a_inv^1 */ - rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0); - - rsaz_1024_scatter5_avx2(table_s,result,0); - rsaz_1024_scatter5_avx2(table_s,a_inv,1); - - /* table[2] = a_inv^2 */ - rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,2); + const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0) { + alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; // 5.5KB + unsigned char *a_inv, *m, *result, *table_s = storage + (320 * 3), + *R2 = table_s; // borrow + if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) { + result = storage; + a_inv = storage + 320; + m = storage + (320 * 2); // should not cross page + } else { + m = storage; // should not cross page + result = storage + 320; + a_inv = storage + (320 * 2); + } + + rsaz_1024_norm2red_avx2(m, m_norm); + rsaz_1024_norm2red_avx2(a_inv, base_norm); + rsaz_1024_norm2red_avx2(R2, RR); + + // Convert |R2| from the usual radix, giving R = 2^1024, to RSAZ's radix, + // giving R = 2^(36*29) = 2^1044. + rsaz_1024_mul_avx2(R2, R2, R2, m, k0); + // R2 = 2^2048 * 2^2048 / 2^1044 = 2^3052 + rsaz_1024_mul_avx2(R2, R2, two80, m, k0); + // R2 = 2^3052 * 2^80 / 2^1044 = 2^2088 = (2^1044)^2 + + // table[0] = 1 + rsaz_1024_mul_avx2(result, R2, one, m, k0); + // table[1] = a_inv^1 + rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0); + + rsaz_1024_scatter5_avx2(table_s, result, 0); + rsaz_1024_scatter5_avx2(table_s, a_inv, 1); + + // table[2] = a_inv^2 + rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 2); #if 0 - /* this is almost 2x smaller and less than 1% slower */ - for (index=3; index<32; index++) { - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,index); - } + // This is almost 2x smaller and less than 1% slower. + for (int index = 3; index < 32; index++) { + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, index); + } #else - /* table[4] = a_inv^4 */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,4); - /* table[8] = a_inv^8 */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,8); - /* table[16] = a_inv^16 */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,16); - /* table[17] = a_inv^17 */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,17); - - /* table[3] */ - rsaz_1024_gather5_avx2(result,table_s,2); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,3); - /* table[6] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,6); - /* table[12] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,12); - /* table[24] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,24); - /* table[25] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,25); - - /* table[5] */ - rsaz_1024_gather5_avx2(result,table_s,4); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,5); - /* table[10] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,10); - /* table[20] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,20); - /* table[21] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,21); - - /* table[7] */ - rsaz_1024_gather5_avx2(result,table_s,6); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,7); - /* table[14] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,14); - /* table[28] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,28); - /* table[29] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,29); - - /* table[9] */ - rsaz_1024_gather5_avx2(result,table_s,8); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,9); - /* table[18] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,18); - /* table[19] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,19); - - /* table[11] */ - rsaz_1024_gather5_avx2(result,table_s,10); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,11); - /* table[22] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,22); - /* table[23] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,23); - - /* table[13] */ - rsaz_1024_gather5_avx2(result,table_s,12); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,13); - /* table[26] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,26); - /* table[27] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,27); - - /* table[15] */ - rsaz_1024_gather5_avx2(result,table_s,14); - rsaz_1024_mul_avx2(result,result,a_inv,m,k0); - rsaz_1024_scatter5_avx2(table_s,result,15); - /* table[30] */ - rsaz_1024_sqr_avx2(result, result, m, k0, 1); - rsaz_1024_scatter5_avx2(table_s,result,30); - /* table[31] */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - rsaz_1024_scatter5_avx2(table_s,result,31); + // table[4] = a_inv^4 + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 4); + // table[8] = a_inv^8 + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 8); + // table[16] = a_inv^16 + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 16); + // table[17] = a_inv^17 + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 17); + + // table[3] + rsaz_1024_gather5_avx2(result, table_s, 2); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 3); + // table[6] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 6); + // table[12] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 12); + // table[24] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 24); + // table[25] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 25); + + // table[5] + rsaz_1024_gather5_avx2(result, table_s, 4); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 5); + // table[10] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 10); + // table[20] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 20); + // table[21] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 21); + + // table[7] + rsaz_1024_gather5_avx2(result, table_s, 6); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 7); + // table[14] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 14); + // table[28] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 28); + // table[29] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 29); + + // table[9] + rsaz_1024_gather5_avx2(result, table_s, 8); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 9); + // table[18] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 18); + // table[19] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 19); + + // table[11] + rsaz_1024_gather5_avx2(result, table_s, 10); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 11); + // table[22] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 22); + // table[23] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 23); + + // table[13] + rsaz_1024_gather5_avx2(result, table_s, 12); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 13); + // table[26] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 26); + // table[27] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 27); + + // table[15] + rsaz_1024_gather5_avx2(result, table_s, 14); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 15); + // table[30] + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 30); + // table[31] + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 31); #endif - const uint8_t *p_str = (const uint8_t *)exponent; - - /* load first window */ - wvalue = p_str[127] >> 3; - rsaz_1024_gather5_avx2(result,table_s,wvalue); + const uint8_t *p_str = (const uint8_t *)exponent; - index = 1014; + // load first window + int wvalue = p_str[127] >> 3; + rsaz_1024_gather5_avx2(result, table_s, wvalue); - while(index > -1) { /* loop for the remaining 127 windows */ + int index = 1014; + while (index > -1) { // Loop for the remaining 127 windows. - rsaz_1024_sqr_avx2(result, result, m, k0, 5); + rsaz_1024_sqr_avx2(result, result, m, k0, 5); - wvalue = *((const unsigned short*)&p_str[index / 8]); - wvalue = (wvalue>> (index%8)) & 31; - index-=5; + uint16_t wvalue_16; + memcpy(&wvalue_16, &p_str[index / 8], sizeof(wvalue_16)); + wvalue = wvalue_16; + wvalue = (wvalue >> (index % 8)) & 31; + index -= 5; - rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - } + rsaz_1024_gather5_avx2(a_inv, table_s, wvalue); // Borrow |a_inv|. + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + } - /* square four times */ - rsaz_1024_sqr_avx2(result, result, m, k0, 4); + // Square four times. + rsaz_1024_sqr_avx2(result, result, m, k0, 4); - wvalue = p_str[0] & 15; + wvalue = p_str[0] & 15; - rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */ - rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_gather5_avx2(a_inv, table_s, wvalue); // Borrow |a_inv|. + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); - /* from Montgomery */ - rsaz_1024_mul_avx2(result, result, one, m, k0); + // Convert from Montgomery. + rsaz_1024_mul_avx2(result, result, one, m, k0); - rsaz_1024_red2norm_avx2(result_norm, result); + rsaz_1024_red2norm_avx2(result_norm, result); - OPENSSL_cleanse(storage,sizeof(storage)); + OPENSSL_cleanse(storage, sizeof(storage)); } -#endif /* OPENSSL_X86_64 */ +#endif // OPENSSL_X86_64 diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.h b/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.h index 4a8967c39..af973a5c7 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.h +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/rsaz_exp.h @@ -1,53 +1,33 @@ -/***************************************************************************** -* * -* Copyright (c) 2012, Intel Corporation * -* * -* All rights reserved. * -* * -* Redistribution and use in source and binary forms, with or without * -* modification, are permitted provided that the following conditions are * -* met: * -* * -* * Redistributions of source code must retain the above copyright * -* notice, this list of conditions and the following disclaimer. * -* * -* * Redistributions in binary form must reproduce the above copyright * -* notice, this list of conditions and the following disclaimer in the * -* documentation and/or other materials provided with the * -* distribution. * -* * -* * Neither the name of the Intel Corporation nor the names of its * -* contributors may be used to endorse or promote products derived from * -* this software without specific prior written permission. * -* * -* * -* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY * -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * -* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR * -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * -* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * -* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * -* * -****************************************************************************** -* Developers and authors: * -* Shay Gueron (1, 2), and Vlad Krasnov (1) * -* (1) Intel Corporation, Israel Development Center, Haifa, Israel * -* (2) University of Haifa, Israel * -*****************************************************************************/ +/* + * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2012, Intel Corporation. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + */ -#ifndef RSAZ_EXP_H -#define RSAZ_EXP_H +#ifndef OPENSSL_HEADER_BN_RSAZ_EXP_H +#define OPENSSL_HEADER_BN_RSAZ_EXP_H #include -void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16], - const BN_ULONG base_norm[16], const BN_ULONG exponent[16], - const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0); +// RSAZ_1024_mod_exp_avx2 sets |result| to |base_norm| raised to |exponent| +// modulo |m_norm|. |base_norm| must be fully-reduced and |exponent| must have +// the high bit set (it is 1024 bits wide). |RR| and |k0| must be |RR| and |n0|, +// respectively, extracted from |m_norm|'s |BN_MONT_CTX|. +void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16], const BN_ULONG base_norm[16], + const BN_ULONG exponent[16], + const BN_ULONG m_norm[16], const BN_ULONG RR[16], + BN_ULONG k0); + +// rsaz_avx2_eligible returns one if |RSAZ_1024_mod_exp_avx2| should be used and +// zero otherwise. int rsaz_avx2_eligible(void); -#endif +#endif // OPENSSL_HEADER_BN_RSAZ_EXP_H diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/shift.c b/Sources/BoringSSL/crypto/fipsmodule/bn/shift.c index d4ed79e44..3e7173960 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/shift.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/shift.c @@ -59,6 +59,7 @@ #include #include +#include #include "internal.h" @@ -75,28 +76,28 @@ int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) { r->neg = a->neg; nw = n / BN_BITS2; - if (!bn_wexpand(r, a->top + nw + 1)) { + if (!bn_wexpand(r, a->width + nw + 1)) { return 0; } lb = n % BN_BITS2; rb = BN_BITS2 - lb; f = a->d; t = r->d; - t[a->top + nw] = 0; + t[a->width + nw] = 0; if (lb == 0) { - for (i = a->top - 1; i >= 0; i--) { + for (i = a->width - 1; i >= 0; i--) { t[nw + i] = f[i]; } } else { - for (i = a->top - 1; i >= 0; i--) { + for (i = a->width - 1; i >= 0; i--) { l = f[i]; t[nw + i + 1] |= l >> rb; t[nw + i] = l << lb; } } OPENSSL_memset(t, 0, nw * sizeof(t[0])); - r->top = a->top + nw + 1; - bn_correct_top(r); + r->width = a->width + nw + 1; + bn_set_minimal_width(r); return 1; } @@ -107,123 +108,113 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a) { if (r != a) { r->neg = a->neg; - if (!bn_wexpand(r, a->top + 1)) { + if (!bn_wexpand(r, a->width + 1)) { return 0; } - r->top = a->top; + r->width = a->width; } else { - if (!bn_wexpand(r, a->top + 1)) { + if (!bn_wexpand(r, a->width + 1)) { return 0; } } ap = a->d; rp = r->d; c = 0; - for (i = 0; i < a->top; i++) { + for (i = 0; i < a->width; i++) { t = *(ap++); *(rp++) = (t << 1) | c; c = t >> (BN_BITS2 - 1); } if (c) { *rp = 1; - r->top++; + r->width++; } return 1; } -int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) { - int i, j, nw, lb, rb; - BN_ULONG *t, *f; - BN_ULONG l, tmp; +static void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift, + size_t num) { + unsigned shift_bits = shift % BN_BITS2; + size_t shift_words = shift / BN_BITS2; + if (shift_words >= num) { + OPENSSL_memset(r, 0, num * sizeof(BN_ULONG)); + return; + } + if (shift_bits == 0) { + OPENSSL_memmove(r, a + shift_words, (num - shift_words) * sizeof(BN_ULONG)); + } else { + for (size_t i = shift_words; i < num - 1; i++) { + r[i - shift_words] = + (a[i] >> shift_bits) | (a[i + 1] << (BN_BITS2 - shift_bits)); + } + r[num - 1 - shift_words] = a[num - 1] >> shift_bits; + } + OPENSSL_memset(r + num - shift_words, 0, shift_words * sizeof(BN_ULONG)); +} +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) { if (n < 0) { OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); return 0; } - nw = n / BN_BITS2; - rb = n % BN_BITS2; - lb = BN_BITS2 - rb; - if (nw >= a->top || a->top == 0) { - BN_zero(r); - return 1; - } - i = (BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2; - if (r != a) { - r->neg = a->neg; - if (!bn_wexpand(r, i)) { - return 0; - } - } else { - if (n == 0) { - return 1; // or the copying loop will go berserk - } + if (!bn_wexpand(r, a->width)) { + return 0; } + bn_rshift_words(r->d, a->d, n, a->width); + r->neg = a->neg; + r->width = a->width; + bn_set_minimal_width(r); + return 1; +} - f = &(a->d[nw]); - t = r->d; - j = a->top - nw; - r->top = i; - - if (rb == 0) { - for (i = j; i != 0; i--) { - *(t++) = *(f++); - } - } else { - l = *(f++); - for (i = j - 1; i != 0; i--) { - tmp = l >> rb; - l = *(f++); - *(t++) = tmp | (l << lb); - } - l >>= rb; - if (l) { - *(t) = l; - } +int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a, unsigned n, + BN_CTX *ctx) { + int ret = 0; + BN_CTX_start(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); + if (tmp == NULL || + !BN_copy(r, a) || + !bn_wexpand(tmp, r->width)) { + goto err; } - if (r->top == 0) { - r->neg = 0; + // Shift conditionally by powers of two. + unsigned max_bits = BN_BITS2 * r->width; + for (unsigned i = 0; (max_bits >> i) != 0; i++) { + BN_ULONG mask = (n >> i) & 1; + mask = 0 - mask; + bn_rshift_words(tmp->d, r->d, 1u << i, r->width); + bn_select_words(r->d, mask, tmp->d /* apply shift */, + r->d /* ignore shift */, r->width); } - return 1; -} + ret = 1; -int BN_rshift1(BIGNUM *r, const BIGNUM *a) { - BN_ULONG *ap, *rp, t, c; - int i, j; +err: + BN_CTX_end(ctx); + return ret; +} - if (BN_is_zero(a)) { - BN_zero(r); - return 1; - } - i = a->top; - ap = a->d; - j = i - (ap[i - 1] == 1); - if (a != r) { - if (!bn_wexpand(r, j)) { - return 0; - } - r->neg = a->neg; - } - rp = r->d; - t = ap[--i]; - c = t << (BN_BITS2 - 1); - if (t >>= 1) { - rp[i] = t; +void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num) { + if (num == 0) { + return; } - while (i > 0) { - t = ap[--i]; - rp[i] = (t >> 1) | c; - c = t << (BN_BITS2 - 1); + for (size_t i = 0; i < num - 1; i++) { + r[i] = (a[i] >> 1) | (a[i + 1] << (BN_BITS2 - 1)); } - r->top = j; + r[num - 1] = a[num - 1] >> 1; +} - if (r->top == 0) { - r->neg = 0; +int BN_rshift1(BIGNUM *r, const BIGNUM *a) { + if (!bn_wexpand(r, a->width)) { + return 0; } - + bn_rshift1_words(r->d, a->d, a->width); + r->width = a->width; + r->neg = a->neg; + bn_set_minimal_width(r); return 1; } @@ -234,14 +225,14 @@ int BN_set_bit(BIGNUM *a, int n) { int i = n / BN_BITS2; int j = n % BN_BITS2; - if (a->top <= i) { + if (a->width <= i) { if (!bn_wexpand(a, i + 1)) { return 0; } - for (int k = a->top; k < i + 1; k++) { + for (int k = a->width; k < i + 1; k++) { a->d[k] = 0; } - a->top = i + 1; + a->width = i + 1; } a->d[i] |= (((BN_ULONG)1) << j); @@ -258,12 +249,12 @@ int BN_clear_bit(BIGNUM *a, int n) { i = n / BN_BITS2; j = n % BN_BITS2; - if (a->top <= i) { + if (a->width <= i) { return 0; } a->d[i] &= (~(((BN_ULONG)1) << j)); - bn_correct_top(a); + bn_set_minimal_width(a); return 1; } @@ -280,7 +271,7 @@ int BN_is_bit_set(const BIGNUM *a, int n) { if (n < 0) { return 0; } - return bn_is_bit_set_words(a->d, a->top, n); + return bn_is_bit_set_words(a->d, a->width, n); } int BN_mask_bits(BIGNUM *a, int n) { @@ -290,16 +281,84 @@ int BN_mask_bits(BIGNUM *a, int n) { int w = n / BN_BITS2; int b = n % BN_BITS2; - if (w >= a->top) { - return 0; + if (w >= a->width) { + return 1; } if (b == 0) { - a->top = w; + a->width = w; } else { - a->top = w + 1; + a->width = w + 1; a->d[w] &= ~(BN_MASK2 << b); } - bn_correct_top(a); + bn_set_minimal_width(a); return 1; } + +static int bn_count_low_zero_bits_word(BN_ULONG l) { + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), + crypto_word_t_too_small); + OPENSSL_COMPILE_ASSERT(sizeof(int) <= sizeof(crypto_word_t), + crypto_word_t_too_small_2); + OPENSSL_COMPILE_ASSERT(BN_BITS2 == sizeof(BN_ULONG) * 8, + bn_ulong_has_padding_bits); + // C has very bizarre rules for types smaller than an int. + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) >= sizeof(int), + bn_ulong_is_promoted_to_int); + + crypto_word_t mask; + int bits = 0; + +#if BN_BITS2 > 32 + // Check if the lower half of |x| are all zero. + mask = constant_time_is_zero_w(l << (BN_BITS2 - 32)); + // If the lower half is all zeros, it is included in the bit count and we + // count the upper half. Otherwise, we count the lower half. + bits += 32 & mask; + l = constant_time_select_w(mask, l >> 32, l); +#endif + + // The remaining blocks are analogous iterations at lower powers of two. + mask = constant_time_is_zero_w(l << (BN_BITS2 - 16)); + bits += 16 & mask; + l = constant_time_select_w(mask, l >> 16, l); + + mask = constant_time_is_zero_w(l << (BN_BITS2 - 8)); + bits += 8 & mask; + l = constant_time_select_w(mask, l >> 8, l); + + mask = constant_time_is_zero_w(l << (BN_BITS2 - 4)); + bits += 4 & mask; + l = constant_time_select_w(mask, l >> 4, l); + + mask = constant_time_is_zero_w(l << (BN_BITS2 - 2)); + bits += 2 & mask; + l = constant_time_select_w(mask, l >> 2, l); + + mask = constant_time_is_zero_w(l << (BN_BITS2 - 1)); + bits += 1 & mask; + + return bits; +} + +int BN_count_low_zero_bits(const BIGNUM *bn) { + OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t), + crypto_word_t_too_small); + OPENSSL_COMPILE_ASSERT(sizeof(int) <= sizeof(crypto_word_t), + crypto_word_t_too_small_2); + + int ret = 0; + crypto_word_t saw_nonzero = 0; + for (int i = 0; i < bn->width; i++) { + crypto_word_t nonzero = ~constant_time_is_zero_w(bn->d[i]); + crypto_word_t first_nonzero = ~saw_nonzero & nonzero; + saw_nonzero |= nonzero; + + int bits = bn_count_low_zero_bits_word(bn->d[i]); + ret |= first_nonzero & (i * BN_BITS2 + bits); + } + + // If got to the end of |bn| and saw no non-zero words, |bn| is zero. |ret| + // will then remain zero. + return ret; +} diff --git a/Sources/BoringSSL/crypto/fipsmodule/bn/sqrt.c b/Sources/BoringSSL/crypto/fipsmodule/bn/sqrt.c index 68ccb9199..23417d140 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/bn/sqrt.c +++ b/Sources/BoringSSL/crypto/fipsmodule/bn/sqrt.c @@ -184,7 +184,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { // November 1992.) // t := 2*a - if (!BN_mod_lshift1_quick(t, A, p)) { + if (!bn_mod_lshift1_consttime(t, A, p, ctx)) { goto end; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/cipher/e_aes.c b/Sources/BoringSSL/crypto/fipsmodule/cipher/e_aes.c index b46927675..8377f0c1d 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/cipher/e_aes.c +++ b/Sources/BoringSSL/crypto/fipsmodule/cipher/e_aes.c @@ -1148,7 +1148,7 @@ struct aead_aes_gcm_ctx { struct aead_aes_gcm_tls12_ctx { struct aead_aes_gcm_ctx gcm_ctx; - uint64_t counter; + uint64_t min_next_nonce; }; static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx, @@ -1349,7 +1349,7 @@ static int aead_aes_gcm_tls12_init(EVP_AEAD_CTX *ctx, const uint8_t *key, return 0; } - gcm_ctx->counter = 0; + gcm_ctx->min_next_nonce = 0; size_t actual_tag_len; if (!aead_aes_gcm_init_impl(&gcm_ctx->gcm_ctx, &actual_tag_len, key, key_len, @@ -1373,23 +1373,23 @@ static int aead_aes_gcm_tls12_seal_scatter( size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in, size_t extra_in_len, const uint8_t *ad, size_t ad_len) { struct aead_aes_gcm_tls12_ctx *gcm_ctx = ctx->aead_state; - if (gcm_ctx->counter == UINT64_MAX) { - OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE); - return 0; - } - if (nonce_len != 12) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); return 0; } - const uint64_t be_counter = CRYPTO_bswap8(gcm_ctx->counter); - if (OPENSSL_memcmp((uint8_t *)&be_counter, nonce + nonce_len - 8, 8) != 0) { + // The given nonces must be strictly monotonically increasing. + uint64_t given_counter; + OPENSSL_memcpy(&given_counter, nonce + nonce_len - sizeof(given_counter), + sizeof(given_counter)); + given_counter = CRYPTO_bswap8(given_counter); + if (given_counter == UINT64_MAX || + given_counter < gcm_ctx->min_next_nonce) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE); return 0; } - gcm_ctx->counter++; + gcm_ctx->min_next_nonce = given_counter + 1; return aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len, max_out_tag_len, nonce, nonce_len, in, diff --git a/Sources/BoringSSL/crypto/fipsmodule/des/internal.h b/Sources/BoringSSL/crypto/fipsmodule/des/internal.h index 4d65ff1d0..1ae3f22a3 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/des/internal.h +++ b/Sources/BoringSSL/crypto/fipsmodule/des/internal.h @@ -59,6 +59,8 @@ #include +#include "../../internal.h" + #if defined(__cplusplus) extern "C" { #endif diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/ec.c b/Sources/BoringSSL/crypto/fipsmodule/ec/ec.c index 977cd265a..904466af3 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/ec.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/ec.c @@ -215,13 +215,6 @@ static const uint8_t kP521Params[6 * 66] = { 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09, }; -// MSan appears to have a bug that causes code to be miscompiled in opt mode. -// While that is being looked at, don't run the uint128_t code under MSan. -#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \ - !defined(MEMORY_SANITIZER) -#define BORINGSSL_USE_INT128_CODE -#endif - DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) { // 1.3.132.0.35 static const uint8_t kOIDP521[] = {0x2b, 0x81, 0x04, 0x00, 0x23}; @@ -253,16 +246,12 @@ DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) { out->curves[2].param_len = 32; out->curves[2].params = kP256Params; out->curves[2].method = -#if defined(BORINGSSL_USE_INT128_CODE) #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ !defined(OPENSSL_SMALL) EC_GFp_nistz256_method(); #else EC_GFp_nistp256_method(); #endif -#else - EC_GFp_mont_method(); -#endif // 1.3.132.0.33 static const uint8_t kOIDP224[] = {0x2b, 0x81, 0x04, 0x00, 0x21}; @@ -273,7 +262,7 @@ DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) { out->curves[3].param_len = 28; out->curves[3].params = kP224Params; out->curves[3].method = -#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL) +#if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL) EC_GFp_nistp224_method(); #else EC_GFp_mont_method(); @@ -398,11 +387,12 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, EC_POINT_free(copy); return 0; } + // Store the order in minimal form, so it can be used with |BN_ULONG| arrays. + bn_set_minimal_width(&group->order); BN_MONT_CTX_free(group->order_mont); - group->order_mont = BN_MONT_CTX_new(); - if (group->order_mont == NULL || - !BN_MONT_CTX_set(group->order_mont, &group->order, NULL)) { + group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL); + if (group->order_mont == NULL) { return 0; } @@ -459,9 +449,8 @@ static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) { goto err; } - group->order_mont = BN_MONT_CTX_new(); - if (group->order_mont == NULL || - !BN_MONT_CTX_set(group->order_mont, &group->order, ctx)) { + group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx); + if (group->order_mont == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } @@ -779,6 +768,15 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, } if (!EC_POINT_is_on_curve(group, point, ctx)) { + // In the event of an error, defend against the caller not checking the + // return value by setting a known safe value: the base point. + const EC_POINT *generator = EC_GROUP_get0_generator(group); + // The generator can be missing if the caller is in the process of + // constructing an arbitrary group. In this, we give up and hope they're + // checking the return value. + if (generator) { + EC_POINT_copy(point, generator); + } OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); return 0; } @@ -817,6 +815,25 @@ int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { return ec_GFp_simple_invert(group, a, ctx); } +static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out, + const BIGNUM *in, BN_CTX *ctx) { + if (ec_bignum_to_scalar(group, out, in)) { + return 1; + } + + ERR_clear_error(); + + // This is an unusual input, so we do not guarantee constant-time processing. + const BIGNUM *order = &group->order; + BN_CTX_start(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); + int ok = tmp != NULL && + BN_nnmod(tmp, in, order, ctx) && + ec_bignum_to_scalar_unchecked(group, out, tmp); + BN_CTX_end(ctx); + return ok; +} + int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { // Previously, this function set |r| to the point at infinity if there was @@ -828,30 +845,27 @@ int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, return 0; } - // We cannot easily process arbitrary scalars in constant-time, and there is - // no need to do so. Require that scalars be the same size as the order. - // - // One could require they be fully reduced, but some consumers try to check - // that |order| * |pubkey| is the identity. This comes from following NIST SP - // 800-56A section 5.6.2.3.2. (Though all our curves have cofactor one, so - // this check isn't useful.) int ret = 0; EC_SCALAR g_scalar_storage, p_scalar_storage; EC_SCALAR *g_scalar_arg = NULL, *p_scalar_arg = NULL; - unsigned order_bits = BN_num_bits(&group->order); + BN_CTX *new_ctx = NULL; + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + goto err; + } + ctx = new_ctx; + } + if (g_scalar != NULL) { - if (BN_is_negative(g_scalar) || BN_num_bits(g_scalar) > order_bits || - !ec_bignum_to_scalar(group, &g_scalar_storage, g_scalar)) { - OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR); + if (!arbitrary_bignum_to_scalar(group, &g_scalar_storage, g_scalar, ctx)) { goto err; } g_scalar_arg = &g_scalar_storage; } if (p_scalar != NULL) { - if (BN_is_negative(p_scalar) || BN_num_bits(p_scalar) > order_bits || - !ec_bignum_to_scalar(group, &p_scalar_storage, p_scalar)) { - OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR); + if (!arbitrary_bignum_to_scalar(group, &p_scalar_storage, p_scalar, ctx)) { goto err; } p_scalar_arg = &p_scalar_storage; @@ -860,14 +874,15 @@ int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, ret = ec_point_mul_scalar(group, r, g_scalar_arg, p, p_scalar_arg, ctx); err: + BN_CTX_free(new_ctx); OPENSSL_cleanse(&g_scalar_storage, sizeof(g_scalar_storage)); OPENSSL_cleanse(&p_scalar_storage, sizeof(p_scalar_storage)); return ret; } -int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r, - const EC_SCALAR *g_scalar, const EC_POINT *p, - const EC_SCALAR *p_scalar, BN_CTX *ctx) { +int ec_point_mul_scalar_public(const EC_GROUP *group, EC_POINT *r, + const EC_SCALAR *g_scalar, const EC_POINT *p, + const EC_SCALAR *p_scalar, BN_CTX *ctx) { if ((g_scalar == NULL && p_scalar == NULL) || (p == NULL) != (p_scalar == NULL)) { OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); @@ -880,19 +895,25 @@ int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r, return 0; } - return group->meth->mul(group, r, g_scalar, p, p_scalar, ctx); + return group->meth->mul_public(group, r, g_scalar, p, p_scalar, ctx); } -int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, - EC_POINT *point, const BIGNUM *x, - const BIGNUM *y, const BIGNUM *z, - BN_CTX *ctx) { - if (EC_GROUP_cmp(group, point->group, NULL) != 0) { +int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r, + const EC_SCALAR *g_scalar, const EC_POINT *p, + const EC_SCALAR *p_scalar, BN_CTX *ctx) { + if ((g_scalar == NULL && p_scalar == NULL) || + (p == NULL) != (p_scalar == NULL)) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (EC_GROUP_cmp(group, r->group, NULL) != 0 || + (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) { OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } - return ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, x, y, z, - ctx); + + return group->meth->mul(group, r, g_scalar, p, p_scalar, ctx); } void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {} @@ -927,17 +948,27 @@ size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out, const BIGNUM *in) { - if (BN_is_negative(in) || in->top > group->order.top) { + if (!ec_bignum_to_scalar_unchecked(group, out, in)) { + return 0; + } + if (!bn_less_than_words(out->words, group->order.d, group->order.width)) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR); + return 0; + } + return 1; +} + +int ec_bignum_to_scalar_unchecked(const EC_GROUP *group, EC_SCALAR *out, + const BIGNUM *in) { + if (!bn_copy_words(out->words, group->order.width, in)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR); return 0; } - OPENSSL_memset(out->words, 0, group->order.top * sizeof(BN_ULONG)); - OPENSSL_memcpy(out->words, in->d, in->top * sizeof(BN_ULONG)); return 1; } int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out, const uint8_t additional_data[32]) { - return bn_rand_range_words(out->words, 1, group->order.d, group->order.top, + return bn_rand_range_words(out->words, 1, group->order.d, group->order.width, additional_data); } diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/ec_key.c b/Sources/BoringSSL/crypto/fipsmodule/ec/ec_key.c index bba4402bc..a6d469767 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/ec_key.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/ec_key.c @@ -84,6 +84,25 @@ DEFINE_STATIC_EX_DATA_CLASS(g_ec_ex_data_class); +static EC_WRAPPED_SCALAR *ec_wrapped_scalar_new(const EC_GROUP *group) { + EC_WRAPPED_SCALAR *wrapped = OPENSSL_malloc(sizeof(EC_WRAPPED_SCALAR)); + if (wrapped == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + + OPENSSL_memset(wrapped, 0, sizeof(EC_WRAPPED_SCALAR)); + wrapped->bignum.d = wrapped->scalar.words; + wrapped->bignum.width = group->order.width; + wrapped->bignum.dmax = group->order.width; + wrapped->bignum.flags = BN_FLG_STATIC_DATA; + return wrapped; +} + +static void ec_wrapped_scalar_free(EC_WRAPPED_SCALAR *scalar) { + OPENSSL_free(scalar); +} + EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } EC_KEY *EC_KEY_new_method(const ENGINE *engine) { @@ -151,7 +170,7 @@ void EC_KEY_free(EC_KEY *r) { EC_GROUP_free(r->group); EC_POINT_free(r->pub_key); - BN_clear_free(r->priv_key); + ec_wrapped_scalar_free(r->priv_key); BN_free(r->fixed_k); CRYPTO_free_ex_data(g_ec_ex_data_class_bss_get(), r, &r->ex_data); @@ -159,65 +178,29 @@ void EC_KEY_free(EC_KEY *r) { OPENSSL_free(r); } -EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { - if (dest == NULL || src == NULL) { +EC_KEY *EC_KEY_dup(const EC_KEY *src) { + if (src == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return NULL; } - // Copy the parameters. - if (src->group) { - // TODO(fork): duplicating the group seems wasteful. - EC_GROUP_free(dest->group); - dest->group = EC_GROUP_dup(src->group); - if (dest->group == NULL) { - return NULL; - } - } - - // Copy the public key. - if (src->pub_key && src->group) { - EC_POINT_free(dest->pub_key); - dest->pub_key = EC_POINT_dup(src->pub_key, src->group); - if (dest->pub_key == NULL) { - return NULL; - } - } - // copy the private key - if (src->priv_key) { - if (dest->priv_key == NULL) { - dest->priv_key = BN_new(); - if (dest->priv_key == NULL) { - return NULL; - } - } - if (!BN_copy(dest->priv_key, src->priv_key)) { - return NULL; - } - } - // copy method/extra data - if (src->ecdsa_meth) { - METHOD_unref(dest->ecdsa_meth); - dest->ecdsa_meth = src->ecdsa_meth; - METHOD_ref(dest->ecdsa_meth); - } - - // copy the rest - dest->enc_flag = src->enc_flag; - dest->conv_form = src->conv_form; - - return dest; -} - -EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) { EC_KEY *ret = EC_KEY_new(); if (ret == NULL) { return NULL; } - if (EC_KEY_copy(ret, ec_key) == NULL) { + + if ((src->group != NULL && + !EC_KEY_set_group(ret, src->group)) || + (src->pub_key != NULL && + !EC_KEY_set_public_key(ret, src->pub_key)) || + (src->priv_key != NULL && + !EC_KEY_set_private_key(ret, EC_KEY_get0_private_key(src)))) { EC_KEY_free(ret); return NULL; } + + ret->enc_flag = src->enc_flag; + ret->conv_form = src->conv_form; return ret; } @@ -233,35 +216,45 @@ int EC_KEY_is_opaque(const EC_KEY *key) { const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; } int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + // If |key| already has a group, it is an error to switch to another one. + if (key->group != NULL) { + if (EC_GROUP_cmp(key->group, group, NULL) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); + return 0; + } + return 1; + } + + assert(key->priv_key == NULL); + assert(key->pub_key == NULL); + EC_GROUP_free(key->group); - // TODO(fork): duplicating the group seems wasteful but see - // |EC_KEY_set_conv_form|. key->group = EC_GROUP_dup(group); - if (key->group == NULL) { - return 0; - } - // XXX: |BN_cmp| is not constant time. - if (key->priv_key != NULL && - BN_cmp(key->priv_key, EC_GROUP_get0_order(group)) >= 0) { - return 0; - } - return 1; + return key->group != NULL; } const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) { - return key->priv_key; + return key->priv_key != NULL ? &key->priv_key->bignum : NULL; } int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) { - // XXX: |BN_cmp| is not constant time. - if (key->group != NULL && - BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0) { + if (key->group == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); + return 0; + } + + EC_WRAPPED_SCALAR *scalar = ec_wrapped_scalar_new(key->group); + if (scalar == NULL) { + return 0; + } + if (!ec_bignum_to_scalar(key->group, &scalar->scalar, priv_key)) { OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + ec_wrapped_scalar_free(scalar); return 0; } - BN_clear_free(key->priv_key); - key->priv_key = BN_dup(priv_key); - return (key->priv_key == NULL) ? 0 : 1; + ec_wrapped_scalar_free(key->priv_key); + key->priv_key = scalar; + return 1; } const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { @@ -269,6 +262,16 @@ const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { } int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) { + if (key->group == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); + return 0; + } + + if (EC_GROUP_cmp(key->group, pub_key->group, NULL) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); + return 0; + } + EC_POINT_free(key->pub_key); key->pub_key = EC_POINT_dup(pub_key, key->group); return (key->pub_key == NULL) ? 0 : 1; @@ -316,15 +319,11 @@ int EC_KEY_check_key(const EC_KEY *eckey) { } // in case the priv_key is present : // check if generator * priv_key == pub_key - if (eckey->priv_key) { - // XXX: |BN_cmp| is not constant time. - if (BN_cmp(eckey->priv_key, EC_GROUP_get0_order(eckey->group)) >= 0) { - OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); - goto err; - } + if (eckey->priv_key != NULL) { point = EC_POINT_new(eckey->group); if (point == NULL || - !EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { + !ec_point_mul_scalar(eckey->group, point, &eckey->priv_key->scalar, + NULL, NULL, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } @@ -372,8 +371,6 @@ int EC_KEY_check_fips(const EC_KEY *key) { int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) { - BN_CTX *ctx = NULL; - BIGNUM *tx, *ty; EC_POINT *point = NULL; int ok = 0; @@ -381,114 +378,53 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } - ctx = BN_CTX_new(); - if (ctx == NULL) { - return 0; - } - - BN_CTX_start(ctx); point = EC_POINT_new(key->group); - - if (point == NULL) { - goto err; - } - - tx = BN_CTX_get(ctx); - ty = BN_CTX_get(ctx); - if (tx == NULL || - ty == NULL) { - goto err; - } - - if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) || - !EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) { - goto err; - } - - // Check if retrieved coordinates match originals: if not values - // are out of range. - if (BN_cmp(x, tx) || BN_cmp(y, ty)) { - OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); - goto err; - } - - if (!EC_KEY_set_public_key(key, point)) { - goto err; - } - - if (EC_KEY_check_key(key) == 0) { + if (point == NULL || + !EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, NULL) || + !EC_KEY_set_public_key(key, point) || + !EC_KEY_check_key(key)) { goto err; } ok = 1; err: - BN_CTX_end(ctx); - BN_CTX_free(ctx); EC_POINT_free(point); return ok; } -int EC_KEY_generate_key(EC_KEY *eckey) { - int ok = 0; - BIGNUM *priv_key = NULL; - EC_POINT *pub_key = NULL; - - if (!eckey || !eckey->group) { +int EC_KEY_generate_key(EC_KEY *key) { + if (key == NULL || key->group == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if (eckey->priv_key == NULL) { - priv_key = BN_new(); - if (priv_key == NULL) { - goto err; - } - } else { - priv_key = eckey->priv_key; - } - - const BIGNUM *order = EC_GROUP_get0_order(eckey->group); - - // Check that the size of the group order is FIPS compliant (FIPS 186-4 - // B.4.2). - if (BN_num_bits(order) < 160) { + // Check that the group order is FIPS compliant (FIPS 186-4 B.4.2). + if (BN_num_bits(EC_GROUP_get0_order(key->group)) < 160) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER); - goto err; - } - - // Generate the private key by testing candidates (FIPS 186-4 B.4.2). - if (!BN_rand_range_ex(priv_key, 1, order)) { - goto err; - } - - if (eckey->pub_key == NULL) { - pub_key = EC_POINT_new(eckey->group); - if (pub_key == NULL) { - goto err; - } - } else { - pub_key = eckey->pub_key; - } - - if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL)) { - goto err; + return 0; } - eckey->priv_key = priv_key; - eckey->pub_key = pub_key; - - ok = 1; - -err: - if (eckey->pub_key == NULL) { + static const uint8_t kDefaultAdditionalData[32] = {0}; + EC_WRAPPED_SCALAR *priv_key = ec_wrapped_scalar_new(key->group); + EC_POINT *pub_key = EC_POINT_new(key->group); + if (priv_key == NULL || pub_key == NULL || + // Generate the private key by testing candidates (FIPS 186-4 B.4.2). + !ec_random_nonzero_scalar(key->group, &priv_key->scalar, + kDefaultAdditionalData) || + !ec_point_mul_scalar(key->group, pub_key, &priv_key->scalar, NULL, NULL, + NULL)) { EC_POINT_free(pub_key); + ec_wrapped_scalar_free(priv_key); + return 0; } - if (eckey->priv_key == NULL) { - BN_free(priv_key); - } - return ok; + + ec_wrapped_scalar_free(key->priv_key); + key->priv_key = priv_key; + EC_POINT_free(key->pub_key); + key->pub_key = pub_key; + return 1; } int EC_KEY_generate_key_fips(EC_KEY *eckey) { diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/ec_montgomery.c b/Sources/BoringSSL/crypto/fipsmodule/ec/ec_montgomery.c index 6670b84ee..165c06f19 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/ec_montgomery.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/ec_montgomery.c @@ -93,7 +93,6 @@ void ec_GFp_mont_group_finish(EC_GROUP *group) { int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; - BN_MONT_CTX *mont = NULL; int ret = 0; BN_MONT_CTX_free(group->mont); @@ -106,18 +105,12 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, } } - mont = BN_MONT_CTX_new(); - if (mont == NULL) { - goto err; - } - if (!BN_MONT_CTX_set(mont, p, ctx)) { + group->mont = BN_MONT_CTX_new_for_modulus(p, ctx); + if (group->mont == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } - group->mont = mont; - mont = NULL; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); if (!ret) { @@ -127,7 +120,6 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, err: BN_CTX_free(new_ctx); - BN_MONT_CTX_free(mont); return ret; } @@ -270,6 +262,7 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) { out->group_set_curve = ec_GFp_mont_group_set_curve; out->point_get_affine_coordinates = ec_GFp_mont_point_get_affine_coordinates; out->mul = ec_wNAF_mul /* XXX: Not constant time. */; + out->mul_public = ec_wNAF_mul; out->field_mul = ec_GFp_mont_field_mul; out->field_sqr = ec_GFp_mont_field_sqr; out->field_encode = ec_GFp_mont_field_encode; diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/internal.h b/Sources/BoringSSL/crypto/fipsmodule/ec/internal.h index 7374e8b57..c198cc292 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/internal.h +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/internal.h @@ -91,10 +91,9 @@ extern "C" { OPENSSL_COMPILE_ASSERT(EC_MAX_SCALAR_WORDS <= BN_SMALL_MAX_WORDS, bn_small_functions_applicable); -// An EC_SCALAR is a |BN_num_bits(order)|-bit integer. Only the first -// |order->top| words are used. An |EC_SCALAR| is specific to an |EC_GROUP| and -// must not be mixed between groups. Unless otherwise specified, it is fully -// reduced modulo the |order|. +// An EC_SCALAR is an integer fully reduced modulo the order. Only the first +// |order->width| words are used. An |EC_SCALAR| is specific to an |EC_GROUP| +// and must not be mixed between groups. typedef union { // bytes is the representation of the scalar in little-endian order. uint8_t bytes[EC_MAX_SCALAR_BYTES]; @@ -116,6 +115,12 @@ struct ec_method_st { // non-null. int (*mul)(const EC_GROUP *group, EC_POINT *r, const EC_SCALAR *g_scalar, const EC_POINT *p, const EC_SCALAR *p_scalar, BN_CTX *ctx); + // mul_public performs the same computation as mul. It further assumes that + // the inputs are public so there is no concern about leaking their values + // through timing. + int (*mul_public)(const EC_GROUP *group, EC_POINT *r, + const EC_SCALAR *g_scalar, const EC_POINT *p, + const EC_SCALAR *p_scalar, BN_CTX *ctx); // 'field_mul' and 'field_sqr' can be used by 'add' and 'dbl' so that the // same implementations of point operations can be used with different @@ -173,12 +178,15 @@ struct ec_point_st { EC_GROUP *ec_group_new(const EC_METHOD *meth); -// ec_bignum_to_scalar converts |in| to an |EC_SCALAR| and writes it to |*out|. -// |in| must be non-negative and have at most |BN_num_bits(&group->order)| bits. -// It returns one on success and zero on error. It does not ensure |in| is fully -// reduced. -int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out, - const BIGNUM *in); +// ec_bignum_to_scalar converts |in| to an |EC_SCALAR| and writes it to +// |*out|. It returns one on success and zero if |in| is out of range. +OPENSSL_EXPORT int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out, + const BIGNUM *in); + +// ec_bignum_to_scalar_unchecked behaves like |ec_bignum_to_scalar| but does not +// check |in| is fully reduced. +int ec_bignum_to_scalar_unchecked(const EC_GROUP *group, EC_SCALAR *out, + const BIGNUM *in); // ec_random_nonzero_scalar sets |out| to a uniformly selected random value from // 1 to |group->order| - 1. It returns one on success and zero on error. @@ -193,6 +201,24 @@ int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r, const EC_SCALAR *g_scalar, const EC_POINT *p, const EC_SCALAR *p_scalar, BN_CTX *ctx); +// ec_point_mul_scalar_public performs the same computation as +// ec_point_mul_scalar. It further assumes that the inputs are public so +// there is no concern about leaking their values through timing. +OPENSSL_EXPORT int ec_point_mul_scalar_public( + const EC_GROUP *group, EC_POINT *r, const EC_SCALAR *g_scalar, + const EC_POINT *p, const EC_SCALAR *p_scalar, BN_CTX *ctx); + +// ec_compute_wNAF writes the modified width-(w+1) Non-Adjacent Form (wNAF) of +// |scalar| to |out| and returns one on success or zero on internal error. |out| +// must have room for |bits| + 1 elements, each of which will be either zero or +// odd with an absolute value less than 2^w satisfying +// scalar = \sum_j out[j]*2^j +// where at most one of any w+1 consecutive digits is non-zero +// with the exception that the most significant digit may be only +// w-1 zeros away from that next non-zero digit. +int ec_compute_wNAF(const EC_GROUP *group, int8_t *out, const EC_SCALAR *scalar, + size_t bits, int w); + int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const EC_SCALAR *g_scalar, const EC_POINT *p, const EC_SCALAR *p_scalar, BN_CTX *ctx); @@ -208,16 +234,9 @@ int ec_GFp_simple_point_init(EC_POINT *); void ec_GFp_simple_point_finish(EC_POINT *); int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); -int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, - const BIGNUM *y, - const BIGNUM *z, BN_CTX *); int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, const BIGNUM *x, const BIGNUM *y, BN_CTX *); -int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, int y_bit, - BN_CTX *); int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, @@ -249,11 +268,6 @@ int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); -int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, - EC_POINT *point, const BIGNUM *x, - const BIGNUM *y, const BIGNUM *z, - BN_CTX *ctx); - void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in); const EC_METHOD *EC_GFp_nistp224_method(void); @@ -263,11 +277,18 @@ const EC_METHOD *EC_GFp_nistp256_method(void); // x86-64 optimized P256. See http://eprint.iacr.org/2013/816. const EC_METHOD *EC_GFp_nistz256_method(void); +// An EC_WRAPPED_SCALAR is an |EC_SCALAR| with a parallel |BIGNUM| +// representation. It exists to support the |EC_KEY_get0_private_key| API. +typedef struct { + BIGNUM bignum; + EC_SCALAR scalar; +} EC_WRAPPED_SCALAR; + struct ec_key_st { EC_GROUP *group; EC_POINT *pub_key; - BIGNUM *priv_key; + EC_WRAPPED_SCALAR *priv_key; // fixed_k may contain a specific value of 'k', to be used in ECDSA signing. // This is only for the FIPS power-on tests. diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/oct.c b/Sources/BoringSSL/crypto/fipsmodule/ec/oct.c index 7d6239567..19e17a7c0 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/oct.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/oct.c @@ -77,11 +77,9 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, uint8_t *buf, size_t len, BN_CTX *ctx) { - size_t ret; + size_t ret = 0; BN_CTX *new_ctx = NULL; int used_ctx = 0; - BIGNUM *x, *y; - size_t field_len, i; if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED)) { @@ -94,14 +92,16 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, goto err; } - // ret := required output buffer length - field_len = BN_num_bytes(&group->field); - ret = - (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + const size_t field_len = BN_num_bytes(&group->field); + size_t output_len = 1 /* type byte */ + field_len; + if (form == POINT_CONVERSION_UNCOMPRESSED) { + // Uncompressed points have a second coordinate. + output_len += field_len; + } // if 'buf' is NULL, just return required length if (buf != NULL) { - if (len < ret) { + if (len < output_len) { OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); goto err; } @@ -115,8 +115,8 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, BN_CTX_start(ctx); used_ctx = 1; - x = BN_CTX_get(ctx); - y = BN_CTX_get(ctx); + BIGNUM *x = BN_CTX_get(ctx); + BIGNUM *y = BN_CTX_get(ctx); if (y == NULL) { goto err; } @@ -131,7 +131,7 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, } else { buf[0] = form; } - i = 1; + size_t i = 1; if (!BN_bn2bin_padded(buf + i, field_len, x)) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); @@ -147,70 +147,66 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, i += field_len; } - if (i != ret) { + if (i != output_len) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } } - if (used_ctx) { - BN_CTX_end(ctx); - } - BN_CTX_free(new_ctx); - return ret; + ret = output_len; err: if (used_ctx) { BN_CTX_end(ctx); } BN_CTX_free(new_ctx); - return 0; + return ret; } - static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, const uint8_t *buf, size_t len, BN_CTX *ctx) { - point_conversion_form_t form; - int y_bit; BN_CTX *new_ctx = NULL; - BIGNUM *x, *y; - size_t field_len, enc_len; - int ret = 0; + int ret = 0, used_ctx = 0; if (len == 0) { OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); - return 0; + goto err; } - form = buf[0]; - y_bit = form & 1; + + point_conversion_form_t form = buf[0]; + const int y_bit = form & 1; form = form & ~1U; if ((form != POINT_CONVERSION_COMPRESSED && form != POINT_CONVERSION_UNCOMPRESSED) || (form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); - return 0; + goto err; } - field_len = BN_num_bytes(&group->field); - enc_len = - (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + const size_t field_len = BN_num_bytes(&group->field); + size_t enc_len = 1 /* type byte */ + field_len; + if (form == POINT_CONVERSION_UNCOMPRESSED) { + // Uncompressed points have a second coordinate. + enc_len += field_len; + } if (len != enc_len) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); - return 0; + goto err; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { - return 0; + goto err; } } BN_CTX_start(ctx); - x = BN_CTX_get(ctx); - y = BN_CTX_get(ctx); + used_ctx = 1; + BIGNUM *x = BN_CTX_get(ctx); + BIGNUM *y = BN_CTX_get(ctx); if (x == NULL || y == NULL) { goto err; } @@ -244,7 +240,9 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, ret = 1; err: - BN_CTX_end(ctx); + if (used_ctx) { + BN_CTX_end(ctx); + } BN_CTX_free(new_ctx); return ret; } @@ -268,16 +266,20 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); } -int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, - EC_POINT *point, const BIGNUM *x, - int y_bit, BN_CTX *ctx) { +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) { + if (EC_GROUP_cmp(group, point->group, NULL) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); return 0; } BN_CTX *new_ctx = NULL; - BIGNUM *tmp1, *tmp2, *y; int ret = 0; ERR_clear_error(); @@ -292,10 +294,13 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, y_bit = (y_bit != 0); BN_CTX_start(ctx); - tmp1 = BN_CTX_get(ctx); - tmp2 = BN_CTX_get(ctx); - y = BN_CTX_get(ctx); - if (y == NULL) { + BIGNUM *tmp1 = BN_CTX_get(ctx); + BIGNUM *tmp2 = BN_CTX_get(ctx); + BIGNUM *a = BN_CTX_get(ctx); + BIGNUM *b = BN_CTX_get(ctx); + BIGNUM *y = BN_CTX_get(ctx); + if (y == NULL || + !EC_GROUP_get_curve_GFp(group, NULL, a, b, ctx)) { goto err; } @@ -304,54 +309,28 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, // so y is one of the square roots of x^3 + a*x + b. // tmp1 := x^3 - if (group->meth->field_decode == 0) { - // field_{sqr,mul} work on standard representation - if (!group->meth->field_sqr(group, tmp2, x, ctx) || - !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) { - goto err; - } - } else { - if (!BN_mod_sqr(tmp2, x, &group->field, ctx) || - !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) { - goto err; - } + if (!BN_mod_sqr(tmp2, x, &group->field, ctx) || + !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) { + goto err; } // tmp1 := tmp1 + a*x if (group->a_is_minus3) { - if (!BN_mod_lshift1_quick(tmp2, x, &group->field) || - !BN_mod_add_quick(tmp2, tmp2, x, &group->field) || - !BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) { + if (!bn_mod_lshift1_consttime(tmp2, x, &group->field, ctx) || + !bn_mod_add_consttime(tmp2, tmp2, x, &group->field, ctx) || + !bn_mod_sub_consttime(tmp1, tmp1, tmp2, &group->field, ctx)) { goto err; } } else { - if (group->meth->field_decode) { - if (!group->meth->field_decode(group, tmp2, &group->a, ctx) || - !BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) { - goto err; - } - } else { - // field_mul works on standard representation - if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) { - goto err; - } - } - - if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) { + if (!BN_mod_mul(tmp2, a, x, &group->field, ctx) || + !bn_mod_add_consttime(tmp1, tmp1, tmp2, &group->field, ctx)) { goto err; } } // tmp1 := tmp1 + b - if (group->meth->field_decode) { - if (!group->meth->field_decode(group, tmp2, &group->b, ctx) || - !BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) { - goto err; - } - } else { - if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) { - goto err; - } + if (!bn_mod_add_consttime(tmp1, tmp1, b, &group->field, ctx)) { + goto err; } if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { @@ -392,13 +371,3 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, BN_CTX_free(new_ctx); return ret; } - -int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, - EC_POINT *point, const BIGNUM *x, - int y_bit, BN_CTX *ctx) { - if (EC_GROUP_cmp(group, point->group, NULL) != 0) { - OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit, ctx); -} diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/p224-64.c b/Sources/BoringSSL/crypto/fipsmodule/ec/p224-64.c index ba25d22a7..028197b6d 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/p224-64.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/p224-64.c @@ -19,9 +19,6 @@ #include -#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \ - !defined(OPENSSL_SMALL) - #include #include #include @@ -34,6 +31,8 @@ #include "../../internal.h" +#if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL) + // Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3 // using 64-bit coefficients called 'limbs', and sometimes (for multiplication // results) as b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 + @@ -258,23 +257,6 @@ static void p224_felem_sum(p224_felem out, const p224_felem in) { out[3] += in[3]; } -// Get negative value: out = -in -// Assumes in[i] < 2^57 -static void p224_felem_neg(p224_felem out, const p224_felem in) { - static const p224_limb two58p2 = - (((p224_limb)1) << 58) + (((p224_limb)1) << 2); - static const p224_limb two58m2 = - (((p224_limb)1) << 58) - (((p224_limb)1) << 2); - static const p224_limb two58m42m2 = - (((p224_limb)1) << 58) - (((p224_limb)1) << 42) - (((p224_limb)1) << 2); - - // Set to 0 mod 2^224-2^96+1 to ensure out > in - out[0] = two58p2 - in[0]; - out[1] = two58m42m2 - in[1]; - out[2] = two58m2 - in[2]; - out[3] = two58m2 - in[3]; -} - // Subtract field elements: out -= in // Assumes in[i] < 2^57 static void p224_felem_diff(p224_felem out, const p224_felem in) { @@ -514,6 +496,15 @@ static void p224_felem_contract(p224_felem out, const p224_felem in) { out[3] = tmp[3]; } +// Get negative value: out = -in +// Requires in[i] < 2^63, +// ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 +static void p224_felem_neg(p224_felem out, const p224_felem in) { + p224_widefelem tmp = {0}; + p224_felem_diff_128_64(tmp, in); + p224_felem_reduce(out, tmp); +} + // Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field // elements are reduced to in < 2^225, so we only need to check three cases: 0, // 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2 @@ -1016,22 +1007,27 @@ static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, p224_felem_inv(z2, z1); p224_felem_square(tmp, z2); p224_felem_reduce(z1, tmp); - p224_felem_mul(tmp, x_in, z1); - p224_felem_reduce(x_in, tmp); - p224_felem_contract(x_out, x_in); - if (x != NULL && !p224_felem_to_BN(x, x_out)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - return 0; + + if (x != NULL) { + p224_felem_mul(tmp, x_in, z1); + p224_felem_reduce(x_in, tmp); + p224_felem_contract(x_out, x_in); + if (!p224_felem_to_BN(x, x_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } } - p224_felem_mul(tmp, z1, z2); - p224_felem_reduce(z1, tmp); - p224_felem_mul(tmp, y_in, z1); - p224_felem_reduce(y_in, tmp); - p224_felem_contract(y_out, y_in); - if (y != NULL && !p224_felem_to_BN(y, y_out)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - return 0; + if (y != NULL) { + p224_felem_mul(tmp, z1, z2); + p224_felem_reduce(z1, tmp); + p224_felem_mul(tmp, y_in, z1); + p224_felem_reduce(y_in, tmp); + p224_felem_contract(y_out, y_in); + if (!p224_felem_to_BN(y, y_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } } return 1; @@ -1041,28 +1037,9 @@ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, const EC_SCALAR *g_scalar, const EC_POINT *p, const EC_SCALAR *p_scalar, BN_CTX *ctx) { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y, *z, *tmp_scalar; p224_felem p_pre_comp[17][3]; p224_felem x_in, y_in, z_in, x_out, y_out, z_out; - if (ctx == NULL) { - ctx = BN_CTX_new(); - new_ctx = ctx; - if (ctx == NULL) { - return 0; - } - } - - BN_CTX_start(ctx); - if ((x = BN_CTX_get(ctx)) == NULL || - (y = BN_CTX_get(ctx)) == NULL || - (z = BN_CTX_get(ctx)) == NULL || - (tmp_scalar = BN_CTX_get(ctx)) == NULL) { - goto err; - } - if (p != NULL && p_scalar != NULL) { // We treat NULL scalars as 0, and NULL points as points at infinity, i.e., // they contribute nothing to the linear combination. @@ -1071,7 +1048,7 @@ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, if (!p224_BN_to_felem(x_out, &p->X) || !p224_BN_to_felem(y_out, &p->Y) || !p224_BN_to_felem(z_out, &p->Z)) { - goto err; + return 0; } p224_felem_assign(p_pre_comp[1][0], x_out); @@ -1101,18 +1078,13 @@ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, p224_felem_contract(x_in, x_out); p224_felem_contract(y_in, y_out); p224_felem_contract(z_in, z_out); - if (!p224_felem_to_BN(x, x_in) || - !p224_felem_to_BN(y, y_in) || - !p224_felem_to_BN(z, z_in)) { + if (!p224_felem_to_BN(&r->X, x_in) || + !p224_felem_to_BN(&r->Y, y_in) || + !p224_felem_to_BN(&r->Z, z_in)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - goto err; + return 0; } - ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - -err: - BN_CTX_end(ctx); - BN_CTX_free(new_ctx); - return ret; + return 1; } DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) { @@ -1122,10 +1094,11 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) { out->point_get_affine_coordinates = ec_GFp_nistp224_point_get_affine_coordinates; out->mul = ec_GFp_nistp224_points_mul; + out->mul_public = ec_GFp_nistp224_points_mul; out->field_mul = ec_GFp_simple_field_mul; out->field_sqr = ec_GFp_simple_field_sqr; out->field_encode = NULL; out->field_decode = NULL; }; -#endif // 64_BIT && !WINDOWS && !SMALL +#endif // BORINGSSL_HAS_UINT128 && !SMALL diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-64.c b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-64.c deleted file mode 100644 index d4a8ff681..000000000 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-64.c +++ /dev/null @@ -1,1674 +0,0 @@ -/* Copyright (c) 2015, Google Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -// A 64-bit implementation of the NIST P-256 elliptic curve point -// multiplication -// -// OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. -// Otherwise based on Emilia's P224 work, which was inspired by my curve25519 -// work which got its smarts from Daniel J. Bernstein's work on the same. - -#include - -#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) - -#include -#include -#include -#include - -#include - -#include "../delocate.h" -#include "../../internal.h" -#include "internal.h" - - -// The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We -// can serialise an element of this field into 32 bytes. We call this an -// felem_bytearray. -typedef uint8_t felem_bytearray[32]; - -// The representation of field elements. -// ------------------------------------ -// -// We represent field elements with either four 128-bit values, eight 128-bit -// values, or four 64-bit values. The field element represented is: -// v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p) -// or: -// v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p) -// -// 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits -// apart, but are 128-bits wide, the most significant bits of each limb overlap -// with the least significant bits of the next. -// -// A field element with four limbs is an 'felem'. One with eight limbs is a -// 'longfelem' -// -// A field element with four, 64-bit values is called a 'smallfelem'. Small -// values are used as intermediate values before multiplication. - -#define NLIMBS 4 - -typedef uint128_t limb; -typedef limb felem[NLIMBS]; -typedef limb longfelem[NLIMBS * 2]; -typedef uint64_t smallfelem[NLIMBS]; - -// This is the value of the prime as four 64-bit words, little-endian. -static const uint64_t kPrime[4] = {0xfffffffffffffffful, 0xffffffff, 0, - 0xffffffff00000001ul}; -static const uint64_t bottom63bits = 0x7ffffffffffffffful; - -static uint64_t load_u64(const uint8_t in[8]) { - uint64_t ret; - OPENSSL_memcpy(&ret, in, sizeof(ret)); - return ret; -} - -static void store_u64(uint8_t out[8], uint64_t in) { - OPENSSL_memcpy(out, &in, sizeof(in)); -} - -// bin32_to_felem takes a little-endian byte array and converts it into felem -// form. This assumes that the CPU is little-endian. -static void bin32_to_felem(felem out, const uint8_t in[32]) { - out[0] = load_u64(&in[0]); - out[1] = load_u64(&in[8]); - out[2] = load_u64(&in[16]); - out[3] = load_u64(&in[24]); -} - -// smallfelem_to_bin32 takes a smallfelem and serialises into a little endian, -// 32 byte array. This assumes that the CPU is little-endian. -static void smallfelem_to_bin32(uint8_t out[32], const smallfelem in) { - store_u64(&out[0], in[0]); - store_u64(&out[8], in[1]); - store_u64(&out[16], in[2]); - store_u64(&out[24], in[3]); -} - -// To preserve endianness when using BN_bn2bin and BN_bin2bn. -static void flip_endian(uint8_t *out, const uint8_t *in, size_t len) { - for (size_t i = 0; i < len; ++i) { - out[i] = in[len - 1 - i]; - } -} - -// BN_to_felem converts an OpenSSL BIGNUM into an felem. -static int BN_to_felem(felem out, const BIGNUM *bn) { - if (BN_is_negative(bn)) { - OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - - felem_bytearray b_out; - // BN_bn2bin eats leading zeroes - OPENSSL_memset(b_out, 0, sizeof(b_out)); - size_t num_bytes = BN_num_bytes(bn); - if (num_bytes > sizeof(b_out)) { - OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - - felem_bytearray b_in; - num_bytes = BN_bn2bin(bn, b_in); - flip_endian(b_out, b_in, num_bytes); - bin32_to_felem(out, b_out); - return 1; -} - -// felem_to_BN converts an felem into an OpenSSL BIGNUM. -static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) { - felem_bytearray b_in, b_out; - smallfelem_to_bin32(b_in, in); - flip_endian(b_out, b_in, sizeof(b_out)); - return BN_bin2bn(b_out, sizeof(b_out), out); -} - -// Field operations. - -static void felem_assign(felem out, const felem in) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -// felem_sum sets out = out + in. -static void felem_sum(felem out, const felem in) { - out[0] += in[0]; - out[1] += in[1]; - out[2] += in[2]; - out[3] += in[3]; -} - -// felem_small_sum sets out = out + in. -static void felem_small_sum(felem out, const smallfelem in) { - out[0] += in[0]; - out[1] += in[1]; - out[2] += in[2]; - out[3] += in[3]; -} - -// felem_scalar sets out = out * scalar -static void felem_scalar(felem out, const uint64_t scalar) { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; -} - -// longfelem_scalar sets out = out * scalar -static void longfelem_scalar(longfelem out, const uint64_t scalar) { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - out[4] *= scalar; - out[5] *= scalar; - out[6] *= scalar; - out[7] *= scalar; -} - -#define two105m41m9 ((((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)) -#define two105 (((limb)1) << 105) -#define two105m41p9 ((((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)) - -// zero105 is 0 mod p -static const felem zero105 = {two105m41m9, two105, two105m41p9, two105m41p9}; - -// smallfelem_neg sets |out| to |-small| -// On exit: -// out[i] < out[i] + 2^105 -static void smallfelem_neg(felem out, const smallfelem small) { - // In order to prevent underflow, we subtract from 0 mod p. - out[0] = zero105[0] - small[0]; - out[1] = zero105[1] - small[1]; - out[2] = zero105[2] - small[2]; - out[3] = zero105[3] - small[3]; -} - -// felem_diff subtracts |in| from |out| -// On entry: -// in[i] < 2^104 -// On exit: -// out[i] < out[i] + 2^105. -static void felem_diff(felem out, const felem in) { - // In order to prevent underflow, we add 0 mod p before subtracting. - out[0] += zero105[0]; - out[1] += zero105[1]; - out[2] += zero105[2]; - out[3] += zero105[3]; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; -} - -#define two107m43m11 \ - ((((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)) -#define two107 (((limb)1) << 107) -#define two107m43p11 \ - ((((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)) - -// zero107 is 0 mod p -static const felem zero107 = {two107m43m11, two107, two107m43p11, two107m43p11}; - -// An alternative felem_diff for larger inputs |in| -// felem_diff_zero107 subtracts |in| from |out| -// On entry: -// in[i] < 2^106 -// On exit: -// out[i] < out[i] + 2^107. -static void felem_diff_zero107(felem out, const felem in) { - // In order to prevent underflow, we add 0 mod p before subtracting. - out[0] += zero107[0]; - out[1] += zero107[1]; - out[2] += zero107[2]; - out[3] += zero107[3]; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; -} - -// longfelem_diff subtracts |in| from |out| -// On entry: -// in[i] < 7*2^67 -// On exit: -// out[i] < out[i] + 2^70 + 2^40. -static void longfelem_diff(longfelem out, const longfelem in) { - static const limb two70m8p6 = - (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6); - static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40); - static const limb two70 = (((limb)1) << 70); - static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) - - (((limb)1) << 38) + (((limb)1) << 6); - static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6); - - // add 0 mod p to avoid underflow - out[0] += two70m8p6; - out[1] += two70p40; - out[2] += two70; - out[3] += two70m40m38p6; - out[4] += two70m6; - out[5] += two70m6; - out[6] += two70m6; - out[7] += two70m6; - - // in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - out[4] -= in[4]; - out[5] -= in[5]; - out[6] -= in[6]; - out[7] -= in[7]; -} - -#define two64m0 ((((limb)1) << 64) - 1) -#define two110p32m0 ((((limb)1) << 110) + (((limb)1) << 32) - 1) -#define two64m46 ((((limb)1) << 64) - (((limb)1) << 46)) -#define two64m32 ((((limb)1) << 64) - (((limb)1) << 32)) - -// zero110 is 0 mod p. -static const felem zero110 = {two64m0, two110p32m0, two64m46, two64m32}; - -// felem_shrink converts an felem into a smallfelem. The result isn't quite -// minimal as the value may be greater than p. -// -// On entry: -// in[i] < 2^109 -// On exit: -// out[i] < 2^64. -static void felem_shrink(smallfelem out, const felem in) { - felem tmp; - uint64_t a, b, mask; - int64_t high, low; - static const uint64_t kPrime3Test = - 0x7fffffff00000001ul; // 2^63 - 2^32 + 1 - - // Carry 2->3 - tmp[3] = zero110[3] + in[3] + ((uint64_t)(in[2] >> 64)); - // tmp[3] < 2^110 - - tmp[2] = zero110[2] + (uint64_t)in[2]; - tmp[0] = zero110[0] + in[0]; - tmp[1] = zero110[1] + in[1]; - // tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 - - // We perform two partial reductions where we eliminate the high-word of - // tmp[3]. We don't update the other words till the end. - a = tmp[3] >> 64; // a < 2^46 - tmp[3] = (uint64_t)tmp[3]; - tmp[3] -= a; - tmp[3] += ((limb)a) << 32; - // tmp[3] < 2^79 - - b = a; - a = tmp[3] >> 64; // a < 2^15 - b += a; // b < 2^46 + 2^15 < 2^47 - tmp[3] = (uint64_t)tmp[3]; - tmp[3] -= a; - tmp[3] += ((limb)a) << 32; - // tmp[3] < 2^64 + 2^47 - - // This adjusts the other two words to complete the two partial - // reductions. - tmp[0] += b; - tmp[1] -= (((limb)b) << 32); - - // In order to make space in tmp[3] for the carry from 2 -> 3, we - // conditionally subtract kPrime if tmp[3] is large enough. - high = tmp[3] >> 64; - // As tmp[3] < 2^65, high is either 1 or 0 - high = ~(high - 1); - // high is: - // all ones if the high word of tmp[3] is 1 - // all zeros if the high word of tmp[3] if 0 - low = tmp[3]; - mask = low >> 63; - // mask is: - // all ones if the MSB of low is 1 - // all zeros if the MSB of low if 0 - low &= bottom63bits; - low -= kPrime3Test; - // if low was greater than kPrime3Test then the MSB is zero - low = ~low; - low >>= 63; - // low is: - // all ones if low was > kPrime3Test - // all zeros if low was <= kPrime3Test - mask = (mask & low) | high; - tmp[0] -= mask & kPrime[0]; - tmp[1] -= mask & kPrime[1]; - // kPrime[2] is zero, so omitted - tmp[3] -= mask & kPrime[3]; - // tmp[3] < 2**64 - 2**32 + 1 - - tmp[1] += ((uint64_t)(tmp[0] >> 64)); - tmp[0] = (uint64_t)tmp[0]; - tmp[2] += ((uint64_t)(tmp[1] >> 64)); - tmp[1] = (uint64_t)tmp[1]; - tmp[3] += ((uint64_t)(tmp[2] >> 64)); - tmp[2] = (uint64_t)tmp[2]; - // tmp[i] < 2^64 - - out[0] = tmp[0]; - out[1] = tmp[1]; - out[2] = tmp[2]; - out[3] = tmp[3]; -} - -// smallfelem_expand converts a smallfelem to an felem -static void smallfelem_expand(felem out, const smallfelem in) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -// smallfelem_square sets |out| = |small|^2 -// On entry: -// small[i] < 2^64 -// On exit: -// out[i] < 7 * 2^64 < 2^67 -static void smallfelem_square(longfelem out, const smallfelem small) { - limb a; - uint64_t high, low; - - a = ((uint128_t)small[0]) * small[0]; - low = a; - high = a >> 64; - out[0] = low; - out[1] = high; - - a = ((uint128_t)small[0]) * small[1]; - low = a; - high = a >> 64; - out[1] += low; - out[1] += low; - out[2] = high; - - a = ((uint128_t)small[0]) * small[2]; - low = a; - high = a >> 64; - out[2] += low; - out[2] *= 2; - out[3] = high; - - a = ((uint128_t)small[0]) * small[3]; - low = a; - high = a >> 64; - out[3] += low; - out[4] = high; - - a = ((uint128_t)small[1]) * small[2]; - low = a; - high = a >> 64; - out[3] += low; - out[3] *= 2; - out[4] += high; - - a = ((uint128_t)small[1]) * small[1]; - low = a; - high = a >> 64; - out[2] += low; - out[3] += high; - - a = ((uint128_t)small[1]) * small[3]; - low = a; - high = a >> 64; - out[4] += low; - out[4] *= 2; - out[5] = high; - - a = ((uint128_t)small[2]) * small[3]; - low = a; - high = a >> 64; - out[5] += low; - out[5] *= 2; - out[6] = high; - out[6] += high; - - a = ((uint128_t)small[2]) * small[2]; - low = a; - high = a >> 64; - out[4] += low; - out[5] += high; - - a = ((uint128_t)small[3]) * small[3]; - low = a; - high = a >> 64; - out[6] += low; - out[7] = high; -} - -//felem_square sets |out| = |in|^2 -// On entry: -// in[i] < 2^109 -// On exit: -// out[i] < 7 * 2^64 < 2^67. -static void felem_square(longfelem out, const felem in) { - uint64_t small[4]; - felem_shrink(small, in); - smallfelem_square(out, small); -} - -// smallfelem_mul sets |out| = |small1| * |small2| -// On entry: -// small1[i] < 2^64 -// small2[i] < 2^64 -// On exit: -// out[i] < 7 * 2^64 < 2^67. -static void smallfelem_mul(longfelem out, const smallfelem small1, - const smallfelem small2) { - limb a; - uint64_t high, low; - - a = ((uint128_t)small1[0]) * small2[0]; - low = a; - high = a >> 64; - out[0] = low; - out[1] = high; - - a = ((uint128_t)small1[0]) * small2[1]; - low = a; - high = a >> 64; - out[1] += low; - out[2] = high; - - a = ((uint128_t)small1[1]) * small2[0]; - low = a; - high = a >> 64; - out[1] += low; - out[2] += high; - - a = ((uint128_t)small1[0]) * small2[2]; - low = a; - high = a >> 64; - out[2] += low; - out[3] = high; - - a = ((uint128_t)small1[1]) * small2[1]; - low = a; - high = a >> 64; - out[2] += low; - out[3] += high; - - a = ((uint128_t)small1[2]) * small2[0]; - low = a; - high = a >> 64; - out[2] += low; - out[3] += high; - - a = ((uint128_t)small1[0]) * small2[3]; - low = a; - high = a >> 64; - out[3] += low; - out[4] = high; - - a = ((uint128_t)small1[1]) * small2[2]; - low = a; - high = a >> 64; - out[3] += low; - out[4] += high; - - a = ((uint128_t)small1[2]) * small2[1]; - low = a; - high = a >> 64; - out[3] += low; - out[4] += high; - - a = ((uint128_t)small1[3]) * small2[0]; - low = a; - high = a >> 64; - out[3] += low; - out[4] += high; - - a = ((uint128_t)small1[1]) * small2[3]; - low = a; - high = a >> 64; - out[4] += low; - out[5] = high; - - a = ((uint128_t)small1[2]) * small2[2]; - low = a; - high = a >> 64; - out[4] += low; - out[5] += high; - - a = ((uint128_t)small1[3]) * small2[1]; - low = a; - high = a >> 64; - out[4] += low; - out[5] += high; - - a = ((uint128_t)small1[2]) * small2[3]; - low = a; - high = a >> 64; - out[5] += low; - out[6] = high; - - a = ((uint128_t)small1[3]) * small2[2]; - low = a; - high = a >> 64; - out[5] += low; - out[6] += high; - - a = ((uint128_t)small1[3]) * small2[3]; - low = a; - high = a >> 64; - out[6] += low; - out[7] = high; -} - -// felem_mul sets |out| = |in1| * |in2| -// On entry: -// in1[i] < 2^109 -// in2[i] < 2^109 -// On exit: -// out[i] < 7 * 2^64 < 2^67 -static void felem_mul(longfelem out, const felem in1, const felem in2) { - smallfelem small1, small2; - felem_shrink(small1, in1); - felem_shrink(small2, in2); - smallfelem_mul(out, small1, small2); -} - -// felem_small_mul sets |out| = |small1| * |in2| -// On entry: -// small1[i] < 2^64 -// in2[i] < 2^109 -// On exit: -// out[i] < 7 * 2^64 < 2^67 -static void felem_small_mul(longfelem out, const smallfelem small1, - const felem in2) { - smallfelem small2; - felem_shrink(small2, in2); - smallfelem_mul(out, small1, small2); -} - -#define two100m36m4 ((((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)) -#define two100 (((limb)1) << 100) -#define two100m36p4 ((((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)) - -// zero100 is 0 mod p -static const felem zero100 = {two100m36m4, two100, two100m36p4, two100m36p4}; - -// Internal function for the different flavours of felem_reduce. -// felem_reduce_ reduces the higher coefficients in[4]-in[7]. -// On entry: -// out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7] -// out[1] >= in[7] + 2^32*in[4] -// out[2] >= in[5] + 2^32*in[5] -// out[3] >= in[4] + 2^32*in[5] + 2^32*in[6] -// On exit: -// out[0] <= out[0] + in[4] + 2^32*in[5] -// out[1] <= out[1] + in[5] + 2^33*in[6] -// out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7] -// out[3] <= out[3] + 2^32*in[4] + 3*in[7] -static void felem_reduce_(felem out, const longfelem in) { - int128_t c; - // combine common terms from below - c = in[4] + (in[5] << 32); - out[0] += c; - out[3] -= c; - - c = in[5] - in[7]; - out[1] += c; - out[2] -= c; - - // the remaining terms - // 256: [(0,1),(96,-1),(192,-1),(224,1)] - out[1] -= (in[4] << 32); - out[3] += (in[4] << 32); - - // 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] - out[2] -= (in[5] << 32); - - // 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] - out[0] -= in[6]; - out[0] -= (in[6] << 32); - out[1] += (in[6] << 33); - out[2] += (in[6] * 2); - out[3] -= (in[6] << 32); - - // 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] - out[0] -= in[7]; - out[0] -= (in[7] << 32); - out[2] += (in[7] << 33); - out[3] += (in[7] * 3); -} - -// felem_reduce converts a longfelem into an felem. -// To be called directly after felem_square or felem_mul. -// On entry: -// in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64 -// in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64 -// On exit: -// out[i] < 2^101 -static void felem_reduce(felem out, const longfelem in) { - out[0] = zero100[0] + in[0]; - out[1] = zero100[1] + in[1]; - out[2] = zero100[2] + in[2]; - out[3] = zero100[3] + in[3]; - - felem_reduce_(out, in); - - // out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0 - // out[1] > 2^100 - 2^64 - 7*2^96 > 0 - // out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0 - // out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0 - // - // out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101 - // out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101 - // out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101 - // out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 -} - -// felem_reduce_zero105 converts a larger longfelem into an felem. -// On entry: -// in[0] < 2^71 -// On exit: -// out[i] < 2^106 -static void felem_reduce_zero105(felem out, const longfelem in) { - out[0] = zero105[0] + in[0]; - out[1] = zero105[1] + in[1]; - out[2] = zero105[2] + in[2]; - out[3] = zero105[3] + in[3]; - - felem_reduce_(out, in); - - // out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0 - // out[1] > 2^105 - 2^71 - 2^103 > 0 - // out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0 - // out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0 - // - // out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 - // out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 - // out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106 - // out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 -} - -// subtract_u64 sets *result = *result - v and *carry to one if the -// subtraction underflowed. -static void subtract_u64(uint64_t *result, uint64_t *carry, uint64_t v) { - uint128_t r = *result; - r -= v; - *carry = (r >> 64) & 1; - *result = (uint64_t)r; -} - -// felem_contract converts |in| to its unique, minimal representation. On -// entry: in[i] < 2^109. -static void felem_contract(smallfelem out, const felem in) { - uint64_t all_equal_so_far = 0, result = 0; - - felem_shrink(out, in); - // small is minimal except that the value might be > p - - all_equal_so_far--; - // We are doing a constant time test if out >= kPrime. We need to compare - // each uint64_t, from most-significant to least significant. For each one, if - // all words so far have been equal (m is all ones) then a non-equal - // result is the answer. Otherwise we continue. - for (size_t i = 3; i < 4; i--) { - uint64_t equal; - uint128_t a = ((uint128_t)kPrime[i]) - out[i]; - // if out[i] > kPrime[i] then a will underflow and the high 64-bits - // will all be set. - result |= all_equal_so_far & ((uint64_t)(a >> 64)); - - // if kPrime[i] == out[i] then |equal| will be all zeros and the - // decrement will make it all ones. - equal = kPrime[i] ^ out[i]; - equal--; - equal &= equal << 32; - equal &= equal << 16; - equal &= equal << 8; - equal &= equal << 4; - equal &= equal << 2; - equal &= equal << 1; - equal = ((int64_t)equal) >> 63; - - all_equal_so_far &= equal; - } - - // if all_equal_so_far is still all ones then the two values are equal - // and so out >= kPrime is true. - result |= all_equal_so_far; - - // if out >= kPrime then we subtract kPrime. - uint64_t carry; - subtract_u64(&out[0], &carry, result & kPrime[0]); - subtract_u64(&out[1], &carry, carry); - subtract_u64(&out[2], &carry, carry); - subtract_u64(&out[3], &carry, carry); - - subtract_u64(&out[1], &carry, result & kPrime[1]); - subtract_u64(&out[2], &carry, carry); - subtract_u64(&out[3], &carry, carry); - - subtract_u64(&out[2], &carry, result & kPrime[2]); - subtract_u64(&out[3], &carry, carry); - - subtract_u64(&out[3], &carry, result & kPrime[3]); -} - -// felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 -// otherwise. -// On entry: -// small[i] < 2^64 -static limb smallfelem_is_zero(const smallfelem small) { - limb result; - uint64_t is_p; - - uint64_t is_zero = small[0] | small[1] | small[2] | small[3]; - is_zero--; - is_zero &= is_zero << 32; - is_zero &= is_zero << 16; - is_zero &= is_zero << 8; - is_zero &= is_zero << 4; - is_zero &= is_zero << 2; - is_zero &= is_zero << 1; - is_zero = ((int64_t)is_zero) >> 63; - - is_p = (small[0] ^ kPrime[0]) | (small[1] ^ kPrime[1]) | - (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]); - is_p--; - is_p &= is_p << 32; - is_p &= is_p << 16; - is_p &= is_p << 8; - is_p &= is_p << 4; - is_p &= is_p << 2; - is_p &= is_p << 1; - is_p = ((int64_t)is_p) >> 63; - - is_zero |= is_p; - - result = is_zero; - result |= ((limb)is_zero) << 64; - return result; -} - -// felem_inv calculates |out| = |in|^{-1} -// -// Based on Fermat's Little Theorem: -// a^p = a (mod p) -// a^{p-1} = 1 (mod p) -// a^{p-2} = a^{-1} (mod p) -static void felem_inv(felem out, const felem in) { - felem ftmp, ftmp2; - // each e_I will hold |in|^{2^I - 1} - felem e2, e4, e8, e16, e32, e64; - longfelem tmp; - - felem_square(tmp, in); - felem_reduce(ftmp, tmp); // 2^1 - felem_mul(tmp, in, ftmp); - felem_reduce(ftmp, tmp); // 2^2 - 2^0 - felem_assign(e2, ftmp); - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); // 2^3 - 2^1 - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); // 2^4 - 2^2 - felem_mul(tmp, ftmp, e2); - felem_reduce(ftmp, tmp); // 2^4 - 2^0 - felem_assign(e4, ftmp); - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); // 2^5 - 2^1 - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); // 2^6 - 2^2 - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); // 2^7 - 2^3 - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); // 2^8 - 2^4 - felem_mul(tmp, ftmp, e4); - felem_reduce(ftmp, tmp); // 2^8 - 2^0 - felem_assign(e8, ftmp); - for (size_t i = 0; i < 8; i++) { - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - } // 2^16 - 2^8 - felem_mul(tmp, ftmp, e8); - felem_reduce(ftmp, tmp); // 2^16 - 2^0 - felem_assign(e16, ftmp); - for (size_t i = 0; i < 16; i++) { - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - } // 2^32 - 2^16 - felem_mul(tmp, ftmp, e16); - felem_reduce(ftmp, tmp); // 2^32 - 2^0 - felem_assign(e32, ftmp); - for (size_t i = 0; i < 32; i++) { - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - } // 2^64 - 2^32 - felem_assign(e64, ftmp); - felem_mul(tmp, ftmp, in); - felem_reduce(ftmp, tmp); // 2^64 - 2^32 + 2^0 - for (size_t i = 0; i < 192; i++) { - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - } // 2^256 - 2^224 + 2^192 - - felem_mul(tmp, e64, e32); - felem_reduce(ftmp2, tmp); // 2^64 - 2^0 - for (size_t i = 0; i < 16; i++) { - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); - } // 2^80 - 2^16 - felem_mul(tmp, ftmp2, e16); - felem_reduce(ftmp2, tmp); // 2^80 - 2^0 - for (size_t i = 0; i < 8; i++) { - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); - } // 2^88 - 2^8 - felem_mul(tmp, ftmp2, e8); - felem_reduce(ftmp2, tmp); // 2^88 - 2^0 - for (size_t i = 0; i < 4; i++) { - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); - } // 2^92 - 2^4 - felem_mul(tmp, ftmp2, e4); - felem_reduce(ftmp2, tmp); // 2^92 - 2^0 - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); // 2^93 - 2^1 - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); // 2^94 - 2^2 - felem_mul(tmp, ftmp2, e2); - felem_reduce(ftmp2, tmp); // 2^94 - 2^0 - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); // 2^95 - 2^1 - felem_square(tmp, ftmp2); - felem_reduce(ftmp2, tmp); // 2^96 - 2^2 - felem_mul(tmp, ftmp2, in); - felem_reduce(ftmp2, tmp); // 2^96 - 3 - - felem_mul(tmp, ftmp2, ftmp); - felem_reduce(out, tmp); // 2^256 - 2^224 + 2^192 + 2^96 - 3 -} - -// Group operations -// ---------------- -// -// Building on top of the field operations we have the operations on the -// elliptic curve group itself. Points on the curve are represented in Jacobian -// coordinates. - -// point_double calculates 2*(x_in, y_in, z_in) -// -// The method is taken from: -// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b -// -// Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. -// while x_out == y_in is not (maybe this works, but it's not tested). -static void point_double(felem x_out, felem y_out, felem z_out, - const felem x_in, const felem y_in, const felem z_in) { - longfelem tmp, tmp2; - felem delta, gamma, beta, alpha, ftmp, ftmp2; - smallfelem small1, small2; - - felem_assign(ftmp, x_in); - // ftmp[i] < 2^106 - felem_assign(ftmp2, x_in); - // ftmp2[i] < 2^106 - - // delta = z^2 - felem_square(tmp, z_in); - felem_reduce(delta, tmp); - // delta[i] < 2^101 - - // gamma = y^2 - felem_square(tmp, y_in); - felem_reduce(gamma, tmp); - // gamma[i] < 2^101 - felem_shrink(small1, gamma); - - // beta = x*gamma - felem_small_mul(tmp, small1, x_in); - felem_reduce(beta, tmp); - // beta[i] < 2^101 - - // alpha = 3*(x-delta)*(x+delta) - felem_diff(ftmp, delta); - // ftmp[i] < 2^105 + 2^106 < 2^107 - felem_sum(ftmp2, delta); - // ftmp2[i] < 2^105 + 2^106 < 2^107 - felem_scalar(ftmp2, 3); - // ftmp2[i] < 3 * 2^107 < 2^109 - felem_mul(tmp, ftmp, ftmp2); - felem_reduce(alpha, tmp); - // alpha[i] < 2^101 - felem_shrink(small2, alpha); - - // x' = alpha^2 - 8*beta - smallfelem_square(tmp, small2); - felem_reduce(x_out, tmp); - felem_assign(ftmp, beta); - felem_scalar(ftmp, 8); - // ftmp[i] < 8 * 2^101 = 2^104 - felem_diff(x_out, ftmp); - // x_out[i] < 2^105 + 2^101 < 2^106 - - // z' = (y + z)^2 - gamma - delta - felem_sum(delta, gamma); - // delta[i] < 2^101 + 2^101 = 2^102 - felem_assign(ftmp, y_in); - felem_sum(ftmp, z_in); - // ftmp[i] < 2^106 + 2^106 = 2^107 - felem_square(tmp, ftmp); - felem_reduce(z_out, tmp); - felem_diff(z_out, delta); - // z_out[i] < 2^105 + 2^101 < 2^106 - - // y' = alpha*(4*beta - x') - 8*gamma^2 - felem_scalar(beta, 4); - // beta[i] < 4 * 2^101 = 2^103 - felem_diff_zero107(beta, x_out); - // beta[i] < 2^107 + 2^103 < 2^108 - felem_small_mul(tmp, small2, beta); - // tmp[i] < 7 * 2^64 < 2^67 - smallfelem_square(tmp2, small1); - // tmp2[i] < 7 * 2^64 - longfelem_scalar(tmp2, 8); - // tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 - longfelem_diff(tmp, tmp2); - // tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 - felem_reduce_zero105(y_out, tmp); - // y_out[i] < 2^106 -} - -// point_double_small is the same as point_double, except that it operates on -// smallfelems. -static void point_double_small(smallfelem x_out, smallfelem y_out, - smallfelem z_out, const smallfelem x_in, - const smallfelem y_in, const smallfelem z_in) { - felem felem_x_out, felem_y_out, felem_z_out; - felem felem_x_in, felem_y_in, felem_z_in; - - smallfelem_expand(felem_x_in, x_in); - smallfelem_expand(felem_y_in, y_in); - smallfelem_expand(felem_z_in, z_in); - point_double(felem_x_out, felem_y_out, felem_z_out, felem_x_in, felem_y_in, - felem_z_in); - felem_shrink(x_out, felem_x_out); - felem_shrink(y_out, felem_y_out); - felem_shrink(z_out, felem_z_out); -} - -// p256_copy_conditional copies in to out iff mask is all ones. -static void p256_copy_conditional(felem out, const felem in, limb mask) { - for (size_t i = 0; i < NLIMBS; ++i) { - const limb tmp = mask & (in[i] ^ out[i]); - out[i] ^= tmp; - } -} - -// copy_small_conditional copies in to out iff mask is all ones. -static void copy_small_conditional(felem out, const smallfelem in, limb mask) { - const uint64_t mask64 = mask; - for (size_t i = 0; i < NLIMBS; ++i) { - out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask); - } -} - -// point_add calcuates (x1, y1, z1) + (x2, y2, z2) -// -// The method is taken from: -// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, -// adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). -// -// This function includes a branch for checking whether the two input points -// are equal, (while not equal to the point at infinity). This case never -// happens during single point multiplication, so there is no timing leak for -// ECDH or ECDSA signing. -static void point_add(felem x3, felem y3, felem z3, const felem x1, - const felem y1, const felem z1, const int mixed, - const smallfelem x2, const smallfelem y2, - const smallfelem z2) { - felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; - longfelem tmp, tmp2; - smallfelem small1, small2, small3, small4, small5; - limb x_equal, y_equal, z1_is_zero, z2_is_zero; - - felem_shrink(small3, z1); - - z1_is_zero = smallfelem_is_zero(small3); - z2_is_zero = smallfelem_is_zero(z2); - - // ftmp = z1z1 = z1**2 - smallfelem_square(tmp, small3); - felem_reduce(ftmp, tmp); - // ftmp[i] < 2^101 - felem_shrink(small1, ftmp); - - if (!mixed) { - // ftmp2 = z2z2 = z2**2 - smallfelem_square(tmp, z2); - felem_reduce(ftmp2, tmp); - // ftmp2[i] < 2^101 - felem_shrink(small2, ftmp2); - - felem_shrink(small5, x1); - - // u1 = ftmp3 = x1*z2z2 - smallfelem_mul(tmp, small5, small2); - felem_reduce(ftmp3, tmp); - // ftmp3[i] < 2^101 - - // ftmp5 = z1 + z2 - felem_assign(ftmp5, z1); - felem_small_sum(ftmp5, z2); - // ftmp5[i] < 2^107 - - // ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 - felem_square(tmp, ftmp5); - felem_reduce(ftmp5, tmp); - // ftmp2 = z2z2 + z1z1 - felem_sum(ftmp2, ftmp); - // ftmp2[i] < 2^101 + 2^101 = 2^102 - felem_diff(ftmp5, ftmp2); - // ftmp5[i] < 2^105 + 2^101 < 2^106 - - // ftmp2 = z2 * z2z2 - smallfelem_mul(tmp, small2, z2); - felem_reduce(ftmp2, tmp); - - // s1 = ftmp2 = y1 * z2**3 - felem_mul(tmp, y1, ftmp2); - felem_reduce(ftmp6, tmp); - // ftmp6[i] < 2^101 - } else { - // We'll assume z2 = 1 (special case z2 = 0 is handled later). - - // u1 = ftmp3 = x1*z2z2 - felem_assign(ftmp3, x1); - // ftmp3[i] < 2^106 - - // ftmp5 = 2z1z2 - felem_assign(ftmp5, z1); - felem_scalar(ftmp5, 2); - // ftmp5[i] < 2*2^106 = 2^107 - - // s1 = ftmp2 = y1 * z2**3 - felem_assign(ftmp6, y1); - // ftmp6[i] < 2^106 - } - - // u2 = x2*z1z1 - smallfelem_mul(tmp, x2, small1); - felem_reduce(ftmp4, tmp); - - // h = ftmp4 = u2 - u1 - felem_diff_zero107(ftmp4, ftmp3); - // ftmp4[i] < 2^107 + 2^101 < 2^108 - felem_shrink(small4, ftmp4); - - x_equal = smallfelem_is_zero(small4); - - // z_out = ftmp5 * h - felem_small_mul(tmp, small4, ftmp5); - felem_reduce(z_out, tmp); - // z_out[i] < 2^101 - - // ftmp = z1 * z1z1 - smallfelem_mul(tmp, small1, small3); - felem_reduce(ftmp, tmp); - - // s2 = tmp = y2 * z1**3 - felem_small_mul(tmp, y2, ftmp); - felem_reduce(ftmp5, tmp); - - // r = ftmp5 = (s2 - s1)*2 - felem_diff_zero107(ftmp5, ftmp6); - // ftmp5[i] < 2^107 + 2^107 = 2^108 - felem_scalar(ftmp5, 2); - // ftmp5[i] < 2^109 - felem_shrink(small1, ftmp5); - y_equal = smallfelem_is_zero(small1); - - if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { - point_double(x3, y3, z3, x1, y1, z1); - return; - } - - // I = ftmp = (2h)**2 - felem_assign(ftmp, ftmp4); - felem_scalar(ftmp, 2); - // ftmp[i] < 2*2^108 = 2^109 - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - - // J = ftmp2 = h * I - felem_mul(tmp, ftmp4, ftmp); - felem_reduce(ftmp2, tmp); - - // V = ftmp4 = U1 * I - felem_mul(tmp, ftmp3, ftmp); - felem_reduce(ftmp4, tmp); - - // x_out = r**2 - J - 2V - smallfelem_square(tmp, small1); - felem_reduce(x_out, tmp); - felem_assign(ftmp3, ftmp4); - felem_scalar(ftmp4, 2); - felem_sum(ftmp4, ftmp2); - // ftmp4[i] < 2*2^101 + 2^101 < 2^103 - felem_diff(x_out, ftmp4); - // x_out[i] < 2^105 + 2^101 - - // y_out = r(V-x_out) - 2 * s1 * J - felem_diff_zero107(ftmp3, x_out); - // ftmp3[i] < 2^107 + 2^101 < 2^108 - felem_small_mul(tmp, small1, ftmp3); - felem_mul(tmp2, ftmp6, ftmp2); - longfelem_scalar(tmp2, 2); - // tmp2[i] < 2*2^67 = 2^68 - longfelem_diff(tmp, tmp2); - // tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 - felem_reduce_zero105(y_out, tmp); - // y_out[i] < 2^106 - - copy_small_conditional(x_out, x2, z1_is_zero); - p256_copy_conditional(x_out, x1, z2_is_zero); - copy_small_conditional(y_out, y2, z1_is_zero); - p256_copy_conditional(y_out, y1, z2_is_zero); - copy_small_conditional(z_out, z2, z1_is_zero); - p256_copy_conditional(z_out, z1, z2_is_zero); - felem_assign(x3, x_out); - felem_assign(y3, y_out); - felem_assign(z3, z_out); -} - -// point_add_small is the same as point_add, except that it operates on -// smallfelems. -static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3, - smallfelem x1, smallfelem y1, smallfelem z1, - smallfelem x2, smallfelem y2, smallfelem z2) { - felem felem_x3, felem_y3, felem_z3; - felem felem_x1, felem_y1, felem_z1; - smallfelem_expand(felem_x1, x1); - smallfelem_expand(felem_y1, y1); - smallfelem_expand(felem_z1, z1); - point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2, - y2, z2); - felem_shrink(x3, felem_x3); - felem_shrink(y3, felem_y3); - felem_shrink(z3, felem_z3); -} - -// Base point pre computation -// -------------------------- -// -// Two different sorts of precomputed tables are used in the following code. -// Each contain various points on the curve, where each point is three field -// elements (x, y, z). -// -// For the base point table, z is usually 1 (0 for the point at infinity). -// This table has 2 * 16 elements, starting with the following: -// index | bits | point -// ------+---------+------------------------------ -// 0 | 0 0 0 0 | 0G -// 1 | 0 0 0 1 | 1G -// 2 | 0 0 1 0 | 2^64G -// 3 | 0 0 1 1 | (2^64 + 1)G -// 4 | 0 1 0 0 | 2^128G -// 5 | 0 1 0 1 | (2^128 + 1)G -// 6 | 0 1 1 0 | (2^128 + 2^64)G -// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G -// 8 | 1 0 0 0 | 2^192G -// 9 | 1 0 0 1 | (2^192 + 1)G -// 10 | 1 0 1 0 | (2^192 + 2^64)G -// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G -// 12 | 1 1 0 0 | (2^192 + 2^128)G -// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G -// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G -// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G -// followed by a copy of this with each element multiplied by 2^32. -// -// The reason for this is so that we can clock bits into four different -// locations when doing simple scalar multiplies against the base point, -// and then another four locations using the second 16 elements. -// -// Tables for other points have table[i] = iG for i in 0 .. 16. - -// g_pre_comp is the table of precomputed base points -static const smallfelem g_pre_comp[2][16][3] = { - {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, - {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, - 0x6b17d1f2e12c4247}, - {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, - 0x4fe342e2fe1a7f9b}, - {1, 0, 0, 0}}, - {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, - 0x0fa822bc2811aaa5}, - {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, - 0xbff44ae8f5dba80d}, - {1, 0, 0, 0}}, - {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, - 0x300a4bbc89d6726f}, - {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, - 0x72aac7e0d09b4644}, - {1, 0, 0, 0}}, - {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, - 0x447d739beedb5e67}, - {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, - 0x2d4825ab834131ee}, - {1, 0, 0, 0}}, - {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, - 0xef9519328a9c72ff}, - {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, - 0x611e9fc37dbb2c9b}, - {1, 0, 0, 0}}, - {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, - 0x550663797b51f5d8}, - {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, - 0x157164848aecb851}, - {1, 0, 0, 0}}, - {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, - 0xeb5d7745b21141ea}, - {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, - 0xeafd72ebdbecc17b}, - {1, 0, 0, 0}}, - {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, - 0xa6d39677a7849276}, - {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, - 0x674f84749b0b8816}, - {1, 0, 0, 0}}, - {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, - 0x4e769e7672c9ddad}, - {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, - 0x42b99082de830663}, - {1, 0, 0, 0}}, - {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, - 0x78878ef61c6ce04d}, - {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, - 0xb6cb3f5d7b72c321}, - {1, 0, 0, 0}}, - {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, - 0x0c88bc4d716b1287}, - {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, - 0xdd5ddea3f3901dc6}, - {1, 0, 0, 0}}, - {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, - 0x68f344af6b317466}, - {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, - 0x31b9c405f8540a20}, - {1, 0, 0, 0}}, - {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, - 0x4052bf4b6f461db9}, - {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, - 0xfecf4d5190b0fc61}, - {1, 0, 0, 0}}, - {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, - 0x1eddbae2c802e41a}, - {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, - 0x43104d86560ebcfc}, - {1, 0, 0, 0}}, - {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, - 0xb48e26b484f7a21c}, - {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, - 0xfac015404d4d3dab}, - {1, 0, 0, 0}}}, - {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, - {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, - 0x7fe36b40af22af89}, - {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, - 0xe697d45825b63624}, - {1, 0, 0, 0}}, - {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, - 0x4a5b506612a677a6}, - {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, - 0xeb13461ceac089f1}, - {1, 0, 0, 0}}, - {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, - 0x0781b8291c6a220a}, - {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, - 0x690cde8df0151593}, - {1, 0, 0, 0}}, - {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, - 0x8a535f566ec73617}, - {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, - 0x0455c08468b08bd7}, - {1, 0, 0, 0}}, - {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, - 0x06bada7ab77f8276}, - {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, - 0x5b476dfd0e6cb18a}, - {1, 0, 0, 0}}, - {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, - 0x3e29864e8a2ec908}, - {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, - 0x239b90ea3dc31e7e}, - {1, 0, 0, 0}}, - {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, - 0x820f4dd949f72ff7}, - {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, - 0x140406ec783a05ec}, - {1, 0, 0, 0}}, - {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, - 0x68f6b8542783dfee}, - {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, - 0xcbe1feba92e40ce6}, - {1, 0, 0, 0}}, - {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, - 0xd0b2f94d2f420109}, - {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, - 0x971459828b0719e5}, - {1, 0, 0, 0}}, - {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, - 0x961610004a866aba}, - {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, - 0x7acb9fadcee75e44}, - {1, 0, 0, 0}}, - {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, - 0x24eb9acca333bf5b}, - {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, - 0x69f891c5acd079cc}, - {1, 0, 0, 0}}, - {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, - 0xe51f547c5972a107}, - {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, - 0x1c309a2b25bb1387}, - {1, 0, 0, 0}}, - {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, - 0x20b87b8aa2c4e503}, - {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, - 0xf5c6fa49919776be}, - {1, 0, 0, 0}}, - {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, - 0x1ed7d1b9332010b9}, - {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, - 0x3a2b03f03217257a}, - {1, 0, 0, 0}}, - {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, - 0x15fee545c78dd9f6}, - {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, - 0x4ab5b6b2b8753f81}, - {1, 0, 0, 0}}}}; - -// select_point selects the |idx|th point from a precomputation table and -// copies it to out. -static void select_point(const uint64_t idx, size_t size, - const smallfelem pre_comp[/*size*/][3], - smallfelem out[3]) { - uint64_t *outlimbs = &out[0][0]; - OPENSSL_memset(outlimbs, 0, 3 * sizeof(smallfelem)); - - for (size_t i = 0; i < size; i++) { - const uint64_t *inlimbs = (const uint64_t *)&pre_comp[i][0][0]; - uint64_t mask = i ^ idx; - mask |= mask >> 4; - mask |= mask >> 2; - mask |= mask >> 1; - mask &= 1; - mask--; - for (size_t j = 0; j < NLIMBS * 3; j++) { - outlimbs[j] |= inlimbs[j] & mask; - } - } -} - -// get_bit returns the |i|th bit in |in| -static char get_bit(const felem_bytearray in, int i) { - if (i < 0 || i >= 256) { - return 0; - } - return (in[i >> 3] >> (i & 7)) & 1; -} - -// Interleaved point multiplication using precomputed point multiples: The -// small point multiples 0*P, 1*P, ..., 17*P are in p_pre_comp, the scalar -// in p_scalar, if non-NULL. If g_scalar is non-NULL, we also add this multiple -// of the generator, using certain (large) precomputed multiples in g_pre_comp. -// Output point (X, Y, Z) is stored in x_out, y_out, z_out. -static void batch_mul(felem x_out, felem y_out, felem z_out, - const uint8_t *p_scalar, const uint8_t *g_scalar, - const smallfelem p_pre_comp[17][3]) { - felem nq[3], ftmp; - smallfelem tmp[3]; - uint64_t bits; - uint8_t sign, digit; - - // set nq to the point at infinity - OPENSSL_memset(nq, 0, 3 * sizeof(felem)); - - // Loop over both scalars msb-to-lsb, interleaving additions of multiples - // of the generator (two in each of the last 32 rounds) and additions of p - // (every 5th round). - - int skip = 1; // save two point operations in the first round - size_t i = p_scalar != NULL ? 255 : 31; - for (;;) { - // double - if (!skip) { - point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); - } - - // add multiples of the generator - if (g_scalar != NULL && i <= 31) { - // first, look 32 bits upwards - bits = get_bit(g_scalar, i + 224) << 3; - bits |= get_bit(g_scalar, i + 160) << 2; - bits |= get_bit(g_scalar, i + 96) << 1; - bits |= get_bit(g_scalar, i + 32); - // select the point to add, in constant time - select_point(bits, 16, g_pre_comp[1], tmp); - - if (!skip) { - point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, - tmp[0], tmp[1], tmp[2]); - } else { - smallfelem_expand(nq[0], tmp[0]); - smallfelem_expand(nq[1], tmp[1]); - smallfelem_expand(nq[2], tmp[2]); - skip = 0; - } - - // second, look at the current position - bits = get_bit(g_scalar, i + 192) << 3; - bits |= get_bit(g_scalar, i + 128) << 2; - bits |= get_bit(g_scalar, i + 64) << 1; - bits |= get_bit(g_scalar, i); - // select the point to add, in constant time - select_point(bits, 16, g_pre_comp[0], tmp); - point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0], - tmp[1], tmp[2]); - } - - // do other additions every 5 doublings - if (p_scalar != NULL && i % 5 == 0) { - bits = get_bit(p_scalar, i + 4) << 5; - bits |= get_bit(p_scalar, i + 3) << 4; - bits |= get_bit(p_scalar, i + 2) << 3; - bits |= get_bit(p_scalar, i + 1) << 2; - bits |= get_bit(p_scalar, i) << 1; - bits |= get_bit(p_scalar, i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); - - // select the point to add or subtract, in constant time. - select_point(digit, 17, p_pre_comp, tmp); - smallfelem_neg(ftmp, tmp[1]); // (X, -Y, Z) is the negative - // point - copy_small_conditional(ftmp, tmp[1], (((limb)sign) - 1)); - felem_contract(tmp[1], ftmp); - - if (!skip) { - point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */, - tmp[0], tmp[1], tmp[2]); - } else { - smallfelem_expand(nq[0], tmp[0]); - smallfelem_expand(nq[1], tmp[1]); - smallfelem_expand(nq[2], tmp[2]); - skip = 0; - } - } - - if (i == 0) { - break; - } - --i; - } - felem_assign(x_out, nq[0]); - felem_assign(y_out, nq[1]); - felem_assign(z_out, nq[2]); -} - -// OPENSSL EC_METHOD FUNCTIONS - -// Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = -// (X/Z^2, Y/Z^3). -static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) { - felem z1, z2, x_in, y_in; - smallfelem x_out, y_out; - longfelem tmp; - - if (EC_POINT_is_at_infinity(group, point)) { - OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); - return 0; - } - if (!BN_to_felem(x_in, &point->X) || - !BN_to_felem(y_in, &point->Y) || - !BN_to_felem(z1, &point->Z)) { - return 0; - } - felem_inv(z2, z1); - felem_square(tmp, z2); - felem_reduce(z1, tmp); - - if (x != NULL) { - felem_mul(tmp, x_in, z1); - felem_reduce(x_in, tmp); - felem_contract(x_out, x_in); - if (!smallfelem_to_BN(x, x_out)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - return 0; - } - } - - if (y != NULL) { - felem_mul(tmp, z1, z2); - felem_reduce(z1, tmp); - felem_mul(tmp, y_in, z1); - felem_reduce(y_in, tmp); - felem_contract(y_out, y_in); - if (!smallfelem_to_BN(y, y_out)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - return 0; - } - } - - return 1; -} - -static int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, - const EC_SCALAR *g_scalar, - const EC_POINT *p, - const EC_SCALAR *p_scalar, BN_CTX *ctx) { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y, *z, *tmp_scalar; - smallfelem p_pre_comp[17][3]; - smallfelem x_in, y_in, z_in; - felem x_out, y_out, z_out; - - if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) { - return 0; - } - } - - BN_CTX_start(ctx); - if ((x = BN_CTX_get(ctx)) == NULL || - (y = BN_CTX_get(ctx)) == NULL || - (z = BN_CTX_get(ctx)) == NULL || - (tmp_scalar = BN_CTX_get(ctx)) == NULL) { - goto err; - } - - if (p != NULL && p_scalar != NULL) { - // We treat NULL scalars as 0, and NULL points as points at infinity, i.e., - // they contribute nothing to the linear combination. - OPENSSL_memset(&p_pre_comp, 0, sizeof(p_pre_comp)); - // Precompute multiples. - if (!BN_to_felem(x_out, &p->X) || - !BN_to_felem(y_out, &p->Y) || - !BN_to_felem(z_out, &p->Z)) { - goto err; - } - felem_shrink(p_pre_comp[1][0], x_out); - felem_shrink(p_pre_comp[1][1], y_out); - felem_shrink(p_pre_comp[1][2], z_out); - for (size_t j = 2; j <= 16; ++j) { - if (j & 1) { - point_add_small(p_pre_comp[j][0], p_pre_comp[j][1], - p_pre_comp[j][2], p_pre_comp[1][0], - p_pre_comp[1][1], p_pre_comp[1][2], - p_pre_comp[j - 1][0], p_pre_comp[j - 1][1], - p_pre_comp[j - 1][2]); - } else { - point_double_small(p_pre_comp[j][0], p_pre_comp[j][1], - p_pre_comp[j][2], p_pre_comp[j / 2][0], - p_pre_comp[j / 2][1], p_pre_comp[j / 2][2]); - } - } - } - - batch_mul(x_out, y_out, z_out, - (p != NULL && p_scalar != NULL) ? p_scalar->bytes : NULL, - g_scalar != NULL ? g_scalar->bytes : NULL, - (const smallfelem(*)[3]) & p_pre_comp); - - // reduce the output to its unique minimal representation - felem_contract(x_in, x_out); - felem_contract(y_in, y_out); - felem_contract(z_in, z_out); - if (!smallfelem_to_BN(x, x_in) || - !smallfelem_to_BN(y, y_in) || - !smallfelem_to_BN(z, z_in)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - goto err; - } - ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - -err: - BN_CTX_end(ctx); - BN_CTX_free(new_ctx); - return ret; -} - -DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp256_method) { - out->group_init = ec_GFp_simple_group_init; - out->group_finish = ec_GFp_simple_group_finish; - out->group_set_curve = ec_GFp_simple_group_set_curve; - out->point_get_affine_coordinates = - ec_GFp_nistp256_point_get_affine_coordinates; - out->mul = ec_GFp_nistp256_points_mul; - out->field_mul = ec_GFp_simple_field_mul; - out->field_sqr = ec_GFp_simple_field_sqr; - out->field_encode = NULL; - out->field_decode = NULL; -}; - -#endif // 64_BIT && !WINDOWS diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64-table.h b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64-table.h index 575a2034a..bcb05f674 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64-table.h +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64-table.h @@ -24,6 +24,8 @@ // in order to increase the chances of using a large page but that appears to // lead to invalid ELF files being produced. +// This file is generated by make_p256-x86_64-table.go. + static const alignas(4096) BN_ULONG ecp_nistz256_precomputed[37][64 * sizeof(P256_POINT_AFFINE) / sizeof(BN_ULONG)] = { @@ -2843,264 +2845,262 @@ static const alignas(4096) BN_ULONG TOBN(0x5e3295a6, 0x4e969285), TOBN(0x22aabc59, 0xa6a45670), TOBN(0xb929714c, 0x5f5942bc), TOBN(0x9a6168bd, 0xfa3182ed), TOBN(0x2216a665, 0x104152ba), TOBN(0x46908d03, 0xb6926368)}, - { - TOBN(0xa9f5d874, 0x5a1251fb), TOBN(0x967747a8, 0xc72725c7), - TOBN(0x195c33e5, 0x31ffe89e), TOBN(0x609d210f, 0xe964935e), - TOBN(0xcafd6ca8, 0x2fe12227), TOBN(0xaf9b5b96, 0x0426469d), - TOBN(0x2e9ee04c, 0x5693183c), TOBN(0x1084a333, 0xc8146fef), - TOBN(0x96649933, 0xaed1d1f7), TOBN(0x566eaff3, 0x50563090), - TOBN(0x345057f0, 0xad2e39cf), TOBN(0x148ff65b, 0x1f832124), - TOBN(0x042e89d4, 0xcf94cf0d), TOBN(0x319bec84, 0x520c58b3), - TOBN(0x2a267626, 0x5361aa0d), TOBN(0xc86fa302, 0x8fbc87ad), - TOBN(0xfc83d2ab, 0x5c8b06d5), TOBN(0xb1a785a2, 0xfe4eac46), - TOBN(0xb99315bc, 0x846f7779), TOBN(0xcf31d816, 0xef9ea505), - TOBN(0x2391fe6a, 0x15d7dc85), TOBN(0x2f132b04, 0xb4016b33), - TOBN(0x29547fe3, 0x181cb4c7), TOBN(0xdb66d8a6, 0x650155a1), - TOBN(0x6b66d7e1, 0xadc1696f), TOBN(0x98ebe593, 0x0acd72d0), - TOBN(0x65f24550, 0xcc1b7435), TOBN(0xce231393, 0xb4b9a5ec), - TOBN(0x234a22d4, 0xdb067df9), TOBN(0x98dda095, 0xcaff9b00), - TOBN(0x1bbc75a0, 0x6100c9c1), TOBN(0x1560a9c8, 0x939cf695), - TOBN(0xcf006d3e, 0x99e0925f), TOBN(0x2dd74a96, 0x6322375a), - TOBN(0xc58b446a, 0xb56af5ba), TOBN(0x50292683, 0xe0b9b4f1), - TOBN(0xe2c34cb4, 0x1aeaffa3), TOBN(0x8b17203f, 0x9b9587c1), - TOBN(0x6d559207, 0xead1350c), TOBN(0x2b66a215, 0xfb7f9604), - TOBN(0x0850325e, 0xfe51bf74), TOBN(0x9c4f579e, 0x5e460094), - TOBN(0x5c87b92a, 0x76da2f25), TOBN(0x889de4e0, 0x6febef33), - TOBN(0x6900ec06, 0x646083ce), TOBN(0xbe2a0335, 0xbfe12773), - TOBN(0xadd1da35, 0xc5344110), TOBN(0x757568b7, 0xb802cd20), - TOBN(0x75559779, 0x00f7e6c8), TOBN(0x38e8b94f, 0x0facd2f0), - TOBN(0xfea1f3af, 0x03fde375), TOBN(0x5e11a1d8, 0x75881dfc), - TOBN(0xb3a6b02e, 0xc1e2f2ef), TOBN(0x193d2bbb, 0xc605a6c5), - TOBN(0x325ffeee, 0x339a0b2d), TOBN(0x27b6a724, 0x9e0c8846), - TOBN(0xe4050f1c, 0xf1c367ca), TOBN(0x9bc85a9b, 0xc90fbc7d), - TOBN(0xa373c4a2, 0xe1a11032), TOBN(0xb64232b7, 0xad0393a9), - TOBN(0xf5577eb0, 0x167dad29), TOBN(0x1604f301, 0x94b78ab2), - TOBN(0x0baa94af, 0xe829348b), TOBN(0x77fbd8dd, 0x41654342), - TOBN(0xdab50ea5, 0xb964e39a), TOBN(0xd4c29e3c, 0xd0d3c76e), - TOBN(0x80dae67c, 0x56d11964), TOBN(0x7307a8bf, 0xe5ffcc2f), - TOBN(0x65bbc1aa, 0x91708c3b), TOBN(0xa151e62c, 0x28bf0eeb), - TOBN(0x6cb53381, 0x6fa34db7), TOBN(0x5139e05c, 0xa29403a8), - TOBN(0x6ff651b4, 0x94a7cd2e), TOBN(0x5671ffd1, 0x0699336c), - TOBN(0x6f5fd2cc, 0x979a896a), TOBN(0x11e893a8, 0xd8148cef), - TOBN(0x988906a1, 0x65cf7b10), TOBN(0x81b67178, 0xc50d8485), - TOBN(0x7c0deb35, 0x8a35b3de), TOBN(0x423ac855, 0xc1d29799), - TOBN(0xaf580d87, 0xdac50b74), TOBN(0x28b2b89f, 0x5869734c), - TOBN(0x99a3b936, 0x874e28fb), TOBN(0xbb2c9190, 0x25f3f73a), - TOBN(0x199f6918, 0x84a9d5b7), TOBN(0x7ebe2325, 0x7e770374), - TOBN(0xf442e107, 0x0738efe2), TOBN(0xcf9f3f56, 0xcf9082d2), - TOBN(0x719f69e1, 0x09618708), TOBN(0xcc9e8364, 0xc183f9b1), - TOBN(0xec203a95, 0x366a21af), TOBN(0x6aec5d6d, 0x068b141f), - TOBN(0xee2df78a, 0x994f04e9), TOBN(0xb39ccae8, 0x271245b0), - TOBN(0xb875a4a9, 0x97e43f4f), TOBN(0x507dfe11, 0xdb2cea98), - TOBN(0x4fbf81cb, 0x489b03e9), TOBN(0xdb86ec5b, 0x6ec414fa), - TOBN(0xfad444f9, 0xf51b3ae5), TOBN(0xca7d33d6, 0x1914e3fe), - TOBN(0xa9c32f5c, 0x0ae6c4d0), TOBN(0xa9ca1d1e, 0x73969568), - TOBN(0x98043c31, 0x1aa7467e), TOBN(0xe832e75c, 0xe21b5ac6), - TOBN(0x314b7aea, 0x5232123d), TOBN(0x08307c8c, 0x65ae86db), - TOBN(0x06e7165c, 0xaa4668ed), TOBN(0xb170458b, 0xb4d3ec39), - TOBN(0x4d2e3ec6, 0xc19bb986), TOBN(0xc5f34846, 0xae0304ed), - TOBN(0x917695a0, 0x6c9f9722), TOBN(0x6c7f7317, 0x4cab1c0a), - TOBN(0x6295940e, 0x9d6d2e8b), TOBN(0xd318b8c1, 0x549f7c97), - TOBN(0x22453204, 0x97713885), TOBN(0x468d834b, 0xa8a440fe), - TOBN(0xd81fe5b2, 0xbfba796e), TOBN(0x152364db, 0x6d71f116), - TOBN(0xbb8c7c59, 0xb5b66e53), TOBN(0x0b12c61b, 0x2641a192), - TOBN(0x31f14802, 0xfcf0a7fd), TOBN(0x42fd0789, 0x5488b01e), - TOBN(0x71d78d6d, 0x9952b498), TOBN(0x8eb572d9, 0x07ac5201), - TOBN(0xe0a2a44c, 0x4d194a88), TOBN(0xd2b63fd9, 0xba017e66), - TOBN(0x78efc6c8, 0xf888aefc), TOBN(0xb76f6bda, 0x4a881a11), - TOBN(0x187f314b, 0xb46c2397), TOBN(0x004cf566, 0x5ded2819), - TOBN(0xa9ea5704, 0x38764d34), TOBN(0xbba45217, 0x78084709), - TOBN(0x06474571, 0x1171121e), TOBN(0xad7b7eb1, 0xe7c9b671), - TOBN(0xdacfbc40, 0x730f7507), TOBN(0x178cd8c6, 0xc7ad7bd1), - TOBN(0xbf0be101, 0xb2a67238), TOBN(0x3556d367, 0xaf9c14f2), - TOBN(0x104b7831, 0xa5662075), TOBN(0x58ca59bb, 0x79d9e60a), - TOBN(0x4bc45392, 0xa569a73b), TOBN(0x517a52e8, 0x5698f6c9), - TOBN(0x85643da5, 0xaeadd755), TOBN(0x1aed0cd5, 0x2a581b84), - TOBN(0xb9b4ff84, 0x80af1372), TOBN(0x244c3113, 0xf1ba5d1f), - TOBN(0x2a5dacbe, 0xf5f98d31), TOBN(0x2c3323e8, 0x4375bc2a), - TOBN(0x17a3ab4a, 0x5594b1dd), TOBN(0xa1928bfb, 0xceb4797e), - TOBN(0xe83af245, 0xe4886a19), TOBN(0x8979d546, 0x72b5a74a), - TOBN(0xa0f726bc, 0x19f9e967), TOBN(0xd9d03152, 0xe8fbbf4e), - TOBN(0xcfd6f51d, 0xb7707d40), TOBN(0x633084d9, 0x63f6e6e0), - TOBN(0xedcd9cdc, 0x55667eaf), TOBN(0x73b7f92b, 0x2e44d56f), - TOBN(0xfb2e39b6, 0x4e962b14), TOBN(0x7d408f6e, 0xf671fcbf), - TOBN(0xcc634ddc, 0x164a89bb), TOBN(0x74a42bb2, 0x3ef3bd05), - TOBN(0x1280dbb2, 0x428decbb), TOBN(0x6103f6bb, 0x402c8596), - TOBN(0xfa2bf581, 0x355a5752), TOBN(0x562f96a8, 0x00946674), - TOBN(0x4e4ca16d, 0x6da0223b), TOBN(0xfe47819f, 0x28d3aa25), - TOBN(0x9eea3075, 0xf8dfcf8a), TOBN(0xa284f0aa, 0x95669825), - TOBN(0xb3fca250, 0x867d3fd8), TOBN(0x20757b5f, 0x269d691e), - TOBN(0xf2c24020, 0x93b8a5de), TOBN(0xd3f93359, 0xebc06da6), - TOBN(0x1178293e, 0xb2739c33), TOBN(0xd2a3e770, 0xbcd686e5), - TOBN(0xa76f49f4, 0xcd941534), TOBN(0x0d37406b, 0xe3c71c0e), - TOBN(0x172d9397, 0x3b97f7e3), TOBN(0xec17e239, 0xbd7fd0de), - TOBN(0xe3290551, 0x6f496ba2), TOBN(0x6a693172, 0x36ad50e7), - TOBN(0xc4e539a2, 0x83e7eff5), TOBN(0x752737e7, 0x18e1b4cf), - TOBN(0xa2f7932c, 0x68af43ee), TOBN(0x5502468e, 0x703d00bd), - TOBN(0xe5dc978f, 0x2fb061f5), TOBN(0xc9a1904a, 0x28c815ad), - TOBN(0xd3af538d, 0x470c56a4), TOBN(0x159abc5f, 0x193d8ced), - TOBN(0x2a37245f, 0x20108ef3), TOBN(0xfa17081e, 0x223f7178), - TOBN(0x27b0fb2b, 0x10c8c0f5), TOBN(0x2102c3ea, 0x40650547), - TOBN(0x594564df, 0x8ac3bfa7), TOBN(0x98102033, 0x509dad96), - TOBN(0x6989643f, 0xf1d18a13), TOBN(0x35eebd91, 0xd7fc5af0), - TOBN(0x078d096a, 0xfaeaafd8), TOBN(0xb7a89341, 0xdef3de98), - TOBN(0x2a206e8d, 0xecf2a73a), TOBN(0x066a6397, 0x8e551994), - TOBN(0x3a6a088a, 0xb98d53a2), TOBN(0x0ce7c67c, 0x2d1124aa), - TOBN(0x48cec671, 0x759a113c), TOBN(0xe3b373d3, 0x4f6f67fa), - TOBN(0x5455d479, 0xfd36727b), TOBN(0xe5a428ee, 0xa13c0d81), - TOBN(0xb853dbc8, 0x1c86682b), TOBN(0xb78d2727, 0xb8d02b2a), - TOBN(0xaaf69bed, 0x8ebc329a), TOBN(0xdb6b40b3, 0x293b2148), - TOBN(0xe42ea77d, 0xb8c4961f), TOBN(0xb1a12f7c, 0x20e5e0ab), - TOBN(0xa0ec5274, 0x79e8b05e), TOBN(0x68027391, 0xfab60a80), - TOBN(0x6bfeea5f, 0x16b1bd5e), TOBN(0xf957e420, 0x4de30ad3), - TOBN(0xcbaf664e, 0x6a353b9e), TOBN(0x5c873312, 0x26d14feb), - TOBN(0x4e87f98c, 0xb65f57cb), TOBN(0xdb60a621, 0x5e0cdd41), - TOBN(0x67c16865, 0xa6881440), TOBN(0x1093ef1a, 0x46ab52aa), - TOBN(0xc095afb5, 0x3f4ece64), TOBN(0x6a6bb02e, 0x7604551a), - TOBN(0x55d44b4e, 0x0b26b8cd), TOBN(0xe5f9a999, 0xf971268a), - TOBN(0xc08ec425, 0x11a7de84), TOBN(0x83568095, 0xfda469dd), - TOBN(0x737bfba1, 0x6c6c90a2), TOBN(0x1cb9c4a0, 0xbe229831), - TOBN(0x93bccbba, 0xbb2eec64), TOBN(0xa0c23b64, 0xda03adbe), - TOBN(0x5f7aa00a, 0xe0e86ac4), TOBN(0x470b941e, 0xfc1401e6), - TOBN(0x5ad8d679, 0x9df43574), TOBN(0x4ccfb8a9, 0x0f65d810), - TOBN(0x1bce80e3, 0xaa7fbd81), TOBN(0x273291ad, 0x9508d20a), - TOBN(0xf5c4b46b, 0x42a92806), TOBN(0x810684ec, 0xa86ab44a), - TOBN(0x4591640b, 0xca0bc9f8), TOBN(0xb5efcdfc, 0x5c4b6054), - TOBN(0x16fc8907, 0x6e9edd12), TOBN(0xe29d0b50, 0xd4d792f9), - TOBN(0xa45fd01c, 0x9b03116d), TOBN(0x85035235, 0xc81765a4), - TOBN(0x1fe2a9b2, 0xb4b4b67c), TOBN(0xc1d10df0, 0xe8020604), - TOBN(0x9d64abfc, 0xbc8058d8), TOBN(0x8943b9b2, 0x712a0fbb), - TOBN(0x90eed914, 0x3b3def04), TOBN(0x85ab3aa2, 0x4ce775ff), - TOBN(0x605fd4ca, 0x7bbc9040), TOBN(0x8b34a564, 0xe2c75dfb), - TOBN(0x41ffc94a, 0x10358560), TOBN(0x2d8a5072, 0x9e5c28aa), - TOBN(0xe915a0fc, 0x4cc7eb15), TOBN(0xe9efab05, 0x8f6d0f5d), - TOBN(0xdbab47a9, 0xd19e9b91), TOBN(0x8cfed745, 0x0276154c), - TOBN(0x154357ae, 0x2cfede0d), TOBN(0x520630df, 0x19f5a4ef), - TOBN(0x25759f7c, 0xe382360f), TOBN(0xb6db05c9, 0x88bf5857), - TOBN(0x2917d61d, 0x6c58d46c), TOBN(0x14f8e491, 0xfd20cb7a), - TOBN(0xb68a727a, 0x11c20340), TOBN(0x0386f86f, 0xaf7ccbb6), - TOBN(0x5c8bc6cc, 0xfee09a20), TOBN(0x7d76ff4a, 0xbb7eea35), - TOBN(0xa7bdebe7, 0xdb15be7a), TOBN(0x67a08054, 0xd89f0302), - TOBN(0x56bf0ea9, 0xc1193364), TOBN(0xc8244467, 0x62837ebe), - TOBN(0x32bd8e8b, 0x20d841b8), TOBN(0x127a0548, 0xdbb8a54f), - TOBN(0x83dd4ca6, 0x63b20236), TOBN(0x87714718, 0x203491fa), - TOBN(0x4dabcaaa, 0xaa8a5288), TOBN(0x91cc0c8a, 0xaf23a1c9), - TOBN(0x34c72c6a, 0x3f220e0c), TOBN(0xbcc20bdf, 0x1232144a), - TOBN(0x6e2f42da, 0xa20ede1b), TOBN(0xc441f00c, 0x74a00515), - TOBN(0xbf46a5b6, 0x734b8c4b), TOBN(0x57409503, 0x7b56c9a4), - TOBN(0x9f735261, 0xe4585d45), TOBN(0x9231faed, 0x6734e642), - TOBN(0x1158a176, 0xbe70ee6c), TOBN(0x35f1068d, 0x7c3501bf), - TOBN(0x6beef900, 0xa2d26115), TOBN(0x649406f2, 0xef0afee3), - TOBN(0x3f43a60a, 0xbc2420a1), TOBN(0x509002a7, 0xd5aee4ac), - TOBN(0xb46836a5, 0x3ff3571b), TOBN(0x24f98b78, 0x837927c1), - TOBN(0x6254256a, 0x4533c716), TOBN(0xf27abb0b, 0xd07ee196), - TOBN(0xd7cf64fc, 0x5c6d5bfd), TOBN(0x6915c751, 0xf0cd7a77), - TOBN(0xd9f59012, 0x8798f534), TOBN(0x772b0da8, 0xf81d8b5f), - TOBN(0x1244260c, 0x2e03fa69), TOBN(0x36cf0e3a, 0x3be1a374), - TOBN(0x6e7c1633, 0xef06b960), TOBN(0xa71a4c55, 0x671f90f6), - TOBN(0x7a941251, 0x33c673db), TOBN(0xc0bea510, 0x73e8c131), - TOBN(0x61a8a699, 0xd4f6c734), TOBN(0x25e78c88, 0x341ed001), - TOBN(0x5c18acf8, 0x8e2f7d90), TOBN(0xfdbf33d7, 0x77be32cd), - TOBN(0x0a085cd7, 0xd2eb5ee9), TOBN(0x2d702cfb, 0xb3201115), - TOBN(0xb6e0ebdb, 0x85c88ce8), TOBN(0x23a3ce3c, 0x1e01d617), - TOBN(0x3041618e, 0x567333ac), TOBN(0x9dd0fd8f, 0x157edb6b), - TOBN(0x27f74702, 0xb57872b8), TOBN(0x2ef26b4f, 0x657d5fe1), - TOBN(0x95426f0a, 0x57cf3d40), TOBN(0x847e2ad1, 0x65a6067a), - TOBN(0xd474d9a0, 0x09996a74), TOBN(0x16a56acd, 0x2a26115c), - TOBN(0x02a615c3, 0xd16f4d43), TOBN(0xcc3fc965, 0xaadb85b7), - TOBN(0x386bda73, 0xce07d1b0), TOBN(0xd82910c2, 0x58ad4178), - TOBN(0x124f82cf, 0xcd2617f4), TOBN(0xcc2f5e8d, 0xef691770), - TOBN(0x82702550, 0xb8c30ccc), TOBN(0x7b856aea, 0x1a8e575a), - TOBN(0xbb822fef, 0xb1ab9459), TOBN(0x085928bc, 0xec24e38e), - TOBN(0x5d0402ec, 0xba8f4b4d), TOBN(0xc07cd4ba, 0x00b4d58b), - TOBN(0x5d8dffd5, 0x29227e7a), TOBN(0x61d44d0c, 0x31bf386f), - TOBN(0xe486dc2b, 0x135e6f4d), TOBN(0x680962eb, 0xe79410ef), - TOBN(0xa61bd343, 0xf10088b5), TOBN(0x6aa76076, 0xe2e28686), - TOBN(0x80463d11, 0x8fb98871), TOBN(0xcb26f5c3, 0xbbc76aff), - TOBN(0xd4ab8edd, 0xfbe03614), TOBN(0xc8eb579b, 0xc0cf2dee), - TOBN(0xcc004c15, 0xc93bae41), TOBN(0x46fbae5d, 0x3aeca3b2), - TOBN(0x671235cf, 0x0f1e9ab1), TOBN(0xadfba934, 0x9ec285c1), - TOBN(0x88ded013, 0xf216c980), TOBN(0xc8ac4fb8, 0xf79e0bc1), - TOBN(0xa29b89c6, 0xfb97a237), TOBN(0xb697b780, 0x9922d8e7), - TOBN(0x3142c639, 0xddb945b5), TOBN(0x447b06c7, 0xe094c3a9), - TOBN(0xcdcb3642, 0x72266c90), TOBN(0x633aad08, 0xa9385046), - TOBN(0xa36c936b, 0xb57c6477), TOBN(0x871f8b64, 0xe94dbcc6), - TOBN(0x28d0fb62, 0xa591a67b), TOBN(0x9d40e081, 0xc1d926f5), - TOBN(0x3111eaf6, 0xf2d84b5a), TOBN(0x228993f9, 0xa565b644), - TOBN(0x0ccbf592, 0x2c83188b), TOBN(0xf87b30ab, 0x3df3e197), - TOBN(0xb8658b31, 0x7642bca8), TOBN(0x1a032d7f, 0x52800f17), - TOBN(0x051dcae5, 0x79bf9445), TOBN(0xeba6b8ee, 0x54a2e253), - TOBN(0x5c8b9cad, 0xd4485692), TOBN(0x84bda40e, 0x8986e9be), - TOBN(0xd16d16a4, 0x2f0db448), TOBN(0x8ec80050, 0xa14d4188), - TOBN(0xb2b26107, 0x98fa7aaa), TOBN(0x41209ee4, 0xf073aa4e), - TOBN(0xf1570359, 0xf2d6b19b), TOBN(0xcbe6868c, 0xfc577caf), - TOBN(0x186c4bdc, 0x32c04dd3), TOBN(0xa6c35fae, 0xcfeee397), - TOBN(0xb4a1b312, 0xf086c0cf), TOBN(0xe0a5ccc6, 0xd9461fe2), - TOBN(0xc32278aa, 0x1536189f), TOBN(0x1126c55f, 0xba6df571), - TOBN(0x0f71a602, 0xb194560e), TOBN(0x8b2d7405, 0x324bd6e1), - TOBN(0x8481939e, 0x3738be71), TOBN(0xb5090b1a, 0x1a4d97a9), - TOBN(0x116c65a3, 0xf05ba915), TOBN(0x21863ad3, 0xaae448aa), - TOBN(0xd24e2679, 0xa7aae5d3), TOBN(0x7076013d, 0x0de5c1c4), - TOBN(0x2d50f8ba, 0xbb05b629), TOBN(0x73c1abe2, 0x6e66efbb), - TOBN(0xefd4b422, 0xf2488af7), TOBN(0xe4105d02, 0x663ba575), - TOBN(0x7eb60a8b, 0x53a69457), TOBN(0x62210008, 0xc945973b), - TOBN(0xfb255478, 0x77a50ec6), TOBN(0xbf0392f7, 0x0a37a72c), - TOBN(0xa0a7a19c, 0x4be18e7a), TOBN(0x90d8ea16, 0x25b1e0af), - TOBN(0x7582a293, 0xef953f57), TOBN(0x90a64d05, 0xbdc5465a), - TOBN(0xca79c497, 0xe2510717), TOBN(0x560dbb7c, 0x18cb641f), - TOBN(0x1d8e3286, 0x4b66abfb), TOBN(0xd26f52e5, 0x59030900), - TOBN(0x1ee3f643, 0x5584941a), TOBN(0x6d3b3730, 0x569f5958), - TOBN(0x9ff2a62f, 0x4789dba5), TOBN(0x91fcb815, 0x72b5c9b7), - TOBN(0xf446cb7d, 0x6c8f9a0e), TOBN(0x48f625c1, 0x39b7ecb5), - TOBN(0xbabae801, 0x1c6219b8), TOBN(0xe7a562d9, 0x28ac2f23), - TOBN(0xe1b48732, 0x26e20588), TOBN(0x06ee1cad, 0x775af051), - TOBN(0xda29ae43, 0xfaff79f7), TOBN(0xc141a412, 0x652ee9e0), - TOBN(0x1e127f6f, 0x195f4bd0), TOBN(0x29c6ab4f, 0x072f34f8), - TOBN(0x7b7c1477, 0x30448112), TOBN(0x82b51af1, 0xe4a38656), - TOBN(0x2bf2028a, 0x2f315010), TOBN(0xc9a4a01f, 0x6ea88cd4), - TOBN(0xf63e95d8, 0x257e5818), TOBN(0xdd8efa10, 0xb4519b16), - TOBN(0xed8973e0, 0x0da910bf), TOBN(0xed49d077, 0x5c0fe4a9), - TOBN(0xac3aac5e, 0xb7caee1e), TOBN(0x1033898d, 0xa7f4da57), - TOBN(0x42145c0e, 0x5c6669b9), TOBN(0x42daa688, 0xc1aa2aa0), - TOBN(0x629cc15c, 0x1a1d885a), TOBN(0x25572ec0, 0xf4b76817), - TOBN(0x8312e435, 0x9c8f8f28), TOBN(0x8107f8cd, 0x81965490), - TOBN(0x516ff3a3, 0x6fa6110c), TOBN(0x74fb1eb1, 0xfb93561f), - TOBN(0x6c0c9047, 0x8457522b), TOBN(0xcfd32104, 0x6bb8bdc6), - TOBN(0x2d6884a2, 0xcc80ad57), TOBN(0x7c27fc35, 0x86a9b637), - TOBN(0x3461baed, 0xadf4e8cd), TOBN(0x1d56251a, 0x617242f0), - TOBN(0x0b80d209, 0xc955bef4), TOBN(0xdf02cad2, 0x06adb047), - TOBN(0xf0d7cb91, 0x5ec74fee), TOBN(0xd2503375, 0x1111ba44), - TOBN(0x9671755e, 0xdf53cb36), TOBN(0x54dcb612, 0x3368551b), - TOBN(0x66d69aac, 0xc8a025a4), TOBN(0x6be946c6, 0xe77ef445), - TOBN(0x719946d1, 0xa995e094), TOBN(0x65e848f6, 0xe51e04d8), - TOBN(0xe62f3300, 0x6a1e3113), TOBN(0x1541c7c1, 0x501de503), - TOBN(0x4daac9fa, 0xf4acfade), TOBN(0x0e585897, 0x44cd0b71), - TOBN(0x544fd869, 0x0a51cd77), TOBN(0x60fc20ed, 0x0031016d), - TOBN(0x58b404ec, 0xa4276867), TOBN(0x46f6c3cc, 0x34f34993), - TOBN(0x477ca007, 0xc636e5bd), TOBN(0x8018f5e5, 0x7c458b47), - TOBN(0xa1202270, 0xe47b668f), TOBN(0xcef48ccd, 0xee14f203), - TOBN(0x23f98bae, 0x62ff9b4d), TOBN(0x55acc035, 0xc589eddd), - TOBN(0x3fe712af, 0x64db4444), TOBN(0x19e9d634, 0xbecdd480), - TOBN(0xe08bc047, 0xa930978a), TOBN(0x2dbf24ec, 0xa1280733), - TOBN(0x3c0ae38c, 0x2cd706b2), TOBN(0x5b012a5b, 0x359017b9), - TOBN(0x3943c38c, 0x72e0f5ae), TOBN(0x786167ea, 0x57176fa3), - TOBN(0xe5f9897d, 0x594881dc), TOBN(0x6b5efad8, 0xcfb820c1), - TOBN(0xb2179093, 0xd55018de), TOBN(0x39ad7d32, 0x0bac56ce), - TOBN(0xb55122e0, 0x2cfc0e81), TOBN(0x117c4661, 0xf6d89daa), - TOBN(0x362d01e1, 0xcb64fa09), TOBN(0x6a309b4e, 0x3e9c4ddd), - TOBN(0xfa979fb7, 0xabea49b1), TOBN(0xb4b1d27d, 0x10e2c6c5), - TOBN(0xbd61c2c4, 0x23afde7a), TOBN(0xeb6614f8, 0x9786d358), - TOBN(0x4a5d816b, 0x7f6f7459), TOBN(0xe431a44f, 0x09360e7b), - TOBN(0x8c27a032, 0xc309914c), TOBN(0xcea5d68a, 0xcaede3d8), - TOBN(0x3668f665, 0x3a0a3f95), TOBN(0x89369416, 0x7ceba27b), - TOBN(0x89981fad, 0xe4728fe9), TOBN(0x7102c8a0, 0x8a093562), - TOBN(0xbb80310e, 0x235d21c8), TOBN(0x505e55d1, 0xbefb7f7b), - TOBN(0xa0a90811, 0x12958a67), TOBN(0xd67e106a, 0x4d851fef), - TOBN(0xb84011a9, 0x431dd80e), TOBN(0xeb7c7cca, 0x73306cd9), - TOBN(0x20fadd29, 0xd1b3b730), TOBN(0x83858b5b, 0xfe37b3d3), - TOBN(0xbf4cd193, 0xb6251d5c), TOBN(0x1cca1fd3, 0x1352d952), - TOBN(0xc66157a4, 0x90fbc051), TOBN(0x7990a638, 0x89b98636), - }, + {TOBN(0xa9f5d874, 0x5a1251fb), TOBN(0x967747a8, 0xc72725c7), + TOBN(0x195c33e5, 0x31ffe89e), TOBN(0x609d210f, 0xe964935e), + TOBN(0xcafd6ca8, 0x2fe12227), TOBN(0xaf9b5b96, 0x0426469d), + TOBN(0x2e9ee04c, 0x5693183c), TOBN(0x1084a333, 0xc8146fef), + TOBN(0x96649933, 0xaed1d1f7), TOBN(0x566eaff3, 0x50563090), + TOBN(0x345057f0, 0xad2e39cf), TOBN(0x148ff65b, 0x1f832124), + TOBN(0x042e89d4, 0xcf94cf0d), TOBN(0x319bec84, 0x520c58b3), + TOBN(0x2a267626, 0x5361aa0d), TOBN(0xc86fa302, 0x8fbc87ad), + TOBN(0xfc83d2ab, 0x5c8b06d5), TOBN(0xb1a785a2, 0xfe4eac46), + TOBN(0xb99315bc, 0x846f7779), TOBN(0xcf31d816, 0xef9ea505), + TOBN(0x2391fe6a, 0x15d7dc85), TOBN(0x2f132b04, 0xb4016b33), + TOBN(0x29547fe3, 0x181cb4c7), TOBN(0xdb66d8a6, 0x650155a1), + TOBN(0x6b66d7e1, 0xadc1696f), TOBN(0x98ebe593, 0x0acd72d0), + TOBN(0x65f24550, 0xcc1b7435), TOBN(0xce231393, 0xb4b9a5ec), + TOBN(0x234a22d4, 0xdb067df9), TOBN(0x98dda095, 0xcaff9b00), + TOBN(0x1bbc75a0, 0x6100c9c1), TOBN(0x1560a9c8, 0x939cf695), + TOBN(0xcf006d3e, 0x99e0925f), TOBN(0x2dd74a96, 0x6322375a), + TOBN(0xc58b446a, 0xb56af5ba), TOBN(0x50292683, 0xe0b9b4f1), + TOBN(0xe2c34cb4, 0x1aeaffa3), TOBN(0x8b17203f, 0x9b9587c1), + TOBN(0x6d559207, 0xead1350c), TOBN(0x2b66a215, 0xfb7f9604), + TOBN(0x0850325e, 0xfe51bf74), TOBN(0x9c4f579e, 0x5e460094), + TOBN(0x5c87b92a, 0x76da2f25), TOBN(0x889de4e0, 0x6febef33), + TOBN(0x6900ec06, 0x646083ce), TOBN(0xbe2a0335, 0xbfe12773), + TOBN(0xadd1da35, 0xc5344110), TOBN(0x757568b7, 0xb802cd20), + TOBN(0x75559779, 0x00f7e6c8), TOBN(0x38e8b94f, 0x0facd2f0), + TOBN(0xfea1f3af, 0x03fde375), TOBN(0x5e11a1d8, 0x75881dfc), + TOBN(0xb3a6b02e, 0xc1e2f2ef), TOBN(0x193d2bbb, 0xc605a6c5), + TOBN(0x325ffeee, 0x339a0b2d), TOBN(0x27b6a724, 0x9e0c8846), + TOBN(0xe4050f1c, 0xf1c367ca), TOBN(0x9bc85a9b, 0xc90fbc7d), + TOBN(0xa373c4a2, 0xe1a11032), TOBN(0xb64232b7, 0xad0393a9), + TOBN(0xf5577eb0, 0x167dad29), TOBN(0x1604f301, 0x94b78ab2), + TOBN(0x0baa94af, 0xe829348b), TOBN(0x77fbd8dd, 0x41654342), + TOBN(0xdab50ea5, 0xb964e39a), TOBN(0xd4c29e3c, 0xd0d3c76e), + TOBN(0x80dae67c, 0x56d11964), TOBN(0x7307a8bf, 0xe5ffcc2f), + TOBN(0x65bbc1aa, 0x91708c3b), TOBN(0xa151e62c, 0x28bf0eeb), + TOBN(0x6cb53381, 0x6fa34db7), TOBN(0x5139e05c, 0xa29403a8), + TOBN(0x6ff651b4, 0x94a7cd2e), TOBN(0x5671ffd1, 0x0699336c), + TOBN(0x6f5fd2cc, 0x979a896a), TOBN(0x11e893a8, 0xd8148cef), + TOBN(0x988906a1, 0x65cf7b10), TOBN(0x81b67178, 0xc50d8485), + TOBN(0x7c0deb35, 0x8a35b3de), TOBN(0x423ac855, 0xc1d29799), + TOBN(0xaf580d87, 0xdac50b74), TOBN(0x28b2b89f, 0x5869734c), + TOBN(0x99a3b936, 0x874e28fb), TOBN(0xbb2c9190, 0x25f3f73a), + TOBN(0x199f6918, 0x84a9d5b7), TOBN(0x7ebe2325, 0x7e770374), + TOBN(0xf442e107, 0x0738efe2), TOBN(0xcf9f3f56, 0xcf9082d2), + TOBN(0x719f69e1, 0x09618708), TOBN(0xcc9e8364, 0xc183f9b1), + TOBN(0xec203a95, 0x366a21af), TOBN(0x6aec5d6d, 0x068b141f), + TOBN(0xee2df78a, 0x994f04e9), TOBN(0xb39ccae8, 0x271245b0), + TOBN(0xb875a4a9, 0x97e43f4f), TOBN(0x507dfe11, 0xdb2cea98), + TOBN(0x4fbf81cb, 0x489b03e9), TOBN(0xdb86ec5b, 0x6ec414fa), + TOBN(0xfad444f9, 0xf51b3ae5), TOBN(0xca7d33d6, 0x1914e3fe), + TOBN(0xa9c32f5c, 0x0ae6c4d0), TOBN(0xa9ca1d1e, 0x73969568), + TOBN(0x98043c31, 0x1aa7467e), TOBN(0xe832e75c, 0xe21b5ac6), + TOBN(0x314b7aea, 0x5232123d), TOBN(0x08307c8c, 0x65ae86db), + TOBN(0x06e7165c, 0xaa4668ed), TOBN(0xb170458b, 0xb4d3ec39), + TOBN(0x4d2e3ec6, 0xc19bb986), TOBN(0xc5f34846, 0xae0304ed), + TOBN(0x917695a0, 0x6c9f9722), TOBN(0x6c7f7317, 0x4cab1c0a), + TOBN(0x6295940e, 0x9d6d2e8b), TOBN(0xd318b8c1, 0x549f7c97), + TOBN(0x22453204, 0x97713885), TOBN(0x468d834b, 0xa8a440fe), + TOBN(0xd81fe5b2, 0xbfba796e), TOBN(0x152364db, 0x6d71f116), + TOBN(0xbb8c7c59, 0xb5b66e53), TOBN(0x0b12c61b, 0x2641a192), + TOBN(0x31f14802, 0xfcf0a7fd), TOBN(0x42fd0789, 0x5488b01e), + TOBN(0x71d78d6d, 0x9952b498), TOBN(0x8eb572d9, 0x07ac5201), + TOBN(0xe0a2a44c, 0x4d194a88), TOBN(0xd2b63fd9, 0xba017e66), + TOBN(0x78efc6c8, 0xf888aefc), TOBN(0xb76f6bda, 0x4a881a11), + TOBN(0x187f314b, 0xb46c2397), TOBN(0x004cf566, 0x5ded2819), + TOBN(0xa9ea5704, 0x38764d34), TOBN(0xbba45217, 0x78084709), + TOBN(0x06474571, 0x1171121e), TOBN(0xad7b7eb1, 0xe7c9b671), + TOBN(0xdacfbc40, 0x730f7507), TOBN(0x178cd8c6, 0xc7ad7bd1), + TOBN(0xbf0be101, 0xb2a67238), TOBN(0x3556d367, 0xaf9c14f2), + TOBN(0x104b7831, 0xa5662075), TOBN(0x58ca59bb, 0x79d9e60a), + TOBN(0x4bc45392, 0xa569a73b), TOBN(0x517a52e8, 0x5698f6c9), + TOBN(0x85643da5, 0xaeadd755), TOBN(0x1aed0cd5, 0x2a581b84), + TOBN(0xb9b4ff84, 0x80af1372), TOBN(0x244c3113, 0xf1ba5d1f), + TOBN(0x2a5dacbe, 0xf5f98d31), TOBN(0x2c3323e8, 0x4375bc2a), + TOBN(0x17a3ab4a, 0x5594b1dd), TOBN(0xa1928bfb, 0xceb4797e), + TOBN(0xe83af245, 0xe4886a19), TOBN(0x8979d546, 0x72b5a74a), + TOBN(0xa0f726bc, 0x19f9e967), TOBN(0xd9d03152, 0xe8fbbf4e), + TOBN(0xcfd6f51d, 0xb7707d40), TOBN(0x633084d9, 0x63f6e6e0), + TOBN(0xedcd9cdc, 0x55667eaf), TOBN(0x73b7f92b, 0x2e44d56f), + TOBN(0xfb2e39b6, 0x4e962b14), TOBN(0x7d408f6e, 0xf671fcbf), + TOBN(0xcc634ddc, 0x164a89bb), TOBN(0x74a42bb2, 0x3ef3bd05), + TOBN(0x1280dbb2, 0x428decbb), TOBN(0x6103f6bb, 0x402c8596), + TOBN(0xfa2bf581, 0x355a5752), TOBN(0x562f96a8, 0x00946674), + TOBN(0x4e4ca16d, 0x6da0223b), TOBN(0xfe47819f, 0x28d3aa25), + TOBN(0x9eea3075, 0xf8dfcf8a), TOBN(0xa284f0aa, 0x95669825), + TOBN(0xb3fca250, 0x867d3fd8), TOBN(0x20757b5f, 0x269d691e), + TOBN(0xf2c24020, 0x93b8a5de), TOBN(0xd3f93359, 0xebc06da6), + TOBN(0x1178293e, 0xb2739c33), TOBN(0xd2a3e770, 0xbcd686e5), + TOBN(0xa76f49f4, 0xcd941534), TOBN(0x0d37406b, 0xe3c71c0e), + TOBN(0x172d9397, 0x3b97f7e3), TOBN(0xec17e239, 0xbd7fd0de), + TOBN(0xe3290551, 0x6f496ba2), TOBN(0x6a693172, 0x36ad50e7), + TOBN(0xc4e539a2, 0x83e7eff5), TOBN(0x752737e7, 0x18e1b4cf), + TOBN(0xa2f7932c, 0x68af43ee), TOBN(0x5502468e, 0x703d00bd), + TOBN(0xe5dc978f, 0x2fb061f5), TOBN(0xc9a1904a, 0x28c815ad), + TOBN(0xd3af538d, 0x470c56a4), TOBN(0x159abc5f, 0x193d8ced), + TOBN(0x2a37245f, 0x20108ef3), TOBN(0xfa17081e, 0x223f7178), + TOBN(0x27b0fb2b, 0x10c8c0f5), TOBN(0x2102c3ea, 0x40650547), + TOBN(0x594564df, 0x8ac3bfa7), TOBN(0x98102033, 0x509dad96), + TOBN(0x6989643f, 0xf1d18a13), TOBN(0x35eebd91, 0xd7fc5af0), + TOBN(0x078d096a, 0xfaeaafd8), TOBN(0xb7a89341, 0xdef3de98), + TOBN(0x2a206e8d, 0xecf2a73a), TOBN(0x066a6397, 0x8e551994), + TOBN(0x3a6a088a, 0xb98d53a2), TOBN(0x0ce7c67c, 0x2d1124aa), + TOBN(0x48cec671, 0x759a113c), TOBN(0xe3b373d3, 0x4f6f67fa), + TOBN(0x5455d479, 0xfd36727b), TOBN(0xe5a428ee, 0xa13c0d81), + TOBN(0xb853dbc8, 0x1c86682b), TOBN(0xb78d2727, 0xb8d02b2a), + TOBN(0xaaf69bed, 0x8ebc329a), TOBN(0xdb6b40b3, 0x293b2148), + TOBN(0xe42ea77d, 0xb8c4961f), TOBN(0xb1a12f7c, 0x20e5e0ab), + TOBN(0xa0ec5274, 0x79e8b05e), TOBN(0x68027391, 0xfab60a80), + TOBN(0x6bfeea5f, 0x16b1bd5e), TOBN(0xf957e420, 0x4de30ad3), + TOBN(0xcbaf664e, 0x6a353b9e), TOBN(0x5c873312, 0x26d14feb), + TOBN(0x4e87f98c, 0xb65f57cb), TOBN(0xdb60a621, 0x5e0cdd41), + TOBN(0x67c16865, 0xa6881440), TOBN(0x1093ef1a, 0x46ab52aa), + TOBN(0xc095afb5, 0x3f4ece64), TOBN(0x6a6bb02e, 0x7604551a), + TOBN(0x55d44b4e, 0x0b26b8cd), TOBN(0xe5f9a999, 0xf971268a), + TOBN(0xc08ec425, 0x11a7de84), TOBN(0x83568095, 0xfda469dd), + TOBN(0x737bfba1, 0x6c6c90a2), TOBN(0x1cb9c4a0, 0xbe229831), + TOBN(0x93bccbba, 0xbb2eec64), TOBN(0xa0c23b64, 0xda03adbe), + TOBN(0x5f7aa00a, 0xe0e86ac4), TOBN(0x470b941e, 0xfc1401e6), + TOBN(0x5ad8d679, 0x9df43574), TOBN(0x4ccfb8a9, 0x0f65d810), + TOBN(0x1bce80e3, 0xaa7fbd81), TOBN(0x273291ad, 0x9508d20a), + TOBN(0xf5c4b46b, 0x42a92806), TOBN(0x810684ec, 0xa86ab44a), + TOBN(0x4591640b, 0xca0bc9f8), TOBN(0xb5efcdfc, 0x5c4b6054), + TOBN(0x16fc8907, 0x6e9edd12), TOBN(0xe29d0b50, 0xd4d792f9), + TOBN(0xa45fd01c, 0x9b03116d), TOBN(0x85035235, 0xc81765a4), + TOBN(0x1fe2a9b2, 0xb4b4b67c), TOBN(0xc1d10df0, 0xe8020604), + TOBN(0x9d64abfc, 0xbc8058d8), TOBN(0x8943b9b2, 0x712a0fbb), + TOBN(0x90eed914, 0x3b3def04), TOBN(0x85ab3aa2, 0x4ce775ff), + TOBN(0x605fd4ca, 0x7bbc9040), TOBN(0x8b34a564, 0xe2c75dfb), + TOBN(0x41ffc94a, 0x10358560), TOBN(0x2d8a5072, 0x9e5c28aa), + TOBN(0xe915a0fc, 0x4cc7eb15), TOBN(0xe9efab05, 0x8f6d0f5d), + TOBN(0xdbab47a9, 0xd19e9b91), TOBN(0x8cfed745, 0x0276154c), + TOBN(0x154357ae, 0x2cfede0d), TOBN(0x520630df, 0x19f5a4ef), + TOBN(0x25759f7c, 0xe382360f), TOBN(0xb6db05c9, 0x88bf5857), + TOBN(0x2917d61d, 0x6c58d46c), TOBN(0x14f8e491, 0xfd20cb7a), + TOBN(0xb68a727a, 0x11c20340), TOBN(0x0386f86f, 0xaf7ccbb6), + TOBN(0x5c8bc6cc, 0xfee09a20), TOBN(0x7d76ff4a, 0xbb7eea35), + TOBN(0xa7bdebe7, 0xdb15be7a), TOBN(0x67a08054, 0xd89f0302), + TOBN(0x56bf0ea9, 0xc1193364), TOBN(0xc8244467, 0x62837ebe), + TOBN(0x32bd8e8b, 0x20d841b8), TOBN(0x127a0548, 0xdbb8a54f), + TOBN(0x83dd4ca6, 0x63b20236), TOBN(0x87714718, 0x203491fa), + TOBN(0x4dabcaaa, 0xaa8a5288), TOBN(0x91cc0c8a, 0xaf23a1c9), + TOBN(0x34c72c6a, 0x3f220e0c), TOBN(0xbcc20bdf, 0x1232144a), + TOBN(0x6e2f42da, 0xa20ede1b), TOBN(0xc441f00c, 0x74a00515), + TOBN(0xbf46a5b6, 0x734b8c4b), TOBN(0x57409503, 0x7b56c9a4), + TOBN(0x9f735261, 0xe4585d45), TOBN(0x9231faed, 0x6734e642), + TOBN(0x1158a176, 0xbe70ee6c), TOBN(0x35f1068d, 0x7c3501bf), + TOBN(0x6beef900, 0xa2d26115), TOBN(0x649406f2, 0xef0afee3), + TOBN(0x3f43a60a, 0xbc2420a1), TOBN(0x509002a7, 0xd5aee4ac), + TOBN(0xb46836a5, 0x3ff3571b), TOBN(0x24f98b78, 0x837927c1), + TOBN(0x6254256a, 0x4533c716), TOBN(0xf27abb0b, 0xd07ee196), + TOBN(0xd7cf64fc, 0x5c6d5bfd), TOBN(0x6915c751, 0xf0cd7a77), + TOBN(0xd9f59012, 0x8798f534), TOBN(0x772b0da8, 0xf81d8b5f), + TOBN(0x1244260c, 0x2e03fa69), TOBN(0x36cf0e3a, 0x3be1a374), + TOBN(0x6e7c1633, 0xef06b960), TOBN(0xa71a4c55, 0x671f90f6), + TOBN(0x7a941251, 0x33c673db), TOBN(0xc0bea510, 0x73e8c131), + TOBN(0x61a8a699, 0xd4f6c734), TOBN(0x25e78c88, 0x341ed001), + TOBN(0x5c18acf8, 0x8e2f7d90), TOBN(0xfdbf33d7, 0x77be32cd), + TOBN(0x0a085cd7, 0xd2eb5ee9), TOBN(0x2d702cfb, 0xb3201115), + TOBN(0xb6e0ebdb, 0x85c88ce8), TOBN(0x23a3ce3c, 0x1e01d617), + TOBN(0x3041618e, 0x567333ac), TOBN(0x9dd0fd8f, 0x157edb6b), + TOBN(0x27f74702, 0xb57872b8), TOBN(0x2ef26b4f, 0x657d5fe1), + TOBN(0x95426f0a, 0x57cf3d40), TOBN(0x847e2ad1, 0x65a6067a), + TOBN(0xd474d9a0, 0x09996a74), TOBN(0x16a56acd, 0x2a26115c), + TOBN(0x02a615c3, 0xd16f4d43), TOBN(0xcc3fc965, 0xaadb85b7), + TOBN(0x386bda73, 0xce07d1b0), TOBN(0xd82910c2, 0x58ad4178), + TOBN(0x124f82cf, 0xcd2617f4), TOBN(0xcc2f5e8d, 0xef691770), + TOBN(0x82702550, 0xb8c30ccc), TOBN(0x7b856aea, 0x1a8e575a), + TOBN(0xbb822fef, 0xb1ab9459), TOBN(0x085928bc, 0xec24e38e), + TOBN(0x5d0402ec, 0xba8f4b4d), TOBN(0xc07cd4ba, 0x00b4d58b), + TOBN(0x5d8dffd5, 0x29227e7a), TOBN(0x61d44d0c, 0x31bf386f), + TOBN(0xe486dc2b, 0x135e6f4d), TOBN(0x680962eb, 0xe79410ef), + TOBN(0xa61bd343, 0xf10088b5), TOBN(0x6aa76076, 0xe2e28686), + TOBN(0x80463d11, 0x8fb98871), TOBN(0xcb26f5c3, 0xbbc76aff), + TOBN(0xd4ab8edd, 0xfbe03614), TOBN(0xc8eb579b, 0xc0cf2dee), + TOBN(0xcc004c15, 0xc93bae41), TOBN(0x46fbae5d, 0x3aeca3b2), + TOBN(0x671235cf, 0x0f1e9ab1), TOBN(0xadfba934, 0x9ec285c1), + TOBN(0x88ded013, 0xf216c980), TOBN(0xc8ac4fb8, 0xf79e0bc1), + TOBN(0xa29b89c6, 0xfb97a237), TOBN(0xb697b780, 0x9922d8e7), + TOBN(0x3142c639, 0xddb945b5), TOBN(0x447b06c7, 0xe094c3a9), + TOBN(0xcdcb3642, 0x72266c90), TOBN(0x633aad08, 0xa9385046), + TOBN(0xa36c936b, 0xb57c6477), TOBN(0x871f8b64, 0xe94dbcc6), + TOBN(0x28d0fb62, 0xa591a67b), TOBN(0x9d40e081, 0xc1d926f5), + TOBN(0x3111eaf6, 0xf2d84b5a), TOBN(0x228993f9, 0xa565b644), + TOBN(0x0ccbf592, 0x2c83188b), TOBN(0xf87b30ab, 0x3df3e197), + TOBN(0xb8658b31, 0x7642bca8), TOBN(0x1a032d7f, 0x52800f17), + TOBN(0x051dcae5, 0x79bf9445), TOBN(0xeba6b8ee, 0x54a2e253), + TOBN(0x5c8b9cad, 0xd4485692), TOBN(0x84bda40e, 0x8986e9be), + TOBN(0xd16d16a4, 0x2f0db448), TOBN(0x8ec80050, 0xa14d4188), + TOBN(0xb2b26107, 0x98fa7aaa), TOBN(0x41209ee4, 0xf073aa4e), + TOBN(0xf1570359, 0xf2d6b19b), TOBN(0xcbe6868c, 0xfc577caf), + TOBN(0x186c4bdc, 0x32c04dd3), TOBN(0xa6c35fae, 0xcfeee397), + TOBN(0xb4a1b312, 0xf086c0cf), TOBN(0xe0a5ccc6, 0xd9461fe2), + TOBN(0xc32278aa, 0x1536189f), TOBN(0x1126c55f, 0xba6df571), + TOBN(0x0f71a602, 0xb194560e), TOBN(0x8b2d7405, 0x324bd6e1), + TOBN(0x8481939e, 0x3738be71), TOBN(0xb5090b1a, 0x1a4d97a9), + TOBN(0x116c65a3, 0xf05ba915), TOBN(0x21863ad3, 0xaae448aa), + TOBN(0xd24e2679, 0xa7aae5d3), TOBN(0x7076013d, 0x0de5c1c4), + TOBN(0x2d50f8ba, 0xbb05b629), TOBN(0x73c1abe2, 0x6e66efbb), + TOBN(0xefd4b422, 0xf2488af7), TOBN(0xe4105d02, 0x663ba575), + TOBN(0x7eb60a8b, 0x53a69457), TOBN(0x62210008, 0xc945973b), + TOBN(0xfb255478, 0x77a50ec6), TOBN(0xbf0392f7, 0x0a37a72c), + TOBN(0xa0a7a19c, 0x4be18e7a), TOBN(0x90d8ea16, 0x25b1e0af), + TOBN(0x7582a293, 0xef953f57), TOBN(0x90a64d05, 0xbdc5465a), + TOBN(0xca79c497, 0xe2510717), TOBN(0x560dbb7c, 0x18cb641f), + TOBN(0x1d8e3286, 0x4b66abfb), TOBN(0xd26f52e5, 0x59030900), + TOBN(0x1ee3f643, 0x5584941a), TOBN(0x6d3b3730, 0x569f5958), + TOBN(0x9ff2a62f, 0x4789dba5), TOBN(0x91fcb815, 0x72b5c9b7), + TOBN(0xf446cb7d, 0x6c8f9a0e), TOBN(0x48f625c1, 0x39b7ecb5), + TOBN(0xbabae801, 0x1c6219b8), TOBN(0xe7a562d9, 0x28ac2f23), + TOBN(0xe1b48732, 0x26e20588), TOBN(0x06ee1cad, 0x775af051), + TOBN(0xda29ae43, 0xfaff79f7), TOBN(0xc141a412, 0x652ee9e0), + TOBN(0x1e127f6f, 0x195f4bd0), TOBN(0x29c6ab4f, 0x072f34f8), + TOBN(0x7b7c1477, 0x30448112), TOBN(0x82b51af1, 0xe4a38656), + TOBN(0x2bf2028a, 0x2f315010), TOBN(0xc9a4a01f, 0x6ea88cd4), + TOBN(0xf63e95d8, 0x257e5818), TOBN(0xdd8efa10, 0xb4519b16), + TOBN(0xed8973e0, 0x0da910bf), TOBN(0xed49d077, 0x5c0fe4a9), + TOBN(0xac3aac5e, 0xb7caee1e), TOBN(0x1033898d, 0xa7f4da57), + TOBN(0x42145c0e, 0x5c6669b9), TOBN(0x42daa688, 0xc1aa2aa0), + TOBN(0x629cc15c, 0x1a1d885a), TOBN(0x25572ec0, 0xf4b76817), + TOBN(0x8312e435, 0x9c8f8f28), TOBN(0x8107f8cd, 0x81965490), + TOBN(0x516ff3a3, 0x6fa6110c), TOBN(0x74fb1eb1, 0xfb93561f), + TOBN(0x6c0c9047, 0x8457522b), TOBN(0xcfd32104, 0x6bb8bdc6), + TOBN(0x2d6884a2, 0xcc80ad57), TOBN(0x7c27fc35, 0x86a9b637), + TOBN(0x3461baed, 0xadf4e8cd), TOBN(0x1d56251a, 0x617242f0), + TOBN(0x0b80d209, 0xc955bef4), TOBN(0xdf02cad2, 0x06adb047), + TOBN(0xf0d7cb91, 0x5ec74fee), TOBN(0xd2503375, 0x1111ba44), + TOBN(0x9671755e, 0xdf53cb36), TOBN(0x54dcb612, 0x3368551b), + TOBN(0x66d69aac, 0xc8a025a4), TOBN(0x6be946c6, 0xe77ef445), + TOBN(0x719946d1, 0xa995e094), TOBN(0x65e848f6, 0xe51e04d8), + TOBN(0xe62f3300, 0x6a1e3113), TOBN(0x1541c7c1, 0x501de503), + TOBN(0x4daac9fa, 0xf4acfade), TOBN(0x0e585897, 0x44cd0b71), + TOBN(0x544fd869, 0x0a51cd77), TOBN(0x60fc20ed, 0x0031016d), + TOBN(0x58b404ec, 0xa4276867), TOBN(0x46f6c3cc, 0x34f34993), + TOBN(0x477ca007, 0xc636e5bd), TOBN(0x8018f5e5, 0x7c458b47), + TOBN(0xa1202270, 0xe47b668f), TOBN(0xcef48ccd, 0xee14f203), + TOBN(0x23f98bae, 0x62ff9b4d), TOBN(0x55acc035, 0xc589eddd), + TOBN(0x3fe712af, 0x64db4444), TOBN(0x19e9d634, 0xbecdd480), + TOBN(0xe08bc047, 0xa930978a), TOBN(0x2dbf24ec, 0xa1280733), + TOBN(0x3c0ae38c, 0x2cd706b2), TOBN(0x5b012a5b, 0x359017b9), + TOBN(0x3943c38c, 0x72e0f5ae), TOBN(0x786167ea, 0x57176fa3), + TOBN(0xe5f9897d, 0x594881dc), TOBN(0x6b5efad8, 0xcfb820c1), + TOBN(0xb2179093, 0xd55018de), TOBN(0x39ad7d32, 0x0bac56ce), + TOBN(0xb55122e0, 0x2cfc0e81), TOBN(0x117c4661, 0xf6d89daa), + TOBN(0x362d01e1, 0xcb64fa09), TOBN(0x6a309b4e, 0x3e9c4ddd), + TOBN(0xfa979fb7, 0xabea49b1), TOBN(0xb4b1d27d, 0x10e2c6c5), + TOBN(0xbd61c2c4, 0x23afde7a), TOBN(0xeb6614f8, 0x9786d358), + TOBN(0x4a5d816b, 0x7f6f7459), TOBN(0xe431a44f, 0x09360e7b), + TOBN(0x8c27a032, 0xc309914c), TOBN(0xcea5d68a, 0xcaede3d8), + TOBN(0x3668f665, 0x3a0a3f95), TOBN(0x89369416, 0x7ceba27b), + TOBN(0x89981fad, 0xe4728fe9), TOBN(0x7102c8a0, 0x8a093562), + TOBN(0xbb80310e, 0x235d21c8), TOBN(0x505e55d1, 0xbefb7f7b), + TOBN(0xa0a90811, 0x12958a67), TOBN(0xd67e106a, 0x4d851fef), + TOBN(0xb84011a9, 0x431dd80e), TOBN(0xeb7c7cca, 0x73306cd9), + TOBN(0x20fadd29, 0xd1b3b730), TOBN(0x83858b5b, 0xfe37b3d3), + TOBN(0xbf4cd193, 0xb6251d5c), TOBN(0x1cca1fd3, 0x1352d952), + TOBN(0xc66157a4, 0x90fbc051), TOBN(0x7990a638, 0x89b98636)}, {TOBN(0xe5aa692a, 0x87dec0e1), TOBN(0x010ded8d, 0xf7b39d00), TOBN(0x7b1b80c8, 0x54cfa0b5), TOBN(0x66beb876, 0xa0f8ea28), TOBN(0x50d7f531, 0x3476cd0e), TOBN(0xa63d0e65, 0xb08d3949), @@ -3357,264 +3357,262 @@ static const alignas(4096) BN_ULONG TOBN(0xdaea066b, 0xa5e5c2f2), TOBN(0x3fc8a614, 0x08c8c7b3), TOBN(0x7adff88f, 0x06d0de9f), TOBN(0xbbc11cf5, 0x3b75ce0a), TOBN(0x9fbb7acc, 0xfbbc87d5), TOBN(0xa1458e26, 0x7badfde2)}, - { - TOBN(0x1cb43668, 0xe039c256), TOBN(0x5f26fb8b, 0x7c17fd5d), - TOBN(0xeee426af, 0x79aa062b), TOBN(0x072002d0, 0xd78fbf04), - TOBN(0x4c9ca237, 0xe84fb7e3), TOBN(0xb401d8a1, 0x0c82133d), - TOBN(0xaaa52592, 0x6d7e4181), TOBN(0xe9430833, 0x73dbb152), - TOBN(0xf92dda31, 0xbe24319a), TOBN(0x03f7d28b, 0xe095a8e7), - TOBN(0xa52fe840, 0x98782185), TOBN(0x276ddafe, 0x29c24dbc), - TOBN(0x80cd5496, 0x1d7a64eb), TOBN(0xe4360889, 0x7f1dbe42), - TOBN(0x2f81a877, 0x8438d2d5), TOBN(0x7e4d52a8, 0x85169036), - TOBN(0x19e3d5b1, 0x1d59715d), TOBN(0xc7eaa762, 0xd788983e), - TOBN(0xe5a730b0, 0xabf1f248), TOBN(0xfbab8084, 0xfae3fd83), - TOBN(0x65e50d21, 0x53765b2f), TOBN(0xbdd4e083, 0xfa127f3d), - TOBN(0x9cf3c074, 0x397b1b10), TOBN(0x59f8090c, 0xb1b59fd3), - TOBN(0x7b15fd9d, 0x615faa8f), TOBN(0x8fa1eb40, 0x968554ed), - TOBN(0x7bb4447e, 0x7aa44882), TOBN(0x2bb2d0d1, 0x029fff32), - TOBN(0x075e2a64, 0x6caa6d2f), TOBN(0x8eb879de, 0x22e7351b), - TOBN(0xbcd5624e, 0x9a506c62), TOBN(0x218eaef0, 0xa87e24dc), - TOBN(0x37e56847, 0x44ddfa35), TOBN(0x9ccfc5c5, 0xdab3f747), - TOBN(0x9ac1df3f, 0x1ee96cf4), TOBN(0x0c0571a1, 0x3b480b8f), - TOBN(0x2fbeb3d5, 0x4b3a7b3c), TOBN(0x35c03669, 0x5dcdbb99), - TOBN(0x52a0f5dc, 0xb2415b3a), TOBN(0xd57759b4, 0x4413ed9a), - TOBN(0x1fe647d8, 0x3d30a2c5), TOBN(0x0857f77e, 0xf78a81dc), - TOBN(0x11d5a334, 0x131a4a9b), TOBN(0xc0a94af9, 0x29d393f5), - TOBN(0xbc3a5c0b, 0xdaa6ec1a), TOBN(0xba9fe493, 0x88d2d7ed), - TOBN(0xbb4335b4, 0xbb614797), TOBN(0x991c4d68, 0x72f83533), - TOBN(0x53258c28, 0xd2f01cb3), TOBN(0x93d6eaa3, 0xd75db0b1), - TOBN(0x419a2b0d, 0xe87d0db4), TOBN(0xa1e48f03, 0xd8fe8493), - TOBN(0xf747faf6, 0xc508b23a), TOBN(0xf137571a, 0x35d53549), - TOBN(0x9f5e58e2, 0xfcf9b838), TOBN(0xc7186cee, 0xa7fd3cf5), - TOBN(0x77b868ce, 0xe978a1d3), TOBN(0xe3a68b33, 0x7ab92d04), - TOBN(0x51029794, 0x87a5b862), TOBN(0x5f0606c3, 0x3a61d41d), - TOBN(0x2814be27, 0x6f9326f1), TOBN(0x2f521c14, 0xc6fe3c2e), - TOBN(0x17464d7d, 0xacdf7351), TOBN(0x10f5f9d3, 0x777f7e44), - TOBN(0xce8e616b, 0x269fb37d), TOBN(0xaaf73804, 0x7de62de5), - TOBN(0xaba11175, 0x4fdd4153), TOBN(0x515759ba, 0x3770b49b), - TOBN(0x8b09ebf8, 0xaa423a61), TOBN(0x592245a1, 0xcd41fb92), - TOBN(0x1cba8ec1, 0x9b4c8936), TOBN(0xa87e91e3, 0xaf36710e), - TOBN(0x1fd84ce4, 0x3d34a2e3), TOBN(0xee3759ce, 0xb43b5d61), - TOBN(0x895bc78c, 0x619186c7), TOBN(0xf19c3809, 0xcbb9725a), - TOBN(0xc0be21aa, 0xde744b1f), TOBN(0xa7d222b0, 0x60f8056b), - TOBN(0x74be6157, 0xb23efe11), TOBN(0x6fab2b4f, 0x0cd68253), - TOBN(0xad33ea5f, 0x4bf1d725), TOBN(0x9c1d8ee2, 0x4f6c950f), - TOBN(0x544ee78a, 0xa377af06), TOBN(0x54f489bb, 0x94a113e1), - TOBN(0x8f11d634, 0x992fb7e8), TOBN(0x0169a7aa, 0xa2a44347), - TOBN(0x1d49d4af, 0x95020e00), TOBN(0x95945722, 0xe08e120b), - TOBN(0xb6e33878, 0xa4d32282), TOBN(0xe36e029d, 0x48020ae7), - TOBN(0xe05847fb, 0x37a9b750), TOBN(0xf876812c, 0xb29e3819), - TOBN(0x84ad138e, 0xd23a17f0), TOBN(0x6d7b4480, 0xf0b3950e), - TOBN(0xdfa8aef4, 0x2fd67ae0), TOBN(0x8d3eea24, 0x52333af6), - TOBN(0x0d052075, 0xb15d5acc), TOBN(0xc6d9c79f, 0xbd815bc4), - TOBN(0x8dcafd88, 0xdfa36cf2), TOBN(0x908ccbe2, 0x38aa9070), - TOBN(0x638722c4, 0xba35afce), TOBN(0x5a3da8b0, 0xfd6abf0b), - TOBN(0x2dce252c, 0xc9c335c1), TOBN(0x84e7f0de, 0x65aa799b), - TOBN(0x2101a522, 0xb99a72cb), TOBN(0x06de6e67, 0x87618016), - TOBN(0x5ff8c7cd, 0xe6f3653e), TOBN(0x0a821ab5, 0xc7a6754a), - TOBN(0x7e3fa52b, 0x7cb0b5a2), TOBN(0xa7fb121c, 0xc9048790), - TOBN(0x1a725020, 0x06ce053a), TOBN(0xb490a31f, 0x04e929b0), - TOBN(0xe17be47d, 0x62dd61ad), TOBN(0x781a961c, 0x6be01371), - TOBN(0x1063bfd3, 0xdae3cbba), TOBN(0x35647406, 0x7f73c9ba), - TOBN(0xf50e957b, 0x2736a129), TOBN(0xa6313702, 0xed13f256), - TOBN(0x9436ee65, 0x3a19fcc5), TOBN(0xcf2bdb29, 0xe7a4c8b6), - TOBN(0xb06b1244, 0xc5f95cd8), TOBN(0xda8c8af0, 0xf4ab95f4), - TOBN(0x1bae59c2, 0xb9e5836d), TOBN(0x07d51e7e, 0x3acffffc), - TOBN(0x01e15e6a, 0xc2ccbcda), TOBN(0x3bc1923f, 0x8528c3e0), - TOBN(0x43324577, 0xa49fead4), TOBN(0x61a1b884, 0x2aa7a711), - TOBN(0xf9a86e08, 0x700230ef), TOBN(0x0af585a1, 0xbd19adf8), - TOBN(0x7645f361, 0xf55ad8f2), TOBN(0x6e676223, 0x46c3614c), - TOBN(0x23cb257c, 0x4e774d3f), TOBN(0x82a38513, 0xac102d1b), - TOBN(0x9bcddd88, 0x7b126aa5), TOBN(0xe716998b, 0xeefd3ee4), - TOBN(0x4239d571, 0xfb167583), TOBN(0xdd011c78, 0xd16c8f8a), - TOBN(0x271c2895, 0x69a27519), TOBN(0x9ce0a3b7, 0xd2d64b6a), - TOBN(0x8c977289, 0xd5ec6738), TOBN(0xa3b49f9a, 0x8840ef6b), - TOBN(0x808c14c9, 0x9a453419), TOBN(0x5c00295b, 0x0cf0a2d5), - TOBN(0x524414fb, 0x1d4bcc76), TOBN(0xb07691d2, 0x459a88f1), - TOBN(0x77f43263, 0xf70d110f), TOBN(0x64ada5e0, 0xb7abf9f3), - TOBN(0xafd0f94e, 0x5b544cf5), TOBN(0xb4a13a15, 0xfd2713fe), - TOBN(0xb99b7d6e, 0x250c74f4), TOBN(0x097f2f73, 0x20324e45), - TOBN(0x994b37d8, 0xaffa8208), TOBN(0xc3c31b0b, 0xdc29aafc), - TOBN(0x3da74651, 0x7a3a607f), TOBN(0xd8e1b8c1, 0xfe6955d6), - TOBN(0x716e1815, 0xc8418682), TOBN(0x541d487f, 0x7dc91d97), - TOBN(0x48a04669, 0xc6996982), TOBN(0xf39cab15, 0x83a6502e), - TOBN(0x025801a0, 0xe68db055), TOBN(0xf3569758, 0xba3338d5), - TOBN(0xb0c8c0aa, 0xee2afa84), TOBN(0x4f6985d3, 0xfb6562d1), - TOBN(0x351f1f15, 0x132ed17a), TOBN(0x510ed0b4, 0xc04365fe), - TOBN(0xa3f98138, 0xe5b1f066), TOBN(0xbc9d95d6, 0x32df03dc), - TOBN(0xa83ccf6e, 0x19abd09e), TOBN(0x0b4097c1, 0x4ff17edb), - TOBN(0x58a5c478, 0xd64a06ce), TOBN(0x2ddcc3fd, 0x544a58fd), - TOBN(0xd449503d, 0x9e8153b8), TOBN(0x3324fd02, 0x7774179b), - TOBN(0xaf5d47c8, 0xdbd9120c), TOBN(0xeb860162, 0x34fa94db), - TOBN(0x5817bdd1, 0x972f07f4), TOBN(0xe5579e2e, 0xd27bbceb), - TOBN(0x86847a1f, 0x5f11e5a6), TOBN(0xb39ed255, 0x7c3cf048), - TOBN(0xe1076417, 0xa2f62e55), TOBN(0x6b9ab38f, 0x1bcf82a2), - TOBN(0x4bb7c319, 0x7aeb29f9), TOBN(0xf6d17da3, 0x17227a46), - TOBN(0xab53ddbd, 0x0f968c00), TOBN(0xa03da7ec, 0x000c880b), - TOBN(0x7b239624, 0x6a9ad24d), TOBN(0x612c0401, 0x01ec60d0), - TOBN(0x70d10493, 0x109f5df1), TOBN(0xfbda4030, 0x80af7550), - TOBN(0x30b93f95, 0xc6b9a9b3), TOBN(0x0c74ec71, 0x007d9418), - TOBN(0x94175564, 0x6edb951f), TOBN(0x5f4a9d78, 0x7f22c282), - TOBN(0xb7870895, 0xb38d1196), TOBN(0xbc593df3, 0xa228ce7c), - TOBN(0xc78c5bd4, 0x6af3641a), TOBN(0x7802200b, 0x3d9b3dcc), - TOBN(0x0dc73f32, 0x8be33304), TOBN(0x847ed87d, 0x61ffb79a), - TOBN(0xf85c974e, 0x6d671192), TOBN(0x1e14100a, 0xde16f60f), - TOBN(0x45cb0d5a, 0x95c38797), TOBN(0x18923bba, 0x9b022da4), - TOBN(0xef2be899, 0xbbe7e86e), TOBN(0x4a1510ee, 0x216067bf), - TOBN(0xd98c8154, 0x84d5ce3e), TOBN(0x1af777f0, 0xf92a2b90), - TOBN(0x9fbcb400, 0x4ef65724), TOBN(0x3e04a4c9, 0x3c0ca6fe), - TOBN(0xfb3e2cb5, 0x55002994), TOBN(0x1f3a93c5, 0x5363ecab), - TOBN(0x1fe00efe, 0x3923555b), TOBN(0x744bedd9, 0x1e1751ea), - TOBN(0x3fb2db59, 0x6ab69357), TOBN(0x8dbd7365, 0xf5e6618b), - TOBN(0x99d53099, 0xdf1ea40e), TOBN(0xb3f24a0b, 0x57d61e64), - TOBN(0xd088a198, 0x596eb812), TOBN(0x22c8361b, 0x5762940b), - TOBN(0x66f01f97, 0xf9c0d95c), TOBN(0x88461172, 0x8e43cdae), - TOBN(0x11599a7f, 0xb72b15c3), TOBN(0x135a7536, 0x420d95cc), - TOBN(0x2dcdf0f7, 0x5f7ae2f6), TOBN(0x15fc6e1d, 0xd7fa6da2), - TOBN(0x81ca829a, 0xd1d441b6), TOBN(0x84c10cf8, 0x04a106b6), - TOBN(0xa9b26c95, 0xa73fbbd0), TOBN(0x7f24e0cb, 0x4d8f6ee8), - TOBN(0x48b45937, 0x1e25a043), TOBN(0xf8a74fca, 0x036f3dfe), - TOBN(0x1ed46585, 0xc9f84296), TOBN(0x7fbaa8fb, 0x3bc278b0), - TOBN(0xa8e96cd4, 0x6c4fcbd0), TOBN(0x940a1202, 0x73b60a5f), - TOBN(0x34aae120, 0x55a4aec8), TOBN(0x550e9a74, 0xdbd742f0), - TOBN(0x794456d7, 0x228c68ab), TOBN(0x492f8868, 0xa4e25ec6), - TOBN(0x682915ad, 0xb2d8f398), TOBN(0xf13b51cc, 0x5b84c953), - TOBN(0xcda90ab8, 0x5bb917d6), TOBN(0x4b615560, 0x4ea3dee1), - TOBN(0x578b4e85, 0x0a52c1c8), TOBN(0xeab1a695, 0x20b75fc4), - TOBN(0x60c14f3c, 0xaa0bb3c6), TOBN(0x220f448a, 0xb8216094), - TOBN(0x4fe7ee31, 0xb0e63d34), TOBN(0xf4600572, 0xa9e54fab), - TOBN(0xc0493334, 0xd5e7b5a4), TOBN(0x8589fb92, 0x06d54831), - TOBN(0xaa70f5cc, 0x6583553a), TOBN(0x0879094a, 0xe25649e5), - TOBN(0xcc904507, 0x10044652), TOBN(0xebb0696d, 0x02541c4f), - TOBN(0x5a171fde, 0xb9718710), TOBN(0x38f1bed8, 0xf374a9f5), - TOBN(0xc8c582e1, 0xba39bdc1), TOBN(0xfc457b0a, 0x908cc0ce), - TOBN(0x9a187fd4, 0x883841e2), TOBN(0x8ec25b39, 0x38725381), - TOBN(0x2553ed05, 0x96f84395), TOBN(0x095c7661, 0x6f6c6897), - TOBN(0x917ac85c, 0x4bdc5610), TOBN(0xb2885fe4, 0x179eb301), - TOBN(0x5fc65547, 0x8b78bdcc), TOBN(0x4a9fc893, 0xe59e4699), - TOBN(0xbb7ff0cd, 0x3ce299af), TOBN(0x195be9b3, 0xadf38b20), - TOBN(0x6a929c87, 0xd38ddb8f), TOBN(0x55fcc99c, 0xb21a51b9), - TOBN(0x2b695b4c, 0x721a4593), TOBN(0xed1e9a15, 0x768eaac2), - TOBN(0xfb63d71c, 0x7489f914), TOBN(0xf98ba31c, 0x78118910), - TOBN(0x80291373, 0x9b128eb4), TOBN(0x7801214e, 0xd448af4a), - TOBN(0xdbd2e22b, 0x55418dd3), TOBN(0xeffb3c0d, 0xd3998242), - TOBN(0xdfa6077c, 0xc7bf3827), TOBN(0xf2165bcb, 0x47f8238f), - TOBN(0xfe37cf68, 0x8564d554), TOBN(0xe5f825c4, 0x0a81fb98), - TOBN(0x43cc4f67, 0xffed4d6f), TOBN(0xbc609578, 0xb50a34b0), - TOBN(0x8aa8fcf9, 0x5041faf1), TOBN(0x5659f053, 0x651773b6), - TOBN(0xe87582c3, 0x6044d63b), TOBN(0xa6089409, 0x0cdb0ca0), - TOBN(0x8c993e0f, 0xbfb2bcf6), TOBN(0xfc64a719, 0x45985cfc), - TOBN(0x15c4da80, 0x83dbedba), TOBN(0x804ae112, 0x2be67df7), - TOBN(0xda4c9658, 0xa23defde), TOBN(0x12002ddd, 0x5156e0d3), - TOBN(0xe68eae89, 0x5dd21b96), TOBN(0x8b99f28b, 0xcf44624d), - TOBN(0x0ae00808, 0x1ec8897a), TOBN(0xdd0a9303, 0x6712f76e), - TOBN(0x96237522, 0x4e233de4), TOBN(0x192445b1, 0x2b36a8a5), - TOBN(0xabf9ff74, 0x023993d9), TOBN(0x21f37bf4, 0x2aad4a8f), - TOBN(0x340a4349, 0xf8bd2bbd), TOBN(0x1d902cd9, 0x4868195d), - TOBN(0x3d27bbf1, 0xe5fdb6f1), TOBN(0x7a5ab088, 0x124f9f1c), - TOBN(0xc466ab06, 0xf7a09e03), TOBN(0x2f8a1977, 0x31f2c123), - TOBN(0xda355dc7, 0x041b6657), TOBN(0xcb840d12, 0x8ece2a7c), - TOBN(0xb600ad9f, 0x7db32675), TOBN(0x78fea133, 0x07a06f1b), - TOBN(0x5d032269, 0xb31f6094), TOBN(0x07753ef5, 0x83ec37aa), - TOBN(0x03485aed, 0x9c0bea78), TOBN(0x41bb3989, 0xbc3f4524), - TOBN(0x09403761, 0x697f726d), TOBN(0x6109beb3, 0xdf394820), - TOBN(0x804111ea, 0x3b6d1145), TOBN(0xb6271ea9, 0xa8582654), - TOBN(0x619615e6, 0x24e66562), TOBN(0xa2554945, 0xd7b6ad9c), - TOBN(0xd9c4985e, 0x99bfe35f), TOBN(0x9770ccc0, 0x7b51cdf6), - TOBN(0x7c327013, 0x92881832), TOBN(0x8777d45f, 0x286b26d1), - TOBN(0x9bbeda22, 0xd847999d), TOBN(0x03aa33b6, 0xc3525d32), - TOBN(0x4b7b96d4, 0x28a959a1), TOBN(0xbb3786e5, 0x31e5d234), - TOBN(0xaeb5d3ce, 0x6961f247), TOBN(0x20aa85af, 0x02f93d3f), - TOBN(0x9cd1ad3d, 0xd7a7ae4f), TOBN(0xbf6688f0, 0x781adaa8), - TOBN(0xb1b40e86, 0x7469cead), TOBN(0x1904c524, 0x309fca48), - TOBN(0x9b7312af, 0x4b54bbc7), TOBN(0xbe24bf8f, 0x593affa2), - TOBN(0xbe5e0790, 0xbd98764b), TOBN(0xa0f45f17, 0xa26e299e), - TOBN(0x4af0d2c2, 0x6b8fe4c7), TOBN(0xef170db1, 0x8ae8a3e6), - TOBN(0x0e8d61a0, 0x29e0ccc1), TOBN(0xcd53e87e, 0x60ad36ca), - TOBN(0x328c6623, 0xc8173822), TOBN(0x7ee1767d, 0xa496be55), - TOBN(0x89f13259, 0x648945af), TOBN(0x9e45a5fd, 0x25c8009c), - TOBN(0xaf2febd9, 0x1f61ab8c), TOBN(0x43f6bc86, 0x8a275385), - TOBN(0x87792348, 0xf2142e79), TOBN(0x17d89259, 0xc6e6238a), - TOBN(0x7536d2f6, 0x4a839d9b), TOBN(0x1f428fce, 0x76a1fbdc), - TOBN(0x1c109601, 0x0db06dfe), TOBN(0xbfc16bc1, 0x50a3a3cc), - TOBN(0xf9cbd9ec, 0x9b30f41b), TOBN(0x5b5da0d6, 0x00138cce), - TOBN(0xec1d0a48, 0x56ef96a7), TOBN(0xb47eb848, 0x982bf842), - TOBN(0x66deae32, 0xec3f700d), TOBN(0x4e43c42c, 0xaa1181e0), - TOBN(0xa1d72a31, 0xd1a4aa2a), TOBN(0x440d4668, 0xc004f3ce), - TOBN(0x0d6a2d3b, 0x45fe8a7a), TOBN(0x820e52e2, 0xfb128365), - TOBN(0x29ac5fcf, 0x25e51b09), TOBN(0x180cd2bf, 0x2023d159), - TOBN(0xa9892171, 0xa1ebf90e), TOBN(0xf97c4c87, 0x7c132181), - TOBN(0x9f1dc724, 0xc03dbb7e), TOBN(0xae043765, 0x018cbbe4), - TOBN(0xfb0b2a36, 0x0767d153), TOBN(0xa8e2f4d6, 0x249cbaeb), - TOBN(0x172a5247, 0xd95ea168), TOBN(0x1758fada, 0x2970764a), - TOBN(0xac803a51, 0x1d978169), TOBN(0x299cfe2e, 0xde77e01b), - TOBN(0x652a1e17, 0xb0a98927), TOBN(0x2e26e1d1, 0x20014495), - TOBN(0x7ae0af9f, 0x7175b56a), TOBN(0xc2e22a80, 0xd64b9f95), - TOBN(0x4d0ff9fb, 0xd90a060a), TOBN(0x496a27db, 0xbaf38085), - TOBN(0x32305401, 0xda776bcf), TOBN(0xb8cdcef6, 0x725f209e), - TOBN(0x61ba0f37, 0x436a0bba), TOBN(0x263fa108, 0x76860049), - TOBN(0x92beb98e, 0xda3542cf), TOBN(0xa2d4d14a, 0xd5849538), - TOBN(0x989b9d68, 0x12e9a1bc), TOBN(0x61d9075c, 0x5f6e3268), - TOBN(0x352c6aa9, 0x99ace638), TOBN(0xde4e4a55, 0x920f43ff), - TOBN(0xe5e4144a, 0xd673c017), TOBN(0x667417ae, 0x6f6e05ea), - TOBN(0x613416ae, 0xdcd1bd56), TOBN(0x5eb36201, 0x86693711), - TOBN(0x2d7bc504, 0x3a1aa914), TOBN(0x175a1299, 0x76dc5975), - TOBN(0xe900e0f2, 0x3fc8125c), TOBN(0x569ef68c, 0x11198875), - TOBN(0x9012db63, 0x63a113b4), TOBN(0xe3bd3f56, 0x98835766), - TOBN(0xa5c94a52, 0x76412dea), TOBN(0xad9e2a09, 0xaa735e5c), - TOBN(0x405a984c, 0x508b65e9), TOBN(0xbde4a1d1, 0x6df1a0d1), - TOBN(0x1a9433a1, 0xdfba80da), TOBN(0xe9192ff9, 0x9440ad2e), - TOBN(0x9f649696, 0x5099fe92), TOBN(0x25ddb65c, 0x0b27a54a), - TOBN(0x178279dd, 0xc590da61), TOBN(0x5479a999, 0xfbde681a), - TOBN(0xd0e84e05, 0x013fe162), TOBN(0xbe11dc92, 0x632d471b), - TOBN(0xdf0b0c45, 0xfc0e089f), TOBN(0x04fb15b0, 0x4c144025), - TOBN(0xa61d5fc2, 0x13c99927), TOBN(0xa033e9e0, 0x3de2eb35), - TOBN(0xf8185d5c, 0xb8dacbb4), TOBN(0x9a88e265, 0x8644549d), - TOBN(0xf717af62, 0x54671ff6), TOBN(0x4bd4241b, 0x5fa58603), - TOBN(0x06fba40b, 0xe67773c0), TOBN(0xc1d933d2, 0x6a2847e9), - TOBN(0xf4f5acf3, 0x689e2c70), TOBN(0x92aab0e7, 0x46bafd31), - TOBN(0x798d76aa, 0x3473f6e5), TOBN(0xcc6641db, 0x93141934), - TOBN(0xcae27757, 0xd31e535e), TOBN(0x04cc43b6, 0x87c2ee11), - TOBN(0x8d1f9675, 0x2e029ffa), TOBN(0xc2150672, 0xe4cc7a2c), - TOBN(0x3b03c1e0, 0x8d68b013), TOBN(0xa9d6816f, 0xedf298f3), - TOBN(0x1bfbb529, 0xa2804464), TOBN(0x95a52fae, 0x5db22125), - TOBN(0x55b32160, 0x0e1cb64e), TOBN(0x004828f6, 0x7e7fc9fe), - TOBN(0x13394b82, 0x1bb0fb93), TOBN(0xb6293a2d, 0x35f1a920), - TOBN(0xde35ef21, 0xd145d2d9), TOBN(0xbe6225b3, 0xbb8fa603), - TOBN(0x00fc8f6b, 0x32cf252d), TOBN(0xa28e52e6, 0x117cf8c2), - TOBN(0x9d1dc89b, 0x4c371e6d), TOBN(0xcebe0675, 0x36ef0f28), - TOBN(0x5de05d09, 0xa4292f81), TOBN(0xa8303593, 0x353e3083), - TOBN(0xa1715b0a, 0x7e37a9bb), TOBN(0x8c56f61e, 0x2b8faec3), - TOBN(0x52507431, 0x33c9b102), TOBN(0x0130cefc, 0xa44431f0), - TOBN(0x56039fa0, 0xbd865cfb), TOBN(0x4b03e578, 0xbc5f1dd7), - TOBN(0x40edf2e4, 0xbabe7224), TOBN(0xc752496d, 0x3a1988f6), - TOBN(0xd1572d3b, 0x564beb6b), TOBN(0x0db1d110, 0x39a1c608), - TOBN(0x568d1934, 0x16f60126), TOBN(0x05ae9668, 0xf354af33), - TOBN(0x19de6d37, 0xc92544f2), TOBN(0xcc084353, 0xa35837d5), - TOBN(0xcbb6869c, 0x1a514ece), TOBN(0xb633e728, 0x2e1d1066), - TOBN(0xf15dd69f, 0x936c581c), TOBN(0x96e7b8ce, 0x7439c4f9), - TOBN(0x5e676f48, 0x2e448a5b), TOBN(0xb2ca7d5b, 0xfd916bbb), - TOBN(0xd55a2541, 0xf5024025), TOBN(0x47bc5769, 0xe4c2d937), - TOBN(0x7d31b92a, 0x0362189f), TOBN(0x83f3086e, 0xef7816f9), - TOBN(0xf9f46d94, 0xb587579a), TOBN(0xec2d22d8, 0x30e76c5f), - TOBN(0x27d57461, 0xb000ffcf), TOBN(0xbb7e65f9, 0x364ffc2c), - TOBN(0x7c7c9477, 0x6652a220), TOBN(0x61618f89, 0xd696c981), - TOBN(0x5021701d, 0x89effff3), TOBN(0xf2c8ff8e, 0x7c314163), - TOBN(0x2da413ad, 0x8efb4d3e), TOBN(0x937b5adf, 0xce176d95), - TOBN(0x22867d34, 0x2a67d51c), TOBN(0x262b9b10, 0x18eb3ac9), - TOBN(0x4e314fe4, 0xc43ff28b), TOBN(0x76476627, 0x6a664e7a), - TOBN(0x3e90e40b, 0xb7a565c2), TOBN(0x8588993a, 0xc1acf831), - TOBN(0xd7b501d6, 0x8f938829), TOBN(0x996627ee, 0x3edd7d4c), - TOBN(0x37d44a62, 0x90cd34c7), TOBN(0xa8327499, 0xf3833e8d), - TOBN(0x2e18917d, 0x4bf50353), TOBN(0x85dd726b, 0x556765fb), - TOBN(0x54fe65d6, 0x93d5ab66), TOBN(0x3ddbaced, 0x915c25fe), - TOBN(0xa799d9a4, 0x12f22e85), TOBN(0xe2a24867, 0x6d06f6bc), - TOBN(0xf4f1ee56, 0x43ca1637), TOBN(0xfda2828b, 0x61ece30a), - TOBN(0x758c1a3e, 0xa2dee7a6), TOBN(0xdcde2f3c, 0x734b2284), - TOBN(0xaba445d2, 0x4eaba6ad), TOBN(0x35aaf668, 0x76cee0a7), - TOBN(0x7e0b04a9, 0xe5aa049a), TOBN(0xe74083ad, 0x91103e84), - TOBN(0xbeb183ce, 0x40afecc3), TOBN(0x6b89de9f, 0xea043f7a), - }, + {TOBN(0x1cb43668, 0xe039c256), TOBN(0x5f26fb8b, 0x7c17fd5d), + TOBN(0xeee426af, 0x79aa062b), TOBN(0x072002d0, 0xd78fbf04), + TOBN(0x4c9ca237, 0xe84fb7e3), TOBN(0xb401d8a1, 0x0c82133d), + TOBN(0xaaa52592, 0x6d7e4181), TOBN(0xe9430833, 0x73dbb152), + TOBN(0xf92dda31, 0xbe24319a), TOBN(0x03f7d28b, 0xe095a8e7), + TOBN(0xa52fe840, 0x98782185), TOBN(0x276ddafe, 0x29c24dbc), + TOBN(0x80cd5496, 0x1d7a64eb), TOBN(0xe4360889, 0x7f1dbe42), + TOBN(0x2f81a877, 0x8438d2d5), TOBN(0x7e4d52a8, 0x85169036), + TOBN(0x19e3d5b1, 0x1d59715d), TOBN(0xc7eaa762, 0xd788983e), + TOBN(0xe5a730b0, 0xabf1f248), TOBN(0xfbab8084, 0xfae3fd83), + TOBN(0x65e50d21, 0x53765b2f), TOBN(0xbdd4e083, 0xfa127f3d), + TOBN(0x9cf3c074, 0x397b1b10), TOBN(0x59f8090c, 0xb1b59fd3), + TOBN(0x7b15fd9d, 0x615faa8f), TOBN(0x8fa1eb40, 0x968554ed), + TOBN(0x7bb4447e, 0x7aa44882), TOBN(0x2bb2d0d1, 0x029fff32), + TOBN(0x075e2a64, 0x6caa6d2f), TOBN(0x8eb879de, 0x22e7351b), + TOBN(0xbcd5624e, 0x9a506c62), TOBN(0x218eaef0, 0xa87e24dc), + TOBN(0x37e56847, 0x44ddfa35), TOBN(0x9ccfc5c5, 0xdab3f747), + TOBN(0x9ac1df3f, 0x1ee96cf4), TOBN(0x0c0571a1, 0x3b480b8f), + TOBN(0x2fbeb3d5, 0x4b3a7b3c), TOBN(0x35c03669, 0x5dcdbb99), + TOBN(0x52a0f5dc, 0xb2415b3a), TOBN(0xd57759b4, 0x4413ed9a), + TOBN(0x1fe647d8, 0x3d30a2c5), TOBN(0x0857f77e, 0xf78a81dc), + TOBN(0x11d5a334, 0x131a4a9b), TOBN(0xc0a94af9, 0x29d393f5), + TOBN(0xbc3a5c0b, 0xdaa6ec1a), TOBN(0xba9fe493, 0x88d2d7ed), + TOBN(0xbb4335b4, 0xbb614797), TOBN(0x991c4d68, 0x72f83533), + TOBN(0x53258c28, 0xd2f01cb3), TOBN(0x93d6eaa3, 0xd75db0b1), + TOBN(0x419a2b0d, 0xe87d0db4), TOBN(0xa1e48f03, 0xd8fe8493), + TOBN(0xf747faf6, 0xc508b23a), TOBN(0xf137571a, 0x35d53549), + TOBN(0x9f5e58e2, 0xfcf9b838), TOBN(0xc7186cee, 0xa7fd3cf5), + TOBN(0x77b868ce, 0xe978a1d3), TOBN(0xe3a68b33, 0x7ab92d04), + TOBN(0x51029794, 0x87a5b862), TOBN(0x5f0606c3, 0x3a61d41d), + TOBN(0x2814be27, 0x6f9326f1), TOBN(0x2f521c14, 0xc6fe3c2e), + TOBN(0x17464d7d, 0xacdf7351), TOBN(0x10f5f9d3, 0x777f7e44), + TOBN(0xce8e616b, 0x269fb37d), TOBN(0xaaf73804, 0x7de62de5), + TOBN(0xaba11175, 0x4fdd4153), TOBN(0x515759ba, 0x3770b49b), + TOBN(0x8b09ebf8, 0xaa423a61), TOBN(0x592245a1, 0xcd41fb92), + TOBN(0x1cba8ec1, 0x9b4c8936), TOBN(0xa87e91e3, 0xaf36710e), + TOBN(0x1fd84ce4, 0x3d34a2e3), TOBN(0xee3759ce, 0xb43b5d61), + TOBN(0x895bc78c, 0x619186c7), TOBN(0xf19c3809, 0xcbb9725a), + TOBN(0xc0be21aa, 0xde744b1f), TOBN(0xa7d222b0, 0x60f8056b), + TOBN(0x74be6157, 0xb23efe11), TOBN(0x6fab2b4f, 0x0cd68253), + TOBN(0xad33ea5f, 0x4bf1d725), TOBN(0x9c1d8ee2, 0x4f6c950f), + TOBN(0x544ee78a, 0xa377af06), TOBN(0x54f489bb, 0x94a113e1), + TOBN(0x8f11d634, 0x992fb7e8), TOBN(0x0169a7aa, 0xa2a44347), + TOBN(0x1d49d4af, 0x95020e00), TOBN(0x95945722, 0xe08e120b), + TOBN(0xb6e33878, 0xa4d32282), TOBN(0xe36e029d, 0x48020ae7), + TOBN(0xe05847fb, 0x37a9b750), TOBN(0xf876812c, 0xb29e3819), + TOBN(0x84ad138e, 0xd23a17f0), TOBN(0x6d7b4480, 0xf0b3950e), + TOBN(0xdfa8aef4, 0x2fd67ae0), TOBN(0x8d3eea24, 0x52333af6), + TOBN(0x0d052075, 0xb15d5acc), TOBN(0xc6d9c79f, 0xbd815bc4), + TOBN(0x8dcafd88, 0xdfa36cf2), TOBN(0x908ccbe2, 0x38aa9070), + TOBN(0x638722c4, 0xba35afce), TOBN(0x5a3da8b0, 0xfd6abf0b), + TOBN(0x2dce252c, 0xc9c335c1), TOBN(0x84e7f0de, 0x65aa799b), + TOBN(0x2101a522, 0xb99a72cb), TOBN(0x06de6e67, 0x87618016), + TOBN(0x5ff8c7cd, 0xe6f3653e), TOBN(0x0a821ab5, 0xc7a6754a), + TOBN(0x7e3fa52b, 0x7cb0b5a2), TOBN(0xa7fb121c, 0xc9048790), + TOBN(0x1a725020, 0x06ce053a), TOBN(0xb490a31f, 0x04e929b0), + TOBN(0xe17be47d, 0x62dd61ad), TOBN(0x781a961c, 0x6be01371), + TOBN(0x1063bfd3, 0xdae3cbba), TOBN(0x35647406, 0x7f73c9ba), + TOBN(0xf50e957b, 0x2736a129), TOBN(0xa6313702, 0xed13f256), + TOBN(0x9436ee65, 0x3a19fcc5), TOBN(0xcf2bdb29, 0xe7a4c8b6), + TOBN(0xb06b1244, 0xc5f95cd8), TOBN(0xda8c8af0, 0xf4ab95f4), + TOBN(0x1bae59c2, 0xb9e5836d), TOBN(0x07d51e7e, 0x3acffffc), + TOBN(0x01e15e6a, 0xc2ccbcda), TOBN(0x3bc1923f, 0x8528c3e0), + TOBN(0x43324577, 0xa49fead4), TOBN(0x61a1b884, 0x2aa7a711), + TOBN(0xf9a86e08, 0x700230ef), TOBN(0x0af585a1, 0xbd19adf8), + TOBN(0x7645f361, 0xf55ad8f2), TOBN(0x6e676223, 0x46c3614c), + TOBN(0x23cb257c, 0x4e774d3f), TOBN(0x82a38513, 0xac102d1b), + TOBN(0x9bcddd88, 0x7b126aa5), TOBN(0xe716998b, 0xeefd3ee4), + TOBN(0x4239d571, 0xfb167583), TOBN(0xdd011c78, 0xd16c8f8a), + TOBN(0x271c2895, 0x69a27519), TOBN(0x9ce0a3b7, 0xd2d64b6a), + TOBN(0x8c977289, 0xd5ec6738), TOBN(0xa3b49f9a, 0x8840ef6b), + TOBN(0x808c14c9, 0x9a453419), TOBN(0x5c00295b, 0x0cf0a2d5), + TOBN(0x524414fb, 0x1d4bcc76), TOBN(0xb07691d2, 0x459a88f1), + TOBN(0x77f43263, 0xf70d110f), TOBN(0x64ada5e0, 0xb7abf9f3), + TOBN(0xafd0f94e, 0x5b544cf5), TOBN(0xb4a13a15, 0xfd2713fe), + TOBN(0xb99b7d6e, 0x250c74f4), TOBN(0x097f2f73, 0x20324e45), + TOBN(0x994b37d8, 0xaffa8208), TOBN(0xc3c31b0b, 0xdc29aafc), + TOBN(0x3da74651, 0x7a3a607f), TOBN(0xd8e1b8c1, 0xfe6955d6), + TOBN(0x716e1815, 0xc8418682), TOBN(0x541d487f, 0x7dc91d97), + TOBN(0x48a04669, 0xc6996982), TOBN(0xf39cab15, 0x83a6502e), + TOBN(0x025801a0, 0xe68db055), TOBN(0xf3569758, 0xba3338d5), + TOBN(0xb0c8c0aa, 0xee2afa84), TOBN(0x4f6985d3, 0xfb6562d1), + TOBN(0x351f1f15, 0x132ed17a), TOBN(0x510ed0b4, 0xc04365fe), + TOBN(0xa3f98138, 0xe5b1f066), TOBN(0xbc9d95d6, 0x32df03dc), + TOBN(0xa83ccf6e, 0x19abd09e), TOBN(0x0b4097c1, 0x4ff17edb), + TOBN(0x58a5c478, 0xd64a06ce), TOBN(0x2ddcc3fd, 0x544a58fd), + TOBN(0xd449503d, 0x9e8153b8), TOBN(0x3324fd02, 0x7774179b), + TOBN(0xaf5d47c8, 0xdbd9120c), TOBN(0xeb860162, 0x34fa94db), + TOBN(0x5817bdd1, 0x972f07f4), TOBN(0xe5579e2e, 0xd27bbceb), + TOBN(0x86847a1f, 0x5f11e5a6), TOBN(0xb39ed255, 0x7c3cf048), + TOBN(0xe1076417, 0xa2f62e55), TOBN(0x6b9ab38f, 0x1bcf82a2), + TOBN(0x4bb7c319, 0x7aeb29f9), TOBN(0xf6d17da3, 0x17227a46), + TOBN(0xab53ddbd, 0x0f968c00), TOBN(0xa03da7ec, 0x000c880b), + TOBN(0x7b239624, 0x6a9ad24d), TOBN(0x612c0401, 0x01ec60d0), + TOBN(0x70d10493, 0x109f5df1), TOBN(0xfbda4030, 0x80af7550), + TOBN(0x30b93f95, 0xc6b9a9b3), TOBN(0x0c74ec71, 0x007d9418), + TOBN(0x94175564, 0x6edb951f), TOBN(0x5f4a9d78, 0x7f22c282), + TOBN(0xb7870895, 0xb38d1196), TOBN(0xbc593df3, 0xa228ce7c), + TOBN(0xc78c5bd4, 0x6af3641a), TOBN(0x7802200b, 0x3d9b3dcc), + TOBN(0x0dc73f32, 0x8be33304), TOBN(0x847ed87d, 0x61ffb79a), + TOBN(0xf85c974e, 0x6d671192), TOBN(0x1e14100a, 0xde16f60f), + TOBN(0x45cb0d5a, 0x95c38797), TOBN(0x18923bba, 0x9b022da4), + TOBN(0xef2be899, 0xbbe7e86e), TOBN(0x4a1510ee, 0x216067bf), + TOBN(0xd98c8154, 0x84d5ce3e), TOBN(0x1af777f0, 0xf92a2b90), + TOBN(0x9fbcb400, 0x4ef65724), TOBN(0x3e04a4c9, 0x3c0ca6fe), + TOBN(0xfb3e2cb5, 0x55002994), TOBN(0x1f3a93c5, 0x5363ecab), + TOBN(0x1fe00efe, 0x3923555b), TOBN(0x744bedd9, 0x1e1751ea), + TOBN(0x3fb2db59, 0x6ab69357), TOBN(0x8dbd7365, 0xf5e6618b), + TOBN(0x99d53099, 0xdf1ea40e), TOBN(0xb3f24a0b, 0x57d61e64), + TOBN(0xd088a198, 0x596eb812), TOBN(0x22c8361b, 0x5762940b), + TOBN(0x66f01f97, 0xf9c0d95c), TOBN(0x88461172, 0x8e43cdae), + TOBN(0x11599a7f, 0xb72b15c3), TOBN(0x135a7536, 0x420d95cc), + TOBN(0x2dcdf0f7, 0x5f7ae2f6), TOBN(0x15fc6e1d, 0xd7fa6da2), + TOBN(0x81ca829a, 0xd1d441b6), TOBN(0x84c10cf8, 0x04a106b6), + TOBN(0xa9b26c95, 0xa73fbbd0), TOBN(0x7f24e0cb, 0x4d8f6ee8), + TOBN(0x48b45937, 0x1e25a043), TOBN(0xf8a74fca, 0x036f3dfe), + TOBN(0x1ed46585, 0xc9f84296), TOBN(0x7fbaa8fb, 0x3bc278b0), + TOBN(0xa8e96cd4, 0x6c4fcbd0), TOBN(0x940a1202, 0x73b60a5f), + TOBN(0x34aae120, 0x55a4aec8), TOBN(0x550e9a74, 0xdbd742f0), + TOBN(0x794456d7, 0x228c68ab), TOBN(0x492f8868, 0xa4e25ec6), + TOBN(0x682915ad, 0xb2d8f398), TOBN(0xf13b51cc, 0x5b84c953), + TOBN(0xcda90ab8, 0x5bb917d6), TOBN(0x4b615560, 0x4ea3dee1), + TOBN(0x578b4e85, 0x0a52c1c8), TOBN(0xeab1a695, 0x20b75fc4), + TOBN(0x60c14f3c, 0xaa0bb3c6), TOBN(0x220f448a, 0xb8216094), + TOBN(0x4fe7ee31, 0xb0e63d34), TOBN(0xf4600572, 0xa9e54fab), + TOBN(0xc0493334, 0xd5e7b5a4), TOBN(0x8589fb92, 0x06d54831), + TOBN(0xaa70f5cc, 0x6583553a), TOBN(0x0879094a, 0xe25649e5), + TOBN(0xcc904507, 0x10044652), TOBN(0xebb0696d, 0x02541c4f), + TOBN(0x5a171fde, 0xb9718710), TOBN(0x38f1bed8, 0xf374a9f5), + TOBN(0xc8c582e1, 0xba39bdc1), TOBN(0xfc457b0a, 0x908cc0ce), + TOBN(0x9a187fd4, 0x883841e2), TOBN(0x8ec25b39, 0x38725381), + TOBN(0x2553ed05, 0x96f84395), TOBN(0x095c7661, 0x6f6c6897), + TOBN(0x917ac85c, 0x4bdc5610), TOBN(0xb2885fe4, 0x179eb301), + TOBN(0x5fc65547, 0x8b78bdcc), TOBN(0x4a9fc893, 0xe59e4699), + TOBN(0xbb7ff0cd, 0x3ce299af), TOBN(0x195be9b3, 0xadf38b20), + TOBN(0x6a929c87, 0xd38ddb8f), TOBN(0x55fcc99c, 0xb21a51b9), + TOBN(0x2b695b4c, 0x721a4593), TOBN(0xed1e9a15, 0x768eaac2), + TOBN(0xfb63d71c, 0x7489f914), TOBN(0xf98ba31c, 0x78118910), + TOBN(0x80291373, 0x9b128eb4), TOBN(0x7801214e, 0xd448af4a), + TOBN(0xdbd2e22b, 0x55418dd3), TOBN(0xeffb3c0d, 0xd3998242), + TOBN(0xdfa6077c, 0xc7bf3827), TOBN(0xf2165bcb, 0x47f8238f), + TOBN(0xfe37cf68, 0x8564d554), TOBN(0xe5f825c4, 0x0a81fb98), + TOBN(0x43cc4f67, 0xffed4d6f), TOBN(0xbc609578, 0xb50a34b0), + TOBN(0x8aa8fcf9, 0x5041faf1), TOBN(0x5659f053, 0x651773b6), + TOBN(0xe87582c3, 0x6044d63b), TOBN(0xa6089409, 0x0cdb0ca0), + TOBN(0x8c993e0f, 0xbfb2bcf6), TOBN(0xfc64a719, 0x45985cfc), + TOBN(0x15c4da80, 0x83dbedba), TOBN(0x804ae112, 0x2be67df7), + TOBN(0xda4c9658, 0xa23defde), TOBN(0x12002ddd, 0x5156e0d3), + TOBN(0xe68eae89, 0x5dd21b96), TOBN(0x8b99f28b, 0xcf44624d), + TOBN(0x0ae00808, 0x1ec8897a), TOBN(0xdd0a9303, 0x6712f76e), + TOBN(0x96237522, 0x4e233de4), TOBN(0x192445b1, 0x2b36a8a5), + TOBN(0xabf9ff74, 0x023993d9), TOBN(0x21f37bf4, 0x2aad4a8f), + TOBN(0x340a4349, 0xf8bd2bbd), TOBN(0x1d902cd9, 0x4868195d), + TOBN(0x3d27bbf1, 0xe5fdb6f1), TOBN(0x7a5ab088, 0x124f9f1c), + TOBN(0xc466ab06, 0xf7a09e03), TOBN(0x2f8a1977, 0x31f2c123), + TOBN(0xda355dc7, 0x041b6657), TOBN(0xcb840d12, 0x8ece2a7c), + TOBN(0xb600ad9f, 0x7db32675), TOBN(0x78fea133, 0x07a06f1b), + TOBN(0x5d032269, 0xb31f6094), TOBN(0x07753ef5, 0x83ec37aa), + TOBN(0x03485aed, 0x9c0bea78), TOBN(0x41bb3989, 0xbc3f4524), + TOBN(0x09403761, 0x697f726d), TOBN(0x6109beb3, 0xdf394820), + TOBN(0x804111ea, 0x3b6d1145), TOBN(0xb6271ea9, 0xa8582654), + TOBN(0x619615e6, 0x24e66562), TOBN(0xa2554945, 0xd7b6ad9c), + TOBN(0xd9c4985e, 0x99bfe35f), TOBN(0x9770ccc0, 0x7b51cdf6), + TOBN(0x7c327013, 0x92881832), TOBN(0x8777d45f, 0x286b26d1), + TOBN(0x9bbeda22, 0xd847999d), TOBN(0x03aa33b6, 0xc3525d32), + TOBN(0x4b7b96d4, 0x28a959a1), TOBN(0xbb3786e5, 0x31e5d234), + TOBN(0xaeb5d3ce, 0x6961f247), TOBN(0x20aa85af, 0x02f93d3f), + TOBN(0x9cd1ad3d, 0xd7a7ae4f), TOBN(0xbf6688f0, 0x781adaa8), + TOBN(0xb1b40e86, 0x7469cead), TOBN(0x1904c524, 0x309fca48), + TOBN(0x9b7312af, 0x4b54bbc7), TOBN(0xbe24bf8f, 0x593affa2), + TOBN(0xbe5e0790, 0xbd98764b), TOBN(0xa0f45f17, 0xa26e299e), + TOBN(0x4af0d2c2, 0x6b8fe4c7), TOBN(0xef170db1, 0x8ae8a3e6), + TOBN(0x0e8d61a0, 0x29e0ccc1), TOBN(0xcd53e87e, 0x60ad36ca), + TOBN(0x328c6623, 0xc8173822), TOBN(0x7ee1767d, 0xa496be55), + TOBN(0x89f13259, 0x648945af), TOBN(0x9e45a5fd, 0x25c8009c), + TOBN(0xaf2febd9, 0x1f61ab8c), TOBN(0x43f6bc86, 0x8a275385), + TOBN(0x87792348, 0xf2142e79), TOBN(0x17d89259, 0xc6e6238a), + TOBN(0x7536d2f6, 0x4a839d9b), TOBN(0x1f428fce, 0x76a1fbdc), + TOBN(0x1c109601, 0x0db06dfe), TOBN(0xbfc16bc1, 0x50a3a3cc), + TOBN(0xf9cbd9ec, 0x9b30f41b), TOBN(0x5b5da0d6, 0x00138cce), + TOBN(0xec1d0a48, 0x56ef96a7), TOBN(0xb47eb848, 0x982bf842), + TOBN(0x66deae32, 0xec3f700d), TOBN(0x4e43c42c, 0xaa1181e0), + TOBN(0xa1d72a31, 0xd1a4aa2a), TOBN(0x440d4668, 0xc004f3ce), + TOBN(0x0d6a2d3b, 0x45fe8a7a), TOBN(0x820e52e2, 0xfb128365), + TOBN(0x29ac5fcf, 0x25e51b09), TOBN(0x180cd2bf, 0x2023d159), + TOBN(0xa9892171, 0xa1ebf90e), TOBN(0xf97c4c87, 0x7c132181), + TOBN(0x9f1dc724, 0xc03dbb7e), TOBN(0xae043765, 0x018cbbe4), + TOBN(0xfb0b2a36, 0x0767d153), TOBN(0xa8e2f4d6, 0x249cbaeb), + TOBN(0x172a5247, 0xd95ea168), TOBN(0x1758fada, 0x2970764a), + TOBN(0xac803a51, 0x1d978169), TOBN(0x299cfe2e, 0xde77e01b), + TOBN(0x652a1e17, 0xb0a98927), TOBN(0x2e26e1d1, 0x20014495), + TOBN(0x7ae0af9f, 0x7175b56a), TOBN(0xc2e22a80, 0xd64b9f95), + TOBN(0x4d0ff9fb, 0xd90a060a), TOBN(0x496a27db, 0xbaf38085), + TOBN(0x32305401, 0xda776bcf), TOBN(0xb8cdcef6, 0x725f209e), + TOBN(0x61ba0f37, 0x436a0bba), TOBN(0x263fa108, 0x76860049), + TOBN(0x92beb98e, 0xda3542cf), TOBN(0xa2d4d14a, 0xd5849538), + TOBN(0x989b9d68, 0x12e9a1bc), TOBN(0x61d9075c, 0x5f6e3268), + TOBN(0x352c6aa9, 0x99ace638), TOBN(0xde4e4a55, 0x920f43ff), + TOBN(0xe5e4144a, 0xd673c017), TOBN(0x667417ae, 0x6f6e05ea), + TOBN(0x613416ae, 0xdcd1bd56), TOBN(0x5eb36201, 0x86693711), + TOBN(0x2d7bc504, 0x3a1aa914), TOBN(0x175a1299, 0x76dc5975), + TOBN(0xe900e0f2, 0x3fc8125c), TOBN(0x569ef68c, 0x11198875), + TOBN(0x9012db63, 0x63a113b4), TOBN(0xe3bd3f56, 0x98835766), + TOBN(0xa5c94a52, 0x76412dea), TOBN(0xad9e2a09, 0xaa735e5c), + TOBN(0x405a984c, 0x508b65e9), TOBN(0xbde4a1d1, 0x6df1a0d1), + TOBN(0x1a9433a1, 0xdfba80da), TOBN(0xe9192ff9, 0x9440ad2e), + TOBN(0x9f649696, 0x5099fe92), TOBN(0x25ddb65c, 0x0b27a54a), + TOBN(0x178279dd, 0xc590da61), TOBN(0x5479a999, 0xfbde681a), + TOBN(0xd0e84e05, 0x013fe162), TOBN(0xbe11dc92, 0x632d471b), + TOBN(0xdf0b0c45, 0xfc0e089f), TOBN(0x04fb15b0, 0x4c144025), + TOBN(0xa61d5fc2, 0x13c99927), TOBN(0xa033e9e0, 0x3de2eb35), + TOBN(0xf8185d5c, 0xb8dacbb4), TOBN(0x9a88e265, 0x8644549d), + TOBN(0xf717af62, 0x54671ff6), TOBN(0x4bd4241b, 0x5fa58603), + TOBN(0x06fba40b, 0xe67773c0), TOBN(0xc1d933d2, 0x6a2847e9), + TOBN(0xf4f5acf3, 0x689e2c70), TOBN(0x92aab0e7, 0x46bafd31), + TOBN(0x798d76aa, 0x3473f6e5), TOBN(0xcc6641db, 0x93141934), + TOBN(0xcae27757, 0xd31e535e), TOBN(0x04cc43b6, 0x87c2ee11), + TOBN(0x8d1f9675, 0x2e029ffa), TOBN(0xc2150672, 0xe4cc7a2c), + TOBN(0x3b03c1e0, 0x8d68b013), TOBN(0xa9d6816f, 0xedf298f3), + TOBN(0x1bfbb529, 0xa2804464), TOBN(0x95a52fae, 0x5db22125), + TOBN(0x55b32160, 0x0e1cb64e), TOBN(0x004828f6, 0x7e7fc9fe), + TOBN(0x13394b82, 0x1bb0fb93), TOBN(0xb6293a2d, 0x35f1a920), + TOBN(0xde35ef21, 0xd145d2d9), TOBN(0xbe6225b3, 0xbb8fa603), + TOBN(0x00fc8f6b, 0x32cf252d), TOBN(0xa28e52e6, 0x117cf8c2), + TOBN(0x9d1dc89b, 0x4c371e6d), TOBN(0xcebe0675, 0x36ef0f28), + TOBN(0x5de05d09, 0xa4292f81), TOBN(0xa8303593, 0x353e3083), + TOBN(0xa1715b0a, 0x7e37a9bb), TOBN(0x8c56f61e, 0x2b8faec3), + TOBN(0x52507431, 0x33c9b102), TOBN(0x0130cefc, 0xa44431f0), + TOBN(0x56039fa0, 0xbd865cfb), TOBN(0x4b03e578, 0xbc5f1dd7), + TOBN(0x40edf2e4, 0xbabe7224), TOBN(0xc752496d, 0x3a1988f6), + TOBN(0xd1572d3b, 0x564beb6b), TOBN(0x0db1d110, 0x39a1c608), + TOBN(0x568d1934, 0x16f60126), TOBN(0x05ae9668, 0xf354af33), + TOBN(0x19de6d37, 0xc92544f2), TOBN(0xcc084353, 0xa35837d5), + TOBN(0xcbb6869c, 0x1a514ece), TOBN(0xb633e728, 0x2e1d1066), + TOBN(0xf15dd69f, 0x936c581c), TOBN(0x96e7b8ce, 0x7439c4f9), + TOBN(0x5e676f48, 0x2e448a5b), TOBN(0xb2ca7d5b, 0xfd916bbb), + TOBN(0xd55a2541, 0xf5024025), TOBN(0x47bc5769, 0xe4c2d937), + TOBN(0x7d31b92a, 0x0362189f), TOBN(0x83f3086e, 0xef7816f9), + TOBN(0xf9f46d94, 0xb587579a), TOBN(0xec2d22d8, 0x30e76c5f), + TOBN(0x27d57461, 0xb000ffcf), TOBN(0xbb7e65f9, 0x364ffc2c), + TOBN(0x7c7c9477, 0x6652a220), TOBN(0x61618f89, 0xd696c981), + TOBN(0x5021701d, 0x89effff3), TOBN(0xf2c8ff8e, 0x7c314163), + TOBN(0x2da413ad, 0x8efb4d3e), TOBN(0x937b5adf, 0xce176d95), + TOBN(0x22867d34, 0x2a67d51c), TOBN(0x262b9b10, 0x18eb3ac9), + TOBN(0x4e314fe4, 0xc43ff28b), TOBN(0x76476627, 0x6a664e7a), + TOBN(0x3e90e40b, 0xb7a565c2), TOBN(0x8588993a, 0xc1acf831), + TOBN(0xd7b501d6, 0x8f938829), TOBN(0x996627ee, 0x3edd7d4c), + TOBN(0x37d44a62, 0x90cd34c7), TOBN(0xa8327499, 0xf3833e8d), + TOBN(0x2e18917d, 0x4bf50353), TOBN(0x85dd726b, 0x556765fb), + TOBN(0x54fe65d6, 0x93d5ab66), TOBN(0x3ddbaced, 0x915c25fe), + TOBN(0xa799d9a4, 0x12f22e85), TOBN(0xe2a24867, 0x6d06f6bc), + TOBN(0xf4f1ee56, 0x43ca1637), TOBN(0xfda2828b, 0x61ece30a), + TOBN(0x758c1a3e, 0xa2dee7a6), TOBN(0xdcde2f3c, 0x734b2284), + TOBN(0xaba445d2, 0x4eaba6ad), TOBN(0x35aaf668, 0x76cee0a7), + TOBN(0x7e0b04a9, 0xe5aa049a), TOBN(0xe74083ad, 0x91103e84), + TOBN(0xbeb183ce, 0x40afecc3), TOBN(0x6b89de9f, 0xea043f7a)}, {TOBN(0x0e299d23, 0xfe67ba66), TOBN(0x91450760, 0x93cf2f34), TOBN(0xf45b5ea9, 0x97fcf913), TOBN(0x5be00843, 0x8bd7ddda), TOBN(0x358c3e05, 0xd53ff04d), TOBN(0xbf7ccdc3, 0x5de91ef7), @@ -4383,4908 +4381,4870 @@ static const alignas(4096) BN_ULONG TOBN(0x2f69d39e, 0xaf7eded5), TOBN(0x73c2f434, 0xde6af11b), TOBN(0x4ca52493, 0xa4a375fa), TOBN(0x5f06787c, 0xb833c5c2), TOBN(0x814e091f, 0x3e6e71cf), TOBN(0x76451f57, 0x8b746666)}, - { - TOBN(0x80f9bdef, 0x694db7e0), TOBN(0xedca8787, 0xb9fcddc6), - TOBN(0x51981c34, 0x03b8dce1), TOBN(0x4274dcf1, 0x70e10ba1), - TOBN(0xf72743b8, 0x6def6d1a), TOBN(0xd25b1670, 0xebdb1866), - TOBN(0xc4491e8c, 0x050c6f58), TOBN(0x2be2b2ab, 0x87fbd7f5), - TOBN(0x3e0e5c9d, 0xd111f8ec), TOBN(0xbcc33f8d, 0xb7c4e760), - TOBN(0x702f9a91, 0xbd392a51), TOBN(0x7da4a795, 0xc132e92d), - TOBN(0x1a0b0ae3, 0x0bb1151b), TOBN(0x54febac8, 0x02e32251), - TOBN(0xea3a5082, 0x694e9e78), TOBN(0xe58ffec1, 0xe4fe40b8), - TOBN(0xf85592fc, 0xd1e0cf9e), TOBN(0xdea75f0d, 0xc0e7b2e8), - TOBN(0xc04215cf, 0xc135584e), TOBN(0x174fc727, 0x2f57092a), - TOBN(0xe7277877, 0xeb930bea), TOBN(0x504caccb, 0x5eb02a5a), - TOBN(0xf9fe08f7, 0xf5241b9b), TOBN(0xe7fb62f4, 0x8d5ca954), - TOBN(0xfbb8349d, 0x29c4120b), TOBN(0x9f94391f, 0xc0d0d915), - TOBN(0xc4074fa7, 0x5410ba51), TOBN(0xa66adbf6, 0x150a5911), - TOBN(0xc164543c, 0x34bfca38), TOBN(0xe0f27560, 0xb9e1ccfc), - TOBN(0x99da0f53, 0xe820219c), TOBN(0xe8234498, 0xc6b4997a), - TOBN(0xcfb88b76, 0x9d4c5423), TOBN(0x9e56eb10, 0xb0521c49), - TOBN(0x418e0b5e, 0xbe8700a1), TOBN(0x00cbaad6, 0xf93cb58a), - TOBN(0xe923fbde, 0xd92a5e67), TOBN(0xca4979ac, 0x1f347f11), - TOBN(0x89162d85, 0x6bc0585b), TOBN(0xdd6254af, 0xac3c70e3), - TOBN(0x7b23c513, 0x516e19e4), TOBN(0x56e2e847, 0xc5c4d593), - TOBN(0x9f727d73, 0x5ce71ef6), TOBN(0x5b6304a6, 0xf79a44c5), - TOBN(0x6638a736, 0x3ab7e433), TOBN(0x1adea470, 0xfe742f83), - TOBN(0xe054b854, 0x5b7fc19f), TOBN(0xf935381a, 0xba1d0698), - TOBN(0x546eab2d, 0x799e9a74), TOBN(0x96239e0e, 0xa949f729), - TOBN(0xca274c6b, 0x7090055a), TOBN(0x835142c3, 0x9020c9b0), - TOBN(0xa405667a, 0xa2e8807f), TOBN(0x29f2c085, 0x1aa3d39e), - TOBN(0xcc555d64, 0x42fc72f5), TOBN(0xe856e0e7, 0xfbeacb3c), - TOBN(0xb5504f9d, 0x918e4936), TOBN(0x65035ef6, 0xb2513982), - TOBN(0x0553a0c2, 0x6f4d9cb9), TOBN(0x6cb10d56, 0xbea85509), - TOBN(0x48d957b7, 0xa242da11), TOBN(0x16a4d3dd, 0x672b7268), - TOBN(0x3d7e637c, 0x8502a96b), TOBN(0x27c7032b, 0x730d463b), - TOBN(0xbdc02b18, 0xe4136a14), TOBN(0xbacf969d, 0x678e32bf), - TOBN(0xc98d89a3, 0xdd9c3c03), TOBN(0x7b92420a, 0x23becc4f), - TOBN(0xd4b41f78, 0xc64d565c), TOBN(0x9f969d00, 0x10f28295), - TOBN(0xec7f7f76, 0xb13d051a), TOBN(0x08945e1e, 0xa92da585), - TOBN(0x55366b7d, 0x5846426f), TOBN(0xe7d09e89, 0x247d441d), - TOBN(0x510b404d, 0x736fbf48), TOBN(0x7fa003d0, 0xe784bd7d), - TOBN(0x25f7614f, 0x17fd9596), TOBN(0x49e0e0a1, 0x35cb98db), - TOBN(0x2c65957b, 0x2e83a76a), TOBN(0x5d40da8d, 0xcddbe0f8), - TOBN(0xf2b8c405, 0x050bad24), TOBN(0x8918426d, 0xc2aa4823), - TOBN(0x2aeab3dd, 0xa38365a7), TOBN(0x72031717, 0x7c91b690), - TOBN(0x8b00d699, 0x60a94120), TOBN(0x478a255d, 0xe99eaeec), - TOBN(0xbf656a5f, 0x6f60aafd), TOBN(0xdfd7cb75, 0x5dee77b3), - TOBN(0x37f68bb4, 0xa595939d), TOBN(0x03556479, 0x28740217), - TOBN(0x8e740e7c, 0x84ad7612), TOBN(0xd89bc843, 0x9044695f), - TOBN(0xf7f3da5d, 0x85a9184d), TOBN(0x562563bb, 0x9fc0b074), - TOBN(0x06d2e6aa, 0xf88a888e), TOBN(0x612d8643, 0x161fbe7c), - TOBN(0x465edba7, 0xf64085e7), TOBN(0xb230f304, 0x29aa8511), - TOBN(0x53388426, 0xcda2d188), TOBN(0x90885735, 0x4b666649), - TOBN(0x6f02ff9a, 0x652f54f6), TOBN(0x65c82294, 0x5fae2bf0), - TOBN(0x7816ade0, 0x62f5eee3), TOBN(0xdcdbdf43, 0xfcc56d70), - TOBN(0x9fb3bba3, 0x54530bb2), TOBN(0xbde3ef77, 0xcb0869ea), - TOBN(0x89bc9046, 0x0b431163), TOBN(0x4d03d7d2, 0xe4819a35), - TOBN(0x33ae4f9e, 0x43b6a782), TOBN(0x216db307, 0x9c88a686), - TOBN(0x91dd88e0, 0x00ffedd9), TOBN(0xb280da9f, 0x12bd4840), - TOBN(0x32a7cb8a, 0x1635e741), TOBN(0xfe14008a, 0x78be02a7), - TOBN(0x3fafb334, 0x1b7ae030), TOBN(0x7fd508e7, 0x5add0ce9), - TOBN(0x72c83219, 0xd607ad51), TOBN(0x0f229c0a, 0x8d40964a), - TOBN(0x1be2c336, 0x1c878da2), TOBN(0xe0c96742, 0xeab2ab86), - TOBN(0x458f8691, 0x3e538cd7), TOBN(0xa7001f6c, 0x8e08ad53), - TOBN(0x52b8c6e6, 0xbf5d15ff), TOBN(0x548234a4, 0x011215dd), - TOBN(0xff5a9d2d, 0x3d5b4045), TOBN(0xb0ffeeb6, 0x4a904190), - TOBN(0x55a3aca4, 0x48607f8b), TOBN(0x8cbd665c, 0x30a0672a), - TOBN(0x87f834e0, 0x42583068), TOBN(0x02da2aeb, 0xf3f6e683), - TOBN(0x6b763e5d, 0x05c12248), TOBN(0x7230378f, 0x65a8aefc), - TOBN(0x93bd80b5, 0x71e8e5ca), TOBN(0x53ab041c, 0xb3b62524), - TOBN(0x1b860513, 0x6c9c552e), TOBN(0xe84d402c, 0xd5524e66), - TOBN(0xa37f3573, 0xf37f5937), TOBN(0xeb0f6c7d, 0xd1e4fca5), - TOBN(0x2965a554, 0xac8ab0fc), TOBN(0x17fbf56c, 0x274676ac), - TOBN(0x2e2f6bd9, 0xacf7d720), TOBN(0x41fc8f88, 0x10224766), - TOBN(0x517a14b3, 0x85d53bef), TOBN(0xdae327a5, 0x7d76a7d1), - TOBN(0x6ad0a065, 0xc4818267), TOBN(0x33aa189b, 0x37c1bbc1), - TOBN(0x64970b52, 0x27392a92), TOBN(0x21699a1c, 0x2d1535ea), - TOBN(0xcd20779c, 0xc2d7a7fd), TOBN(0xe3186059, 0x99c83cf2), - TOBN(0x9b69440b, 0x72c0b8c7), TOBN(0xa81497d7, 0x7b9e0e4d), - TOBN(0x515d5c89, 0x1f5f82dc), TOBN(0x9a7f67d7, 0x6361079e), - TOBN(0xa8da81e3, 0x11a35330), TOBN(0xe44990c4, 0x4b18be1b), - TOBN(0xc7d5ed95, 0xaf103e59), TOBN(0xece8aba7, 0x8dac9261), - TOBN(0xbe82b099, 0x9394b8d3), TOBN(0x6830f09a, 0x16adfe83), - TOBN(0x250a29b4, 0x88172d01), TOBN(0x8b20bd65, 0xcaff9e02), - TOBN(0xb8a7661e, 0xe8a6329a), TOBN(0x4520304d, 0xd3fce920), - TOBN(0xae45da1f, 0x2b47f7ef), TOBN(0xe07f5288, 0x5bffc540), - TOBN(0xf7997009, 0x3464f874), TOBN(0x2244c2cd, 0xa6fa1f38), - TOBN(0x43c41ac1, 0x94d7d9b1), TOBN(0x5bafdd82, 0xc82e7f17), - TOBN(0xdf0614c1, 0x5fda0fca), TOBN(0x74b043a7, 0xa8ae37ad), - TOBN(0x3ba6afa1, 0x9e71734c), TOBN(0x15d5437e, 0x9c450f2e), - TOBN(0x4a5883fe, 0x67e242b1), TOBN(0x5143bdc2, 0x2c1953c2), - TOBN(0x542b8b53, 0xfc5e8920), TOBN(0x363bf9a8, 0x9a9cee08), - TOBN(0x02375f10, 0xc3486e08), TOBN(0x2037543b, 0x8c5e70d2), - TOBN(0x7109bccc, 0x625640b4), TOBN(0xcbc1051e, 0x8bc62c3b), - TOBN(0xf8455fed, 0x803f26ea), TOBN(0x6badceab, 0xeb372424), - TOBN(0xa2a9ce7c, 0x6b53f5f9), TOBN(0x64246595, 0x1b176d99), - TOBN(0xb1298d36, 0xb95c081b), TOBN(0x53505bb8, 0x1d9a9ee6), - TOBN(0x3f6f9e61, 0xf2ba70b0), TOBN(0xd07e16c9, 0x8afad453), - TOBN(0x9f1694bb, 0xe7eb4a6a), TOBN(0xdfebced9, 0x3cb0bc8e), - TOBN(0x92d3dcdc, 0x53868c8b), TOBN(0x174311a2, 0x386107a6), - TOBN(0x4109e07c, 0x689b4e64), TOBN(0x30e4587f, 0x2df3dcb6), - TOBN(0x841aea31, 0x0811b3b2), TOBN(0x6144d41d, 0x0cce43ea), - TOBN(0x464c4581, 0x2a9a7803), TOBN(0xd03d371f, 0x3e158930), - TOBN(0xc676d7f2, 0xb1f3390b), TOBN(0x9f7a1b8c, 0xa5b61272), - TOBN(0x4ebebfc9, 0xc2e127a9), TOBN(0x4602500c, 0x5dd997bf), - TOBN(0x7f09771c, 0x4711230f), TOBN(0x058eb37c, 0x020f09c1), - TOBN(0xab693d4b, 0xfee5e38b), TOBN(0x9289eb1f, 0x4653cbc0), - TOBN(0xbecf46ab, 0xd51b9cf5), TOBN(0xd2aa9c02, 0x9f0121af), - TOBN(0x36aaf7d2, 0xe90dc274), TOBN(0x909e4ea0, 0x48b95a3c), - TOBN(0xe6b70496, 0x6f32dbdb), TOBN(0x672188a0, 0x8b030b3e), - TOBN(0xeeffe5b3, 0xcfb617e2), TOBN(0x87e947de, 0x7c82709e), - TOBN(0xa44d2b39, 0x1770f5a7), TOBN(0xe4d4d791, 0x0e44eb82), - TOBN(0x42e69d1e, 0x3f69712a), TOBN(0xbf11c4d6, 0xac6a820e), - TOBN(0xb5e7f3e5, 0x42c4224c), TOBN(0xd6b4e81c, 0x449d941c), - TOBN(0x5d72bd16, 0x5450e878), TOBN(0x6a61e28a, 0xee25ac54), - TOBN(0x33272094, 0xe6f1cd95), TOBN(0x7512f30d, 0x0d18673f), - TOBN(0x32f7a4ca, 0x5afc1464), TOBN(0x2f095656, 0x6bbb977b), - TOBN(0x586f47ca, 0xa8226200), TOBN(0x02c868ad, 0x1ac07369), - TOBN(0x4ef2b845, 0xc613acbe), TOBN(0x43d7563e, 0x0386054c), - TOBN(0x54da9dc7, 0xab952578), TOBN(0xb5423df2, 0x26e84d0b), - TOBN(0xa8b64eeb, 0x9b872042), TOBN(0xac205782, 0x5990f6df), - TOBN(0x4ff696eb, 0x21f4c77a), TOBN(0x1a79c3e4, 0xaab273af), - TOBN(0x29bc922e, 0x9436b3f1), TOBN(0xff807ef8, 0xd6d9a27a), - TOBN(0x82acea3d, 0x778f22a0), TOBN(0xfb10b2e8, 0x5b5e7469), - TOBN(0xc0b16980, 0x2818ee7d), TOBN(0x011afff4, 0xc91c1a2f), - TOBN(0x95a6d126, 0xad124418), TOBN(0x31c081a5, 0xe72e295f), - TOBN(0x36bb283a, 0xf2f4db75), TOBN(0xd115540f, 0x7acef462), - TOBN(0xc7f3a8f8, 0x33f6746c), TOBN(0x21e46f65, 0xfea990ca), - TOBN(0x915fd5c5, 0xcaddb0a9), TOBN(0xbd41f016, 0x78614555), - TOBN(0x346f4434, 0x426ffb58), TOBN(0x80559436, 0x14dbc204), - TOBN(0xf3dd20fe, 0x5a969b7f), TOBN(0x9d59e956, 0xe899a39a), - TOBN(0xf1b0971c, 0x8ad4cf4b), TOBN(0x03448860, 0x2ffb8fb8), - TOBN(0xf071ac3c, 0x65340ba4), TOBN(0x408d0596, 0xb27fd758), - TOBN(0xe7c78ea4, 0x98c364b0), TOBN(0xa4aac4a5, 0x051e8ab5), - TOBN(0xb9e1d560, 0x485d9002), TOBN(0x9acd518a, 0x88844455), - TOBN(0xe4ca688f, 0xd06f56c0), TOBN(0xa48af70d, 0xdf027972), - TOBN(0x691f0f04, 0x5e9a609d), TOBN(0xa9dd82cd, 0xee61270e), - TOBN(0x8903ca63, 0xa0ef18d3), TOBN(0x9fb7ee35, 0x3d6ca3bd), - TOBN(0xa7b4a09c, 0xabf47d03), TOBN(0x4cdada01, 0x1c67de8e), - TOBN(0x52003749, 0x9355a244), TOBN(0xe77fd2b6, 0x4f2151a9), - TOBN(0x695d6cf6, 0x66b4efcb), TOBN(0xc5a0cacf, 0xda2cfe25), - TOBN(0x104efe5c, 0xef811865), TOBN(0xf52813e8, 0x9ea5cc3d), - TOBN(0x855683dc, 0x40b58dbc), TOBN(0x0338ecde, 0x175fcb11), - TOBN(0xf9a05637, 0x74921592), TOBN(0xb4f1261d, 0xb9bb9d31), - TOBN(0x551429b7, 0x4e9c5459), TOBN(0xbe182e6f, 0x6ea71f53), - TOBN(0xd3a3b07c, 0xdfc50573), TOBN(0x9ba1afda, 0x62be8d44), - TOBN(0x9bcfd2cb, 0x52ab65d3), TOBN(0xdf11d547, 0xa9571802), - TOBN(0x099403ee, 0x02a2404a), TOBN(0x497406f4, 0x21088a71), - TOBN(0x99479409, 0x5004ae71), TOBN(0xbdb42078, 0xa812c362), - TOBN(0x2b72a30f, 0xd8828442), TOBN(0x283add27, 0xfcb5ed1c), - TOBN(0xf7c0e200, 0x66a40015), TOBN(0x3e3be641, 0x08b295ef), - TOBN(0xac127dc1, 0xe038a675), TOBN(0x729deff3, 0x8c5c6320), - TOBN(0xb7df8fd4, 0xa90d2c53), TOBN(0x9b74b0ec, 0x681e7cd3), - TOBN(0x5cb5a623, 0xdab407e5), TOBN(0xcdbd3615, 0x76b340c6), - TOBN(0xa184415a, 0x7d28392c), TOBN(0xc184c1d8, 0xe96f7830), - TOBN(0xc3204f19, 0x81d3a80f), TOBN(0xfde0c841, 0xc8e02432), - TOBN(0x78203b3e, 0x8149e0c1), TOBN(0x5904bdbb, 0x08053a73), - TOBN(0x30fc1dd1, 0x101b6805), TOBN(0x43c223bc, 0x49aa6d49), - TOBN(0x9ed67141, 0x7a174087), TOBN(0x311469a0, 0xd5997008), - TOBN(0xb189b684, 0x5e43fc61), TOBN(0xf3282375, 0xe0d3ab57), - TOBN(0x4fa34b67, 0xb1181da8), TOBN(0x621ed0b2, 0x99ee52b8), - TOBN(0x9b178de1, 0xad990676), TOBN(0xd51de67b, 0x56d54065), - TOBN(0x2a2c27c4, 0x7538c201), TOBN(0x33856ec8, 0x38a40f5c), - TOBN(0x2522fc15, 0xbe6cdcde), TOBN(0x1e603f33, 0x9f0c6f89), - TOBN(0x7994edc3, 0x103e30a6), TOBN(0x033a00db, 0x220c853e), - TOBN(0xd3cfa409, 0xf7bb7fd7), TOBN(0x70f8781e, 0x462d18f6), - TOBN(0xbbd82980, 0x687fe295), TOBN(0x6eef4c32, 0x595669f3), - TOBN(0x86a9303b, 0x2f7e85c3), TOBN(0x5fce4621, 0x71988f9b), - TOBN(0x5b935bf6, 0xc138acb5), TOBN(0x30ea7d67, 0x25661212), - TOBN(0xef1eb5f4, 0xe51ab9a2), TOBN(0x0587c98a, 0xae067c78), - TOBN(0xb3ce1b3c, 0x77ca9ca6), TOBN(0x2a553d4d, 0x54b5f057), - TOBN(0xc7898236, 0x4da29ec2), TOBN(0xdbdd5d13, 0xb9c57316), - TOBN(0xc57d6e6b, 0x2cd80d47), TOBN(0x80b460cf, 0xfe9e7391), - TOBN(0x98648cab, 0xf963c31e), TOBN(0x67f9f633, 0xcc4d32fd), - TOBN(0x0af42a9d, 0xfdf7c687), TOBN(0x55f292a3, 0x0b015ea7), - TOBN(0x89e468b2, 0xcd21ab3d), TOBN(0xe504f022, 0xc393d392), - TOBN(0xab21e1d4, 0xa5013af9), TOBN(0xe3283f78, 0xc2c28acb), - TOBN(0xf38b35f6, 0x226bf99f), TOBN(0xe8354274, 0x0e291e69), - TOBN(0x61673a15, 0xb20c162d), TOBN(0xc101dc75, 0xb04fbdbe), - TOBN(0x8323b4c2, 0x255bd617), TOBN(0x6c969693, 0x6c2a9154), - TOBN(0xc6e65860, 0x62679387), TOBN(0x8e01db0c, 0xb8c88e23), - TOBN(0x33c42873, 0x893a5559), TOBN(0x7630f04b, 0x47a3e149), - TOBN(0xb5d80805, 0xddcf35f8), TOBN(0x582ca080, 0x77dfe732), - TOBN(0x2c7156e1, 0x0b1894a0), TOBN(0x92034001, 0xd81c68c0), - TOBN(0xed225d00, 0xc8b115b5), TOBN(0x237f9c22, 0x83b907f2), - TOBN(0x0ea2f32f, 0x4470e2c0), TOBN(0xb725f7c1, 0x58be4e95), - TOBN(0x0f1dcafa, 0xb1ae5463), TOBN(0x59ed5187, 0x1ba2fc04), - TOBN(0xf6e0f316, 0xd0115d4d), TOBN(0x5180b12f, 0xd3691599), - TOBN(0x157e32c9, 0x527f0a41), TOBN(0x7b0b081d, 0xa8e0ecc0), - TOBN(0x6dbaaa8a, 0xbf4f0dd0), TOBN(0x99b289c7, 0x4d252696), - TOBN(0x79b7755e, 0xdbf864fe), TOBN(0x6974e2b1, 0x76cad3ab), - TOBN(0x35dbbee2, 0x06ddd657), TOBN(0xe7cbdd11, 0x2ff3a96d), - TOBN(0x88381968, 0x076be758), TOBN(0x2d737e72, 0x08c91f5d), - TOBN(0x5f83ab62, 0x86ec3776), TOBN(0x98aa649d, 0x945fa7a1), - TOBN(0xf477ec37, 0x72ef0933), TOBN(0x66f52b1e, 0x098c17b1), - TOBN(0x9eec58fb, 0xd803738b), TOBN(0x91aaade7, 0xe4e86aa4), - TOBN(0x6b1ae617, 0xa5b51492), TOBN(0x63272121, 0xbbc45974), - TOBN(0x7e0e28f0, 0x862c5129), TOBN(0x0a8f79a9, 0x3321a4a0), - TOBN(0xe26d1664, 0x5041c88f), TOBN(0x0571b805, 0x53233e3a), - TOBN(0xd1b0ccde, 0xc9520711), TOBN(0x55a9e4ed, 0x3c8b84bf), - TOBN(0x9426bd39, 0xa1fef314), TOBN(0x4f5f638e, 0x6eb93f2b), - TOBN(0xba2a1ed3, 0x2bf9341b), TOBN(0xd63c1321, 0x4d42d5a9), - TOBN(0xd2964a89, 0x316dc7c5), TOBN(0xd1759606, 0xca511851), - TOBN(0xd8a9201f, 0xf9e6ed35), TOBN(0xb7b5ee45, 0x6736925a), - TOBN(0x0a83fbbc, 0x99581af7), TOBN(0x3076bc40, 0x64eeb051), - TOBN(0x5511c98c, 0x02dec312), TOBN(0x270de898, 0x238dcb78), - TOBN(0x2cf4cf9c, 0x539c08c9), TOBN(0xa70cb65e, 0x38d3b06e), - TOBN(0xb12ec10e, 0xcfe57bbd), TOBN(0x82c7b656, 0x35a0c2b5), - TOBN(0xddc7d5cd, 0x161c67bd), TOBN(0xe32e8985, 0xae3a32cc), - TOBN(0x7aba9444, 0xd11a5529), TOBN(0xe964ed02, 0x2427fa1a), - TOBN(0x1528392d, 0x24a1770a), TOBN(0xa152ce2c, 0x12c72fcd), - TOBN(0x714553a4, 0x8ec07649), TOBN(0x18b4c290, 0x459dd453), - TOBN(0xea32b714, 0x7b64b110), TOBN(0xb871bfa5, 0x2e6f07a2), - TOBN(0xb67112e5, 0x9e2e3c9b), TOBN(0xfbf250e5, 0x44aa90f6), - TOBN(0xf77aedb8, 0xbd539006), TOBN(0x3b0cdf9a, 0xd172a66f), - TOBN(0xedf69fea, 0xf8c51187), TOBN(0x05bb67ec, 0x741e4da7), - TOBN(0x47df0f32, 0x08114345), TOBN(0x56facb07, 0xbb9792b1), - TOBN(0xf3e007e9, 0x8f6229e4), TOBN(0x62d103f4, 0x526fba0f), - TOBN(0x4f33bef7, 0xb0339d79), TOBN(0x9841357b, 0xb59bfec1), - TOBN(0xfa8dbb59, 0xc34e6705), TOBN(0xc3c7180b, 0x7fdaa84c), - TOBN(0xf95872fc, 0xa4108537), TOBN(0x8750cc3b, 0x932a3e5a), - TOBN(0xb61cc69d, 0xb7275d7d), TOBN(0xffa0168b, 0x2e59b2e9), - TOBN(0xca032abc, 0x6ecbb493), TOBN(0x1d86dbd3, 0x2c9082d8), - TOBN(0xae1e0b67, 0xe28ef5ba), TOBN(0x2c9a4699, 0xcb18e169), - TOBN(0x0ecd0e33, 0x1e6bbd20), TOBN(0x571b360e, 0xaf5e81d2), - TOBN(0xcd9fea58, 0x101c1d45), TOBN(0x6651788e, 0x18880452), - TOBN(0xa9972635, 0x1f8dd446), TOBN(0x44bed022, 0xe37281d0), - TOBN(0x094b2b2d, 0x33da525d), TOBN(0xf193678e, 0x13144fd8), - TOBN(0xb8ab5ba4, 0xf4c1061d), TOBN(0x4343b5fa, 0xdccbe0f4), - TOBN(0xa8702371, 0x63812713), TOBN(0x47bf6d2d, 0xf7611d93), - TOBN(0x46729b8c, 0xbd21e1d7), TOBN(0x7484d4e0, 0xd629e77d), - TOBN(0x830e6eea, 0x60dbac1f), TOBN(0x23d8c484, 0xda06a2f7), - TOBN(0x896714b0, 0x50ca535b), TOBN(0xdc8d3644, 0xebd97a9b), - TOBN(0x106ef9fa, 0xb12177b4), TOBN(0xf79bf464, 0x534d5d9c), - TOBN(0x2537a349, 0xa6ab360b), TOBN(0xc7c54253, 0xa00c744f), - TOBN(0xb3c7a047, 0xe5911a76), TOBN(0x61ffa5c8, 0x647f1ee7), - TOBN(0x15aed36f, 0x8f56ab42), TOBN(0x6a0d41b0, 0xa3ff9ac9), - TOBN(0x68f469f5, 0xcc30d357), TOBN(0xbe9adf81, 0x6b72be96), - TOBN(0x1cd926fe, 0x903ad461), TOBN(0x7e89e38f, 0xcaca441b), - TOBN(0xf0f82de5, 0xfacf69d4), TOBN(0x363b7e76, 0x4775344c), - TOBN(0x6894f312, 0xb2e36d04), TOBN(0x3c6cb4fe, 0x11d1c9a5), - TOBN(0x85d9c339, 0x4008e1f2), TOBN(0x5e9a85ea, 0x249f326c), - TOBN(0xdc35c60a, 0x678c5e06), TOBN(0xc08b944f, 0x9f86fba9), - TOBN(0xde40c02c, 0x89f71f0f), TOBN(0xad8f3e31, 0xff3da3c0), - TOBN(0x3ea5096b, 0x42125ded), TOBN(0x13879cbf, 0xa7379183), - TOBN(0x6f4714a5, 0x6b306a0b), TOBN(0x359c2ea6, 0x67646c5e), - TOBN(0xfacf8943, 0x07726368), TOBN(0x07a58935, 0x65ff431e), - TOBN(0x24d661d1, 0x68754ab0), TOBN(0x801fce1d, 0x6f429a76), - TOBN(0xc068a85f, 0xa58ce769), TOBN(0xedc35c54, 0x5d5eca2b), - TOBN(0xea31276f, 0xa3f660d1), TOBN(0xa0184ebe, 0xb8fc7167), - TOBN(0x0f20f21a, 0x1d8db0ae), TOBN(0xd96d095f, 0x56c35e12), - TOBN(0xedf402b5, 0xf8c2a25b), TOBN(0x1bb772b9, 0x059204b6), - TOBN(0x50cbeae2, 0x19b4e34c), TOBN(0x93109d80, 0x3fa0845a), - TOBN(0x54f7ccf7, 0x8ef59fb5), TOBN(0x3b438fe2, 0x88070963), - TOBN(0x9e28c659, 0x31f3ba9b), TOBN(0x9cc31b46, 0xead9da92), - TOBN(0x3c2f0ba9, 0xb733aa5f), TOBN(0xdece47cb, 0xf05af235), - TOBN(0xf8e3f715, 0xa2ac82a5), TOBN(0xc97ba641, 0x2203f18a), - TOBN(0xc3af5504, 0x09c11060), TOBN(0x56ea2c05, 0x46af512d), - TOBN(0xfac28daf, 0xf3f28146), TOBN(0x87fab43a, 0x959ef494), - }, - { - TOBN(0x09891641, 0xd4c5105f), TOBN(0x1ae80f8e, 0x6d7fbd65), - TOBN(0x9d67225f, 0xbee6bdb0), TOBN(0x3b433b59, 0x7fc4d860), - TOBN(0x44e66db6, 0x93e85638), TOBN(0xf7b59252, 0xe3e9862f), - TOBN(0xdb785157, 0x665c32ec), TOBN(0x702fefd7, 0xae362f50), - TOBN(0x3754475d, 0x0fefb0c3), TOBN(0xd48fb56b, 0x46d7c35d), - TOBN(0xa070b633, 0x363798a4), TOBN(0xae89f3d2, 0x8fdb98e6), - TOBN(0x970b89c8, 0x6363d14c), TOBN(0x89817521, 0x67abd27d), - TOBN(0x9bf7d474, 0x44d5a021), TOBN(0xb3083baf, 0xcac72aee), - TOBN(0x389741de, 0xbe949a44), TOBN(0x638e9388, 0x546a4fa5), - TOBN(0x3fe6419c, 0xa0047bdc), TOBN(0x7047f648, 0xaaea57ca), - TOBN(0x54e48a90, 0x41fbab17), TOBN(0xda8e0b28, 0x576bdba2), - TOBN(0xe807eebc, 0xc72afddc), TOBN(0x07d3336d, 0xf42577bf), - TOBN(0x62a8c244, 0xbfe20925), TOBN(0x91c19ac3, 0x8fdce867), - TOBN(0x5a96a5d5, 0xdd387063), TOBN(0x61d587d4, 0x21d324f6), - TOBN(0xe87673a2, 0xa37173ea), TOBN(0x23848008, 0x53778b65), - TOBN(0x10f8441e, 0x05bab43e), TOBN(0xfa11fe12, 0x4621efbe), - TOBN(0x047b772e, 0x81685d7b), TOBN(0x23f27d81, 0xbf34a976), - TOBN(0xc27608e2, 0x915f48ef), TOBN(0x3b0b43fa, 0xa521d5c3), - TOBN(0x7613fb26, 0x63ca7284), TOBN(0x7f5729b4, 0x1d4db837), - TOBN(0x87b14898, 0x583b526b), TOBN(0x00b732a6, 0xbbadd3d1), - TOBN(0x8e02f426, 0x2048e396), TOBN(0x436b50b6, 0x383d9de4), - TOBN(0xf78d3481, 0x471e85ad), TOBN(0x8b01ea6a, 0xd005c8d6), - TOBN(0xd3c7afee, 0x97015c07), TOBN(0x46cdf1a9, 0x4e3ba2ae), - TOBN(0x7a42e501, 0x83d3a1d2), TOBN(0xd54b5268, 0xb541dff4), - TOBN(0x3f24cf30, 0x4e23e9bc), TOBN(0x4387f816, 0x126e3624), - TOBN(0x26a46a03, 0x3b0b6d61), TOBN(0xaf1bc845, 0x8b2d777c), - TOBN(0x25c401ba, 0x527de79c), TOBN(0x0e1346d4, 0x4261bbb6), - TOBN(0x4b96c44b, 0x287b4bc7), TOBN(0x658493c7, 0x5254562f), - TOBN(0x23f949fe, 0xb8a24a20), TOBN(0x17ebfed1, 0xf52ca53f), - TOBN(0x9b691bbe, 0xbcfb4853), TOBN(0x5617ff6b, 0x6278a05d), - TOBN(0x241b34c5, 0xe3c99ebd), TOBN(0xfc64242e, 0x1784156a), - TOBN(0x4206482f, 0x695d67df), TOBN(0xb967ce0e, 0xee27c011), - TOBN(0x65db3751, 0x21c80b5d), TOBN(0x2e7a563c, 0xa31ecca0), - TOBN(0xe56ffc4e, 0x5238a07e), TOBN(0x3d6c2966, 0x32ced854), - TOBN(0xe99d7d1a, 0xaf70b885), TOBN(0xafc3bad9, 0x2d686459), - TOBN(0x9c78bf46, 0x0cc8ba5b), TOBN(0x5a439519, 0x18955aa3), - TOBN(0xf8b517a8, 0x5fe4e314), TOBN(0xe60234d0, 0xfcb8906f), - TOBN(0xffe542ac, 0xf2061b23), TOBN(0x287e191f, 0x6b4cb59c), - TOBN(0x21857ddc, 0x09d877d8), TOBN(0x1c23478c, 0x14678941), - TOBN(0xbbf0c056, 0xb6e05ea4), TOBN(0x82da4b53, 0xb01594fe), - TOBN(0xf7526791, 0xfadb8608), TOBN(0x049e832d, 0x7b74cdf6), - TOBN(0xa43581cc, 0xc2b90a34), TOBN(0x73639eb8, 0x9360b10c), - TOBN(0x4fba331f, 0xe1e4a71b), TOBN(0x6ffd6b93, 0x8072f919), - TOBN(0x6e53271c, 0x65679032), TOBN(0x67206444, 0xf14272ce), - TOBN(0xc0f734a3, 0xb2335834), TOBN(0x9526205a, 0x90ef6860), - TOBN(0xcb8be717, 0x04e2bb0d), TOBN(0x2418871e, 0x02f383fa), - TOBN(0xd7177681, 0x4082c157), TOBN(0xcc914ad0, 0x29c20073), - TOBN(0xf186c1eb, 0xe587e728), TOBN(0x6fdb3c22, 0x61bcd5fd), - TOBN(0x30d014a6, 0xf2f9f8e9), TOBN(0x963ece23, 0x4fec49d2), - TOBN(0x862025c5, 0x9605a8d9), TOBN(0x39874445, 0x19f8929a), - TOBN(0x01b6ff65, 0x12bf476a), TOBN(0x598a64d8, 0x09cf7d91), - TOBN(0xd7ec7749, 0x93be56ca), TOBN(0x10899785, 0xcbb33615), - TOBN(0xb8a092fd, 0x02eee3ad), TOBN(0xa86b3d35, 0x30145270), - TOBN(0x323d98c6, 0x8512b675), TOBN(0x4b8bc785, 0x62ebb40f), - TOBN(0x7d301f54, 0x413f9cde), TOBN(0xa5e4fb4f, 0x2bab5664), - TOBN(0x1d2b252d, 0x1cbfec23), TOBN(0xfcd576bb, 0xe177120d), - TOBN(0x04427d3e, 0x83731a34), TOBN(0x2bb9028e, 0xed836e8e), - TOBN(0xb36acff8, 0xb612ca7c), TOBN(0xb88fe5ef, 0xd3d9c73a), - TOBN(0xbe2a6bc6, 0xedea4eb3), TOBN(0x43b93133, 0x488eec77), - TOBN(0xf41ff566, 0xb17106e1), TOBN(0x469e9172, 0x654efa32), - TOBN(0xb4480f04, 0x41c23fa3), TOBN(0xb4712eb0, 0xc1989a2e), - TOBN(0x3ccbba0f, 0x93a29ca7), TOBN(0x6e205c14, 0xd619428c), - TOBN(0x90db7957, 0xb3641686), TOBN(0x0432691d, 0x45ac8b4e), - TOBN(0x07a759ac, 0xf64e0350), TOBN(0x0514d89c, 0x9c972517), - TOBN(0x1701147f, 0xa8e67fc3), TOBN(0x9e2e0b8b, 0xab2085be), - TOBN(0xd5651824, 0xac284e57), TOBN(0x890d4325, 0x74893664), - TOBN(0x8a7c5e6e, 0xc55e68a3), TOBN(0xbf12e90b, 0x4339c85a), - TOBN(0x31846b85, 0xf922b655), TOBN(0x9a54ce4d, 0x0bf4d700), - TOBN(0xd7f4e83a, 0xf1a14295), TOBN(0x916f955c, 0xb285d4f9), - TOBN(0xe57bb0e0, 0x99ffdaba), TOBN(0x28a43034, 0xeab0d152), - TOBN(0x0a36ffa2, 0xb8a9cef8), TOBN(0x5517407e, 0xb9ec051a), - TOBN(0x9c796096, 0xea68e672), TOBN(0x853db5fb, 0xfb3c77fb), - TOBN(0x21474ba9, 0xe864a51a), TOBN(0x6c267699, 0x6e8a1b8b), - TOBN(0x7c823626, 0x94120a28), TOBN(0xe61e9a48, 0x8383a5db), - TOBN(0x7dd75003, 0x9f84216d), TOBN(0xab020d07, 0xad43cd85), - TOBN(0x9437ae48, 0xda12c659), TOBN(0x6449c2eb, 0xe65452ad), - TOBN(0xcc7c4c1c, 0x2cf9d7c1), TOBN(0x1320886a, 0xee95e5ab), - TOBN(0xbb7b9056, 0xbeae170c), TOBN(0xc8a5b250, 0xdbc0d662), - TOBN(0x4ed81432, 0xc11d2303), TOBN(0x7da66912, 0x1f03769f), - TOBN(0x3ac7a5fd, 0x84539828), TOBN(0x14dada94, 0x3bccdd02), - TOBN(0x8b84c321, 0x7ef6b0d1), TOBN(0x52a9477a, 0x7c933f22), - TOBN(0x5ef6728a, 0xfd440b82), TOBN(0x5c3bd859, 0x6ce4bd5e), - TOBN(0x918b80f5, 0xf22c2d3e), TOBN(0x368d5040, 0xb7bb6cc5), - TOBN(0xb66142a1, 0x2695a11c), TOBN(0x60ac583a, 0xeb19ea70), - TOBN(0x317cbb98, 0x0eab2437), TOBN(0x8cc08c55, 0x5e2654c8), - TOBN(0xfe2d6520, 0xe6d8307f), TOBN(0xe9f147f3, 0x57428993), - TOBN(0x5f9c7d14, 0xd2fd6cf1), TOBN(0xa3ecd064, 0x2d4fcbb0), - TOBN(0xad83fef0, 0x8e7341f7), TOBN(0x643f23a0, 0x3a63115c), - TOBN(0xd38a78ab, 0xe65ab743), TOBN(0xbf7c75b1, 0x35edc89c), - TOBN(0x3dd8752e, 0x530df568), TOBN(0xf85c4a76, 0xe308c682), - TOBN(0x4c9955b2, 0xe68acf37), TOBN(0xa544df3d, 0xab32af85), - TOBN(0x4b8ec3f5, 0xa25cf493), TOBN(0x4d8f2764, 0x1a622feb), - TOBN(0x7bb4f7aa, 0xf0dcbc49), TOBN(0x7de551f9, 0x70bbb45b), - TOBN(0xcfd0f3e4, 0x9f2ca2e5), TOBN(0xece58709, 0x1f5c76ef), - TOBN(0x32920edd, 0x167d79ae), TOBN(0x039df8a2, 0xfa7d7ec1), - TOBN(0xf46206c0, 0xbb30af91), TOBN(0x1ff5e2f5, 0x22676b59), - TOBN(0x11f4a039, 0x6ea51d66), TOBN(0x506c1445, 0x807d7a26), - TOBN(0x60da5705, 0x755a9b24), TOBN(0x8fc8cc32, 0x1f1a319e), - TOBN(0x83642d4d, 0x9433d67d), TOBN(0x7fa5cb8f, 0x6a7dd296), - TOBN(0x576591db, 0x9b7bde07), TOBN(0x13173d25, 0x419716fb), - TOBN(0xea30599d, 0xd5b340ff), TOBN(0xfc6b5297, 0xb0fe76c5), - TOBN(0x1c6968c8, 0xab8f5adc), TOBN(0xf723c7f5, 0x901c928d), - TOBN(0x4203c321, 0x9773d402), TOBN(0xdf7c6aa3, 0x1b51dd47), - TOBN(0x3d49e37a, 0x552be23c), TOBN(0x57febee8, 0x0b5a6e87), - TOBN(0xc5ecbee4, 0x7bd8e739), TOBN(0x79d44994, 0xae63bf75), - TOBN(0x168bd00f, 0x38fb8923), TOBN(0x75d48ee4, 0xd0533130), - TOBN(0x554f77aa, 0xdb5cdf33), TOBN(0x3396e896, 0x3c696769), - TOBN(0x2fdddbf2, 0xd3fd674e), TOBN(0xbbb8f6ee, 0x99d0e3e5), - TOBN(0x51b90651, 0xcbae2f70), TOBN(0xefc4bc05, 0x93aaa8eb), - TOBN(0x8ecd8689, 0xdd1df499), TOBN(0x1aee99a8, 0x22f367a5), - TOBN(0x95d485b9, 0xae8274c5), TOBN(0x6c14d445, 0x7d30b39c), - TOBN(0xbafea90b, 0xbcc1ef81), TOBN(0x7c5f317a, 0xa459a2ed), - TOBN(0x01211075, 0x4ef44227), TOBN(0xa17bed6e, 0xdc20f496), - TOBN(0x0cdfe424, 0x819853cd), TOBN(0x13793298, 0xf71e2ce7), - TOBN(0x3c1f3078, 0xdbbe307b), TOBN(0x6dd1c20e, 0x76ee9936), - TOBN(0x23ee4b57, 0x423caa20), TOBN(0x4ac3793b, 0x8efb840e), - TOBN(0x934438eb, 0xed1f8ca0), TOBN(0x3e546658, 0x4ebb25a2), - TOBN(0xc415af0e, 0xc069896f), TOBN(0xc13eddb0, 0x9a5aa43d), - TOBN(0x7a04204f, 0xd49eb8f6), TOBN(0xd0d5bdfc, 0xd74f1670), - TOBN(0x3697e286, 0x56fc0558), TOBN(0x10207371, 0x01cebade), - TOBN(0x5f87e690, 0x0647a82b), TOBN(0x908e0ed4, 0x8f40054f), - TOBN(0xa9f633d4, 0x79853803), TOBN(0x8ed13c9a, 0x4a28b252), - TOBN(0x3e2ef676, 0x1f460f64), TOBN(0x53930b9b, 0x36d06336), - TOBN(0x347073ac, 0x8fc4979b), TOBN(0x84380e0e, 0x5ecd5597), - TOBN(0xe3b22c6b, 0xc4fe3c39), TOBN(0xba4a8153, 0x6c7bebdf), - TOBN(0xf23ab6b7, 0x25693459), TOBN(0x53bc3770, 0x14922b11), - TOBN(0x4645c8ab, 0x5afc60db), TOBN(0xaa022355, 0x20b9f2a3), - TOBN(0x52a2954c, 0xce0fc507), TOBN(0x8c2731bb, 0x7ce1c2e7), - TOBN(0xf39608ab, 0x18a0339d), TOBN(0xac7a658d, 0x3735436c), - TOBN(0xb22c2b07, 0xcd992b4f), TOBN(0x4e83daec, 0xf40dcfd4), - TOBN(0x8a34c7be, 0x2f39ea3e), TOBN(0xef0c005f, 0xb0a56d2e), - TOBN(0x62731f6a, 0x6edd8038), TOBN(0x5721d740, 0x4e3cb075), - TOBN(0x1ea41511, 0xfbeeee1b), TOBN(0xd1ef5e73, 0xef1d0c05), - TOBN(0x42feefd1, 0x73c07d35), TOBN(0xe530a00a, 0x8a329493), - TOBN(0x5d55b7fe, 0xf15ebfb0), TOBN(0x549de03c, 0xd322491a), - TOBN(0xf7b5f602, 0x745b3237), TOBN(0x3632a3a2, 0x1ab6e2b6), - TOBN(0x0d3bba89, 0x0ef59f78), TOBN(0x0dfc6443, 0xc9e52b9a), - TOBN(0x1dc79699, 0x72631447), TOBN(0xef033917, 0xb3be20b1), - TOBN(0x0c92735d, 0xb1383948), TOBN(0xc1fc29a2, 0xc0dd7d7d), - TOBN(0x6485b697, 0x403ed068), TOBN(0x13bfaab3, 0xaac93bdc), - TOBN(0x410dc6a9, 0x0deeaf52), TOBN(0xb003fb02, 0x4c641c15), - TOBN(0x1384978c, 0x5bc504c4), TOBN(0x37640487, 0x864a6a77), - TOBN(0x05991bc6, 0x222a77da), TOBN(0x62260a57, 0x5e47eb11), - TOBN(0xc7af6613, 0xf21b432c), TOBN(0x22f3acc9, 0xab4953e9), - TOBN(0x52934922, 0x8e41d155), TOBN(0x4d024568, 0x3ac059ef), - TOBN(0xb0201755, 0x4d884411), TOBN(0xce8055cf, 0xa59a178f), - TOBN(0xcd77d1af, 0xf6204549), TOBN(0xa0a00a3e, 0xc7066759), - TOBN(0x471071ef, 0x0272c229), TOBN(0x009bcf6b, 0xd3c4b6b0), - TOBN(0x2a2638a8, 0x22305177), TOBN(0xd51d59df, 0x41645bbf), - TOBN(0xa81142fd, 0xc0a7a3c0), TOBN(0xa17eca6d, 0x4c7063ee), - TOBN(0x0bb887ed, 0x60d9dcec), TOBN(0xd6d28e51, 0x20ad2455), - TOBN(0xebed6308, 0xa67102ba), TOBN(0x042c3114, 0x8bffa408), - TOBN(0xfd099ac5, 0x8aa68e30), TOBN(0x7a6a3d7c, 0x1483513e), - TOBN(0xffcc6b75, 0xba2d8f0c), TOBN(0x54dacf96, 0x1e78b954), - TOBN(0xf645696f, 0xa4a9af89), TOBN(0x3a411940, 0x06ac98ec), - TOBN(0x41b8b3f6, 0x22a67a20), TOBN(0x2d0b1e0f, 0x99dec626), - TOBN(0x27c89192, 0x40be34e8), TOBN(0xc7162b37, 0x91907f35), - TOBN(0x90188ec1, 0xa956702b), TOBN(0xca132f7d, 0xdf93769c), - TOBN(0x3ece44f9, 0x0e2025b4), TOBN(0x67aaec69, 0x0c62f14c), - TOBN(0xad741418, 0x22e3cc11), TOBN(0xcf9b75c3, 0x7ff9a50e), - TOBN(0x02fa2b16, 0x4d348272), TOBN(0xbd99d61a, 0x9959d56d), - TOBN(0xbc4f19db, 0x18762916), TOBN(0xcc7cce50, 0x49c1ac80), - TOBN(0x4d59ebaa, 0xd846bd83), TOBN(0x8775a9dc, 0xa9202849), - TOBN(0x07ec4ae1, 0x6e1f4ca9), TOBN(0x27eb5875, 0xba893f11), - TOBN(0x00284d51, 0x662cc565), TOBN(0x82353a6b, 0x0db4138d), - TOBN(0xd9c7aaaa, 0xaa32a594), TOBN(0xf5528b5e, 0xa5669c47), - TOBN(0xf3220231, 0x2f23c5ff), TOBN(0xe3e8147a, 0x6affa3a1), - TOBN(0xfb423d5c, 0x202ddda0), TOBN(0x3d6414ac, 0x6b871bd4), - TOBN(0x586f82e1, 0xa51a168a), TOBN(0xb712c671, 0x48ae5448), - TOBN(0x9a2e4bd1, 0x76233eb8), TOBN(0x0188223a, 0x78811ca9), - TOBN(0x553c5e21, 0xf7c18de1), TOBN(0x7682e451, 0xb27bb286), - TOBN(0x3ed036b3, 0x0e51e929), TOBN(0xf487211b, 0xec9cb34f), - TOBN(0x0d094277, 0x0c24efc8), TOBN(0x0349fd04, 0xbef737a4), - TOBN(0x6d1c9dd2, 0x514cdd28), TOBN(0x29c135ff, 0x30da9521), - TOBN(0xea6e4508, 0xf78b0b6f), TOBN(0x176f5dd2, 0x678c143c), - TOBN(0x08148418, 0x4be21e65), TOBN(0x27f7525c, 0xe7df38c4), - TOBN(0x1fb70e09, 0x748ab1a4), TOBN(0x9cba50a0, 0x5efe4433), - TOBN(0x7846c7a6, 0x15f75af2), TOBN(0x2a7c2c57, 0x5ee73ea8), - TOBN(0x42e566a4, 0x3f0a449a), TOBN(0x45474c3b, 0xad90fc3d), - TOBN(0x7447be3d, 0x8b61d057), TOBN(0x3e9d1cf1, 0x3a4ec092), - TOBN(0x1603e453, 0xf380a6e6), TOBN(0x0b86e431, 0x9b1437c2), - TOBN(0x7a4173f2, 0xef29610a), TOBN(0x8fa729a7, 0xf03d57f7), - TOBN(0x3e186f6e, 0x6c9c217e), TOBN(0xbe1d3079, 0x91919524), - TOBN(0x92a62a70, 0x153d4fb1), TOBN(0x32ed3e34, 0xd68c2f71), - TOBN(0xd785027f, 0x9eb1a8b7), TOBN(0xbc37eb77, 0xc5b22fe8), - TOBN(0x466b34f0, 0xb9d6a191), TOBN(0x008a89af, 0x9a05f816), - TOBN(0x19b028fb, 0x7d42c10a), TOBN(0x7fe8c92f, 0x49b3f6b8), - TOBN(0x58907cc0, 0xa5a0ade3), TOBN(0xb3154f51, 0x559d1a7c), - TOBN(0x5066efb6, 0xd9790ed6), TOBN(0xa77a0cbc, 0xa6aa793b), - TOBN(0x1a915f3c, 0x223e042e), TOBN(0x1c5def04, 0x69c5874b), - TOBN(0x0e830078, 0x73b6c1da), TOBN(0x55cf85d2, 0xfcd8557a), - TOBN(0x0f7c7c76, 0x0460f3b1), TOBN(0x87052acb, 0x46e58063), - TOBN(0x09212b80, 0x907eae66), TOBN(0x3cb068e0, 0x4d721c89), - TOBN(0xa87941ae, 0xdd45ac1c), TOBN(0xde8d5c0d, 0x0daa0dbb), - TOBN(0xda421fdc, 0xe3502e6e), TOBN(0xc8944201, 0x4d89a084), - TOBN(0x7307ba5e, 0xf0c24bfb), TOBN(0xda212beb, 0x20bde0ef), - TOBN(0xea2da24b, 0xf82ce682), TOBN(0x058d3816, 0x07f71fe4), - TOBN(0x35a02462, 0x5ffad8de), TOBN(0xcd7b05dc, 0xaadcefab), - TOBN(0xd442f8ed, 0x1d9f54ec), TOBN(0x8be3d618, 0xb2d3b5ca), - TOBN(0xe2220ed0, 0xe06b2ce2), TOBN(0x82699a5f, 0x1b0da4c0), - TOBN(0x3ff106f5, 0x71c0c3a7), TOBN(0x8f580f5a, 0x0d34180c), - TOBN(0x4ebb120e, 0x22d7d375), TOBN(0x5e5782cc, 0xe9513675), - TOBN(0x2275580c, 0x99c82a70), TOBN(0xe8359fbf, 0x15ea8c4c), - TOBN(0x53b48db8, 0x7b415e70), TOBN(0xaacf2240, 0x100c6014), - TOBN(0x9faaccf5, 0xe4652f1d), TOBN(0xbd6fdd2a, 0xd56157b2), - TOBN(0xa4f4fb1f, 0x6261ec50), TOBN(0x244e55ad, 0x476bcd52), - TOBN(0x881c9305, 0x047d320b), TOBN(0x1ca983d5, 0x6181263f), - TOBN(0x354e9a44, 0x278fb8ee), TOBN(0xad2dbc0f, 0x396e4964), - TOBN(0x723f3aa2, 0x9268b3de), TOBN(0x0d1ca29a, 0xe6e0609a), - TOBN(0x794866aa, 0x6cf44252), TOBN(0x0b59f3e3, 0x01af87ed), - TOBN(0xe234e5ff, 0x7f4a6c51), TOBN(0xa8768fd2, 0x61dc2f7e), - TOBN(0xdafc7332, 0x0a94d81f), TOBN(0xd7f84282, 0x06938ce1), - TOBN(0xae0b3c0e, 0x0546063e), TOBN(0x7fbadcb2, 0x5d61abc6), - TOBN(0xd5d7a2c9, 0x369ac400), TOBN(0xa5978d09, 0xae67d10c), - TOBN(0x290f211e, 0x4f85eaac), TOBN(0xe61e2ad1, 0xfacac681), - TOBN(0xae125225, 0x388384cd), TOBN(0xa7fb68e9, 0xccfde30f), - TOBN(0x7a59b936, 0x3daed4c2), TOBN(0x80a9aa40, 0x2606f789), - TOBN(0xb40c1ea5, 0xf6a6d90a), TOBN(0x948364d3, 0x514d5885), - TOBN(0x062ebc60, 0x70985182), TOBN(0xa6db5b0e, 0x33310895), - TOBN(0x64a12175, 0xe329c2f5), TOBN(0xc5f25bd2, 0x90ea237e), - TOBN(0x7915c524, 0x2d0a4c23), TOBN(0xeb5d26e4, 0x6bb3cc52), - TOBN(0x369a9116, 0xc09e2c92), TOBN(0x0c527f92, 0xcf182cf8), - TOBN(0x9e591938, 0x2aede0ac), TOBN(0xb2922208, 0x6cc34939), - TOBN(0x3c9d8962, 0x99a34361), TOBN(0x3c81836d, 0xc1905fe6), - TOBN(0x4bfeb57f, 0xa001ec5a), TOBN(0xe993f5bb, 0xa0dc5dba), - TOBN(0x47884109, 0x724a1380), TOBN(0x8a0369ab, 0x32fe9a04), - TOBN(0xea068d60, 0x8c927db8), TOBN(0xbf5f37cf, 0x94655741), - TOBN(0x47d402a2, 0x04b6c7ea), TOBN(0x4551c295, 0x6af259cb), - TOBN(0x698b71e7, 0xed77ee8b), TOBN(0xbddf7bd0, 0xf309d5c7), - TOBN(0x6201c22c, 0x34e780ca), TOBN(0xab04f7d8, 0x4c295ef4), - TOBN(0x1c947294, 0x4313a8ce), TOBN(0xe532e4ac, 0x92ca4cfe), - TOBN(0x89738f80, 0xd0a7a97a), TOBN(0xec088c88, 0xa580fd5b), - TOBN(0x612b1ecc, 0x42ce9e51), TOBN(0x8f9840fd, 0xb25fdd2a), - TOBN(0x3cda78c0, 0x01e7f839), TOBN(0x546b3d3a, 0xece05480), - TOBN(0x271719a9, 0x80d30916), TOBN(0x45497107, 0x584c20c4), - TOBN(0xaf8f9478, 0x5bc78608), TOBN(0x28c7d484, 0x277e2a4c), - TOBN(0xfce01767, 0x88a2ffe4), TOBN(0xdc506a35, 0x28e169a5), - TOBN(0x0ea10861, 0x7af9c93a), TOBN(0x1ed24361, 0x03fa0e08), - TOBN(0x96eaaa92, 0xa3d694e7), TOBN(0xc0f43b4d, 0xef50bc74), - TOBN(0xce6aa58c, 0x64114db4), TOBN(0x8218e8ea, 0x7c000fd4), - TOBN(0xac815dfb, 0x185f8844), TOBN(0xcd7e90cb, 0x1557abfb), - TOBN(0x23d16655, 0xafbfecdf), TOBN(0x80f3271f, 0x085cac4a), - TOBN(0x7fc39aa7, 0xd0e62f47), TOBN(0x88d519d1, 0x460a48e5), - TOBN(0x59559ac4, 0xd28f101e), TOBN(0x7981d9e9, 0xca9ae816), - TOBN(0x5c38652c, 0x9ac38203), TOBN(0x86eaf87f, 0x57657fe5), - TOBN(0x568fc472, 0xe21f5416), TOBN(0x2afff39c, 0xe7e597b5), - TOBN(0x3adbbb07, 0x256d4eab), TOBN(0x22598692, 0x8285ab89), - TOBN(0x35f8112a, 0x041caefe), TOBN(0x95df02e3, 0xa5064c8b), - TOBN(0x4d63356e, 0xc7004bf3), TOBN(0x230a08f4, 0xdb83c7de), - TOBN(0xca27b270, 0x8709a7b7), TOBN(0x0d1c4cc4, 0xcb9abd2d), - TOBN(0x8a0bc66e, 0x7550fee8), TOBN(0x369cd4c7, 0x9cf7247e), - TOBN(0x75562e84, 0x92b5b7e7), TOBN(0x8fed0da0, 0x5802af7b), - TOBN(0x6a7091c2, 0xe48fb889), TOBN(0x26882c13, 0x7b8a9d06), - TOBN(0xa2498663, 0x1b82a0e2), TOBN(0x844ed736, 0x3518152d), - TOBN(0x282f476f, 0xd86e27c7), TOBN(0xa04edaca, 0x04afefdc), - TOBN(0x8b256ebc, 0x6119e34d), TOBN(0x56a413e9, 0x0787d78b), - }, - { - TOBN(0x82ee061d, 0x5a74be50), TOBN(0xe41781c4, 0xdea16ff5), - TOBN(0xe0b0c81e, 0x99bfc8a2), TOBN(0x624f4d69, 0x0b547e2d), - TOBN(0x3a83545d, 0xbdcc9ae4), TOBN(0x2573dbb6, 0x409b1e8e), - TOBN(0x482960c4, 0xa6c93539), TOBN(0xf01059ad, 0x5ae18798), - TOBN(0x715c9f97, 0x3112795f), TOBN(0xe8244437, 0x984e6ee1), - TOBN(0x55cb4858, 0xecb66bcd), TOBN(0x7c136735, 0xabaffbee), - TOBN(0x54661595, 0x5dbec38e), TOBN(0x51c0782c, 0x388ad153), - TOBN(0x9ba4c53a, 0xc6e0952f), TOBN(0x27e6782a, 0x1b21dfa8), - TOBN(0x682f903d, 0x4ed2dbc2), TOBN(0x0eba59c8, 0x7c3b2d83), - TOBN(0x8e9dc84d, 0x9c7e9335), TOBN(0x5f9b21b0, 0x0eb226d7), - TOBN(0xe33bd394, 0xaf267bae), TOBN(0xaa86cc25, 0xbe2e15ae), - TOBN(0x4f0bf67d, 0x6a8ec500), TOBN(0x5846aa44, 0xf9630658), - TOBN(0xfeb09740, 0xe2c2bf15), TOBN(0x627a2205, 0xa9e99704), - TOBN(0xec8d73d0, 0xc2fbc565), TOBN(0x223eed8f, 0xc20c8de8), - TOBN(0x1ee32583, 0xa8363b49), TOBN(0x1a0b6cb9, 0xc9c2b0a6), - TOBN(0x49f7c3d2, 0x90dbc85c), TOBN(0xa8dfbb97, 0x1ef4c1ac), - TOBN(0xafb34d4c, 0x65c7c2ab), TOBN(0x1d4610e7, 0xe2c5ea84), - TOBN(0x893f6d1b, 0x973c4ab5), TOBN(0xa3cdd7e9, 0x945ba5c4), - TOBN(0x60514983, 0x064417ee), TOBN(0x1459b23c, 0xad6bdf2b), - TOBN(0x23b2c341, 0x5cf726c3), TOBN(0x3a829635, 0x32d6354a), - TOBN(0x294f901f, 0xab192c18), TOBN(0xec5fcbfe, 0x7030164f), - TOBN(0xe2e2fcb7, 0xe2246ba6), TOBN(0x1e7c88b3, 0x221a1a0c), - TOBN(0x72c7dd93, 0xc92d88c5), TOBN(0x41c2148e, 0x1106fb59), - TOBN(0x547dd4f5, 0xa0f60f14), TOBN(0xed9b52b2, 0x63960f31), - TOBN(0x6c8349eb, 0xb0a5b358), TOBN(0xb154c5c2, 0x9e7e2ed6), - TOBN(0xcad5eccf, 0xeda462db), TOBN(0xf2d6dbe4, 0x2de66b69), - TOBN(0x426aedf3, 0x8665e5b2), TOBN(0x488a8513, 0x7b7f5723), - TOBN(0x15cc43b3, 0x8bcbb386), TOBN(0x27ad0af3, 0xd791d879), - TOBN(0xc16c236e, 0x846e364f), TOBN(0x7f33527c, 0xdea50ca0), - TOBN(0xc4810775, 0x0926b86d), TOBN(0x6c2a3609, 0x0598e70c), - TOBN(0xa6755e52, 0xf024e924), TOBN(0xe0fa07a4, 0x9db4afca), - TOBN(0x15c3ce7d, 0x66831790), TOBN(0x5b4ef350, 0xa6cbb0d6), - TOBN(0x2c4aafc4, 0xb6205969), TOBN(0x42563f02, 0xf6c7854f), - TOBN(0x016aced5, 0x1d983b48), TOBN(0xfeb356d8, 0x99949755), - TOBN(0x8c2a2c81, 0xd1a39bd7), TOBN(0x8f44340f, 0xe6934ae9), - TOBN(0x148cf91c, 0x447904da), TOBN(0x7340185f, 0x0f51a926), - TOBN(0x2f8f00fb, 0x7409ab46), TOBN(0x057e78e6, 0x80e289b2), - TOBN(0x03e5022c, 0xa888e5d1), TOBN(0x3c87111a, 0x9dede4e2), - TOBN(0x5b9b0e1c, 0x7809460b), TOBN(0xe751c852, 0x71c9abc7), - TOBN(0x8b944e28, 0xc7cc1dc9), TOBN(0x4f201ffa, 0x1d3cfa08), - TOBN(0x02fc905c, 0x3e6721ce), TOBN(0xd52d70da, 0xd0b3674c), - TOBN(0x5dc2e5ca, 0x18810da4), TOBN(0xa984b273, 0x5c69dd99), - TOBN(0x63b92527, 0x84de5ca4), TOBN(0x2f1c9872, 0xc852dec4), - TOBN(0x18b03593, 0xc2e3de09), TOBN(0x19d70b01, 0x9813dc2f), - TOBN(0x42806b2d, 0xa6dc1d29), TOBN(0xd3030009, 0xf871e144), - TOBN(0xa1feb333, 0xaaf49276), TOBN(0xb5583b9e, 0xc70bc04b), - TOBN(0x1db0be78, 0x95695f20), TOBN(0xfc841811, 0x89d012b5), - TOBN(0x6409f272, 0x05f61643), TOBN(0x40d34174, 0xd5883128), - TOBN(0xd79196f5, 0x67419833), TOBN(0x6059e252, 0x863b7b08), - TOBN(0x84da1817, 0x1c56700c), TOBN(0x5758ee56, 0xb28d3ec4), - TOBN(0x7da2771d, 0x013b0ea6), TOBN(0xfddf524b, 0x54c5e9b9), - TOBN(0x7df4faf8, 0x24305d80), TOBN(0x58f5c1bf, 0x3a97763f), - TOBN(0xa5af37f1, 0x7c696042), TOBN(0xd4cba22c, 0x4a2538de), - TOBN(0x211cb995, 0x9ea42600), TOBN(0xcd105f41, 0x7b069889), - TOBN(0xb1e1cf19, 0xddb81e74), TOBN(0x472f2d89, 0x5157b8ca), - TOBN(0x086fb008, 0xee9db885), TOBN(0x365cd570, 0x0f26d131), - TOBN(0x284b02bb, 0xa2be7053), TOBN(0xdcbbf7c6, 0x7ab9a6d6), - TOBN(0x4425559c, 0x20f7a530), TOBN(0x961f2dfa, 0x188767c8), - TOBN(0xe2fd9435, 0x70dc80c4), TOBN(0x104d6b63, 0xf0784120), - TOBN(0x7f592bc1, 0x53567122), TOBN(0xf6bc1246, 0xf688ad77), - TOBN(0x05214c05, 0x0f15dde9), TOBN(0xa47a76a8, 0x0d5f2b82), - TOBN(0xbb254d30, 0x62e82b62), TOBN(0x11a05fe0, 0x3ec955ee), - TOBN(0x7eaff46e, 0x9d529b36), TOBN(0x55ab1301, 0x8f9e3df6), - TOBN(0xc463e371, 0x99317698), TOBN(0xfd251438, 0xccda47ad), - TOBN(0xca9c3547, 0x23d695ea), TOBN(0x48ce626e, 0x16e589b5), - TOBN(0x6b5b64c7, 0xb187d086), TOBN(0xd02e1794, 0xb2207948), - TOBN(0x8b58e98f, 0x7198111d), TOBN(0x90ca6305, 0xdcf9c3cc), - TOBN(0x5691fe72, 0xf34089b0), TOBN(0x60941af1, 0xfc7c80ff), - TOBN(0xa09bc0a2, 0x22eb51e5), TOBN(0xc0bb7244, 0xaa9cf09a), - TOBN(0x36a8077f, 0x80159f06), TOBN(0x8b5c989e, 0xdddc560e), - TOBN(0x19d2f316, 0x512e1f43), TOBN(0x02eac554, 0xad08ff62), - TOBN(0x012ab84c, 0x07d20b4e), TOBN(0x37d1e115, 0xd6d4e4e1), - TOBN(0xb6443e1a, 0xab7b19a8), TOBN(0xf08d067e, 0xdef8cd45), - TOBN(0x63adf3e9, 0x685e03da), TOBN(0xcf15a10e, 0x4792b916), - TOBN(0xf44bcce5, 0xb738a425), TOBN(0xebe131d5, 0x9636b2fd), - TOBN(0x94068841, 0x7850d605), TOBN(0x09684eaa, 0xb40d749d), - TOBN(0x8c3c669c, 0x72ba075b), TOBN(0x89f78b55, 0xba469015), - TOBN(0x5706aade, 0x3e9f8ba8), TOBN(0x6d8bd565, 0xb32d7ed7), - TOBN(0x25f4e63b, 0x805f08d6), TOBN(0x7f48200d, 0xc3bcc1b5), - TOBN(0x4e801968, 0xb025d847), TOBN(0x74afac04, 0x87cbe0a8), - TOBN(0x43ed2c2b, 0x7e63d690), TOBN(0xefb6bbf0, 0x0223cdb8), - TOBN(0x4fec3cae, 0x2884d3fe), TOBN(0x065ecce6, 0xd75e25a4), - TOBN(0x6c2294ce, 0x69f79071), TOBN(0x0d9a8e5f, 0x044b8666), - TOBN(0x5009f238, 0x17b69d8f), TOBN(0x3c29f8fe, 0xc5dfdaf7), - TOBN(0x9067528f, 0xebae68c4), TOBN(0x5b385632, 0x30c5ba21), - TOBN(0x540df119, 0x1fdd1aec), TOBN(0xcf37825b, 0xcfba4c78), - TOBN(0x77eff980, 0xbeb11454), TOBN(0x40a1a991, 0x60c1b066), - TOBN(0xe8018980, 0xf889a1c7), TOBN(0xb9c52ae9, 0x76c24be0), - TOBN(0x05fbbcce, 0x45650ef4), TOBN(0xae000f10, 0x8aa29ac7), - TOBN(0x884b7172, 0x4f04c470), TOBN(0x7cd4fde2, 0x19bb5c25), - TOBN(0x6477b22a, 0xe8840869), TOBN(0xa8868859, 0x5fbd0686), - TOBN(0xf23cc02e, 0x1116dfba), TOBN(0x76cd563f, 0xd87d7776), - TOBN(0xe2a37598, 0xa9d82abf), TOBN(0x5f188ccb, 0xe6c170f5), - TOBN(0x81682200, 0x5066b087), TOBN(0xda22c212, 0xc7155ada), - TOBN(0x151e5d3a, 0xfbddb479), TOBN(0x4b606b84, 0x6d715b99), - TOBN(0x4a73b54b, 0xf997cb2e), TOBN(0x9a1bfe43, 0x3ecd8b66), - TOBN(0x1c312809, 0x2a67d48a), TOBN(0xcd6a671e, 0x031fa9e2), - TOBN(0xbec3312a, 0x0e43a34a), TOBN(0x1d935639, 0x55ef47d3), - TOBN(0x5ea02489, 0x8fea73ea), TOBN(0x8247b364, 0xa035afb2), - TOBN(0xb58300a6, 0x5265b54c), TOBN(0x3286662f, 0x722c7148), - TOBN(0xb77fd76b, 0xb4ec4c20), TOBN(0xf0a12fa7, 0x0f3fe3fd), - TOBN(0xf845bbf5, 0x41d8c7e8), TOBN(0xe4d969ca, 0x5ec10aa8), - TOBN(0x4c0053b7, 0x43e232a3), TOBN(0xdc7a3fac, 0x37f8a45a), - TOBN(0x3c4261c5, 0x20d81c8f), TOBN(0xfd4b3453, 0xb00eab00), - TOBN(0x76d48f86, 0xd36e3062), TOBN(0x626c5277, 0xa143ff02), - TOBN(0x538174de, 0xaf76f42e), TOBN(0x2267aa86, 0x6407ceac), - TOBN(0xfad76351, 0x72e572d5), TOBN(0xab861af7, 0xba7330eb), - TOBN(0xa0a1c8c7, 0x418d8657), TOBN(0x988821cb, 0x20289a52), - TOBN(0x79732522, 0xcccc18ad), TOBN(0xaadf3f8d, 0xf1a6e027), - TOBN(0xf7382c93, 0x17c2354d), TOBN(0x5ce1680c, 0xd818b689), - TOBN(0x359ebbfc, 0xd9ecbee9), TOBN(0x4330689c, 0x1cae62ac), - TOBN(0xb55ce5b4, 0xc51ac38a), TOBN(0x7921dfea, 0xfe238ee8), - TOBN(0x3972bef8, 0x271d1ca5), TOBN(0x3e423bc7, 0xe8aabd18), - TOBN(0x57b09f3f, 0x44a3e5e3), TOBN(0x5da886ae, 0x7b444d66), - TOBN(0x68206634, 0xa9964375), TOBN(0x356a2fa3, 0x699cd0ff), - TOBN(0xaf0faa24, 0xdba515e9), TOBN(0x536e1f5c, 0xb321d79a), - TOBN(0xd3b9913a, 0x5c04e4ea), TOBN(0xd549dcfe, 0xd6f11513), - TOBN(0xee227bf5, 0x79fd1d94), TOBN(0x9f35afee, 0xb43f2c67), - TOBN(0xd2638d24, 0xf1314f53), TOBN(0x62baf948, 0xcabcd822), - TOBN(0x5542de29, 0x4ef48db0), TOBN(0xb3eb6a04, 0xfc5f6bb2), - TOBN(0x23c110ae, 0x1208e16a), TOBN(0x1a4d15b5, 0xf8363e24), - TOBN(0x30716844, 0x164be00b), TOBN(0xa8e24824, 0xf6f4690d), - TOBN(0x548773a2, 0x90b170cf), TOBN(0xa1bef331, 0x42f191f4), - TOBN(0x70f418d0, 0x9247aa97), TOBN(0xea06028e, 0x48be9147), - TOBN(0xe13122f3, 0xdbfb894e), TOBN(0xbe9b79f6, 0xce274b18), - TOBN(0x85a49de5, 0xca58aadf), TOBN(0x24957758, 0x11487351), - TOBN(0x111def61, 0xbb939099), TOBN(0x1d6a974a, 0x26d13694), - TOBN(0x4474b4ce, 0xd3fc253b), TOBN(0x3a1485e6, 0x4c5db15e), - TOBN(0xe79667b4, 0x147c15b4), TOBN(0xe34f553b, 0x7bc61301), - TOBN(0x032b80f8, 0x17094381), TOBN(0x55d8bafd, 0x723eaa21), - TOBN(0x5a987995, 0xf1c0e74e), TOBN(0x5a9b292e, 0xebba289c), - TOBN(0x413cd4b2, 0xeb4c8251), TOBN(0x98b5d243, 0xd162db0a), - TOBN(0xbb47bf66, 0x68342520), TOBN(0x08d68949, 0xbaa862d1), - TOBN(0x11f349c7, 0xe906abcd), TOBN(0x454ce985, 0xed7bf00e), - TOBN(0xacab5c9e, 0xb55b803b), TOBN(0xb03468ea, 0x31e3c16d), - TOBN(0x5c24213d, 0xd273bf12), TOBN(0x211538eb, 0x71587887), - TOBN(0x198e4a2f, 0x731dea2d), TOBN(0xd5856cf2, 0x74ed7b2a), - TOBN(0x86a632eb, 0x13a664fe), TOBN(0x932cd909, 0xbda41291), - TOBN(0x850e95d4, 0xc0c4ddc0), TOBN(0xc0f422f8, 0x347fc2c9), - TOBN(0xe68cbec4, 0x86076bcb), TOBN(0xf9e7c0c0, 0xcd6cd286), - TOBN(0x65994ddb, 0x0f5f27ca), TOBN(0xe85461fb, 0xa80d59ff), - TOBN(0xff05481a, 0x66601023), TOBN(0xc665427a, 0xfc9ebbfb), - TOBN(0xb0571a69, 0x7587fd52), TOBN(0x935289f8, 0x8d49efce), - TOBN(0x61becc60, 0xea420688), TOBN(0xb22639d9, 0x13a786af), - TOBN(0x1a8e6220, 0x361ecf90), TOBN(0x001f23e0, 0x25506463), - TOBN(0xe4ae9b5d, 0x0a5c2b79), TOBN(0xebc9cdad, 0xd8149db5), - TOBN(0xb33164a1, 0x934aa728), TOBN(0x750eb00e, 0xae9b60f3), - TOBN(0x5a91615b, 0x9b9cfbfd), TOBN(0x97015cbf, 0xef45f7f6), - TOBN(0xb462c4a5, 0xbf5151df), TOBN(0x21adcc41, 0xb07118f2), - TOBN(0xd60c545b, 0x043fa42c), TOBN(0xfc21aa54, 0xe96be1ab), - TOBN(0xe84bc32f, 0x4e51ea80), TOBN(0x3dae45f0, 0x259b5d8d), - TOBN(0xbb73c7eb, 0xc38f1b5e), TOBN(0xe405a74a, 0xe8ae617d), - TOBN(0xbb1ae9c6, 0x9f1c56bd), TOBN(0x8c176b98, 0x49f196a4), - TOBN(0xc448f311, 0x6875092b), TOBN(0xb5afe3de, 0x9f976033), - TOBN(0xa8dafd49, 0x145813e5), TOBN(0x687fc4d9, 0xe2b34226), - TOBN(0xf2dfc92d, 0x4c7ff57f), TOBN(0x004e3fc1, 0x401f1b46), - TOBN(0x5afddab6, 0x1430c9ab), TOBN(0x0bdd41d3, 0x2238e997), - TOBN(0xf0947430, 0x418042ae), TOBN(0x71f9adda, 0xcdddc4cb), - TOBN(0x7090c016, 0xc52dd907), TOBN(0xd9bdf44d, 0x29e2047f), - TOBN(0xe6f1fe80, 0x1b1011a6), TOBN(0xb63accbc, 0xd9acdc78), - TOBN(0xcfc7e235, 0x1272a95b), TOBN(0x0c667717, 0xa6276ac8), - TOBN(0x3c0d3709, 0xe2d7eef7), TOBN(0x5add2b06, 0x9a685b3e), - TOBN(0x363ad32d, 0x14ea5d65), TOBN(0xf8e01f06, 0x8d7dd506), - TOBN(0xc9ea2213, 0x75b4aac6), TOBN(0xed2a2bf9, 0x0d353466), - TOBN(0x439d79b5, 0xe9d3a7c3), TOBN(0x8e0ee5a6, 0x81b7f34b), - TOBN(0xcf3dacf5, 0x1dc4ba75), TOBN(0x1d3d1773, 0xeb3310c7), - TOBN(0xa8e67112, 0x7747ae83), TOBN(0x31f43160, 0x197d6b40), - TOBN(0x0521ccee, 0xcd961400), TOBN(0x67246f11, 0xf6535768), - TOBN(0x702fcc5a, 0xef0c3133), TOBN(0x247cc45d, 0x7e16693b), - TOBN(0xfd484e49, 0xc729b749), TOBN(0x522cef7d, 0xb218320f), - TOBN(0xe56ef405, 0x59ab93b3), TOBN(0x225fba11, 0x9f181071), - TOBN(0x33bd6595, 0x15330ed0), TOBN(0xc4be69d5, 0x1ddb32f7), - TOBN(0x264c7668, 0x0448087c), TOBN(0xac30903f, 0x71432dae), - TOBN(0x3851b266, 0x00f9bf47), TOBN(0x400ed311, 0x6cdd6d03), - TOBN(0x045e79fe, 0xf8fd2424), TOBN(0xfdfd974a, 0xfa6da98b), - TOBN(0x45c9f641, 0x0c1e673a), TOBN(0x76f2e733, 0x5b2c5168), - TOBN(0x1adaebb5, 0x2a601753), TOBN(0xb286514c, 0xc57c2d49), - TOBN(0xd8769670, 0x1e0bfd24), TOBN(0x950c547e, 0x04478922), - TOBN(0xd1d41969, 0xe5d32bfe), TOBN(0x30bc1472, 0x750d6c3e), - TOBN(0x8f3679fe, 0xe0e27f3a), TOBN(0x8f64a7dc, 0xa4a6ee0c), - TOBN(0x2fe59937, 0x633dfb1f), TOBN(0xea82c395, 0x977f2547), - TOBN(0xcbdfdf1a, 0x661ea646), TOBN(0xc7ccc591, 0xb9085451), - TOBN(0x82177962, 0x81761e13), TOBN(0xda57596f, 0x9196885c), - TOBN(0xbc17e849, 0x28ffbd70), TOBN(0x1e6e0a41, 0x2671d36f), - TOBN(0x61ae872c, 0x4152fcf5), TOBN(0x441c87b0, 0x9e77e754), - TOBN(0xd0799dd5, 0xa34dff09), TOBN(0x766b4e44, 0x88a6b171), - TOBN(0xdc06a512, 0x11f1c792), TOBN(0xea02ae93, 0x4be35c3e), - TOBN(0xe5ca4d6d, 0xe90c469e), TOBN(0x4df4368e, 0x56e4ff5c), - TOBN(0x7817acab, 0x4baef62e), TOBN(0x9f5a2202, 0xa85b91e8), - TOBN(0x9666ebe6, 0x6ce57610), TOBN(0x32ad31f3, 0xf73bfe03), - TOBN(0x628330a4, 0x25bcf4d6), TOBN(0xea950593, 0x515056e6), - TOBN(0x59811c89, 0xe1332156), TOBN(0xc89cf1fe, 0x8c11b2d7), - TOBN(0x75b63913, 0x04e60cc0), TOBN(0xce811e8d, 0x4625d375), - TOBN(0x030e43fc, 0x2d26e562), TOBN(0xfbb30b4b, 0x608d36a0), - TOBN(0x634ff82c, 0x48528118), TOBN(0x7c6fe085, 0xcd285911), - TOBN(0x7f2830c0, 0x99358f28), TOBN(0x2e60a95e, 0x665e6c09), - TOBN(0x08407d3d, 0x9b785dbf), TOBN(0x530889ab, 0xa759bce7), - TOBN(0xf228e0e6, 0x52f61239), TOBN(0x2b6d1461, 0x6879be3c), - TOBN(0xe6902c04, 0x51a7bbf7), TOBN(0x30ad99f0, 0x76f24a64), - TOBN(0x66d9317a, 0x98bc6da0), TOBN(0xf4f877f3, 0xcb596ac0), - TOBN(0xb05ff62d, 0x4c44f119), TOBN(0x4555f536, 0xe9b77416), - TOBN(0xc7c0d059, 0x8caed63b), TOBN(0x0cd2b7ce, 0xc358b2a9), - TOBN(0x3f33287b, 0x46945fa3), TOBN(0xf8785b20, 0xd67c8791), - TOBN(0xc54a7a61, 0x9637bd08), TOBN(0x54d4598c, 0x18be79d7), - TOBN(0x889e5acb, 0xc46d7ce1), TOBN(0x9a515bb7, 0x8b085877), - TOBN(0xfac1a03d, 0x0b7a5050), TOBN(0x7d3e738a, 0xf2926035), - TOBN(0x861cc2ce, 0x2a6cb0eb), TOBN(0x6f2e2955, 0x8f7adc79), - TOBN(0x61c4d451, 0x33016376), TOBN(0xd9fd2c80, 0x5ad59090), - TOBN(0xe5a83738, 0xb2b836a1), TOBN(0x855b41a0, 0x7c0d6622), - TOBN(0x186fe317, 0x7cc19af1), TOBN(0x6465c1ff, 0xfdd99acb), - TOBN(0x46e5c23f, 0x6974b99e), TOBN(0x75a7cf8b, 0xa2717cbe), - TOBN(0x4d2ebc3f, 0x062be658), TOBN(0x094b4447, 0x5f209c98), - TOBN(0x4af285ed, 0xb940cb5a), TOBN(0x6706d792, 0x7cc82f10), - TOBN(0xc8c8776c, 0x030526fa), TOBN(0xfa8e6f76, 0xa0da9140), - TOBN(0x77ea9d34, 0x591ee4f0), TOBN(0x5f46e337, 0x40274166), - TOBN(0x1bdf98bb, 0xea671457), TOBN(0xd7c08b46, 0x862a1fe2), - TOBN(0x46cc303c, 0x1c08ad63), TOBN(0x99543440, 0x4c845e7b), - TOBN(0x1b8fbdb5, 0x48f36bf7), TOBN(0x5b82c392, 0x8c8273a7), - TOBN(0x08f712c4, 0x928435d5), TOBN(0x071cf0f1, 0x79330380), - TOBN(0xc74c2d24, 0xa8da054a), TOBN(0xcb0e7201, 0x43c46b5c), - TOBN(0x0ad7337a, 0xc0b7eff3), TOBN(0x8552225e, 0xc5e48b3c), - TOBN(0xe6f78b0c, 0x73f13a5f), TOBN(0x5e70062e, 0x82349cbe), - TOBN(0x6b8d5048, 0xe7073969), TOBN(0x392d2a29, 0xc33cb3d2), - TOBN(0xee4f727c, 0x4ecaa20f), TOBN(0xa068c99e, 0x2ccde707), - TOBN(0xfcd5651f, 0xb87a2913), TOBN(0xea3e3c15, 0x3cc252f0), - TOBN(0x777d92df, 0x3b6cd3e4), TOBN(0x7a414143, 0xc5a732e7), - TOBN(0xa895951a, 0xa71ff493), TOBN(0xfe980c92, 0xbbd37cf6), - TOBN(0x45bd5e64, 0xdecfeeff), TOBN(0x910dc2a9, 0xa44c43e9), - TOBN(0xcb403f26, 0xcca9f54d), TOBN(0x928bbdfb, 0x9303f6db), - TOBN(0x3c37951e, 0xa9eee67c), TOBN(0x3bd61a52, 0xf79961c3), - TOBN(0x09a238e6, 0x395c9a79), TOBN(0x6940ca2d, 0x61eb352d), - TOBN(0x7d1e5c5e, 0xc1875631), TOBN(0x1e19742c, 0x1e1b20d1), - TOBN(0x4633d908, 0x23fc2e6e), TOBN(0xa76e29a9, 0x08959149), - TOBN(0x61069d9c, 0x84ed7da5), TOBN(0x0baa11cf, 0x5dbcad51), - TOBN(0xd01eec64, 0x961849da), TOBN(0x93b75f1f, 0xaf3d8c28), - TOBN(0x57bc4f9f, 0x1ca2ee44), TOBN(0x5a26322d, 0x00e00558), - TOBN(0x1888d658, 0x61a023ef), TOBN(0x1d72aab4, 0xb9e5246e), - TOBN(0xa9a26348, 0xe5563ec0), TOBN(0xa0971963, 0xc3439a43), - TOBN(0x567dd54b, 0xadb9b5b7), TOBN(0x73fac1a1, 0xc45a524b), - TOBN(0x8fe97ef7, 0xfe38e608), TOBN(0x608748d2, 0x3f384f48), - TOBN(0xb0571794, 0xc486094f), TOBN(0x869254a3, 0x8bf3a8d6), - TOBN(0x148a8dd1, 0x310b0e25), TOBN(0x99ab9f3f, 0x9aa3f7d8), - TOBN(0x0927c68a, 0x6706c02e), TOBN(0x22b5e76c, 0x69790e6c), - TOBN(0x6c325260, 0x6c71376c), TOBN(0x53a57690, 0x09ef6657), - TOBN(0x8d63f852, 0xedffcf3a), TOBN(0xb4d2ed04, 0x3c0a6f55), - TOBN(0xdb3aa8de, 0x12519b9e), TOBN(0x5d38e9c4, 0x1e0a569a), - TOBN(0x871528bf, 0x303747e2), TOBN(0xa208e77c, 0xf5b5c18d), - TOBN(0x9d129c88, 0xca6bf923), TOBN(0xbcbf197f, 0xbf02839f), - TOBN(0x9b9bf030, 0x27323194), TOBN(0x3b055a8b, 0x339ca59d), - TOBN(0xb46b2312, 0x0f669520), TOBN(0x19789f1f, 0x497e5f24), - TOBN(0x9c499468, 0xaaf01801), TOBN(0x72ee1190, 0x8b69d59c), - TOBN(0x8bd39595, 0xacf4c079), TOBN(0x3ee11ece, 0x8e0cd048), - TOBN(0xebde86ec, 0x1ed66f18), TOBN(0x225d906b, 0xd61fce43), - TOBN(0x5cab07d6, 0xe8bed74d), TOBN(0x16e4617f, 0x27855ab7), - TOBN(0x6568aadd, 0xb2fbc3dd), TOBN(0xedb5484f, 0x8aeddf5b), - TOBN(0x878f20e8, 0x6dcf2fad), TOBN(0x3516497c, 0x615f5699), - }, - { - TOBN(0xef0a3fec, 0xfa181e69), TOBN(0x9ea02f81, 0x30d69a98), - TOBN(0xb2e9cf8e, 0x66eab95d), TOBN(0x520f2beb, 0x24720021), - TOBN(0x621c540a, 0x1df84361), TOBN(0x12037721, 0x71fa6d5d), - TOBN(0x6e3c7b51, 0x0ff5f6ff), TOBN(0x817a069b, 0xabb2bef3), - TOBN(0x83572fb6, 0xb294cda6), TOBN(0x6ce9bf75, 0xb9039f34), - TOBN(0x20e012f0, 0x095cbb21), TOBN(0xa0aecc1b, 0xd063f0da), - TOBN(0x57c21c3a, 0xf02909e5), TOBN(0xc7d59ecf, 0x48ce9cdc), - TOBN(0x2732b844, 0x8ae336f8), TOBN(0x056e3723, 0x3f4f85f4), - TOBN(0x8a10b531, 0x89e800ca), TOBN(0x50fe0c17, 0x145208fd), - TOBN(0x9e43c0d3, 0xb714ba37), TOBN(0x427d200e, 0x34189acc), - TOBN(0x05dee24f, 0xe616e2c0), TOBN(0x9c25f4c8, 0xee1854c1), - TOBN(0x4d3222a5, 0x8f342a73), TOBN(0x0807804f, 0xa027c952), - TOBN(0xc222653a, 0x4f0d56f3), TOBN(0x961e4047, 0xca28b805), - TOBN(0x2c03f8b0, 0x4a73434b), TOBN(0x4c966787, 0xab712a19), - TOBN(0xcc196c42, 0x864fee42), TOBN(0xc1be93da, 0x5b0ece5c), - TOBN(0xa87d9f22, 0xc131c159), TOBN(0x2bb6d593, 0xdce45655), - TOBN(0x22c49ec9, 0xb809b7ce), TOBN(0x8a41486b, 0xe2c72c2c), - TOBN(0x813b9420, 0xfea0bf36), TOBN(0xb3d36ee9, 0xa66dac69), - TOBN(0x6fddc08a, 0x328cc987), TOBN(0x0a3bcd2c, 0x3a326461), - TOBN(0x7103c49d, 0xd810dbba), TOBN(0xf9d81a28, 0x4b78a4c4), - TOBN(0x3de865ad, 0xe4d55941), TOBN(0xdedafa5e, 0x30384087), - TOBN(0x6f414abb, 0x4ef18b9b), TOBN(0x9ee9ea42, 0xfaee5268), - TOBN(0x260faa16, 0x37a55a4a), TOBN(0xeb19a514, 0x015f93b9), - TOBN(0x51d7ebd2, 0x9e9c3598), TOBN(0x523fc56d, 0x1932178e), - TOBN(0x501d070c, 0xb98fe684), TOBN(0xd60fbe9a, 0x124a1458), - TOBN(0xa45761c8, 0x92bc6b3f), TOBN(0xf5384858, 0xfe6f27cb), - TOBN(0x4b0271f7, 0xb59e763b), TOBN(0x3d4606a9, 0x5b5a8e5e), - TOBN(0x1eda5d9b, 0x05a48292), TOBN(0xda7731d0, 0xe6fec446), - TOBN(0xa3e33693, 0x90d45871), TOBN(0xe9764040, 0x06166d8d), - TOBN(0xb5c33682, 0x89a90403), TOBN(0x4bd17983, 0x72f1d637), - TOBN(0xa616679e, 0xd5d2c53a), TOBN(0x5ec4bcd8, 0xfdcf3b87), - TOBN(0xae6d7613, 0xb66a694e), TOBN(0x7460fc76, 0xe3fc27e5), - TOBN(0x70469b82, 0x95caabee), TOBN(0xde024ca5, 0x889501e3), - TOBN(0x6bdadc06, 0x076ed265), TOBN(0x0cb1236b, 0x5a0ef8b2), - TOBN(0x4065ddbf, 0x0972ebf9), TOBN(0xf1dd3875, 0x22aca432), - TOBN(0xa88b97cf, 0x744aff76), TOBN(0xd1359afd, 0xfe8e3d24), - TOBN(0x52a3ba2b, 0x91502cf3), TOBN(0x2c3832a8, 0x084db75d), - TOBN(0x04a12ddd, 0xde30b1c9), TOBN(0x7802eabc, 0xe31fd60c), - TOBN(0x33707327, 0xa37fddab), TOBN(0x65d6f2ab, 0xfaafa973), - TOBN(0x3525c5b8, 0x11e6f91a), TOBN(0x76aeb0c9, 0x5f46530b), - TOBN(0xe8815ff6, 0x2f93a675), TOBN(0xa6ec9684, 0x05f48679), - TOBN(0x6dcbb556, 0x358ae884), TOBN(0x0af61472, 0xe19e3873), - TOBN(0x72334372, 0xa5f696be), TOBN(0xc65e57ea, 0x6f22fb70), - TOBN(0x268da30c, 0x946cea90), TOBN(0x136a8a87, 0x65681b2a), - TOBN(0xad5e81dc, 0x0f9f44d4), TOBN(0xf09a6960, 0x2c46585a), - TOBN(0xd1649164, 0xc447d1b1), TOBN(0x3b4b36c8, 0x879dc8b1), - TOBN(0x20d4177b, 0x3b6b234c), TOBN(0x096a2505, 0x1730d9d0), - TOBN(0x0611b9b8, 0xef80531d), TOBN(0xba904b3b, 0x64bb495d), - TOBN(0x1192d9d4, 0x93a3147a), TOBN(0x9f30a5dc, 0x9a565545), - TOBN(0x90b1f9cb, 0x6ef07212), TOBN(0x29958546, 0x0d87fc13), - TOBN(0xd3323eff, 0xc17db9ba), TOBN(0xcb18548c, 0xcb1644a8), - TOBN(0x18a306d4, 0x4f49ffbc), TOBN(0x28d658f1, 0x4c2e8684), - TOBN(0x44ba60cd, 0xa99f8c71), TOBN(0x67b7abdb, 0x4bf742ff), - TOBN(0x66310f9c, 0x914b3f99), TOBN(0xae430a32, 0xf412c161), - TOBN(0x1e6776d3, 0x88ace52f), TOBN(0x4bc0fa24, 0x52d7067d), - TOBN(0x03c286aa, 0x8f07cd1b), TOBN(0x4cb8f38c, 0xa985b2c1), - TOBN(0x83ccbe80, 0x8c3bff36), TOBN(0x005a0bd2, 0x5263e575), - TOBN(0x460d7dda, 0x259bdcd1), TOBN(0x4a1c5642, 0xfa5cab6b), - TOBN(0x2b7bdbb9, 0x9fe4fc88), TOBN(0x09418e28, 0xcc97bbb5), - TOBN(0xd8274fb4, 0xa12321ae), TOBN(0xb137007d, 0x5c87b64e), - TOBN(0x80531fe1, 0xc63c4962), TOBN(0x50541e89, 0x981fdb25), - TOBN(0xdc1291a1, 0xfd4c2b6b), TOBN(0xc0693a17, 0xa6df4fca), - TOBN(0xb2c4604e, 0x0117f203), TOBN(0x245f1963, 0x0a99b8d0), - TOBN(0xaedc20aa, 0xc6212c44), TOBN(0xb1ed4e56, 0x520f52a8), - TOBN(0xfe48f575, 0xf8547be3), TOBN(0x0a7033cd, 0xa9e45f98), - TOBN(0x4b45d3a9, 0x18c50100), TOBN(0xb2a6cd6a, 0xa61d41da), - TOBN(0x60bbb4f5, 0x57933c6b), TOBN(0xa7538ebd, 0x2b0d7ffc), - TOBN(0x9ea3ab8d, 0x8cd626b6), TOBN(0x8273a484, 0x3601625a), - TOBN(0x88859845, 0x0168e508), TOBN(0x8cbc9bb2, 0x99a94abd), - TOBN(0x713ac792, 0xfab0a671), TOBN(0xa3995b19, 0x6c9ebffc), - TOBN(0xe711668e, 0x1239e152), TOBN(0x56892558, 0xbbb8dff4), - TOBN(0x8bfc7dab, 0xdbf17963), TOBN(0x5b59fe5a, 0xb3de1253), - TOBN(0x7e3320eb, 0x34a9f7ae), TOBN(0xe5e8cf72, 0xd751efe4), - TOBN(0x7ea003bc, 0xd9be2f37), TOBN(0xc0f551a0, 0xb6c08ef7), - TOBN(0x56606268, 0x038f6725), TOBN(0x1dd38e35, 0x6d92d3b6), - TOBN(0x07dfce7c, 0xc3cbd686), TOBN(0x4e549e04, 0x651c5da8), - TOBN(0x4058f93b, 0x08b19340), TOBN(0xc2fae6f4, 0xcac6d89d), - TOBN(0x4bad8a8c, 0x8f159cc7), TOBN(0x0ddba4b3, 0xcb0b601c), - TOBN(0xda4fc7b5, 0x1dd95f8c), TOBN(0x1d163cd7, 0xcea5c255), - TOBN(0x30707d06, 0x274a8c4c), TOBN(0x79d9e008, 0x2802e9ce), - TOBN(0x02a29ebf, 0xe6ddd505), TOBN(0x37064e74, 0xb50bed1a), - TOBN(0x3f6bae65, 0xa7327d57), TOBN(0x3846f5f1, 0xf83920bc), - TOBN(0x87c37491, 0x60df1b9b), TOBN(0x4cfb2895, 0x2d1da29f), - TOBN(0x10a478ca, 0x4ed1743c), TOBN(0x390c6030, 0x3edd47c6), - TOBN(0x8f3e5312, 0x8c0a78de), TOBN(0xccd02bda, 0x1e85df70), - TOBN(0xd6c75c03, 0xa61b6582), TOBN(0x0762921c, 0xfc0eebd1), - TOBN(0xd34d0823, 0xd85010c0), TOBN(0xd73aaacb, 0x0044cf1f), - TOBN(0xfb4159bb, 0xa3b5e78a), TOBN(0x2287c7f7, 0xe5826f3f), - TOBN(0x4aeaf742, 0x580b1a01), TOBN(0xf080415d, 0x60423b79), - TOBN(0xe12622cd, 0xa7dea144), TOBN(0x49ea4996, 0x59d62472), - TOBN(0xb42991ef, 0x571f3913), TOBN(0x0610f214, 0xf5b25a8a), - TOBN(0x47adc585, 0x30b79e8f), TOBN(0xf90e3df6, 0x07a065a2), - TOBN(0x5d0a5deb, 0x43e2e034), TOBN(0x53fb5a34, 0x444024aa), - TOBN(0xa8628c68, 0x6b0c9f7f), TOBN(0x9c69c29c, 0xac563656), - TOBN(0x5a231feb, 0xbace47b6), TOBN(0xbdce0289, 0x9ea5a2ec), - TOBN(0x05da1fac, 0x9463853e), TOBN(0x96812c52, 0x509e78aa), - TOBN(0xd3fb5771, 0x57151692), TOBN(0xeb2721f8, 0xd98e1c44), - TOBN(0xc0506087, 0x32399be1), TOBN(0xda5a5511, 0xd979d8b8), - TOBN(0x737ed55d, 0xc6f56780), TOBN(0xe20d3004, 0x0dc7a7f4), - TOBN(0x02ce7301, 0xf5941a03), TOBN(0x91ef5215, 0xed30f83a), - TOBN(0x28727fc1, 0x4092d85f), TOBN(0x72d223c6, 0x5c49e41a), - TOBN(0xa7cf30a2, 0xba6a4d81), TOBN(0x7c086209, 0xb030d87d), - TOBN(0x04844c7d, 0xfc588b09), TOBN(0x728cd499, 0x5874bbb0), - TOBN(0xcc1281ee, 0xe84c0495), TOBN(0x0769b5ba, 0xec31958f), - TOBN(0x665c228b, 0xf99c2471), TOBN(0xf2d8a11b, 0x191eb110), - TOBN(0x4594f494, 0xd36d7024), TOBN(0x482ded8b, 0xcdcb25a1), - TOBN(0xc958a9d8, 0xdadd4885), TOBN(0x7004477e, 0xf1d2b547), - TOBN(0x0a45f6ef, 0x2a0af550), TOBN(0x4fc739d6, 0x2f8d6351), - TOBN(0x75cdaf27, 0x786f08a9), TOBN(0x8700bb26, 0x42c2737f), - TOBN(0x855a7141, 0x1c4e2670), TOBN(0x810188c1, 0x15076fef), - TOBN(0xc251d0c9, 0xabcd3297), TOBN(0xae4c8967, 0xf48108eb), - TOBN(0xbd146de7, 0x18ceed30), TOBN(0xf9d4f07a, 0xc986bced), - TOBN(0x5ad98ed5, 0x83fa1e08), TOBN(0x7780d33e, 0xbeabd1fb), - TOBN(0xe330513c, 0x903b1196), TOBN(0xba11de9e, 0xa47bc8c4), - TOBN(0x684334da, 0x02c2d064), TOBN(0x7ecf360d, 0xa48de23b), - TOBN(0x57a1b474, 0x0a9089d8), TOBN(0xf28fa439, 0xff36734c), - TOBN(0xf2a482cb, 0xea4570b3), TOBN(0xee65d68b, 0xa5ebcee9), - TOBN(0x988d0036, 0xb9694cd5), TOBN(0x53edd0e9, 0x37885d32), - TOBN(0xe37e3307, 0xbeb9bc6d), TOBN(0xe9abb907, 0x9f5c6768), - TOBN(0x4396ccd5, 0x51f2160f), TOBN(0x2500888c, 0x47336da6), - TOBN(0x383f9ed9, 0x926fce43), TOBN(0x809dd1c7, 0x04da2930), - TOBN(0x30f6f596, 0x8a4cb227), TOBN(0x0d700c7f, 0x73a56b38), - TOBN(0x1825ea33, 0xab64a065), TOBN(0xaab9b735, 0x1338df80), - TOBN(0x1516100d, 0x9b63f57f), TOBN(0x2574395a, 0x27a6a634), - TOBN(0xb5560fb6, 0x700a1acd), TOBN(0xe823fd73, 0xfd999681), - TOBN(0xda915d1f, 0x6cb4e1ba), TOBN(0x0d030118, 0x6ebe00a3), - TOBN(0x744fb0c9, 0x89fca8cd), TOBN(0x970d01db, 0xf9da0e0b), - TOBN(0x0ad8c564, 0x7931d76f), TOBN(0xb15737bf, 0xf659b96a), - TOBN(0xdc9933e8, 0xa8b484e7), TOBN(0xb2fdbdf9, 0x7a26dec7), - TOBN(0x2349e9a4, 0x9f1f0136), TOBN(0x7860368e, 0x70fddddb), - TOBN(0xd93d2c1c, 0xf9ad3e18), TOBN(0x6d6c5f17, 0x689f4e79), - TOBN(0x7a544d91, 0xb24ff1b6), TOBN(0x3e12a5eb, 0xfe16cd8c), - TOBN(0x543574e9, 0xa56b872f), TOBN(0xa1ad550c, 0xfcf68ea2), - TOBN(0x689e37d2, 0x3f560ef7), TOBN(0x8c54b9ca, 0xc9d47a8b), - TOBN(0x46d40a4a, 0x088ac342), TOBN(0xec450c7c, 0x1576c6d0), - TOBN(0xb589e31c, 0x1f9689e9), TOBN(0xdacf2602, 0xb8781718), - TOBN(0xa89237c6, 0xc8cb6b42), TOBN(0x1326fc93, 0xb96ef381), - TOBN(0x55d56c6d, 0xb5f07825), TOBN(0xacba2eea, 0x7449e22d), - TOBN(0x74e0887a, 0x633c3000), TOBN(0xcb6cd172, 0xd7cbcf71), - TOBN(0x309e81de, 0xc36cf1be), TOBN(0x07a18a6d, 0x60ae399b), - TOBN(0xb36c2679, 0x9edce57e), TOBN(0x52b892f4, 0xdf001d41), - TOBN(0xd884ae5d, 0x16a1f2c6), TOBN(0x9b329424, 0xefcc370a), - TOBN(0x3120daf2, 0xbd2e21df), TOBN(0x55298d2d, 0x02470a99), - TOBN(0x0b78af6c, 0xa05db32e), TOBN(0x5c76a331, 0x601f5636), - TOBN(0xaae861ff, 0xf8a4f29c), TOBN(0x70dc9240, 0xd68f8d49), - TOBN(0x960e649f, 0x81b1321c), TOBN(0x3d2c801b, 0x8792e4ce), - TOBN(0xf479f772, 0x42521876), TOBN(0x0bed93bc, 0x416c79b1), - TOBN(0xa67fbc05, 0x263e5bc9), TOBN(0x01e8e630, 0x521db049), - TOBN(0x76f26738, 0xc6f3431e), TOBN(0xe609cb02, 0xe3267541), - TOBN(0xb10cff2d, 0x818c877c), TOBN(0x1f0e75ce, 0x786a13cb), - TOBN(0xf4fdca64, 0x1158544d), TOBN(0x5d777e89, 0x6cb71ed0), - TOBN(0x3c233737, 0xa9aa4755), TOBN(0x7b453192, 0xe527ab40), - TOBN(0xdb59f688, 0x39f05ffe), TOBN(0x8f4f4be0, 0x6d82574e), - TOBN(0xcce3450c, 0xee292d1b), TOBN(0xaa448a12, 0x61ccd086), - TOBN(0xabce91b3, 0xf7914967), TOBN(0x4537f09b, 0x1908a5ed), - TOBN(0xa812421e, 0xf51042e7), TOBN(0xfaf5cebc, 0xec0b3a34), - TOBN(0x730ffd87, 0x4ca6b39a), TOBN(0x70fb72ed, 0x02efd342), - TOBN(0xeb4735f9, 0xd75c8edb), TOBN(0xc11f2157, 0xc278aa51), - TOBN(0xc459f635, 0xbf3bfebf), TOBN(0x3a1ff0b4, 0x6bd9601f), - TOBN(0xc9d12823, 0xc420cb73), TOBN(0x3e9af3e2, 0x3c2915a3), - TOBN(0xe0c82c72, 0xb41c3440), TOBN(0x175239e5, 0xe3039a5f), - TOBN(0xe1084b8a, 0x558795a3), TOBN(0x328d0a1d, 0xd01e5c60), - TOBN(0x0a495f2e, 0xd3788a04), TOBN(0x25d8ff16, 0x66c11a9f), - TOBN(0xf5155f05, 0x9ed692d6), TOBN(0x954fa107, 0x4f425fe4), - TOBN(0xd16aabf2, 0xe98aaa99), TOBN(0x90cd8ba0, 0x96b0f88a), - TOBN(0x957f4782, 0xc154026a), TOBN(0x54ee0734, 0x52af56d2), - TOBN(0xbcf89e54, 0x45b4147a), TOBN(0x3d102f21, 0x9a52816c), - TOBN(0x6808517e, 0x39b62e77), TOBN(0x92e25421, 0x69169ad8), - TOBN(0xd721d871, 0xbb608558), TOBN(0x60e4ebae, 0xf6d4ff9b), - TOBN(0x0ba10819, 0x41f2763e), TOBN(0xca2e45be, 0x51ee3247), - TOBN(0x66d172ec, 0x2bfd7a5f), TOBN(0x528a8f2f, 0x74d0b12d), - TOBN(0xe17f1e38, 0xdabe70dc), TOBN(0x1d5d7316, 0x9f93983c), - TOBN(0x51b2184a, 0xdf423e31), TOBN(0xcb417291, 0xaedb1a10), - TOBN(0x2054ca93, 0x625bcab9), TOBN(0x54396860, 0xa98998f0), - TOBN(0x4e53f6c4, 0xa54ae57e), TOBN(0x0ffeb590, 0xee648e9d), - TOBN(0xfbbdaadc, 0x6afaf6bc), TOBN(0xf88ae796, 0xaa3bfb8a), - TOBN(0x209f1d44, 0xd2359ed9), TOBN(0xac68dd03, 0xf3544ce2), - TOBN(0xf378da47, 0xfd51e569), TOBN(0xe1abd860, 0x2cc80097), - TOBN(0x23ca18d9, 0x343b6e3a), TOBN(0x480797e8, 0xb40a1bae), - TOBN(0xd1f0c717, 0x533f3e67), TOBN(0x44896970, 0x06e6cdfc), - TOBN(0x8ca21055, 0x52a82e8d), TOBN(0xb2caf785, 0x78460cdc), - TOBN(0x4c1b7b62, 0xe9037178), TOBN(0xefc09d2c, 0xdb514b58), - TOBN(0x5f2df9ee, 0x9113be5c), TOBN(0x2fbda78f, 0xb3f9271c), - TOBN(0xe09a81af, 0x8f83fc54), TOBN(0x06b13866, 0x8afb5141), - TOBN(0x38f6480f, 0x43e3865d), TOBN(0x72dd77a8, 0x1ddf47d9), - TOBN(0xf2a8e971, 0x4c205ff7), TOBN(0x46d449d8, 0x9d088ad8), - TOBN(0x926619ea, 0x185d706f), TOBN(0xe47e02eb, 0xc7dd7f62), - TOBN(0xe7f120a7, 0x8cbc2031), TOBN(0xc18bef00, 0x998d4ac9), - TOBN(0x18f37a9c, 0x6bdf22da), TOBN(0xefbc432f, 0x90dc82df), - TOBN(0xc52cef8e, 0x5d703651), TOBN(0x82887ba0, 0xd99881a5), - TOBN(0x7cec9dda, 0xb920ec1d), TOBN(0xd0d7e8c3, 0xec3e8d3b), - TOBN(0x445bc395, 0x4ca88747), TOBN(0xedeaa2e0, 0x9fd53535), - TOBN(0x461b1d93, 0x6cc87475), TOBN(0xd92a52e2, 0x6d2383bd), - TOBN(0xfabccb59, 0xd7903546), TOBN(0x6111a761, 0x3d14b112), - TOBN(0x0ae584fe, 0xb3d5f612), TOBN(0x5ea69b8d, 0x60e828ec), - TOBN(0x6c078985, 0x54087030), TOBN(0x649cab04, 0xac4821fe), - TOBN(0x25ecedcf, 0x8bdce214), TOBN(0xb5622f72, 0x86af7361), - TOBN(0x0e1227aa, 0x7038b9e2), TOBN(0xd0efb273, 0xac20fa77), - TOBN(0x817ff88b, 0x79df975b), TOBN(0x856bf286, 0x1999503e), - TOBN(0xb4d5351f, 0x5038ec46), TOBN(0x740a52c5, 0xfc42af6e), - TOBN(0x2e38bb15, 0x2cbb1a3f), TOBN(0xc3eb99fe, 0x17a83429), - TOBN(0xca4fcbf1, 0xdd66bb74), TOBN(0x880784d6, 0xcde5e8fc), - TOBN(0xddc84c1c, 0xb4e7a0be), TOBN(0x8780510d, 0xbd15a72f), - TOBN(0x44bcf1af, 0x81ec30e1), TOBN(0x141e50a8, 0x0a61073e), - TOBN(0x0d955718, 0x47be87ae), TOBN(0x68a61417, 0xf76a4372), - TOBN(0xf57e7e87, 0xc607c3d3), TOBN(0x043afaf8, 0x5252f332), - TOBN(0xcc14e121, 0x1552a4d2), TOBN(0xb6dee692, 0xbb4d4ab4), - TOBN(0xb6ab74c8, 0xa03816a4), TOBN(0x84001ae4, 0x6f394a29), - TOBN(0x5bed8344, 0xd795fb45), TOBN(0x57326e7d, 0xb79f55a5), - TOBN(0xc9533ce0, 0x4accdffc), TOBN(0x53473caf, 0x3993fa04), - TOBN(0x7906eb93, 0xa13df4c8), TOBN(0xa73e51f6, 0x97cbe46f), - TOBN(0xd1ab3ae1, 0x0ae4ccf8), TOBN(0x25614508, 0x8a5b3dbc), - TOBN(0x61eff962, 0x11a71b27), TOBN(0xdf71412b, 0x6bb7fa39), - TOBN(0xb31ba6b8, 0x2bd7f3ef), TOBN(0xb0b9c415, 0x69180d29), - TOBN(0xeec14552, 0x014cdde5), TOBN(0x702c624b, 0x227b4bbb), - TOBN(0x2b15e8c2, 0xd3e988f3), TOBN(0xee3bcc6d, 0xa4f7fd04), - TOBN(0x9d00822a, 0x42ac6c85), TOBN(0x2db0cea6, 0x1df9f2b7), - TOBN(0xd7cad2ab, 0x42de1e58), TOBN(0x346ed526, 0x2d6fbb61), - TOBN(0xb3962995, 0x1a2faf09), TOBN(0x2fa8a580, 0x7c25612e), - TOBN(0x30ae04da, 0x7cf56490), TOBN(0x75662908, 0x0eea3961), - TOBN(0x3609f5c5, 0x3d080847), TOBN(0xcb081d39, 0x5241d4f6), - TOBN(0xb4fb3810, 0x77961a63), TOBN(0xc20c5984, 0x2abb66fc), - TOBN(0x3d40aa7c, 0xf902f245), TOBN(0x9cb12736, 0x4e536b1e), - TOBN(0x5eda24da, 0x99b3134f), TOBN(0xafbd9c69, 0x5cd011af), - TOBN(0x9a16e30a, 0xc7088c7d), TOBN(0x5ab65710, 0x3207389f), - TOBN(0x1b09547f, 0xe7407a53), TOBN(0x2322f9d7, 0x4fdc6eab), - TOBN(0xc0f2f22d, 0x7430de4d), TOBN(0x19382696, 0xe68ca9a9), - TOBN(0x17f1eff1, 0x918e5868), TOBN(0xe3b5b635, 0x586f4204), - TOBN(0x146ef980, 0x3fbc4341), TOBN(0x359f2c80, 0x5b5eed4e), - TOBN(0x9f35744e, 0x7482e41d), TOBN(0x9a9ac3ec, 0xf3b224c2), - TOBN(0x9161a6fe, 0x91fc50ae), TOBN(0x89ccc66b, 0xc613fa7c), - TOBN(0x89268b14, 0xc732f15a), TOBN(0x7cd6f4e2, 0xb467ed03), - TOBN(0xfbf79869, 0xce56b40e), TOBN(0xf93e094c, 0xc02dde98), - TOBN(0xefe0c3a8, 0xedee2cd7), TOBN(0x90f3ffc0, 0xb268fd42), - TOBN(0x81a7fd56, 0x08241aed), TOBN(0x95ab7ad8, 0x00b1afe8), - TOBN(0x40127056, 0x3e310d52), TOBN(0xd3ffdeb1, 0x09d9fc43), - TOBN(0xc8f85c91, 0xd11a8594), TOBN(0x2e74d258, 0x31cf6db8), - TOBN(0x829c7ca3, 0x02b5dfd0), TOBN(0xe389cfbe, 0x69143c86), - TOBN(0xd01b6405, 0x941768d8), TOBN(0x45103995, 0x03bf825d), - TOBN(0xcc4ee166, 0x56cd17e2), TOBN(0xbea3c283, 0xba037e79), - TOBN(0x4e1ac06e, 0xd9a47520), TOBN(0xfbfe18aa, 0xaf852404), - TOBN(0x5615f8e2, 0x8087648a), TOBN(0x7301e47e, 0xb9d150d9), - TOBN(0x79f9f9dd, 0xb299b977), TOBN(0x76697a7b, 0xa5b78314), - TOBN(0x10d67468, 0x7d7c90e7), TOBN(0x7afffe03, 0x937210b5), - TOBN(0x5aef3e4b, 0x28c22cee), TOBN(0xefb0ecd8, 0x09fd55ae), - TOBN(0x4cea7132, 0x0d2a5d6a), TOBN(0x9cfb5fa1, 0x01db6357), - TOBN(0x395e0b57, 0xf36e1ac5), TOBN(0x008fa9ad, 0x36cafb7d), - TOBN(0x8f6cdf70, 0x5308c4db), TOBN(0x51527a37, 0x95ed2477), - TOBN(0xba0dee30, 0x5bd21311), TOBN(0x6ed41b22, 0x909c90d7), - TOBN(0xc5f6b758, 0x7c8696d3), TOBN(0x0db8eaa8, 0x3ce83a80), - TOBN(0xd297fe37, 0xb24b4b6f), TOBN(0xfe58afe8, 0x522d1f0d), - TOBN(0x97358736, 0x8c98dbd9), TOBN(0x6bc226ca, 0x9454a527), - TOBN(0xa12b384e, 0xce53c2d0), TOBN(0x779d897d, 0x5e4606da), - TOBN(0xa53e47b0, 0x73ec12b0), TOBN(0x462dbbba, 0x5756f1ad), - TOBN(0x69fe09f2, 0xcafe37b6), TOBN(0x273d1ebf, 0xecce2e17), - TOBN(0x8ac1d538, 0x3cf607fd), TOBN(0x8035f7ff, 0x12e10c25), - }, - { - TOBN(0x854d34c7, 0x7e6c5520), TOBN(0xc27df9ef, 0xdcb9ea58), - TOBN(0x405f2369, 0xd686666d), TOBN(0x29d1febf, 0x0417aa85), - TOBN(0x9846819e, 0x93470afe), TOBN(0x3e6a9669, 0xe2a27f9e), - TOBN(0x24d008a2, 0xe31e6504), TOBN(0xdba7cecf, 0x9cb7680a), - TOBN(0xecaff541, 0x338d6e43), TOBN(0x56f7dd73, 0x4541d5cc), - TOBN(0xb5d426de, 0x96bc88ca), TOBN(0x48d94f6b, 0x9ed3a2c3), - TOBN(0x6354a3bb, 0x2ef8279c), TOBN(0xd575465b, 0x0b1867f2), - TOBN(0xef99b0ff, 0x95225151), TOBN(0xf3e19d88, 0xf94500d8), - TOBN(0x92a83268, 0xe32dd620), TOBN(0x913ec99f, 0x627849a2), - TOBN(0xedd8fdfa, 0x2c378882), TOBN(0xaf96f33e, 0xee6f8cfe), - TOBN(0xc06737e5, 0xdc3fa8a5), TOBN(0x236bb531, 0xb0b03a1d), - TOBN(0x33e59f29, 0x89f037b0), TOBN(0x13f9b5a7, 0xd9a12a53), - TOBN(0x0d0df6ce, 0x51efb310), TOBN(0xcb5b2eb4, 0x958df5be), - TOBN(0xd6459e29, 0x36158e59), TOBN(0x82aae2b9, 0x1466e336), - TOBN(0xfb658a39, 0x411aa636), TOBN(0x7152ecc5, 0xd4c0a933), - TOBN(0xf10c758a, 0x49f026b7), TOBN(0xf4837f97, 0xcb09311f), - TOBN(0xddfb02c4, 0xc753c45f), TOBN(0x18ca81b6, 0xf9c840fe), - TOBN(0x846fd09a, 0xb0f8a3e6), TOBN(0xb1162add, 0xe7733dbc), - TOBN(0x7070ad20, 0x236e3ab6), TOBN(0xf88cdaf5, 0xb2a56326), - TOBN(0x05fc8719, 0x997cbc7a), TOBN(0x442cd452, 0x4b665272), - TOBN(0x7807f364, 0xb71698f5), TOBN(0x6ba418d2, 0x9f7b605e), - TOBN(0xfd20b00f, 0xa03b2cbb), TOBN(0x883eca37, 0xda54386f), - TOBN(0xff0be43f, 0xf3437f24), TOBN(0xe910b432, 0xa48bb33c), - TOBN(0x4963a128, 0x329df765), TOBN(0xac1dd556, 0xbe2fe6f7), - TOBN(0x557610f9, 0x24a0a3fc), TOBN(0x38e17bf4, 0xe881c3f9), - TOBN(0x6ba84faf, 0xed0dac99), TOBN(0xd4a222c3, 0x59eeb918), - TOBN(0xc79c1dbe, 0x13f542b6), TOBN(0x1fc65e0d, 0xe425d457), - TOBN(0xeffb754f, 0x1debb779), TOBN(0x638d8fd0, 0x9e08af60), - TOBN(0x994f523a, 0x626332d5), TOBN(0x7bc38833, 0x5561bb44), - TOBN(0x005ed4b0, 0x3d845ea2), TOBN(0xd39d3ee1, 0xc2a1f08a), - TOBN(0x6561fdd3, 0xe7676b0d), TOBN(0x620e35ff, 0xfb706017), - TOBN(0x36ce424f, 0xf264f9a8), TOBN(0xc4c3419f, 0xda2681f7), - TOBN(0xfb6afd2f, 0x69beb6e8), TOBN(0x3a50b993, 0x6d700d03), - TOBN(0xc840b2ad, 0x0c83a14f), TOBN(0x573207be, 0x54085bef), - TOBN(0x5af882e3, 0x09fe7e5b), TOBN(0x957678a4, 0x3b40a7e1), - TOBN(0x172d4bdd, 0x543056e2), TOBN(0x9c1b26b4, 0x0df13c0a), - TOBN(0x1c30861c, 0xf405ff06), TOBN(0xebac86bd, 0x486e828b), - TOBN(0xe791a971, 0x636933fc), TOBN(0x50e7c2be, 0x7aeee947), - TOBN(0xc3d4a095, 0xfa90d767), TOBN(0xae60eb7b, 0xe670ab7b), - TOBN(0x17633a64, 0x397b056d), TOBN(0x93a21f33, 0x105012aa), - TOBN(0x663c370b, 0xabb88643), TOBN(0x91df36d7, 0x22e21599), - TOBN(0x183ba835, 0x8b761671), TOBN(0x381eea1d, 0x728f3bf1), - TOBN(0xb9b2f1ba, 0x39966e6c), TOBN(0x7c464a28, 0xe7295492), - TOBN(0x0fd5f70a, 0x09b26b7f), TOBN(0xa9aba1f9, 0xfbe009df), - TOBN(0x857c1f22, 0x369b87ad), TOBN(0x3c00e5d9, 0x32fca556), - TOBN(0x1ad74cab, 0x90b06466), TOBN(0xa7112386, 0x550faaf2), - TOBN(0x7435e198, 0x6d9bd5f5), TOBN(0x2dcc7e38, 0x59c3463f), - TOBN(0xdc7df748, 0xca7bd4b2), TOBN(0x13cd4c08, 0x9dec2f31), - TOBN(0x0d3b5df8, 0xe3237710), TOBN(0x0dadb26e, 0xcbd2f7b0), - TOBN(0x9f5966ab, 0xe4aa082b), TOBN(0x666ec8de, 0x350e966e), - TOBN(0x1bfd1ed5, 0xee524216), TOBN(0xcd93c59b, 0x41dab0b6), - TOBN(0x658a8435, 0xd186d6ba), TOBN(0x1b7d34d2, 0x159d1195), - TOBN(0x5936e460, 0x22caf46b), TOBN(0x6a45dd8f, 0x9a96fe4f), - TOBN(0xf7925434, 0xb98f474e), TOBN(0x41410412, 0x0053ef15), - TOBN(0x71cf8d12, 0x41de97bf), TOBN(0xb8547b61, 0xbd80bef4), - TOBN(0xb47d3970, 0xc4db0037), TOBN(0xf1bcd328, 0xfef20dff), - TOBN(0x31a92e09, 0x10caad67), TOBN(0x1f591960, 0x5531a1e1), - TOBN(0x3bb852e0, 0x5f4fc840), TOBN(0x63e297ca, 0x93a72c6c), - TOBN(0x3c2b0b2e, 0x49abad67), TOBN(0x6ec405fc, 0xed3db0d9), - TOBN(0xdc14a530, 0x7fef1d40), TOBN(0xccd19846, 0x280896fc), - TOBN(0x00f83176, 0x9bb81648), TOBN(0xd69eb485, 0x653120d0), - TOBN(0xd17d75f4, 0x4ccabc62), TOBN(0x34a07f82, 0xb749fcb1), - TOBN(0x2c3af787, 0xbbfb5554), TOBN(0xb06ed4d0, 0x62e283f8), - TOBN(0x5722889f, 0xa19213a0), TOBN(0x162b085e, 0xdcf3c7b4), - TOBN(0xbcaecb31, 0xe0dd3eca), TOBN(0xc6237fbc, 0xe52f13a5), - TOBN(0xcc2b6b03, 0x27bac297), TOBN(0x2ae1cac5, 0xb917f54a), - TOBN(0x474807d4, 0x7845ae4f), TOBN(0xfec7dd92, 0xce5972e0), - TOBN(0xc3bd2541, 0x1d7915bb), TOBN(0x66f85dc4, 0xd94907ca), - TOBN(0xd981b888, 0xbdbcf0ca), TOBN(0xd75f5da6, 0xdf279e9f), - TOBN(0x128bbf24, 0x7054e934), TOBN(0x3c6ff6e5, 0x81db134b), - TOBN(0x795b7cf4, 0x047d26e4), TOBN(0xf370f7b8, 0x5049ec37), - TOBN(0xc6712d4d, 0xced945af), TOBN(0xdf30b5ec, 0x095642bc), - TOBN(0x9b034c62, 0x4896246e), TOBN(0x5652c016, 0xee90bbd1), - TOBN(0xeb38636f, 0x87fedb73), TOBN(0x5e32f847, 0x0135a613), - TOBN(0x0703b312, 0xcf933c83), TOBN(0xd05bb76e, 0x1a7f47e6), - TOBN(0x825e4f0c, 0x949c2415), TOBN(0x569e5622, 0x7250d6f8), - TOBN(0xbbe9eb3a, 0x6568013e), TOBN(0x8dbd203f, 0x22f243fc), - TOBN(0x9dbd7694, 0xb342734a), TOBN(0x8f6d12f8, 0x46afa984), - TOBN(0xb98610a2, 0xc9eade29), TOBN(0xbab4f323, 0x47dd0f18), - TOBN(0x5779737b, 0x671c0d46), TOBN(0x10b6a7c6, 0xd3e0a42a), - TOBN(0xfb19ddf3, 0x3035b41c), TOBN(0xd336343f, 0x99c45895), - TOBN(0x61fe4938, 0x54c857e5), TOBN(0xc4d506be, 0xae4e57d5), - TOBN(0x3cd8c8cb, 0xbbc33f75), TOBN(0x7281f08a, 0x9262c77d), - TOBN(0x083f4ea6, 0xf11a2823), TOBN(0x8895041e, 0x9fba2e33), - TOBN(0xfcdfea49, 0x9c438edf), TOBN(0x7678dcc3, 0x91edba44), - TOBN(0xf07b3b87, 0xe2ba50f0), TOBN(0xc13888ef, 0x43948c1b), - TOBN(0xc2135ad4, 0x1140af42), TOBN(0x8e5104f3, 0x926ed1a7), - TOBN(0xf24430cb, 0x88f6695f), TOBN(0x0ce0637b, 0x6d73c120), - TOBN(0xb2db01e6, 0xfe631e8f), TOBN(0x1c5563d7, 0xd7bdd24b), - TOBN(0x8daea3ba, 0x369ad44f), TOBN(0x000c81b6, 0x8187a9f9), - TOBN(0x5f48a951, 0xaae1fd9a), TOBN(0xe35626c7, 0x8d5aed8a), - TOBN(0x20952763, 0x0498c622), TOBN(0x76d17634, 0x773aa504), - TOBN(0x36d90dda, 0xeb300f7a), TOBN(0x9dcf7dfc, 0xedb5e801), - TOBN(0x645cb268, 0x74d5244c), TOBN(0xa127ee79, 0x348e3aa2), - TOBN(0x488acc53, 0x575f1dbb), TOBN(0x95037e85, 0x80e6161e), - TOBN(0x57e59283, 0x292650d0), TOBN(0xabe67d99, 0x14938216), - TOBN(0x3c7f944b, 0x3f8e1065), TOBN(0xed908cb6, 0x330e8924), - TOBN(0x08ee8fd5, 0x6f530136), TOBN(0x2227b7d5, 0xd7ffc169), - TOBN(0x4f55c893, 0xb5cd6dd5), TOBN(0x82225e11, 0xa62796e8), - TOBN(0x5c6cead1, 0xcb18e12c), TOBN(0x4381ae0c, 0x84f5a51a), - TOBN(0x345913d3, 0x7fafa4c8), TOBN(0x3d918082, 0x0491aac0), - TOBN(0x9347871f, 0x3e69264c), TOBN(0xbea9dd3c, 0xb4f4f0cd), - TOBN(0xbda5d067, 0x3eadd3e7), TOBN(0x0033c1b8, 0x0573bcd8), - TOBN(0x25589379, 0x5da2486c), TOBN(0xcb89ee5b, 0x86abbee7), - TOBN(0x8fe0a8f3, 0x22532e5d), TOBN(0xb6410ff0, 0x727dfc4c), - TOBN(0x619b9d58, 0x226726db), TOBN(0x5ec25669, 0x7a2b2dc7), - TOBN(0xaf4d2e06, 0x4c3beb01), TOBN(0x852123d0, 0x7acea556), - TOBN(0x0e9470fa, 0xf783487a), TOBN(0x75a7ea04, 0x5664b3eb), - TOBN(0x4ad78f35, 0x6798e4ba), TOBN(0x9214e6e5, 0xc7d0e091), - TOBN(0xc420b488, 0xb1290403), TOBN(0x64049e0a, 0xfc295749), - TOBN(0x03ef5af1, 0x3ae9841f), TOBN(0xdbe4ca19, 0xb0b662a6), - TOBN(0x46845c5f, 0xfa453458), TOBN(0xf8dabf19, 0x10b66722), - TOBN(0xb650f0aa, 0xcce2793b), TOBN(0x71db851e, 0xc5ec47c1), - TOBN(0x3eb78f3e, 0x3b234fa9), TOBN(0xb0c60f35, 0xfc0106ce), - TOBN(0x05427121, 0x774eadbd), TOBN(0x25367faf, 0xce323863), - TOBN(0x7541b5c9, 0xcd086976), TOBN(0x4ff069e2, 0xdc507ad1), - TOBN(0x74145256, 0x8776e667), TOBN(0x6e76142c, 0xb23c6bb5), - TOBN(0xdbf30712, 0x1b3a8a87), TOBN(0x60e7363e, 0x98450836), - TOBN(0x5741450e, 0xb7366d80), TOBN(0xe4ee14ca, 0x4837dbdf), - TOBN(0xa765eb9b, 0x69d4316f), TOBN(0x04548dca, 0x8ef43825), - TOBN(0x9c9f4e4c, 0x5ae888eb), TOBN(0x733abb51, 0x56e9ac99), - TOBN(0xdaad3c20, 0xba6ac029), TOBN(0x9b8dd3d3, 0x2ba3e38e), - TOBN(0xa9bb4c92, 0x0bc5d11a), TOBN(0xf20127a7, 0x9c5f88a3), - TOBN(0x4f52b06e, 0x161d3cb8), TOBN(0x26c1ff09, 0x6afaf0a6), - TOBN(0x32670d2f, 0x7189e71f), TOBN(0xc6438748, 0x5ecf91e7), - TOBN(0x15758e57, 0xdb757a21), TOBN(0x427d09f8, 0x290a9ce5), - TOBN(0x846a308f, 0x38384a7a), TOBN(0xaac3acb4, 0xb0732b99), - TOBN(0x9e941009, 0x17845819), TOBN(0x95cba111, 0xa7ce5e03), - TOBN(0x6f3d4f7f, 0xb00009c4), TOBN(0xb8396c27, 0x8ff28b5f), - TOBN(0xb1a9ae43, 0x1c97975d), TOBN(0x9d7ba8af, 0xe5d9fed5), - TOBN(0x338cf09f, 0x34f485b6), TOBN(0xbc0ddacc, 0x64122516), - TOBN(0xa450da12, 0x05d471fe), TOBN(0x4c3a6250, 0x628dd8c9), - TOBN(0x69c7d103, 0xd1295837), TOBN(0xa2893e50, 0x3807eb2f), - TOBN(0xd6e1e1de, 0xbdb41491), TOBN(0xc630745b, 0x5e138235), - TOBN(0xc892109e, 0x48661ae1), TOBN(0x8d17e7eb, 0xea2b2674), - TOBN(0x00ec0f87, 0xc328d6b5), TOBN(0x6d858645, 0xf079ff9e), - TOBN(0x6cdf243e, 0x19115ead), TOBN(0x1ce1393e, 0x4bac4fcf), - TOBN(0x2c960ed0, 0x9c29f25b), TOBN(0x59be4d8e, 0x9d388a05), - TOBN(0x0d46e06c, 0xd0def72b), TOBN(0xb923db5d, 0xe0342748), - TOBN(0xf7d3aacd, 0x936d4a3d), TOBN(0x558519cc, 0x0b0b099e), - TOBN(0x3ea8ebf8, 0x827097ef), TOBN(0x259353db, 0xd054f55d), - TOBN(0x84c89abc, 0x6d2ed089), TOBN(0x5c548b69, 0x8e096a7c), - TOBN(0xd587f616, 0x994b995d), TOBN(0x4d1531f6, 0xa5845601), - TOBN(0x792ab31e, 0x451fd9f0), TOBN(0xc8b57bb2, 0x65adf6ca), - TOBN(0x68440fcb, 0x1cd5ad73), TOBN(0xb9c860e6, 0x6144da4f), - TOBN(0x2ab286aa, 0x8462beb8), TOBN(0xcc6b8fff, 0xef46797f), - TOBN(0xac820da4, 0x20c8a471), TOBN(0x69ae05a1, 0x77ff7faf), - TOBN(0xb9163f39, 0xbfb5da77), TOBN(0xbd03e590, 0x2c73ab7a), - TOBN(0x7e862b5e, 0xb2940d9e), TOBN(0x3c663d86, 0x4b9af564), - TOBN(0xd8309031, 0xbde3033d), TOBN(0x298231b2, 0xd42c5bc6), - TOBN(0x42090d2c, 0x552ad093), TOBN(0xa4799d1c, 0xff854695), - TOBN(0x0a88b5d6, 0xd31f0d00), TOBN(0xf8b40825, 0xa2f26b46), - TOBN(0xec29b1ed, 0xf1bd7218), TOBN(0xd491c53b, 0x4b24c86e), - TOBN(0xd2fe588f, 0x3395ea65), TOBN(0x6f3764f7, 0x4456ef15), - TOBN(0xdb43116d, 0xcdc34800), TOBN(0xcdbcd456, 0xc1e33955), - TOBN(0xefdb5540, 0x74ab286b), TOBN(0x948c7a51, 0xd18c5d7c), - TOBN(0xeb81aa37, 0x7378058e), TOBN(0x41c746a1, 0x04411154), - TOBN(0xa10c73bc, 0xfb828ac7), TOBN(0x6439be91, 0x9d972b29), - TOBN(0x4bf3b4b0, 0x43a2fbad), TOBN(0x39e6dadf, 0x82b5e840), - TOBN(0x4f716408, 0x6397bd4c), TOBN(0x0f7de568, 0x7f1eeccb), - TOBN(0x5865c5a1, 0xd2ffbfc1), TOBN(0xf74211fa, 0x4ccb6451), - TOBN(0x66368a88, 0xc0b32558), TOBN(0x5b539dc2, 0x9ad7812e), - TOBN(0x579483d0, 0x2f3af6f6), TOBN(0x52132078, 0x99934ece), - TOBN(0x50b9650f, 0xdcc9e983), TOBN(0xca989ec9, 0xaee42b8a), - TOBN(0x6a44c829, 0xd6f62f99), TOBN(0x8f06a309, 0x4c2a7c0c), - TOBN(0x4ea2b3a0, 0x98a0cb0a), TOBN(0x5c547b70, 0xbeee8364), - TOBN(0x461d40e1, 0x682afe11), TOBN(0x9e0fc77a, 0x7b41c0a8), - TOBN(0x79e4aefd, 0xe20d5d36), TOBN(0x2916e520, 0x32dd9f63), - TOBN(0xf59e52e8, 0x3f883faf), TOBN(0x396f9639, 0x2b868d35), - TOBN(0xc902a9df, 0x4ca19881), TOBN(0x0fc96822, 0xdb2401a6), - TOBN(0x41237587, 0x66f1c68d), TOBN(0x10fc6de3, 0xfb476c0d), - TOBN(0xf8b6b579, 0x841f5d90), TOBN(0x2ba8446c, 0xfa24f44a), - TOBN(0xa237b920, 0xef4a9975), TOBN(0x60bb6004, 0x2330435f), - TOBN(0xd6f4ab5a, 0xcfb7e7b5), TOBN(0xb2ac5097, 0x83435391), - TOBN(0xf036ee2f, 0xb0d1ea67), TOBN(0xae779a6a, 0x74c56230), - TOBN(0x59bff8c8, 0xab838ae6), TOBN(0xcd83ca99, 0x9b38e6f0), - TOBN(0xbb27bef5, 0xe33deed3), TOBN(0xe6356f6f, 0x001892a8), - TOBN(0xbf3be6cc, 0x7adfbd3e), TOBN(0xaecbc81c, 0x33d1ac9d), - TOBN(0xe4feb909, 0xe6e861dc), TOBN(0x90a247a4, 0x53f5f801), - TOBN(0x01c50acb, 0x27346e57), TOBN(0xce29242e, 0x461acc1b), - TOBN(0x04dd214a, 0x2f998a91), TOBN(0x271ee9b1, 0xd4baf27b), - TOBN(0x7e3027d1, 0xe8c26722), TOBN(0x21d1645c, 0x1820dce5), - TOBN(0x086f242c, 0x7501779c), TOBN(0xf0061407, 0xfa0e8009), - TOBN(0xf23ce477, 0x60187129), TOBN(0x05bbdedb, 0x0fde9bd0), - TOBN(0x682f4832, 0x25d98473), TOBN(0xf207fe85, 0x5c658427), - TOBN(0xb6fdd7ba, 0x4166ffa1), TOBN(0x0c314056, 0x9eed799d), - TOBN(0x0db8048f, 0x4107e28f), TOBN(0x74ed3871, 0x41216840), - TOBN(0x74489f8f, 0x56a3c06e), TOBN(0x1e1c005b, 0x12777134), - TOBN(0xdb332a73, 0xf37ec3c3), TOBN(0xc65259bd, 0xdd59eba0), - TOBN(0x2291709c, 0xdb4d3257), TOBN(0x9a793b25, 0xbd389390), - TOBN(0xf39fe34b, 0xe43756f0), TOBN(0x2f76bdce, 0x9afb56c9), - TOBN(0x9f37867a, 0x61208b27), TOBN(0xea1d4307, 0x089972c3), - TOBN(0x8c595330, 0x8bdf623a), TOBN(0x5f5accda, 0x8441fb7d), - TOBN(0xfafa9418, 0x32ddfd95), TOBN(0x6ad40c5a, 0x0fde9be7), - TOBN(0x43faba89, 0xaeca8709), TOBN(0xc64a7cf1, 0x2c248a9d), - TOBN(0x16620252, 0x72637a76), TOBN(0xaee1c791, 0x22b8d1bb), - TOBN(0xf0f798fd, 0x21a843b2), TOBN(0x56e4ed4d, 0x8d005cb1), - TOBN(0x355f7780, 0x1f0d8abe), TOBN(0x197b04cf, 0x34522326), - TOBN(0x41f9b31f, 0xfd42c13f), TOBN(0x5ef7feb2, 0xb40f933d), - TOBN(0x27326f42, 0x5d60bad4), TOBN(0x027ecdb2, 0x8c92cf89), - TOBN(0x04aae4d1, 0x4e3352fe), TOBN(0x08414d2f, 0x73591b90), - TOBN(0x5ed6124e, 0xb7da7d60), TOBN(0xb985b931, 0x4d13d4ec), - TOBN(0xa592d3ab, 0x96bf36f9), TOBN(0x012dbed5, 0xbbdf51df), - TOBN(0xa57963c0, 0xdf6c177d), TOBN(0x010ec869, 0x87ca29cf), - TOBN(0xba1700f6, 0xbf926dff), TOBN(0x7c9fdbd1, 0xf4bf6bc2), - TOBN(0xdc18dc8f, 0x64da11f5), TOBN(0xa6074b7a, 0xd938ae75), - TOBN(0x14270066, 0xe84f44a4), TOBN(0x99998d38, 0xd27b954e), - TOBN(0xc1be8ab2, 0xb4f38e9a), TOBN(0x8bb55bbf, 0x15c01016), - TOBN(0xf73472b4, 0x0ea2ab30), TOBN(0xd365a340, 0xf73d68dd), - TOBN(0xc01a7168, 0x19c2e1eb), TOBN(0x32f49e37, 0x34061719), - TOBN(0xb73c57f1, 0x01d8b4d6), TOBN(0x03c8423c, 0x26b47700), - TOBN(0x321d0bc8, 0xa4d8826a), TOBN(0x6004213c, 0x4bc0e638), - TOBN(0xf78c64a1, 0xc1c06681), TOBN(0x16e0a16f, 0xef018e50), - TOBN(0x31cbdf91, 0xdb42b2b3), TOBN(0xf8f4ffce, 0xe0d36f58), - TOBN(0xcdcc71cd, 0x4cc5e3e0), TOBN(0xd55c7cfa, 0xa129e3e0), - TOBN(0xccdb6ba0, 0x0fb2cbf1), TOBN(0x6aba0005, 0xc4bce3cb), - TOBN(0x501cdb30, 0xd232cfc4), TOBN(0x9ddcf12e, 0xd58a3cef), - TOBN(0x02d2cf9c, 0x87e09149), TOBN(0xdc5d7ec7, 0x2c976257), - TOBN(0x6447986e, 0x0b50d7dd), TOBN(0x88fdbaf7, 0x807f112a), - TOBN(0x58c9822a, 0xb00ae9f6), TOBN(0x6abfb950, 0x6d3d27e0), - TOBN(0xd0a74487, 0x8a429f4f), TOBN(0x0649712b, 0xdb516609), - TOBN(0xb826ba57, 0xe769b5df), TOBN(0x82335df2, 0x1fc7aaf2), - TOBN(0x2389f067, 0x5c93d995), TOBN(0x59ac367a, 0x68677be6), - TOBN(0xa77985ff, 0x21d9951b), TOBN(0x038956fb, 0x85011cce), - TOBN(0x608e48cb, 0xbb734e37), TOBN(0xc08c0bf2, 0x2be5b26f), - TOBN(0x17bbdd3b, 0xf9b1a0d9), TOBN(0xeac7d898, 0x10483319), - TOBN(0xc95c4baf, 0xbc1a6dea), TOBN(0xfdd0e2bf, 0x172aafdb), - TOBN(0x40373cbc, 0x8235c41a), TOBN(0x14303f21, 0xfb6f41d5), - TOBN(0xba063621, 0x0408f237), TOBN(0xcad3b09a, 0xecd2d1ed), - TOBN(0x4667855a, 0x52abb6a2), TOBN(0xba9157dc, 0xaa8b417b), - TOBN(0xfe7f3507, 0x4f013efb), TOBN(0x1b112c4b, 0xaa38c4a2), - TOBN(0xa1406a60, 0x9ba64345), TOBN(0xe53cba33, 0x6993c80b), - TOBN(0x45466063, 0xded40d23), TOBN(0x3d5f1f4d, 0x54908e25), - TOBN(0x9ebefe62, 0x403c3c31), TOBN(0x274ea0b5, 0x0672a624), - TOBN(0xff818d99, 0x451d1b71), TOBN(0x80e82643, 0x8f79cf79), - TOBN(0xa165df13, 0x73ce37f5), TOBN(0xa744ef4f, 0xfe3a21fd), - TOBN(0x73f1e7f5, 0xcf551396), TOBN(0xc616898e, 0x868c676b), - TOBN(0x671c28c7, 0x8c442c36), TOBN(0xcfe5e558, 0x5e0a317d), - TOBN(0x1242d818, 0x7051f476), TOBN(0x56fad2a6, 0x14f03442), - TOBN(0x262068bc, 0x0a44d0f6), TOBN(0xdfa2cd6e, 0xce6edf4e), - TOBN(0x0f43813a, 0xd15d1517), TOBN(0x61214cb2, 0x377d44f5), - TOBN(0xd399aa29, 0xc639b35f), TOBN(0x42136d71, 0x54c51c19), - TOBN(0x9774711b, 0x08417221), TOBN(0x0a5546b3, 0x52545a57), - TOBN(0x80624c41, 0x1150582d), TOBN(0x9ec5c418, 0xfbc555bc), - TOBN(0x2c87dcad, 0x771849f1), TOBN(0xb0c932c5, 0x01d7bf6f), - TOBN(0x6aa5cd3e, 0x89116eb2), TOBN(0xd378c25a, 0x51ca7bd3), - TOBN(0xc612a0da, 0x9e6e3e31), TOBN(0x0417a54d, 0xb68ad5d0), - TOBN(0x00451e4a, 0x22c6edb8), TOBN(0x9fbfe019, 0xb42827ce), - TOBN(0x2fa92505, 0xba9384a2), TOBN(0x21b8596e, 0x64ad69c1), - TOBN(0x8f4fcc49, 0x983b35a6), TOBN(0xde093760, 0x72754672), - TOBN(0x2f14ccc8, 0xf7bffe6d), TOBN(0x27566bff, 0x5d94263d), - TOBN(0xb5b4e9c6, 0x2df3ec30), TOBN(0x94f1d7d5, 0x3e6ea6ba), - TOBN(0x97b7851a, 0xaaca5e9b), TOBN(0x518aa521, 0x56713b97), - TOBN(0x3357e8c7, 0x150a61f6), TOBN(0x7842e7e2, 0xec2c2b69), - TOBN(0x8dffaf65, 0x6868a548), TOBN(0xd963bd82, 0xe068fc81), - TOBN(0x64da5c8b, 0x65917733), TOBN(0x927090ff, 0x7b247328), - }, - { - TOBN(0x214bc9a7, 0xd298c241), TOBN(0xe3b697ba, 0x56807cfd), - TOBN(0xef1c7802, 0x4564eadb), TOBN(0xdde8cdcf, 0xb48149c5), - TOBN(0x946bf0a7, 0x5a4d2604), TOBN(0x27154d7f, 0x6c1538af), - TOBN(0x95cc9230, 0xde5b1fcc), TOBN(0xd88519e9, 0x66864f82), - TOBN(0xb828dd1a, 0x7cb1282c), TOBN(0xa08d7626, 0xbe46973a), - TOBN(0x6baf8d40, 0xe708d6b2), TOBN(0x72571fa1, 0x4daeb3f3), - TOBN(0x85b1732f, 0xf22dfd98), TOBN(0x87ab01a7, 0x0087108d), - TOBN(0xaaaafea8, 0x5988207a), TOBN(0xccc832f8, 0x69f00755), - TOBN(0x964d950e, 0x36ff3bf0), TOBN(0x8ad20f6f, 0xf0b34638), - TOBN(0x4d9177b3, 0xb5d7585f), TOBN(0xcf839760, 0xef3f019f), - TOBN(0x582fc5b3, 0x8288c545), TOBN(0x2f8e4e9b, 0x13116bd1), - TOBN(0xf91e1b2f, 0x332120ef), TOBN(0xcf568724, 0x2a17dd23), - TOBN(0x488f1185, 0xca8d9d1a), TOBN(0xadf2c77d, 0xd987ded2), - TOBN(0x5f3039f0, 0x60c46124), TOBN(0xe5d70b75, 0x71e095f4), - TOBN(0x82d58650, 0x6260e70f), TOBN(0x39d75ea7, 0xf750d105), - TOBN(0x8cf3d0b1, 0x75bac364), TOBN(0xf3a7564d, 0x21d01329), - TOBN(0x182f04cd, 0x2f52d2a7), TOBN(0x4fde149a, 0xe2df565a), - TOBN(0xb80c5eec, 0xa79fb2f7), TOBN(0xab491d7b, 0x22ddc897), - TOBN(0x99d76c18, 0xc6312c7f), TOBN(0xca0d5f3d, 0x6aa41a57), - TOBN(0x71207325, 0xd15363a0), TOBN(0xe82aa265, 0xbeb252c2), - TOBN(0x94ab4700, 0xec3128c2), TOBN(0x6c76d862, 0x8e383f49), - TOBN(0xdc36b150, 0xc03024eb), TOBN(0xfb439477, 0x53daac69), - TOBN(0xfc68764a, 0x8dc79623), TOBN(0x5b86995d, 0xb440fbb2), - TOBN(0xd66879bf, 0xccc5ee0d), TOBN(0x05228942, 0x95aa8bd3), - TOBN(0xb51a40a5, 0x1e6a75c1), TOBN(0x24327c76, 0x0ea7d817), - TOBN(0x06630182, 0x07774597), TOBN(0xd6fdbec3, 0x97fa7164), - TOBN(0x20c99dfb, 0x13c90f48), TOBN(0xd6ac5273, 0x686ef263), - TOBN(0xc6a50bdc, 0xfef64eeb), TOBN(0xcd87b281, 0x86fdfc32), - TOBN(0xb24aa43e, 0x3fcd3efc), TOBN(0xdd26c034, 0xb8088e9a), - TOBN(0xa5ef4dc9, 0xbd3d46ea), TOBN(0xa2f99d58, 0x8a4c6a6f), - TOBN(0xddabd355, 0x2f1da46c), TOBN(0x72c3f8ce, 0x1afacdd1), - TOBN(0xd90c4eee, 0x92d40578), TOBN(0xd28bb41f, 0xca623b94), - TOBN(0x50fc0711, 0x745edc11), TOBN(0x9dd9ad7d, 0x3dc87558), - TOBN(0xce6931fb, 0xb49d1e64), TOBN(0x6c77a0a2, 0xc98bd0f9), - TOBN(0x62b9a629, 0x6baf7cb1), TOBN(0xcf065f91, 0xccf72d22), - TOBN(0x7203cce9, 0x79639071), TOBN(0x09ae4885, 0xf9cb732f), - TOBN(0x5e7c3bec, 0xee8314f3), TOBN(0x1c068aed, 0xdbea298f), - TOBN(0x08d381f1, 0x7c80acec), TOBN(0x03b56be8, 0xe330495b), - TOBN(0xaeffb8f2, 0x9222882d), TOBN(0x95ff38f6, 0xc4af8bf7), - TOBN(0x50e32d35, 0x1fc57d8c), TOBN(0x6635be52, 0x17b444f0), - TOBN(0x04d15276, 0xa5177900), TOBN(0x4e1dbb47, 0xf6858752), - TOBN(0x5b475622, 0xc615796c), TOBN(0xa6fa0387, 0x691867bf), - TOBN(0xed7f5d56, 0x2844c6d0), TOBN(0xc633cf9b, 0x03a2477d), - TOBN(0xf6be5c40, 0x2d3721d6), TOBN(0xaf312eb7, 0xe9fd68e6), - TOBN(0x242792d2, 0xe7417ce1), TOBN(0xff42bc71, 0x970ee7f5), - TOBN(0x1ff4dc6d, 0x5c67a41e), TOBN(0x77709b7b, 0x20882a58), - TOBN(0x3554731d, 0xbe217f2c), TOBN(0x2af2a8cd, 0x5bb72177), - TOBN(0x58eee769, 0x591dd059), TOBN(0xbb2930c9, 0x4bba6477), - TOBN(0x863ee047, 0x7d930cfc), TOBN(0x4c262ad1, 0x396fd1f4), - TOBN(0xf4765bc8, 0x039af7e1), TOBN(0x2519834b, 0x5ba104f6), - TOBN(0x7cd61b4c, 0xd105f961), TOBN(0xa5415da5, 0xd63bca54), - TOBN(0x778280a0, 0x88a1f17c), TOBN(0xc4968949, 0x2329512c), - TOBN(0x174a9126, 0xcecdaa7a), TOBN(0xfc8c7e0e, 0x0b13247b), - TOBN(0x29c110d2, 0x3484c1c4), TOBN(0xf8eb8757, 0x831dfc3b), - TOBN(0x022f0212, 0xc0067452), TOBN(0x3f6f69ee, 0x7b9b926c), - TOBN(0x09032da0, 0xef42daf4), TOBN(0x79f00ade, 0x83f80de4), - TOBN(0x6210db71, 0x81236c97), TOBN(0x74f7685b, 0x3ee0781f), - TOBN(0x4df7da7b, 0xa3e41372), TOBN(0x2aae38b1, 0xb1a1553e), - TOBN(0x1688e222, 0xf6dd9d1b), TOBN(0x57695448, 0x5b8b6487), - TOBN(0x478d2127, 0x4b2edeaa), TOBN(0xb2818fa5, 0x1e85956a), - TOBN(0x1e6addda, 0xf176f2c0), TOBN(0x01ca4604, 0xe2572658), - TOBN(0x0a404ded, 0x85342ffb), TOBN(0x8cf60f96, 0x441838d6), - TOBN(0x9bbc691c, 0xc9071c4a), TOBN(0xfd588744, 0x34442803), - TOBN(0x97101c85, 0x809c0d81), TOBN(0xa7fb754c, 0x8c456f7f), - TOBN(0xc95f3c5c, 0xd51805e1), TOBN(0xab4ccd39, 0xb299dca8), - TOBN(0x3e03d20b, 0x47eaf500), TOBN(0xfa3165c1, 0xd7b80893), - TOBN(0x005e8b54, 0xe160e552), TOBN(0xdc4972ba, 0x9019d11f), - TOBN(0x21a6972e, 0x0c9a4a7a), TOBN(0xa52c258f, 0x37840fd7), - TOBN(0xf8559ff4, 0xc1e99d81), TOBN(0x08e1a7d6, 0xa3c617c0), - TOBN(0xb398fd43, 0x248c6ba7), TOBN(0x6ffedd91, 0xd1283794), - TOBN(0x8a6a59d2, 0xd629d208), TOBN(0xa9d141d5, 0x3490530e), - TOBN(0x42f6fc18, 0x38505989), TOBN(0x09bf250d, 0x479d94ee), - TOBN(0x223ad3b1, 0xb3822790), TOBN(0x6c5926c0, 0x93b8971c), - TOBN(0x609efc7e, 0x75f7fa62), TOBN(0x45d66a6d, 0x1ec2d989), - TOBN(0x4422d663, 0x987d2792), TOBN(0x4a73caad, 0x3eb31d2b), - TOBN(0xf06c2ac1, 0xa32cb9e6), TOBN(0xd9445c5f, 0x91aeba84), - TOBN(0x6af7a1d5, 0xaf71013f), TOBN(0xe68216e5, 0x0bedc946), - TOBN(0xf4cba30b, 0xd27370a0), TOBN(0x7981afbf, 0x870421cc), - TOBN(0x02496a67, 0x9449f0e1), TOBN(0x86cfc4be, 0x0a47edae), - TOBN(0x3073c936, 0xb1feca22), TOBN(0xf5694612, 0x03f8f8fb), - TOBN(0xd063b723, 0x901515ea), TOBN(0x4c6c77a5, 0x749cf038), - TOBN(0x6361e360, 0xab9e5059), TOBN(0x596cf171, 0xa76a37c0), - TOBN(0x800f53fa, 0x6530ae7a), TOBN(0x0f5e631e, 0x0792a7a6), - TOBN(0x5cc29c24, 0xefdb81c9), TOBN(0xa269e868, 0x3f9c40ba), - TOBN(0xec14f9e1, 0x2cb7191e), TOBN(0x78ea1bd8, 0xe5b08ea6), - TOBN(0x3c65aa9b, 0x46332bb9), TOBN(0x84cc22b3, 0xbf80ce25), - TOBN(0x0098e9e9, 0xd49d5bf1), TOBN(0xcd4ec1c6, 0x19087da4), - TOBN(0x3c9d07c5, 0xaef6e357), TOBN(0x839a0268, 0x9f8f64b8), - TOBN(0xc5e9eb62, 0xc6d8607f), TOBN(0x759689f5, 0x6aa995e4), - TOBN(0x70464669, 0xbbb48317), TOBN(0x921474bf, 0xe402417d), - TOBN(0xcabe135b, 0x2a354c8c), TOBN(0xd51e52d2, 0x812fa4b5), - TOBN(0xec741096, 0x53311fe8), TOBN(0x4f774535, 0xb864514b), - TOBN(0xbcadd671, 0x5bde48f8), TOBN(0xc9703873, 0x2189bc7d), - TOBN(0x5d45299e, 0xc709ee8a), TOBN(0xd1287ee2, 0x845aaff8), - TOBN(0x7d1f8874, 0xdb1dbf1f), TOBN(0xea46588b, 0x990c88d6), - TOBN(0x60ba649a, 0x84368313), TOBN(0xd5fdcbce, 0x60d543ae), - TOBN(0x90b46d43, 0x810d5ab0), TOBN(0x6739d8f9, 0x04d7e5cc), - TOBN(0x021c1a58, 0x0d337c33), TOBN(0x00a61162, 0x68e67c40), - TOBN(0x95ef413b, 0x379f0a1f), TOBN(0xfe126605, 0xe9e2ab95), - TOBN(0x67578b85, 0x2f5f199c), TOBN(0xf5c00329, 0x2cb84913), - TOBN(0xf7956430, 0x37577dd8), TOBN(0x83b82af4, 0x29c5fe88), - TOBN(0x9c1bea26, 0xcdbdc132), TOBN(0x589fa086, 0x9c04339e), - TOBN(0x033e9538, 0xb13799df), TOBN(0x85fa8b21, 0xd295d034), - TOBN(0xdf17f73f, 0xbd9ddcca), TOBN(0xf32bd122, 0xddb66334), - TOBN(0x55ef88a7, 0x858b044c), TOBN(0x1f0d69c2, 0x5aa9e397), - TOBN(0x55fd9cc3, 0x40d85559), TOBN(0xc774df72, 0x7785ddb2), - TOBN(0x5dcce9f6, 0xd3bd2e1c), TOBN(0xeb30da20, 0xa85dfed0), - TOBN(0x5ed7f5bb, 0xd3ed09c4), TOBN(0x7d42a35c, 0x82a9c1bd), - TOBN(0xcf3de995, 0x9890272d), TOBN(0x75f3432a, 0x3e713a10), - TOBN(0x5e13479f, 0xe28227b8), TOBN(0xb8561ea9, 0xfefacdc8), - TOBN(0xa6a297a0, 0x8332aafd), TOBN(0x9b0d8bb5, 0x73809b62), - TOBN(0xd2fa1cfd, 0x0c63036f), TOBN(0x7a16eb55, 0xbd64bda8), - TOBN(0x3f5cf5f6, 0x78e62ddc), TOBN(0x2267c454, 0x07fd752b), - TOBN(0x5e361b6b, 0x5e437bbe), TOBN(0x95c59501, 0x8354e075), - TOBN(0xec725f85, 0xf2b254d9), TOBN(0x844b617d, 0x2cb52b4e), - TOBN(0xed8554f5, 0xcf425fb5), TOBN(0xab67703e, 0x2af9f312), - TOBN(0x4cc34ec1, 0x3cf48283), TOBN(0xb09daa25, 0x9c8a705e), - TOBN(0xd1e9d0d0, 0x5b7d4f84), TOBN(0x4df6ef64, 0xdb38929d), - TOBN(0xe16b0763, 0xaa21ba46), TOBN(0xc6b1d178, 0xa293f8fb), - TOBN(0x0ff5b602, 0xd520aabf), TOBN(0x94d671bd, 0xc339397a), - TOBN(0x7c7d98cf, 0x4f5792fa), TOBN(0x7c5e0d67, 0x11215261), - TOBN(0x9b19a631, 0xa7c5a6d4), TOBN(0xc8511a62, 0x7a45274d), - TOBN(0x0c16621c, 0xa5a60d99), TOBN(0xf7fbab88, 0xcf5e48cb), - TOBN(0xab1e6ca2, 0xf7ddee08), TOBN(0x83bd08ce, 0xe7867f3c), - TOBN(0xf7e48e8a, 0x2ac13e27), TOBN(0x4494f6df, 0x4eb1a9f5), - TOBN(0xedbf84eb, 0x981f0a62), TOBN(0x49badc32, 0x536438f0), - TOBN(0x50bea541, 0x004f7571), TOBN(0xbac67d10, 0xdf1c94ee), - TOBN(0x253d73a1, 0xb727bc31), TOBN(0xb3d01cf2, 0x30686e28), - TOBN(0x51b77b1b, 0x55fd0b8b), TOBN(0xa099d183, 0xfeec3173), - TOBN(0x202b1fb7, 0x670e72b7), TOBN(0xadc88b33, 0xa8e1635f), - TOBN(0x34e8216a, 0xf989d905), TOBN(0xc2e68d20, 0x29b58d01), - TOBN(0x11f81c92, 0x6fe55a93), TOBN(0x15f1462a, 0x8f296f40), - TOBN(0x1915d375, 0xea3d62f2), TOBN(0xa17765a3, 0x01c8977d), - TOBN(0x7559710a, 0xe47b26f6), TOBN(0xe0bd29c8, 0x535077a5), - TOBN(0x615f976d, 0x08d84858), TOBN(0x370dfe85, 0x69ced5c1), - TOBN(0xbbc7503c, 0xa734fa56), TOBN(0xfbb9f1ec, 0x91ac4574), - TOBN(0x95d7ec53, 0x060dd7ef), TOBN(0xeef2dacd, 0x6e657979), - TOBN(0x54511af3, 0xe2a08235), TOBN(0x1e324aa4, 0x1f4aea3d), - TOBN(0x550e7e71, 0xe6e67671), TOBN(0xbccd5190, 0xbf52faf7), - TOBN(0xf880d316, 0x223cc62a), TOBN(0x0d402c7e, 0x2b32eb5d), - TOBN(0xa40bc039, 0x306a5a3b), TOBN(0x4e0a41fd, 0x96783a1b), - TOBN(0xa1e8d39a, 0x0253cdd4), TOBN(0x6480be26, 0xc7388638), - TOBN(0xee365e1d, 0x2285f382), TOBN(0x188d8d8f, 0xec0b5c36), - TOBN(0x34ef1a48, 0x1f0f4d82), TOBN(0x1a8f43e1, 0xa487d29a), - TOBN(0x8168226d, 0x77aefb3a), TOBN(0xf69a751e, 0x1e72c253), - TOBN(0x8e04359a, 0xe9594df1), TOBN(0x475ffd7d, 0xd14c0467), - TOBN(0xb5a2c2b1, 0x3844e95c), TOBN(0x85caf647, 0xdd12ef94), - TOBN(0x1ecd2a9f, 0xf1063d00), TOBN(0x1dd2e229, 0x23843311), - TOBN(0x38f0e09d, 0x73d17244), TOBN(0x3ede7746, 0x8fc653f1), - TOBN(0xae4459f5, 0xdc20e21c), TOBN(0x00db2ffa, 0x6a8599ea), - TOBN(0x11682c39, 0x30cfd905), TOBN(0x4934d074, 0xa5c112a6), - TOBN(0xbdf063c5, 0x568bfe95), TOBN(0x779a440a, 0x016c441a), - TOBN(0x0c23f218, 0x97d6fbdc), TOBN(0xd3a5cd87, 0xe0776aac), - TOBN(0xcee37f72, 0xd712e8db), TOBN(0xfb28c70d, 0x26f74e8d), - TOBN(0xffe0c728, 0xb61301a0), TOBN(0xa6282168, 0xd3724354), - TOBN(0x7ff4cb00, 0x768ffedc), TOBN(0xc51b3088, 0x03b02de9), - TOBN(0xa5a8147c, 0x3902dda5), TOBN(0x35d2f706, 0xfe6973b4), - TOBN(0x5ac2efcf, 0xc257457e), TOBN(0x933f48d4, 0x8700611b), - TOBN(0xc365af88, 0x4912beb2), TOBN(0x7f5a4de6, 0x162edf94), - TOBN(0xc646ba7c, 0x0c32f34b), TOBN(0x632c6af3, 0xb2091074), - TOBN(0x58d4f2e3, 0x753e43a9), TOBN(0x70e1d217, 0x24d4e23f), - TOBN(0xb24bf729, 0xafede6a6), TOBN(0x7f4a94d8, 0x710c8b60), - TOBN(0xaad90a96, 0x8d4faa6a), TOBN(0xd9ed0b32, 0xb066b690), - TOBN(0x52fcd37b, 0x78b6dbfd), TOBN(0x0b64615e, 0x8bd2b431), - TOBN(0x228e2048, 0xcfb9fad5), TOBN(0xbeaa386d, 0x240b76bd), - TOBN(0x2d6681c8, 0x90dad7bc), TOBN(0x3e553fc3, 0x06d38f5e), - TOBN(0xf27cdb9b, 0x9d5f9750), TOBN(0x3e85c52a, 0xd28c5b0e), - TOBN(0x190795af, 0x5247c39b), TOBN(0x547831eb, 0xbddd6828), - TOBN(0xf327a227, 0x4a82f424), TOBN(0x36919c78, 0x7e47f89d), - TOBN(0xe4783919, 0x43c7392c), TOBN(0xf101b9aa, 0x2316fefe), - TOBN(0xbcdc9e9c, 0x1c5009d2), TOBN(0xfb55ea13, 0x9cd18345), - TOBN(0xf5b5e231, 0xa3ce77c7), TOBN(0xde6b4527, 0xd2f2cb3d), - TOBN(0x10f6a333, 0x9bb26f5f), TOBN(0x1e85db8e, 0x044d85b6), - TOBN(0xc3697a08, 0x94197e54), TOBN(0x65e18cc0, 0xa7cb4ea8), - TOBN(0xa38c4f50, 0xa471fe6e), TOBN(0xf031747a, 0x2f13439c), - TOBN(0x53c4a6ba, 0xc007318b), TOBN(0xa8da3ee5, 0x1deccb3d), - TOBN(0x0555b31c, 0x558216b1), TOBN(0x90c7810c, 0x2f79e6c2), - TOBN(0x9b669f4d, 0xfe8eed3c), TOBN(0x70398ec8, 0xe0fac126), - TOBN(0xa96a449e, 0xf701b235), TOBN(0x0ceecdb3, 0xeb94f395), - TOBN(0x285fc368, 0xd0cb7431), TOBN(0x0d37bb52, 0x16a18c64), - TOBN(0x05110d38, 0xb880d2dd), TOBN(0xa60f177b, 0x65930d57), - TOBN(0x7da34a67, 0xf36235f5), TOBN(0x47f5e17c, 0x183816b9), - TOBN(0xc7664b57, 0xdb394af4), TOBN(0x39ba215d, 0x7036f789), - TOBN(0x46d2ca0e, 0x2f27b472), TOBN(0xc42647ee, 0xf73a84b7), - TOBN(0x44bc7545, 0x64488f1d), TOBN(0xaa922708, 0xf4cf85d5), - TOBN(0x721a01d5, 0x53e4df63), TOBN(0x649c0c51, 0x5db46ced), - TOBN(0x6bf0d64e, 0x3cffcb6c), TOBN(0xe3bf93fe, 0x50f71d96), - TOBN(0x75044558, 0xbcc194a0), TOBN(0x16ae3372, 0x6afdc554), - TOBN(0xbfc01adf, 0x5ca48f3f), TOBN(0x64352f06, 0xe22a9b84), - TOBN(0xcee54da1, 0xc1099e4a), TOBN(0xbbda54e8, 0xfa1b89c0), - TOBN(0x166a3df5, 0x6f6e55fb), TOBN(0x1ca44a24, 0x20176f88), - TOBN(0x936afd88, 0xdfb7b5ff), TOBN(0xe34c2437, 0x8611d4a0), - TOBN(0x7effbb75, 0x86142103), TOBN(0x6704ba1b, 0x1f34fc4d), - TOBN(0x7c2a468f, 0x10c1b122), TOBN(0x36b3a610, 0x8c6aace9), - TOBN(0xabfcc0a7, 0x75a0d050), TOBN(0x066f9197, 0x3ce33e32), - TOBN(0xce905ef4, 0x29fe09be), TOBN(0x89ee25ba, 0xa8376351), - TOBN(0x2a3ede22, 0xfd29dc76), TOBN(0x7fd32ed9, 0x36f17260), - TOBN(0x0cadcf68, 0x284b4126), TOBN(0x63422f08, 0xa7951fc8), - TOBN(0x562b24f4, 0x0807e199), TOBN(0xfe9ce5d1, 0x22ad4490), - TOBN(0xc2f51b10, 0x0db2b1b4), TOBN(0xeb3613ff, 0xe4541d0d), - TOBN(0xbd2c4a05, 0x2680813b), TOBN(0x527aa55d, 0x561b08d6), - TOBN(0xa9f8a40e, 0xa7205558), TOBN(0xe3eea56f, 0x243d0bec), - TOBN(0x7b853817, 0xa0ff58b3), TOBN(0xb67d3f65, 0x1a69e627), - TOBN(0x0b76bbb9, 0xa869b5d6), TOBN(0xa3afeb82, 0x546723ed), - TOBN(0x5f24416d, 0x3e554892), TOBN(0x8413b53d, 0x430e2a45), - TOBN(0x99c56aee, 0x9032a2a0), TOBN(0x09432bf6, 0xeec367b1), - TOBN(0x552850c6, 0xdaf0ecc1), TOBN(0x49ebce55, 0x5bc92048), - TOBN(0xdfb66ba6, 0x54811307), TOBN(0x1b84f797, 0x6f298597), - TOBN(0x79590481, 0x8d1d7a0d), TOBN(0xd9fabe03, 0x3a6fa556), - TOBN(0xa40f9c59, 0xba9e5d35), TOBN(0xcb1771c1, 0xf6247577), - TOBN(0x542a47ca, 0xe9a6312b), TOBN(0xa34b3560, 0x552dd8c5), - TOBN(0xfdf94de0, 0x0d794716), TOBN(0xd46124a9, 0x9c623094), - TOBN(0x56b7435d, 0x68afe8b4), TOBN(0x27f20540, 0x6c0d8ea1), - TOBN(0x12b77e14, 0x73186898), TOBN(0xdbc3dd46, 0x7479490f), - TOBN(0x951a9842, 0xc03b0c05), TOBN(0x8b1b3bb3, 0x7921bc96), - TOBN(0xa573b346, 0x2b202e0a), TOBN(0x77e4665d, 0x47254d56), - TOBN(0x08b70dfc, 0xd23e3984), TOBN(0xab86e8bc, 0xebd14236), - TOBN(0xaa3e07f8, 0x57114ba7), TOBN(0x5ac71689, 0xab0ef4f2), - TOBN(0x88fca384, 0x0139d9af), TOBN(0x72733f88, 0x76644af0), - TOBN(0xf122f72a, 0x65d74f4a), TOBN(0x13931577, 0xa5626c7a), - TOBN(0xd5b5d9eb, 0x70f8d5a4), TOBN(0x375adde7, 0xd7bbb228), - TOBN(0x31e88b86, 0x0c1c0b32), TOBN(0xd1f568c4, 0x173edbaa), - TOBN(0x1592fc83, 0x5459df02), TOBN(0x2beac0fb, 0x0fcd9a7e), - TOBN(0xb0a6fdb8, 0x1b473b0a), TOBN(0xe3224c6f, 0x0fe8fc48), - TOBN(0x680bd00e, 0xe87edf5b), TOBN(0x30385f02, 0x20e77cf5), - TOBN(0xe9ab98c0, 0x4d42d1b2), TOBN(0x72d191d2, 0xd3816d77), - TOBN(0x1564daca, 0x0917d9e5), TOBN(0x394eab59, 0x1f8fed7f), - TOBN(0xa209aa8d, 0x7fbb3896), TOBN(0x5564f3b9, 0xbe6ac98e), - TOBN(0xead21d05, 0xd73654ef), TOBN(0x68d1a9c4, 0x13d78d74), - TOBN(0x61e01708, 0x6d4973a0), TOBN(0x83da3500, 0x46e6d32a), - TOBN(0x6a3dfca4, 0x68ae0118), TOBN(0xa1b9a4c9, 0xd02da069), - TOBN(0x0b2ff9c7, 0xebab8302), TOBN(0x98af07c3, 0x944ba436), - TOBN(0x85997326, 0x995f0f9f), TOBN(0x467fade0, 0x71b58bc6), - TOBN(0x47e4495a, 0xbd625a2b), TOBN(0xfdd2d01d, 0x33c3b8cd), - TOBN(0x2c38ae28, 0xc693f9fa), TOBN(0x48622329, 0x348f7999), - TOBN(0x97bf738e, 0x2161f583), TOBN(0x15ee2fa7, 0x565e8cc9), - TOBN(0xa1a5c845, 0x5777e189), TOBN(0xcc10bee0, 0x456f2829), - TOBN(0x8ad95c56, 0xda762bd5), TOBN(0x152e2214, 0xe9d91da8), - TOBN(0x975b0e72, 0x7cb23c74), TOBN(0xfd5d7670, 0xa90c66df), - TOBN(0xb5b5b8ad, 0x225ffc53), TOBN(0xab6dff73, 0xfaded2ae), - TOBN(0xebd56781, 0x6f4cbe9d), TOBN(0x0ed8b249, 0x6a574bd7), - TOBN(0x41c246fe, 0x81a881fa), TOBN(0x91564805, 0xc3db9c70), - TOBN(0xd7c12b08, 0x5b862809), TOBN(0x1facd1f1, 0x55858d7b), - TOBN(0x7693747c, 0xaf09e92a), TOBN(0x3b69dcba, 0x189a425f), - TOBN(0x0be28e9f, 0x967365ef), TOBN(0x57300eb2, 0xe801f5c9), - TOBN(0x93b8ac6a, 0xd583352f), TOBN(0xa2cf1f89, 0xcd05b2b7), - TOBN(0x7c0c9b74, 0x4dcc40cc), TOBN(0xfee38c45, 0xada523fb), - TOBN(0xb49a4dec, 0x1099cc4d), TOBN(0x325c377f, 0x69f069c6), - TOBN(0xe12458ce, 0x476cc9ff), TOBN(0x580e0b6c, 0xc6d4cb63), - TOBN(0xd561c8b7, 0x9072289b), TOBN(0x0377f264, 0xa619e6da), - TOBN(0x26685362, 0x88e591a5), TOBN(0xa453a7bd, 0x7523ca2b), - TOBN(0x8a9536d2, 0xc1df4533), TOBN(0xc8e50f2f, 0xbe972f79), - TOBN(0xd433e50f, 0x6d3549cf), TOBN(0x6f33696f, 0xfacd665e), - TOBN(0x695bfdac, 0xce11fcb4), TOBN(0x810ee252, 0xaf7c9860), - TOBN(0x65450fe1, 0x7159bb2c), TOBN(0xf7dfbebe, 0x758b357b), - TOBN(0x2b057e74, 0xd69fea72), TOBN(0xd485717a, 0x92731745), - }, - { - TOBN(0x896c42e8, 0xee36860c), TOBN(0xdaf04dfd, 0x4113c22d), - TOBN(0x1adbb7b7, 0x44104213), TOBN(0xe5fd5fa1, 0x1fd394ea), - TOBN(0x68235d94, 0x1a4e0551), TOBN(0x6772cfbe, 0x18d10151), - TOBN(0x276071e3, 0x09984523), TOBN(0xe4e879de, 0x5a56ba98), - TOBN(0xaaafafb0, 0x285b9491), TOBN(0x01a0be88, 0x1e4c705e), - TOBN(0xff1d4f5d, 0x2ad9caab), TOBN(0x6e349a4a, 0xc37a233f), - TOBN(0xcf1c1246, 0x4a1c6a16), TOBN(0xd99e6b66, 0x29383260), - TOBN(0xea3d4366, 0x5f6d5471), TOBN(0x36974d04, 0xff8cc89b), - TOBN(0xc26c49a1, 0xcfe89d80), TOBN(0xb42c026d, 0xda9c8371), - TOBN(0xca6c013a, 0xdad066d2), TOBN(0xfb8f7228, 0x56a4f3ee), - TOBN(0x08b579ec, 0xd850935b), TOBN(0x34c1a74c, 0xd631e1b3), - TOBN(0xcb5fe596, 0xac198534), TOBN(0x39ff21f6, 0xe1f24f25), - TOBN(0x27f29e14, 0x8f929057), TOBN(0x7a64ae06, 0xc0c853df), - TOBN(0x256cd183, 0x58e9c5ce), TOBN(0x9d9cce82, 0xded092a5), - TOBN(0xcc6e5979, 0x6e93b7c7), TOBN(0xe1e47092, 0x31bb9e27), - TOBN(0xb70b3083, 0xaa9e29a0), TOBN(0xbf181a75, 0x3785e644), - TOBN(0xf53f2c65, 0x8ead09f7), TOBN(0x1335e1d5, 0x9780d14d), - TOBN(0x69cc20e0, 0xcd1b66bc), TOBN(0x9b670a37, 0xbbe0bfc8), - TOBN(0xce53dc81, 0x28efbeed), TOBN(0x0c74e77c, 0x8326a6e5), - TOBN(0x3604e0d2, 0xb88e9a63), TOBN(0xbab38fca, 0x13dc2248), - TOBN(0x8ed6e8c8, 0x5c0a3f1e), TOBN(0xbcad2492, 0x7c87c37f), - TOBN(0xfdfb62bb, 0x9ee3b78d), TOBN(0xeba8e477, 0xcbceba46), - TOBN(0x37d38cb0, 0xeeaede4b), TOBN(0x0bc498e8, 0x7976deb6), - TOBN(0xb2944c04, 0x6b6147fb), TOBN(0x8b123f35, 0xf71f9609), - TOBN(0xa155dcc7, 0xde79dc24), TOBN(0xf1168a32, 0x558f69cd), - TOBN(0xbac21595, 0x0d1850df), TOBN(0x15c8295b, 0xb204c848), - TOBN(0xf661aa36, 0x7d8184ff), TOBN(0xc396228e, 0x30447bdb), - TOBN(0x11cd5143, 0xbde4a59e), TOBN(0xe3a26e3b, 0x6beab5e6), - TOBN(0xd3b3a13f, 0x1402b9d0), TOBN(0x573441c3, 0x2c7bc863), - TOBN(0x4b301ec4, 0x578c3e6e), TOBN(0xc26fc9c4, 0x0adaf57e), - TOBN(0x96e71bfd, 0x7493cea3), TOBN(0xd05d4b3f, 0x1af81456), - TOBN(0xdaca2a8a, 0x6a8c608f), TOBN(0x53ef07f6, 0x0725b276), - TOBN(0x07a5fbd2, 0x7824fc56), TOBN(0x34675218, 0x13289077), - TOBN(0x5bf69fd5, 0xe0c48349), TOBN(0xa613ddd3, 0xb6aa7875), - TOBN(0x7f78c19c, 0x5450d866), TOBN(0x46f4409c, 0x8f84a481), - TOBN(0x9f1d1928, 0x90fce239), TOBN(0x016c4168, 0xb2ce44b9), - TOBN(0xbae023f0, 0xc7435978), TOBN(0xb152c888, 0x20e30e19), - TOBN(0x9c241645, 0xe3fa6faf), TOBN(0x735d95c1, 0x84823e60), - TOBN(0x03197573, 0x03955317), TOBN(0x0b4b02a9, 0xf03b4995), - TOBN(0x076bf559, 0x70274600), TOBN(0x32c5cc53, 0xaaf57508), - TOBN(0xe8af6d1f, 0x60624129), TOBN(0xb7bc5d64, 0x9a5e2b5e), - TOBN(0x3814b048, 0x5f082d72), TOBN(0x76f267f2, 0xce19677a), - TOBN(0x626c630f, 0xb36eed93), TOBN(0x55230cd7, 0x3bf56803), - TOBN(0x78837949, 0xce2736a0), TOBN(0x0d792d60, 0xaa6c55f1), - TOBN(0x0318dbfd, 0xd5c7c5d2), TOBN(0xb38f8da7, 0x072b342d), - TOBN(0x3569bddc, 0x7b8de38a), TOBN(0xf25b5887, 0xa1c94842), - TOBN(0xb2d5b284, 0x2946ad60), TOBN(0x854f29ad, 0xe9d1707e), - TOBN(0xaa5159dc, 0x2c6a4509), TOBN(0x899f94c0, 0x57189837), - TOBN(0xcf6adc51, 0xf4a55b03), TOBN(0x261762de, 0x35e3b2d5), - TOBN(0x4cc43012, 0x04827b51), TOBN(0xcd22a113, 0xc6021442), - TOBN(0xce2fd61a, 0x247c9569), TOBN(0x59a50973, 0xd152beca), - TOBN(0x6c835a11, 0x63a716d4), TOBN(0xc26455ed, 0x187dedcf), - TOBN(0x27f536e0, 0x49ce89e7), TOBN(0x18908539, 0xcc890cb5), - TOBN(0x308909ab, 0xd83c2aa1), TOBN(0xecd3142b, 0x1ab73bd3), - TOBN(0x6a85bf59, 0xb3f5ab84), TOBN(0x3c320a68, 0xf2bea4c6), - TOBN(0xad8dc538, 0x6da4541f), TOBN(0xeaf34eb0, 0xb7c41186), - TOBN(0x1c780129, 0x977c97c4), TOBN(0x5ff9beeb, 0xc57eb9fa), - TOBN(0xa24d0524, 0xc822c478), TOBN(0xfd8eec2a, 0x461cd415), - TOBN(0xfbde194e, 0xf027458c), TOBN(0xb4ff5319, 0x1d1be115), - TOBN(0x63f874d9, 0x4866d6f4), TOBN(0x35c75015, 0xb21ad0c9), - TOBN(0xa6b5c9d6, 0x46ac49d2), TOBN(0x42c77c0b, 0x83137aa9), - TOBN(0x24d000fc, 0x68225a38), TOBN(0x0f63cfc8, 0x2fe1e907), - TOBN(0x22d1b01b, 0xc6441f95), TOBN(0x7d38f719, 0xec8e448f), - TOBN(0x9b33fa5f, 0x787fb1ba), TOBN(0x94dcfda1, 0x190158df), - TOBN(0xc47cb339, 0x5f6d4a09), TOBN(0x6b4f355c, 0xee52b826), - TOBN(0x3d100f5d, 0xf51b930a), TOBN(0xf4512fac, 0x9f668f69), - TOBN(0x546781d5, 0x206c4c74), TOBN(0xd021d4d4, 0xcb4d2e48), - TOBN(0x494a54c2, 0xca085c2d), TOBN(0xf1dbaca4, 0x520850a8), - TOBN(0x63c79326, 0x490a1aca), TOBN(0xcb64dd9c, 0x41526b02), - TOBN(0xbb772591, 0xa2979258), TOBN(0x3f582970, 0x48d97846), - TOBN(0xd66b70d1, 0x7c213ba7), TOBN(0xc28febb5, 0xe8a0ced4), - TOBN(0x6b911831, 0xc10338c1), TOBN(0x0d54e389, 0xbf0126f3), - TOBN(0x7048d460, 0x4af206ee), TOBN(0x786c88f6, 0x77e97cb9), - TOBN(0xd4375ae1, 0xac64802e), TOBN(0x469bcfe1, 0xd53ec11c), - TOBN(0xfc9b340d, 0x47062230), TOBN(0xe743bb57, 0xc5b4a3ac), - TOBN(0xfe00b4aa, 0x59ef45ac), TOBN(0x29a4ef23, 0x59edf188), - TOBN(0x40242efe, 0xb483689b), TOBN(0x2575d3f6, 0x513ac262), - TOBN(0xf30037c8, 0x0ca6db72), TOBN(0xc9fcce82, 0x98864be2), - TOBN(0x84a112ff, 0x0149362d), TOBN(0x95e57582, 0x1c4ae971), - TOBN(0x1fa4b1a8, 0x945cf86c), TOBN(0x4525a734, 0x0b024a2f), - TOBN(0xe76c8b62, 0x8f338360), TOBN(0x483ff593, 0x28edf32b), - TOBN(0x67e8e90a, 0x298b1aec), TOBN(0x9caab338, 0x736d9a21), - TOBN(0x5c09d2fd, 0x66892709), TOBN(0x2496b4dc, 0xb55a1d41), - TOBN(0x93f5fb1a, 0xe24a4394), TOBN(0x08c75049, 0x6fa8f6c1), - TOBN(0xcaead1c2, 0xc905d85f), TOBN(0xe9d7f790, 0x0733ae57), - TOBN(0x24c9a65c, 0xf07cdd94), TOBN(0x7389359c, 0xa4b55931), - TOBN(0xf58709b7, 0x367e45f7), TOBN(0x1f203067, 0xcb7e7adc), - TOBN(0x82444bff, 0xc7b72818), TOBN(0x07303b35, 0xbaac8033), - TOBN(0x1e1ee4e4, 0xd13b7ea1), TOBN(0xe6489b24, 0xe0e74180), - TOBN(0xa5f2c610, 0x7e70ef70), TOBN(0xa1655412, 0xbdd10894), - TOBN(0x555ebefb, 0x7af4194e), TOBN(0x533c1c3c, 0x8e89bd9c), - TOBN(0x735b9b57, 0x89895856), TOBN(0x15fb3cd2, 0x567f5c15), - TOBN(0x057fed45, 0x526f09fd), TOBN(0xe8a4f10c, 0x8128240a), - TOBN(0x9332efc4, 0xff2bfd8d), TOBN(0x214e77a0, 0xbd35aa31), - TOBN(0x32896d73, 0x14faa40e), TOBN(0x767867ec, 0x01e5f186), - TOBN(0xc9adf8f1, 0x17a1813e), TOBN(0xcb6cda78, 0x54741795), - TOBN(0xb7521b6d, 0x349d51aa), TOBN(0xf56b5a9e, 0xe3c7b8e9), - TOBN(0xc6f1e5c9, 0x32a096df), TOBN(0x083667c4, 0xa3635024), - TOBN(0x365ea135, 0x18087f2f), TOBN(0xf1b8eaac, 0xd136e45d), - TOBN(0xc8a0e484, 0x73aec989), TOBN(0xd75a324b, 0x142c9259), - TOBN(0xb7b4d001, 0x01dae185), TOBN(0x45434e0b, 0x9b7a94bc), - TOBN(0xf54339af, 0xfbd8cb0b), TOBN(0xdcc4569e, 0xe98ef49e), - TOBN(0x7789318a, 0x09a51299), TOBN(0x81b4d206, 0xb2b025d8), - TOBN(0xf64aa418, 0xfae85792), TOBN(0x3e50258f, 0xacd7baf7), - TOBN(0xdce84cdb, 0x2996864b), TOBN(0xa2e67089, 0x1f485fa4), - TOBN(0xb28b2bb6, 0x534c6a5a), TOBN(0x31a7ec6b, 0xc94b9d39), - TOBN(0x1d217766, 0xd6bc20da), TOBN(0x4acdb5ec, 0x86761190), - TOBN(0x68726328, 0x73701063), TOBN(0x4d24ee7c, 0x2128c29b), - TOBN(0xc072ebd3, 0xa19fd868), TOBN(0x612e481c, 0xdb8ddd3b), - TOBN(0xb4e1d754, 0x1a64d852), TOBN(0x00ef95ac, 0xc4c6c4ab), - TOBN(0x1536d2ed, 0xaa0a6c46), TOBN(0x61294086, 0x43774790), - TOBN(0x54af25e8, 0x343fda10), TOBN(0x9ff9d98d, 0xfd25d6f2), - TOBN(0x0746af7c, 0x468b8835), TOBN(0x977a31cb, 0x730ecea7), - TOBN(0xa5096b80, 0xc2cf4a81), TOBN(0xaa986833, 0x6458c37a), - TOBN(0x6af29bf3, 0xa6bd9d34), TOBN(0x6a62fe9b, 0x33c5d854), - TOBN(0x50e6c304, 0xb7133b5e), TOBN(0x04b60159, 0x7d6e6848), - TOBN(0x4cd296df, 0x5579bea4), TOBN(0x10e35ac8, 0x5ceedaf1), - TOBN(0x04c4c5fd, 0xe3bcc5b1), TOBN(0x95f9ee8a, 0x89412cf9), - TOBN(0x2c9459ee, 0x82b6eb0f), TOBN(0x2e845765, 0x95c2aadd), - TOBN(0x774a84ae, 0xd327fcfe), TOBN(0xd8c93722, 0x0368d476), - TOBN(0x0dbd5748, 0xf83e8a3b), TOBN(0xa579aa96, 0x8d2495f3), - TOBN(0x535996a0, 0xae496e9b), TOBN(0x07afbfe9, 0xb7f9bcc2), - TOBN(0x3ac1dc6d, 0x5b7bd293), TOBN(0x3b592cff, 0x7022323d), - TOBN(0xba0deb98, 0x9c0a3e76), TOBN(0x18e78e9f, 0x4b197acb), - TOBN(0x211cde10, 0x296c36ef), TOBN(0x7ee89672, 0x82c4da77), - TOBN(0xb617d270, 0xa57836da), TOBN(0xf0cd9c31, 0x9cb7560b), - TOBN(0x01fdcbf7, 0xe455fe90), TOBN(0x3fb53cbb, 0x7e7334f3), - TOBN(0x781e2ea4, 0x4e7de4ec), TOBN(0x8adab3ad, 0x0b384fd0), - TOBN(0x129eee2f, 0x53d64829), TOBN(0x7a471e17, 0xa261492b), - TOBN(0xe4f9adb9, 0xe4cb4a2c), TOBN(0x3d359f6f, 0x97ba2c2d), - TOBN(0x346c6786, 0x0aacd697), TOBN(0x92b444c3, 0x75c2f8a8), - TOBN(0xc79fa117, 0xd85df44e), TOBN(0x56782372, 0x398ddf31), - TOBN(0x60e690f2, 0xbbbab3b8), TOBN(0x4851f8ae, 0x8b04816b), - TOBN(0xc72046ab, 0x9c92e4d2), TOBN(0x518c74a1, 0x7cf3136b), - TOBN(0xff4eb50a, 0xf9877d4c), TOBN(0x14578d90, 0xa919cabb), - TOBN(0x8218f8c4, 0xac5eb2b6), TOBN(0xa3ccc547, 0x542016e4), - TOBN(0x025bf48e, 0x327f8349), TOBN(0xf3e97346, 0xf43cb641), - TOBN(0xdc2bafdf, 0x500f1085), TOBN(0x57167876, 0x2f063055), - TOBN(0x5bd914b9, 0x411925a6), TOBN(0x7c078d48, 0xa1123de5), - TOBN(0xee6bf835, 0x182b165d), TOBN(0xb11b5e5b, 0xba519727), - TOBN(0xe33ea76c, 0x1eea7b85), TOBN(0x2352b461, 0x92d4f85e), - TOBN(0xf101d334, 0xafe115bb), TOBN(0xfabc1294, 0x889175a3), - TOBN(0x7f6bcdc0, 0x5233f925), TOBN(0xe0a802db, 0xe77fec55), - TOBN(0xbdb47b75, 0x8069b659), TOBN(0x1c5e12de, 0xf98fbd74), - TOBN(0x869c58c6, 0x4b8457ee), TOBN(0xa5360f69, 0x4f7ea9f7), - TOBN(0xe576c09f, 0xf460b38f), TOBN(0x6b70d548, 0x22b7fb36), - TOBN(0x3fd237f1, 0x3bfae315), TOBN(0x33797852, 0xcbdff369), - TOBN(0x97df25f5, 0x25b516f9), TOBN(0x46f388f2, 0xba38ad2d), - TOBN(0x656c4658, 0x89d8ddbb), TOBN(0x8830b26e, 0x70f38ee8), - TOBN(0x4320fd5c, 0xde1212b0), TOBN(0xc34f30cf, 0xe4a2edb2), - TOBN(0xabb131a3, 0x56ab64b8), TOBN(0x7f77f0cc, 0xd99c5d26), - TOBN(0x66856a37, 0xbf981d94), TOBN(0x19e76d09, 0x738bd76e), - TOBN(0xe76c8ac3, 0x96238f39), TOBN(0xc0a482be, 0xa830b366), - TOBN(0xb7b8eaff, 0x0b4eb499), TOBN(0x8ecd83bc, 0x4bfb4865), - TOBN(0x971b2cb7, 0xa2f3776f), TOBN(0xb42176a4, 0xf4b88adf), - TOBN(0xb9617df5, 0xbe1fa446), TOBN(0x8b32d508, 0xcd031bd2), - TOBN(0x1c6bd47d, 0x53b618c0), TOBN(0xc424f46c, 0x6a227923), - TOBN(0x7303ffde, 0xdd92d964), TOBN(0xe9712878, 0x71b5abf2), - TOBN(0x8f48a632, 0xf815561d), TOBN(0x85f48ff5, 0xd3c055d1), - TOBN(0x222a1427, 0x7525684f), TOBN(0xd0d841a0, 0x67360cc3), - TOBN(0x4245a926, 0x0b9267c6), TOBN(0xc78913f1, 0xcf07f863), - TOBN(0xaa844c8e, 0x4d0d9e24), TOBN(0xa42ad522, 0x3d5f9017), - TOBN(0xbd371749, 0xa2c989d5), TOBN(0x928292df, 0xe1f5e78e), - TOBN(0x493b383e, 0x0a1ea6da), TOBN(0x5136fd8d, 0x13aee529), - TOBN(0x860c44b1, 0xf2c34a99), TOBN(0x3b00aca4, 0xbf5855ac), - TOBN(0xabf6aaa0, 0xfaaf37be), TOBN(0x65f43682, 0x2a53ec08), - TOBN(0x1d9a5801, 0xa11b12e1), TOBN(0x78a7ab2c, 0xe20ed475), - TOBN(0x0de1067e, 0x9a41e0d5), TOBN(0x30473f5f, 0x305023ea), - TOBN(0xdd3ae09d, 0x169c7d97), TOBN(0x5cd5baa4, 0xcfaef9cd), - TOBN(0x5cd7440b, 0x65a44803), TOBN(0xdc13966a, 0x47f364de), - TOBN(0x077b2be8, 0x2b8357c1), TOBN(0x0cb1b4c5, 0xe9d57c2a), - TOBN(0x7a4ceb32, 0x05ff363e), TOBN(0xf310fa4d, 0xca35a9ef), - TOBN(0xdbb7b352, 0xf97f68c6), TOBN(0x0c773b50, 0x0b02cf58), - TOBN(0xea2e4821, 0x3c1f96d9), TOBN(0xffb357b0, 0xeee01815), - TOBN(0xb9c924cd, 0xe0f28039), TOBN(0x0b36c95a, 0x46a3fbe4), - TOBN(0x1faaaea4, 0x5e46db6c), TOBN(0xcae575c3, 0x1928aaff), - TOBN(0x7f671302, 0xa70dab86), TOBN(0xfcbd12a9, 0x71c58cfc), - TOBN(0xcbef9acf, 0xbee0cb92), TOBN(0x573da0b9, 0xf8c1b583), - TOBN(0x4752fcfe, 0x0d41d550), TOBN(0xe7eec0e3, 0x2155cffe), - TOBN(0x0fc39fcb, 0x545ae248), TOBN(0x522cb8d1, 0x8065f44e), - TOBN(0x263c962a, 0x70cbb96c), TOBN(0xe034362a, 0xbcd124a9), - TOBN(0xf120db28, 0x3c2ae58d), TOBN(0xb9a38d49, 0xfef6d507), - TOBN(0xb1fd2a82, 0x1ff140fd), TOBN(0xbd162f30, 0x20aee7e0), - TOBN(0x4e17a5d4, 0xcb251949), TOBN(0x2aebcb83, 0x4f7e1c3d), - TOBN(0x608eb25f, 0x937b0527), TOBN(0xf42e1e47, 0xeb7d9997), - TOBN(0xeba699c4, 0xb8a53a29), TOBN(0x1f921c71, 0xe091b536), - TOBN(0xcce29e7b, 0x5b26bbd5), TOBN(0x7a8ef5ed, 0x3b61a680), - TOBN(0xe5ef8043, 0xba1f1c7e), TOBN(0x16ea8217, 0x18158dda), - TOBN(0x01778a2b, 0x599ff0f9), TOBN(0x68a923d7, 0x8104fc6b), - TOBN(0x5bfa44df, 0xda694ff3), TOBN(0x4f7199db, 0xf7667f12), - TOBN(0xc06d8ff6, 0xe46f2a79), TOBN(0x08b5dead, 0xe9f8131d), - TOBN(0x02519a59, 0xabb4ce7c), TOBN(0xc4f710bc, 0xb42aec3e), - TOBN(0x3d77b057, 0x78bde41a), TOBN(0x6474bf80, 0xb4186b5a), - TOBN(0x048b3f67, 0x88c65741), TOBN(0xc64519de, 0x03c7c154), - TOBN(0xdf073846, 0x0edfcc4f), TOBN(0x319aa737, 0x48f1aa6b), - TOBN(0x8b9f8a02, 0xca909f77), TOBN(0x90258139, 0x7580bfef), - TOBN(0xd8bfd3ca, 0xc0c22719), TOBN(0xc60209e4, 0xc9ca151e), - TOBN(0x7a744ab5, 0xd9a1a69c), TOBN(0x6de5048b, 0x14937f8f), - TOBN(0x171938d8, 0xe115ac04), TOBN(0x7df70940, 0x1c6b16d2), - TOBN(0xa6aeb663, 0x7f8e94e7), TOBN(0xc130388e, 0x2a2cf094), - TOBN(0x1850be84, 0x77f54e6e), TOBN(0x9f258a72, 0x65d60fe5), - TOBN(0xff7ff0c0, 0x6c9146d6), TOBN(0x039aaf90, 0xe63a830b), - TOBN(0x38f27a73, 0x9460342f), TOBN(0x4703148c, 0x3f795f8a), - TOBN(0x1bb5467b, 0x9681a97e), TOBN(0x00931ba5, 0xecaeb594), - TOBN(0xcdb6719d, 0x786f337c), TOBN(0xd9c01cd2, 0xe704397d), - TOBN(0x0f4a3f20, 0x555c2fef), TOBN(0x00452509, 0x7c0af223), - TOBN(0x54a58047, 0x84db8e76), TOBN(0x3bacf1aa, 0x93c8aa06), - TOBN(0x11ca957c, 0xf7919422), TOBN(0x50641053, 0x78cdaa40), - TOBN(0x7a303874, 0x9f7144ae), TOBN(0x170c963f, 0x43d4acfd), - TOBN(0x5e148149, 0x58ddd3ef), TOBN(0xa7bde582, 0x9e72dba8), - TOBN(0x0769da8b, 0x6fa68750), TOBN(0xfa64e532, 0x572e0249), - TOBN(0xfcaadf9d, 0x2619ad31), TOBN(0x87882daa, 0xa7b349cd), - TOBN(0x9f6eb731, 0x6c67a775), TOBN(0xcb10471a, 0xefc5d0b1), - TOBN(0xb433750c, 0xe1b806b2), TOBN(0x19c5714d, 0x57b1ae7e), - TOBN(0xc0dc8b7b, 0xed03fd3f), TOBN(0xdd03344f, 0x31bc194e), - TOBN(0xa66c52a7, 0x8c6320b5), TOBN(0x8bc82ce3, 0xd0b6fd93), - TOBN(0xf8e13501, 0xb35f1341), TOBN(0xe53156dd, 0x25a43e42), - TOBN(0xd3adf27e, 0x4daeb85c), TOBN(0xb81d8379, 0xbbeddeb5), - TOBN(0x1b0b546e, 0x2e435867), TOBN(0x9020eb94, 0xeba5dd60), - TOBN(0x37d91161, 0x8210cb9d), TOBN(0x4c596b31, 0x5c91f1cf), - TOBN(0xb228a90f, 0x0e0b040d), TOBN(0xbaf02d82, 0x45ff897f), - TOBN(0x2aac79e6, 0x00fa6122), TOBN(0x24828817, 0x8e36f557), - TOBN(0xb9521d31, 0x113ec356), TOBN(0x9e48861e, 0x15eff1f8), - TOBN(0x2aa1d412, 0xe0d41715), TOBN(0x71f86203, 0x53f131b8), - TOBN(0xf60da8da, 0x3fd19408), TOBN(0x4aa716dc, 0x278d9d99), - TOBN(0x394531f7, 0xa8c51c90), TOBN(0xb560b0e8, 0xf59db51c), - TOBN(0xa28fc992, 0xfa34bdad), TOBN(0xf024fa14, 0x9cd4f8bd), - TOBN(0x5cf530f7, 0x23a9d0d3), TOBN(0x615ca193, 0xe28c9b56), - TOBN(0x6d2a483d, 0x6f73c51e), TOBN(0xa4cb2412, 0xea0dc2dd), - TOBN(0x50663c41, 0x1eb917ff), TOBN(0x3d3a74cf, 0xeade299e), - TOBN(0x29b3990f, 0x4a7a9202), TOBN(0xa9bccf59, 0xa7b15c3d), - TOBN(0x66a3ccdc, 0xa5df9208), TOBN(0x48027c14, 0x43f2f929), - TOBN(0xd385377c, 0x40b557f0), TOBN(0xe001c366, 0xcd684660), - TOBN(0x1b18ed6b, 0xe2183a27), TOBN(0x879738d8, 0x63210329), - TOBN(0xa687c74b, 0xbda94882), TOBN(0xd1bbcc48, 0xa684b299), - TOBN(0xaf6f1112, 0x863b3724), TOBN(0x6943d1b4, 0x2c8ce9f8), - TOBN(0xe044a3bb, 0x098cafb4), TOBN(0x27ed2310, 0x60d48caf), - TOBN(0x542b5675, 0x3a31b84d), TOBN(0xcbf3dd50, 0xfcddbed7), - TOBN(0x25031f16, 0x41b1d830), TOBN(0xa7ec851d, 0xcb0c1e27), - TOBN(0xac1c8fe0, 0xb5ae75db), TOBN(0xb24c7557, 0x08c52120), - TOBN(0x57f811dc, 0x1d4636c3), TOBN(0xf8436526, 0x681a9939), - TOBN(0x1f6bc6d9, 0x9c81adb3), TOBN(0x840f8ac3, 0x5b7d80d4), - TOBN(0x731a9811, 0xf4387f1a), TOBN(0x7c501cd3, 0xb5156880), - TOBN(0xa5ca4a07, 0xdfe68867), TOBN(0xf123d8f0, 0x5fcea120), - TOBN(0x1fbb0e71, 0xd607039e), TOBN(0x2b70e215, 0xcd3a4546), - TOBN(0x32d2f01d, 0x53324091), TOBN(0xb796ff08, 0x180ab19b), - TOBN(0x32d87a86, 0x3c57c4aa), TOBN(0x2aed9caf, 0xb7c49a27), - TOBN(0x9fb35eac, 0x31630d98), TOBN(0x338e8cdf, 0x5c3e20a3), - TOBN(0x80f16182, 0x66cde8db), TOBN(0x4e159980, 0x2d72fd36), - TOBN(0xd7b8f13b, 0x9b6e5072), TOBN(0xf5213907, 0x3b7b5dc1), - TOBN(0x4d431f1d, 0x8ce4396e), TOBN(0x37a1a680, 0xa7ed2142), - TOBN(0xbf375696, 0xd01aaf6b), TOBN(0xaa1c0c54, 0xe63aab66), - TOBN(0x3014368b, 0x4ed80940), TOBN(0x67e6d056, 0x7a6fcedd), - TOBN(0x7c208c49, 0xca97579f), TOBN(0xfe3d7a81, 0xa23597f6), - TOBN(0x5e203202, 0x7e096ae2), TOBN(0xb1f3e1e7, 0x24b39366), - TOBN(0x26da26f3, 0x2fdcdffc), TOBN(0x79422f1d, 0x6097be83), - }, - { - TOBN(0x263a2cfb, 0x9db3b381), TOBN(0x9c3a2dee, 0xd4df0a4b), - TOBN(0x728d06e9, 0x7d04e61f), TOBN(0x8b1adfbc, 0x42449325), - TOBN(0x6ec1d939, 0x7e053a1b), TOBN(0xee2be5c7, 0x66daf707), - TOBN(0x80ba1e14, 0x810ac7ab), TOBN(0xdd2ae778, 0xf530f174), - TOBN(0x0435d97a, 0x205b9d8b), TOBN(0x6eb8f064, 0x056756d4), - TOBN(0xd5e88a8b, 0xb6f8210e), TOBN(0x070ef12d, 0xec9fd9ea), - TOBN(0x4d849505, 0x3bcc876a), TOBN(0x12a75338, 0xa7404ce3), - TOBN(0xd22b49e1, 0xb8a1db5e), TOBN(0xec1f2051, 0x14bfa5ad), - TOBN(0xadbaeb79, 0xb6828f36), TOBN(0x9d7a0258, 0x01bd5b9e), - TOBN(0xeda01e0d, 0x1e844b0c), TOBN(0x4b625175, 0x887edfc9), - TOBN(0x14109fdd, 0x9669b621), TOBN(0x88a2ca56, 0xf6f87b98), - TOBN(0xfe2eb788, 0x170df6bc), TOBN(0x0cea06f4, 0xffa473f9), - TOBN(0x43ed81b5, 0xc4e83d33), TOBN(0xd9f35879, 0x5efd488b), - TOBN(0x164a620f, 0x9deb4d0f), TOBN(0xc6927bdb, 0xac6a7394), - TOBN(0x45c28df7, 0x9f9e0f03), TOBN(0x2868661e, 0xfcd7e1a9), - TOBN(0x7cf4e8d0, 0xffa348f1), TOBN(0x6bd4c284, 0x398538e0), - TOBN(0x2618a091, 0x289a8619), TOBN(0xef796e60, 0x6671b173), - TOBN(0x664e46e5, 0x9090c632), TOBN(0xa38062d4, 0x1e66f8fb), - TOBN(0x6c744a20, 0x0573274e), TOBN(0xd07b67e4, 0xa9271394), - TOBN(0x391223b2, 0x6bdc0e20), TOBN(0xbe2d93f1, 0xeb0a05a7), - TOBN(0xf23e2e53, 0x3f36d141), TOBN(0xe84bb3d4, 0x4dfca442), - TOBN(0xb804a48d, 0x6b7c023a), TOBN(0x1e16a8fa, 0x76431c3b), - TOBN(0x1b5452ad, 0xddd472e0), TOBN(0x7d405ee7, 0x0d1ee127), - TOBN(0x50fc6f1d, 0xffa27599), TOBN(0x351ac53c, 0xbf391b35), - TOBN(0x7efa14b8, 0x4444896b), TOBN(0x64974d2f, 0xf94027fb), - TOBN(0xefdcd0e8, 0xde84487d), TOBN(0x8c45b260, 0x2b48989b), - TOBN(0xa8fcbbc2, 0xd8463487), TOBN(0xd1b2b3f7, 0x3fbc476c), - TOBN(0x21d005b7, 0xc8f443c0), TOBN(0x518f2e67, 0x40c0139c), - TOBN(0x56036e8c, 0x06d75fc1), TOBN(0x2dcf7bb7, 0x3249a89f), - TOBN(0x81dd1d3d, 0xe245e7dd), TOBN(0xf578dc4b, 0xebd6e2a7), - TOBN(0x4c028903, 0xdf2ce7a0), TOBN(0xaee36288, 0x9c39afac), - TOBN(0xdc847c31, 0x146404ab), TOBN(0x6304c0d8, 0xa4e97818), - TOBN(0xae51dca2, 0xa91f6791), TOBN(0x2abe4190, 0x9baa9efc), - TOBN(0xd9d2e2f4, 0x559c7ac1), TOBN(0xe82f4b51, 0xfc9f773a), - TOBN(0xa7713027, 0x4073e81c), TOBN(0xc0276fac, 0xfbb596fc), - TOBN(0x1d819fc9, 0xa684f70c), TOBN(0x29b47fdd, 0xc9f7b1e0), - TOBN(0x358de103, 0x459b1940), TOBN(0xec881c59, 0x5b013e93), - TOBN(0x51574c93, 0x49532ad3), TOBN(0x2db1d445, 0xb37b46de), - TOBN(0xc6445b87, 0xdf239fd8), TOBN(0xc718af75, 0x151d24ee), - TOBN(0xaea1c4a4, 0xf43c6259), TOBN(0x40c0e5d7, 0x70be02f7), - TOBN(0x6a4590f4, 0x721b33f2), TOBN(0x2124f1fb, 0xfedf04ea), - TOBN(0xf8e53cde, 0x9745efe7), TOBN(0xe7e10432, 0x65f046d9), - TOBN(0xc3fca28e, 0xe4d0c7e6), TOBN(0x847e339a, 0x87253b1b), - TOBN(0x9b595348, 0x3743e643), TOBN(0xcb6a0a0b, 0x4fd12fc5), - TOBN(0xfb6836c3, 0x27d02dcc), TOBN(0x5ad00982, 0x7a68bcc2), - TOBN(0x1b24b44c, 0x005e912d), TOBN(0xcc83d20f, 0x811fdcfe), - TOBN(0x36527ec1, 0x666fba0c), TOBN(0x69948197, 0x14754635), - TOBN(0xfcdcb1a8, 0x556da9c2), TOBN(0xa5934267, 0x81a732b2), - TOBN(0xec1214ed, 0xa714181d), TOBN(0x609ac13b, 0x6067b341), - TOBN(0xff4b4c97, 0xa545df1f), TOBN(0xa1240501, 0x34d2076b), - TOBN(0x6efa0c23, 0x1409ca97), TOBN(0x254cc1a8, 0x20638c43), - TOBN(0xd4e363af, 0xdcfb46cd), TOBN(0x62c2adc3, 0x03942a27), - TOBN(0xc67b9df0, 0x56e46483), TOBN(0xa55abb20, 0x63736356), - TOBN(0xab93c098, 0xc551bc52), TOBN(0x382b49f9, 0xb15fe64b), - TOBN(0x9ec221ad, 0x4dff8d47), TOBN(0x79caf615, 0x437df4d6), - TOBN(0x5f13dc64, 0xbb456509), TOBN(0xe4c589d9, 0x191f0714), - TOBN(0x27b6a8ab, 0x3fd40e09), TOBN(0xe455842e, 0x77313ea9), - TOBN(0x8b51d1e2, 0x1f55988b), TOBN(0x5716dd73, 0x062bbbfc), - TOBN(0x633c11e5, 0x4e8bf3de), TOBN(0x9a0e77b6, 0x1b85be3b), - TOBN(0x56510729, 0x0911cca6), TOBN(0x27e76495, 0xefa6590f), - TOBN(0xe4ac8b33, 0x070d3aab), TOBN(0x2643672b, 0x9a2cd5e5), - TOBN(0x52eff79b, 0x1cfc9173), TOBN(0x665ca49b, 0x90a7c13f), - TOBN(0x5a8dda59, 0xb3efb998), TOBN(0x8a5b922d, 0x052f1341), - TOBN(0xae9ebbab, 0x3cf9a530), TOBN(0x35986e7b, 0xf56da4d7), - TOBN(0x3a636b5c, 0xff3513cc), TOBN(0xbb0cf8ba, 0x3198f7dd), - TOBN(0xb8d40522, 0x41f16f86), TOBN(0x760575d8, 0xde13a7bf), - TOBN(0x36f74e16, 0x9f7aa181), TOBN(0x163a3ecf, 0xf509ed1c), - TOBN(0x6aead61f, 0x3c40a491), TOBN(0x158c95fc, 0xdfe8fcaa), - TOBN(0xa3991b6e, 0x13cda46f), TOBN(0x79482415, 0x342faed0), - TOBN(0xf3ba5bde, 0x666b5970), TOBN(0x1d52e6bc, 0xb26ab6dd), - TOBN(0x768ba1e7, 0x8608dd3d), TOBN(0x4930db2a, 0xea076586), - TOBN(0xd9575714, 0xe7dc1afa), TOBN(0x1fc7bf7d, 0xf7c58817), - TOBN(0x6b47accd, 0xd9eee96c), TOBN(0x0ca277fb, 0xe58cec37), - TOBN(0x113fe413, 0xe702c42a), TOBN(0xdd1764ee, 0xc47cbe51), - TOBN(0x041e7cde, 0x7b3ed739), TOBN(0x50cb7459, 0x5ce9e1c0), - TOBN(0x35568513, 0x2925b212), TOBN(0x7cff95c4, 0x001b081c), - TOBN(0x63ee4cbd, 0x8088b454), TOBN(0xdb7f32f7, 0x9a9e0c8a), - TOBN(0xb377d418, 0x6b2447cb), TOBN(0xe3e982aa, 0xd370219b), - TOBN(0x06ccc1e4, 0xc2a2a593), TOBN(0x72c36865, 0x0773f24f), - TOBN(0xa13b4da7, 0x95859423), TOBN(0x8bbf1d33, 0x75040c8f), - TOBN(0x726f0973, 0xda50c991), TOBN(0x48afcd5b, 0x822d6ee2), - TOBN(0xe5fc718b, 0x20fd7771), TOBN(0xb9e8e77d, 0xfd0807a1), - TOBN(0x7f5e0f44, 0x99a7703d), TOBN(0x6972930e, 0x618e36f3), - TOBN(0x2b7c77b8, 0x23807bbe), TOBN(0xe5b82405, 0xcb27ff50), - TOBN(0xba8b8be3, 0xbd379062), TOBN(0xd64b7a1d, 0x2dce4a92), - TOBN(0x040a73c5, 0xb2952e37), TOBN(0x0a9e252e, 0xd438aeca), - TOBN(0xdd43956b, 0xc39d3bcb), TOBN(0x1a31ca00, 0xb32b2d63), - TOBN(0xd67133b8, 0x5c417a18), TOBN(0xd08e4790, 0x2ef442c8), - TOBN(0x98cb1ae9, 0x255c0980), TOBN(0x4bd86381, 0x2b4a739f), - TOBN(0x5a5c31e1, 0x1e4a45a1), TOBN(0x1e5d55fe, 0x9cb0db2f), - TOBN(0x74661b06, 0x8ff5cc29), TOBN(0x026b389f, 0x0eb8a4f4), - TOBN(0x536b21a4, 0x58848c24), TOBN(0x2e5bf8ec, 0x81dc72b0), - TOBN(0x03c187d0, 0xad886aac), TOBN(0x5c16878a, 0xb771b645), - TOBN(0xb07dfc6f, 0xc74045ab), TOBN(0x2c6360bf, 0x7800caed), - TOBN(0x24295bb5, 0xb9c972a3), TOBN(0xc9e6f88e, 0x7c9a6dba), - TOBN(0x90ffbf24, 0x92a79aa6), TOBN(0xde29d50a, 0x41c26ac2), - TOBN(0x9f0af483, 0xd309cbe6), TOBN(0x5b020d8a, 0xe0bced4f), - TOBN(0x606e986d, 0xb38023e3), TOBN(0xad8f2c9d, 0x1abc6933), - TOBN(0x19292e1d, 0xe7400e93), TOBN(0xfe3e18a9, 0x52be5e4d), - TOBN(0xe8e9771d, 0x2e0680bf), TOBN(0x8c5bec98, 0xc54db063), - TOBN(0x2af9662a, 0x74a55d1f), TOBN(0xe3fbf28f, 0x046f66d8), - TOBN(0xa3a72ab4, 0xd4dc4794), TOBN(0x09779f45, 0x5c7c2dd8), - TOBN(0xd893bdaf, 0xc3d19d8d), TOBN(0xd5a75094, 0x57d6a6df), - TOBN(0x8cf8fef9, 0x952e6255), TOBN(0x3da67cfb, 0xda9a8aff), - TOBN(0x4c23f62a, 0x2c160dcd), TOBN(0x34e6c5e3, 0x8f90eaef), - TOBN(0x35865519, 0xa9a65d5a), TOBN(0x07c48aae, 0x8fd38a3d), - TOBN(0xb7e7aeda, 0x50068527), TOBN(0x2c09ef23, 0x1c90936a), - TOBN(0x31ecfeb6, 0xe879324c), TOBN(0xa0871f6b, 0xfb0ec938), - TOBN(0xb1f0fb68, 0xd84d835d), TOBN(0xc90caf39, 0x861dc1e6), - TOBN(0x12e5b046, 0x7594f8d7), TOBN(0x26897ae2, 0x65012b92), - TOBN(0xbcf68a08, 0xa4d6755d), TOBN(0x403ee41c, 0x0991fbda), - TOBN(0x733e343e, 0x3bbf17e8), TOBN(0xd2c7980d, 0x679b3d65), - TOBN(0x33056232, 0xd2e11305), TOBN(0x966be492, 0xf3c07a6f), - TOBN(0x6a8878ff, 0xbb15509d), TOBN(0xff221101, 0x0a9b59a4), - TOBN(0x6c9f564a, 0xabe30129), TOBN(0xc6f2c940, 0x336e64cf), - TOBN(0x0fe75262, 0x8b0c8022), TOBN(0xbe0267e9, 0x6ae8db87), - TOBN(0x22e192f1, 0x93bc042b), TOBN(0xf085b534, 0xb237c458), - TOBN(0xa0d192bd, 0x832c4168), TOBN(0x7a76e9e3, 0xbdf6271d), - TOBN(0x52a882fa, 0xb88911b5), TOBN(0xc85345e4, 0xb4db0eb5), - TOBN(0xa3be02a6, 0x81a7c3ff), TOBN(0x51889c8c, 0xf0ec0469), - TOBN(0x9d031369, 0xa5e829e5), TOBN(0xcbb4c6fc, 0x1607aa41), - TOBN(0x75ac59a6, 0x241d84c1), TOBN(0xc043f2bf, 0x8829e0ee), - TOBN(0x82a38f75, 0x8ea5e185), TOBN(0x8bda40b9, 0xd87cbd9f), - TOBN(0x9e65e75e, 0x2d8fc601), TOBN(0x3d515f74, 0xa35690b3), - TOBN(0x534acf4f, 0xda79e5ac), TOBN(0x68b83b3a, 0x8630215f), - TOBN(0x5c748b2e, 0xd085756e), TOBN(0xb0317258, 0xe5d37cb2), - TOBN(0x6735841a, 0xc5ccc2c4), TOBN(0x7d7dc96b, 0x3d9d5069), - TOBN(0xa147e410, 0xfd1754bd), TOBN(0x65296e94, 0xd399ddd5), - TOBN(0xf6b5b2d0, 0xbc8fa5bc), TOBN(0x8a5ead67, 0x500c277b), - TOBN(0x214625e6, 0xdfa08a5d), TOBN(0x51fdfedc, 0x959cf047), - TOBN(0x6bc9430b, 0x289fca32), TOBN(0xe36ff0cf, 0x9d9bdc3f), - TOBN(0x2fe187cb, 0x58ea0ede), TOBN(0xed66af20, 0x5a900b3f), - TOBN(0x00e0968b, 0x5fa9f4d6), TOBN(0x2d4066ce, 0x37a362e7), - TOBN(0xa99a9748, 0xbd07e772), TOBN(0x710989c0, 0x06a4f1d0), - TOBN(0xd5dedf35, 0xce40cbd8), TOBN(0xab55c5f0, 0x1743293d), - TOBN(0x766f1144, 0x8aa24e2c), TOBN(0x94d874f8, 0x605fbcb4), - TOBN(0xa365f0e8, 0xa518001b), TOBN(0xee605eb6, 0x9d04ef0f), - TOBN(0x5a3915cd, 0xba8d4d25), TOBN(0x44c0e1b8, 0xb5113472), - TOBN(0xcbb024e8, 0x8b6740dc), TOBN(0x89087a53, 0xee1d4f0c), - TOBN(0xa88fa05c, 0x1fc4e372), TOBN(0x8bf395cb, 0xaf8b3af2), - TOBN(0x1e71c9a1, 0xdeb8568b), TOBN(0xa35daea0, 0x80fb3d32), - TOBN(0xe8b6f266, 0x2cf8fb81), TOBN(0x6d51afe8, 0x9490696a), - TOBN(0x81beac6e, 0x51803a19), TOBN(0xe3d24b7f, 0x86219080), - TOBN(0x727cfd9d, 0xdf6f463c), TOBN(0x8c6865ca, 0x72284ee8), - TOBN(0x32c88b7d, 0xb743f4ef), TOBN(0x3793909b, 0xe7d11dce), - TOBN(0xd398f922, 0x2ff2ebe8), TOBN(0x2c70ca44, 0xe5e49796), - TOBN(0xdf4d9929, 0xcb1131b1), TOBN(0x7826f298, 0x25888e79), - TOBN(0x4d3a112c, 0xf1d8740a), TOBN(0x00384cb6, 0x270afa8b), - TOBN(0xcb64125b, 0x3ab48095), TOBN(0x3451c256, 0x62d05106), - TOBN(0xd73d577d, 0xa4955845), TOBN(0x39570c16, 0xbf9f4433), - TOBN(0xd7dfaad3, 0xadecf263), TOBN(0xf1c3d8d1, 0xdc76e102), - TOBN(0x5e774a58, 0x54c6a836), TOBN(0xdad4b672, 0x3e92d47b), - TOBN(0xbe7e990f, 0xf0d796a0), TOBN(0x5fc62478, 0xdf0e8b02), - TOBN(0x8aae8bf4, 0x030c00ad), TOBN(0x3d2db93b, 0x9004ba0f), - TOBN(0xe48c8a79, 0xd85d5ddc), TOBN(0xe907caa7, 0x6bb07f34), - TOBN(0x58db343a, 0xa39eaed5), TOBN(0x0ea6e007, 0xadaf5724), - TOBN(0xe00df169, 0xd23233f3), TOBN(0x3e322796, 0x77cb637f), - TOBN(0x1f897c0e, 0x1da0cf6c), TOBN(0xa651f5d8, 0x31d6bbdd), - TOBN(0xdd61af19, 0x1a230c76), TOBN(0xbd527272, 0xcdaa5e4a), - TOBN(0xca753636, 0xd0abcd7e), TOBN(0x78bdd37c, 0x370bd8dc), - TOBN(0xc23916c2, 0x17cd93fe), TOBN(0x65b97a4d, 0xdadce6e2), - TOBN(0xe04ed4eb, 0x174e42f8), TOBN(0x1491ccaa, 0xbb21480a), - TOBN(0x145a8280, 0x23196332), TOBN(0x3c3862d7, 0x587b479a), - TOBN(0x9f4a88a3, 0x01dcd0ed), TOBN(0x4da2b7ef, 0x3ea12f1f), - TOBN(0xf8e7ae33, 0xb126e48e), TOBN(0x404a0b32, 0xf494e237), - TOBN(0x9beac474, 0xc55acadb), TOBN(0x4ee5cf3b, 0xcbec9fd9), - TOBN(0x336b33b9, 0x7df3c8c3), TOBN(0xbd905fe3, 0xb76808fd), - TOBN(0x8f436981, 0xaa45c16a), TOBN(0x255c5bfa, 0x3dd27b62), - TOBN(0x71965cbf, 0xc3dd9b4d), TOBN(0xce23edbf, 0xfc068a87), - TOBN(0xb78d4725, 0x745b029b), TOBN(0x74610713, 0xcefdd9bd), - TOBN(0x7116f75f, 0x1266bf52), TOBN(0x02046722, 0x18e49bb6), - TOBN(0xdf43df9f, 0x3d6f19e3), TOBN(0xef1bc7d0, 0xe685cb2f), - TOBN(0xcddb27c1, 0x7078c432), TOBN(0xe1961b9c, 0xb77fedb7), - TOBN(0x1edc2f5c, 0xc2290570), TOBN(0x2c3fefca, 0x19cbd886), - TOBN(0xcf880a36, 0xc2af389a), TOBN(0x96c610fd, 0xbda71cea), - TOBN(0xf03977a9, 0x32aa8463), TOBN(0x8eb7763f, 0x8586d90a), - TOBN(0x3f342454, 0x2a296e77), TOBN(0xc8718683, 0x42837a35), - TOBN(0x7dc71090, 0x6a09c731), TOBN(0x54778ffb, 0x51b816db), - TOBN(0x6b33bfec, 0xaf06defd), TOBN(0xfe3c105f, 0x8592b70b), - TOBN(0xf937fda4, 0x61da6114), TOBN(0x3c13e651, 0x4c266ad7), - TOBN(0xe363a829, 0x855938e8), TOBN(0x2eeb5d9e, 0x9de54b72), - TOBN(0xbeb93b0e, 0x20ccfab9), TOBN(0x3dffbb5f, 0x25e61a25), - TOBN(0x7f655e43, 0x1acc093d), TOBN(0x0cb6cc3d, 0x3964ce61), - TOBN(0x6ab283a1, 0xe5e9b460), TOBN(0x55d787c5, 0xa1c7e72d), - TOBN(0x4d2efd47, 0xdeadbf02), TOBN(0x11e80219, 0xac459068), - TOBN(0x810c7626, 0x71f311f0), TOBN(0xfa17ef8d, 0x4ab6ef53), - TOBN(0xaf47fd25, 0x93e43bff), TOBN(0x5cb5ff3f, 0x0be40632), - TOBN(0x54687106, 0x8ee61da3), TOBN(0x7764196e, 0xb08afd0f), - TOBN(0x831ab3ed, 0xf0290a8f), TOBN(0xcae81966, 0xcb47c387), - TOBN(0xaad7dece, 0x184efb4f), TOBN(0xdcfc53b3, 0x4749110e), - TOBN(0x6698f23c, 0x4cb632f9), TOBN(0xc42a1ad6, 0xb91f8067), - TOBN(0xb116a81d, 0x6284180a), TOBN(0xebedf5f8, 0xe901326f), - TOBN(0xf2274c9f, 0x97e3e044), TOBN(0x42018520, 0x11d09fc9), - TOBN(0x56a65f17, 0xd18e6e23), TOBN(0x2ea61e2a, 0x352b683c), - TOBN(0x27d291bc, 0x575eaa94), TOBN(0x9e7bc721, 0xb8ff522d), - TOBN(0x5f7268bf, 0xa7f04d6f), TOBN(0x5868c73f, 0xaba41748), - TOBN(0x9f85c2db, 0x7be0eead), TOBN(0x511e7842, 0xff719135), - TOBN(0x5a06b1e9, 0xc5ea90d7), TOBN(0x0c19e283, 0x26fab631), - TOBN(0x8af8f0cf, 0xe9206c55), TOBN(0x89389cb4, 0x3553c06a), - TOBN(0x39dbed97, 0xf65f8004), TOBN(0x0621b037, 0xc508991d), - TOBN(0x1c52e635, 0x96e78cc4), TOBN(0x5385c8b2, 0x0c06b4a8), - TOBN(0xd84ddfdb, 0xb0e87d03), TOBN(0xc49dfb66, 0x934bafad), - TOBN(0x7071e170, 0x59f70772), TOBN(0x3a073a84, 0x3a1db56b), - TOBN(0x03494903, 0x3b8af190), TOBN(0x7d882de3, 0xd32920f0), - TOBN(0x91633f0a, 0xb2cf8940), TOBN(0x72b0b178, 0x6f948f51), - TOBN(0x2d28dc30, 0x782653c8), TOBN(0x88829849, 0xdb903a05), - TOBN(0xb8095d0c, 0x6a19d2bb), TOBN(0x4b9e7f0c, 0x86f782cb), - TOBN(0x7af73988, 0x2d907064), TOBN(0xd12be0fe, 0x8b32643c), - TOBN(0x358ed23d, 0x0e165dc3), TOBN(0x3d47ce62, 0x4e2378ce), - TOBN(0x7e2bb0b9, 0xfeb8a087), TOBN(0x3246e8ae, 0xe29e10b9), - TOBN(0x459f4ec7, 0x03ce2b4d), TOBN(0xe9b4ca1b, 0xbbc077cf), - TOBN(0x2613b4f2, 0x0e9940c1), TOBN(0xfc598bb9, 0x047d1eb1), - TOBN(0x9744c62b, 0x45036099), TOBN(0xa9dee742, 0x167c65d8), - TOBN(0x0c511525, 0xdabe1943), TOBN(0xda110554, 0x93c6c624), - TOBN(0xae00a52c, 0x651a3be2), TOBN(0xcda5111d, 0x884449a6), - TOBN(0x063c06f4, 0xff33bed1), TOBN(0x73baaf9a, 0x0d3d76b4), - TOBN(0x52fb0c9d, 0x7fc63668), TOBN(0x6886c9dd, 0x0c039cde), - TOBN(0x602bd599, 0x55b22351), TOBN(0xb00cab02, 0x360c7c13), - TOBN(0x8cb616bc, 0x81b69442), TOBN(0x41486700, 0xb55c3cee), - TOBN(0x71093281, 0xf49ba278), TOBN(0xad956d9c, 0x64a50710), - TOBN(0x9561f28b, 0x638a7e81), TOBN(0x54155cdf, 0x5980ddc3), - TOBN(0xb2db4a96, 0xd26f247a), TOBN(0x9d774e4e, 0x4787d100), - TOBN(0x1a9e6e2e, 0x078637d2), TOBN(0x1c363e2d, 0x5e0ae06a), - TOBN(0x7493483e, 0xe9cfa354), TOBN(0x76843cb3, 0x7f74b98d), - TOBN(0xbaca6591, 0xd4b66947), TOBN(0xb452ce98, 0x04460a8c), - TOBN(0x6830d246, 0x43768f55), TOBN(0xf4197ed8, 0x7dff12df), - TOBN(0x6521b472, 0x400dd0f7), TOBN(0x59f5ca8f, 0x4b1e7093), - TOBN(0x6feff11b, 0x080338ae), TOBN(0x0ada31f6, 0xa29ca3c6), - TOBN(0x24794eb6, 0x94a2c215), TOBN(0xd83a43ab, 0x05a57ab4), - TOBN(0x264a543a, 0x2a6f89fe), TOBN(0x2c2a3868, 0xdd5ec7c2), - TOBN(0xd3373940, 0x8439d9b2), TOBN(0x715ea672, 0x0acd1f11), - TOBN(0x42c1d235, 0xe7e6cc19), TOBN(0x81ce6e96, 0xb990585c), - TOBN(0x04e5dfe0, 0xd809c7bd), TOBN(0xd7b2580c, 0x8f1050ab), - TOBN(0x6d91ad78, 0xd8a4176f), TOBN(0x0af556ee, 0x4e2e897c), - TOBN(0x162a8b73, 0x921de0ac), TOBN(0x52ac9c22, 0x7ea78400), - TOBN(0xee2a4eea, 0xefce2174), TOBN(0xbe61844e, 0x6d637f79), - TOBN(0x0491f1bc, 0x789a283b), TOBN(0x72d3ac3d, 0x880836f4), - TOBN(0xaa1c5ea3, 0x88e5402d), TOBN(0x1b192421, 0xd5cc473d), - TOBN(0x5c0b9998, 0x9dc84cac), TOBN(0xb0a8482d, 0x9c6e75b8), - TOBN(0x639961d0, 0x3a191ce2), TOBN(0xda3bc865, 0x6d837930), - TOBN(0xca990653, 0x056e6f8f), TOBN(0x84861c41, 0x64d133a7), - TOBN(0x8b403276, 0x746abe40), TOBN(0xb7b4d51a, 0xebf8e303), - TOBN(0x05b43211, 0x220a255d), TOBN(0xc997152c, 0x02419e6e), - TOBN(0x76ff47b6, 0x630c2fea), TOBN(0x50518677, 0x281fdade), - TOBN(0x3283b8ba, 0xcf902b0b), TOBN(0x8d4b4eb5, 0x37db303b), - TOBN(0xcc89f42d, 0x755011bc), TOBN(0xb43d74bb, 0xdd09d19b), - TOBN(0x65746bc9, 0x8adba350), TOBN(0x364eaf8c, 0xb51c1927), - TOBN(0x13c76596, 0x10ad72ec), TOBN(0x30045121, 0xf8d40c20), - TOBN(0x6d2d99b7, 0xea7b979b), TOBN(0xcd78cd74, 0xe6fb3bcd), - TOBN(0x11e45a9e, 0x86cffbfe), TOBN(0x78a61cf4, 0x637024f6), - TOBN(0xd06bc872, 0x3d502295), TOBN(0xf1376854, 0x458cb288), - TOBN(0xb9db26a1, 0x342f8586), TOBN(0xf33effcf, 0x4beee09e), - TOBN(0xd7e0c4cd, 0xb30cfb3a), TOBN(0x6d09b8c1, 0x6c9db4c8), - TOBN(0x40ba1a42, 0x07c8d9df), TOBN(0x6fd495f7, 0x1c52c66d), - TOBN(0xfb0e169f, 0x275264da), TOBN(0x80c2b746, 0xe57d8362), - TOBN(0xedd987f7, 0x49ad7222), TOBN(0xfdc229af, 0x4398ec7b), - }, - { - TOBN(0xb0d1ed84, 0x52666a58), TOBN(0x4bcb6e00, 0xe6a9c3c2), - TOBN(0x3c57411c, 0x26906408), TOBN(0xcfc20755, 0x13556400), - TOBN(0xa08b1c50, 0x5294dba3), TOBN(0xa30ba286, 0x8b7dd31e), - TOBN(0xd70ba90e, 0x991eca74), TOBN(0x094e142c, 0xe762c2b9), - TOBN(0xb81d783e, 0x979f3925), TOBN(0x1efd130a, 0xaf4c89a7), - TOBN(0x525c2144, 0xfd1bf7fa), TOBN(0x4b296904, 0x1b265a9e), - TOBN(0xed8e9634, 0xb9db65b6), TOBN(0x35c82e32, 0x03599d8a), - TOBN(0xdaa7a54f, 0x403563f3), TOBN(0x9df088ad, 0x022c38ab), - TOBN(0xe5cfb066, 0xbb3fd30a), TOBN(0x429169da, 0xeff0354e), - TOBN(0x809cf852, 0x3524e36c), TOBN(0x136f4fb3, 0x0155be1d), - TOBN(0x4826af01, 0x1fbba712), TOBN(0x6ef0f0b4, 0x506ba1a1), - TOBN(0xd9928b31, 0x77aea73e), TOBN(0xe2bf6af2, 0x5eaa244e), - TOBN(0x8d084f12, 0x4237b64b), TOBN(0x688ebe99, 0xe3ecfd07), - TOBN(0x57b8a70c, 0xf6845dd8), TOBN(0x808fc59c, 0x5da4a325), - TOBN(0xa9032b2b, 0xa3585862), TOBN(0xb66825d5, 0xedf29386), - TOBN(0xb5a5a8db, 0x431ec29b), TOBN(0xbb143a98, 0x3a1e8dc8), - TOBN(0x35ee94ce, 0x12ae381b), TOBN(0x3a7f176c, 0x86ccda90), - TOBN(0xc63a657e, 0x4606eaca), TOBN(0x9ae5a380, 0x43cd04df), - TOBN(0x9bec8d15, 0xed251b46), TOBN(0x1f5d6d30, 0xcaca5e64), - TOBN(0x347b3b35, 0x9ff20f07), TOBN(0x4d65f034, 0xf7e4b286), - TOBN(0x9e93ba24, 0xf111661e), TOBN(0xedced484, 0xb105eb04), - TOBN(0x96dc9ba1, 0xf424b578), TOBN(0xbf8f66b7, 0xe83e9069), - TOBN(0x872d4df4, 0xd7ed8216), TOBN(0xbf07f377, 0x8e2cbecf), - TOBN(0x4281d899, 0x98e73754), TOBN(0xfec85fbb, 0x8aab8708), - TOBN(0x9a3c0dee, 0xa5ba5b0b), TOBN(0xe6a116ce, 0x42d05299), - TOBN(0xae9775fe, 0xe9b02d42), TOBN(0x72b05200, 0xa1545cb6), - TOBN(0xbc506f7d, 0x31a3b4ea), TOBN(0xe5893078, 0x8bbd9b32), - TOBN(0xc8bc5f37, 0xe4b12a97), TOBN(0x6b000c06, 0x4a73b671), - TOBN(0x13b5bf22, 0x765fa7d0), TOBN(0x59805bf0, 0x1d6a5370), - TOBN(0x67a5e29d, 0x4280db98), TOBN(0x4f53916f, 0x776b1ce3), - TOBN(0x714ff61f, 0x33ddf626), TOBN(0x4206238e, 0xa085d103), - TOBN(0x1c50d4b7, 0xe5809ee3), TOBN(0x999f450d, 0x85f8eb1d), - TOBN(0x658a6051, 0xe4c79e9b), TOBN(0x1394cb73, 0xc66a9fea), - TOBN(0x27f31ed5, 0xc6be7b23), TOBN(0xf4c88f36, 0x5aa6f8fe), - TOBN(0x0fb0721f, 0x4aaa499e), TOBN(0x68b3a7d5, 0xe3fb2a6b), - TOBN(0xa788097d, 0x3a92851d), TOBN(0x060e7f8a, 0xe96f4913), - TOBN(0x82eebe73, 0x1a3a93bc), TOBN(0x42bbf465, 0xa21adc1a), - TOBN(0xc10b6fa4, 0xef030efd), TOBN(0x247aa4c7, 0x87b097bb), - TOBN(0x8b8dc632, 0xf60c77da), TOBN(0x6ffbc26a, 0xc223523e), - TOBN(0xa4f6ff11, 0x344579cf), TOBN(0x5825653c, 0x980250f6), - TOBN(0xb2dd097e, 0xbc1aa2b9), TOBN(0x07889393, 0x37a0333a), - TOBN(0x1cf55e71, 0x37a0db38), TOBN(0x2648487f, 0x792c1613), - TOBN(0xdad01336, 0x3fcef261), TOBN(0x6239c81d, 0x0eabf129), - TOBN(0x8ee761de, 0x9d276be2), TOBN(0x406a7a34, 0x1eda6ad3), - TOBN(0x4bf367ba, 0x4a493b31), TOBN(0x54f20a52, 0x9bf7f026), - TOBN(0xb696e062, 0x9795914b), TOBN(0xcddab96d, 0x8bf236ac), - TOBN(0x4ff2c70a, 0xed25ea13), TOBN(0xfa1d09eb, 0x81cbbbe7), - TOBN(0x88fc8c87, 0x468544c5), TOBN(0x847a670d, 0x696b3317), - TOBN(0xf133421e, 0x64bcb626), TOBN(0xaea638c8, 0x26dee0b5), - TOBN(0xd6e7680b, 0xb310346c), TOBN(0xe06f4097, 0xd5d4ced3), - TOBN(0x09961452, 0x7512a30b), TOBN(0xf3d867fd, 0xe589a59a), - TOBN(0x2e73254f, 0x52d0c180), TOBN(0x9063d8a3, 0x333c74ac), - TOBN(0xeda6c595, 0xd314e7bc), TOBN(0x2ee7464b, 0x467899ed), - TOBN(0x1cef423c, 0x0a1ed5d3), TOBN(0x217e76ea, 0x69cc7613), - TOBN(0x27ccce1f, 0xe7cda917), TOBN(0x12d8016b, 0x8a893f16), - TOBN(0xbcd6de84, 0x9fc74f6b), TOBN(0xfa5817e2, 0xf3144e61), - TOBN(0x1f354164, 0x0821ee4c), TOBN(0x1583eab4, 0x0bc61992), - TOBN(0x7490caf6, 0x1d72879f), TOBN(0x998ad9f3, 0xf76ae7b2), - TOBN(0x1e181950, 0xa41157f7), TOBN(0xa9d7e1e6, 0xe8da3a7e), - TOBN(0x963784eb, 0x8426b95f), TOBN(0x0ee4ed6e, 0x542e2a10), - TOBN(0xb79d4cc5, 0xac751e7b), TOBN(0x93f96472, 0xfd4211bd), - TOBN(0x8c72d3d2, 0xc8de4fc6), TOBN(0x7b69cbf5, 0xdf44f064), - TOBN(0x3da90ca2, 0xf4bf94e1), TOBN(0x1a5325f8, 0xf12894e2), - TOBN(0x0a437f6c, 0x7917d60b), TOBN(0x9be70486, 0x96c9cb5d), - TOBN(0xb4d880bf, 0xe1dc5c05), TOBN(0xd738adda, 0xeebeeb57), - TOBN(0x6f0119d3, 0xdf0fe6a3), TOBN(0x5c686e55, 0x66eaaf5a), - TOBN(0x9cb10b50, 0xdfd0b7ec), TOBN(0xbdd0264b, 0x6a497c21), - TOBN(0xfc093514, 0x8c546c96), TOBN(0x58a947fa, 0x79dbf42a), - TOBN(0xc0b48d4e, 0x49ccd6d7), TOBN(0xff8fb02c, 0x88bd5580), - TOBN(0xc75235e9, 0x07d473b2), TOBN(0x4fab1ac5, 0xa2188af3), - TOBN(0x030fa3bc, 0x97576ec0), TOBN(0xe8c946e8, 0x0b7e7d2f), - TOBN(0x40a5c9cc, 0x70305600), TOBN(0x6d8260a9, 0xc8b013b4), - TOBN(0x0368304f, 0x70bba85c), TOBN(0xad090da1, 0xa4a0d311), - TOBN(0x7170e870, 0x2415eec1), TOBN(0xbfba35fe, 0x8461ea47), - TOBN(0x6279019a, 0xc1e91938), TOBN(0xa47638f3, 0x1afc415f), - TOBN(0x36c65cbb, 0xbcba0e0f), TOBN(0x02160efb, 0x034e2c48), - TOBN(0xe6c51073, 0x615cd9e4), TOBN(0x498ec047, 0xf1243c06), - TOBN(0x3e5a8809, 0xb17b3d8c), TOBN(0x5cd99e61, 0x0cc565f1), - TOBN(0x81e312df, 0x7851dafe), TOBN(0xf156f5ba, 0xa79061e2), - TOBN(0x80d62b71, 0x880c590e), TOBN(0xbec9746f, 0x0a39faa1), - TOBN(0x1d98a9c1, 0xc8ed1f7a), TOBN(0x09e43bb5, 0xa81d5ff2), - TOBN(0xd5f00f68, 0x0da0794a), TOBN(0x412050d9, 0x661aa836), - TOBN(0xa89f7c4e, 0x90747e40), TOBN(0x6dc05ebb, 0xb62a3686), - TOBN(0xdf4de847, 0x308e3353), TOBN(0x53868fbb, 0x9fb53bb9), - TOBN(0x2b09d2c3, 0xcfdcf7dd), TOBN(0x41a9fce3, 0x723fcab4), - TOBN(0x73d905f7, 0x07f57ca3), TOBN(0x080f9fb1, 0xac8e1555), - TOBN(0x7c088e84, 0x9ba7a531), TOBN(0x07d35586, 0xed9a147f), - TOBN(0x602846ab, 0xaf48c336), TOBN(0x7320fd32, 0x0ccf0e79), - TOBN(0xaa780798, 0xb18bd1ff), TOBN(0x52c2e300, 0xafdd2905), - TOBN(0xf27ea3d6, 0x434267cd), TOBN(0x8b96d16d, 0x15605b5f), - TOBN(0x7bb31049, 0x4b45706b), TOBN(0xe7f58b8e, 0x743d25f8), - TOBN(0xe9b5e45b, 0x87f30076), TOBN(0xd19448d6, 0x5d053d5a), - TOBN(0x1ecc8cb9, 0xd3210a04), TOBN(0x6bc7d463, 0xdafb5269), - TOBN(0x3e59b10a, 0x67c3489f), TOBN(0x1769788c, 0x65641e1b), - TOBN(0x8a53b82d, 0xbd6cb838), TOBN(0x7066d6e6, 0x236d5f22), - TOBN(0x03aa1c61, 0x6908536e), TOBN(0xc971da0d, 0x66ae9809), - TOBN(0x01b3a86b, 0xc49a2fac), TOBN(0x3b8420c0, 0x3092e77a), - TOBN(0x02057300, 0x7d6fb556), TOBN(0x6941b2a1, 0xbff40a87), - TOBN(0x140b6308, 0x0658ff2a), TOBN(0x87804363, 0x3424ab36), - TOBN(0x0253bd51, 0x5751e299), TOBN(0xc75bcd76, 0x449c3e3a), - TOBN(0x92eb4090, 0x7f8f875d), TOBN(0x9c9d754e, 0x56c26bbf), - TOBN(0x158cea61, 0x8110bbe7), TOBN(0x62a6b802, 0x745f91ea), - TOBN(0xa79c41aa, 0xc6e7394b), TOBN(0x445b6a83, 0xad57ef10), - TOBN(0x0c5277eb, 0x6ea6f40c), TOBN(0x319fe96b, 0x88633365), - TOBN(0x0b0fc61f, 0x385f63cb), TOBN(0x41250c84, 0x22bdd127), - TOBN(0x67d153f1, 0x09e942c2), TOBN(0x60920d08, 0xc021ad5d), - TOBN(0x229f5746, 0x724d81a5), TOBN(0xb7ffb892, 0x5bba3299), - TOBN(0x518c51a1, 0xde413032), TOBN(0x2a9bfe77, 0x3c2fd94c), - TOBN(0xcbcde239, 0x3191f4fd), TOBN(0x43093e16, 0xd3d6ada1), - TOBN(0x184579f3, 0x58769606), TOBN(0x2c94a8b3, 0xd236625c), - TOBN(0x6922b9c0, 0x5c437d8e), TOBN(0x3d4ae423, 0xd8d9f3c8), - TOBN(0xf72c31c1, 0x2e7090a2), TOBN(0x4ac3f5f3, 0xd76a55bd), - TOBN(0x342508fc, 0x6b6af991), TOBN(0x0d527100, 0x1b5cebbd), - TOBN(0xb84740d0, 0xdd440dd7), TOBN(0x748ef841, 0x780162fd), - TOBN(0xa8dbfe0e, 0xdfc6fafb), TOBN(0xeadfdf05, 0xf7300f27), - TOBN(0x7d06555f, 0xfeba4ec9), TOBN(0x12c56f83, 0x9e25fa97), - TOBN(0x77f84203, 0xd39b8c34), TOBN(0xed8b1be6, 0x3125eddb), - TOBN(0x5bbf2441, 0xf6e39dc5), TOBN(0xb00f6ee6, 0x6a5d678a), - TOBN(0xba456ecf, 0x57d0ea99), TOBN(0xdcae0f58, 0x17e06c43), - TOBN(0x01643de4, 0x0f5b4baa), TOBN(0x2c324341, 0xd161b9be), - TOBN(0x80177f55, 0xe126d468), TOBN(0xed325f1f, 0x76748e09), - TOBN(0x6116004a, 0xcfa9bdc2), TOBN(0x2d8607e6, 0x3a9fb468), - TOBN(0x0e573e27, 0x6009d660), TOBN(0x3a525d2e, 0x8d10c5a1), - TOBN(0xd26cb45c, 0x3b9009a0), TOBN(0xb6b0cdc0, 0xde9d7448), - TOBN(0x949c9976, 0xe1337c26), TOBN(0x6faadebd, 0xd73d68e5), - TOBN(0x9e158614, 0xf1b768d9), TOBN(0x22dfa557, 0x9cc4f069), - TOBN(0xccd6da17, 0xbe93c6d6), TOBN(0x24866c61, 0xa504f5b9), - TOBN(0x2121353c, 0x8d694da1), TOBN(0x1c6ca580, 0x0140b8c6), - TOBN(0xc245ad8c, 0xe964021e), TOBN(0xb83bffba, 0x032b82b3), - TOBN(0xfaa220c6, 0x47ef9898), TOBN(0x7e8d3ac6, 0x982c948a), - TOBN(0x1faa2091, 0xbc2d124a), TOBN(0xbd54c3dd, 0x05b15ff4), - TOBN(0x386bf3ab, 0xc87c6fb7), TOBN(0xfb2b0563, 0xfdeb6f66), - TOBN(0x4e77c557, 0x5b45afb4), TOBN(0xe9ded649, 0xefb8912d), - TOBN(0x7ec9bbf5, 0x42f6e557), TOBN(0x2570dfff, 0x62671f00), - TOBN(0x2b3bfb78, 0x88e084bd), TOBN(0xa024b238, 0xf37fe5b4), - TOBN(0x44e7dc04, 0x95649aee), TOBN(0x498ca255, 0x5e7ec1d8), - TOBN(0x3bc766ea, 0xaaa07e86), TOBN(0x0db6facb, 0xf3608586), - TOBN(0xbadd2549, 0xbdc259c8), TOBN(0x95af3c6e, 0x041c649f), - TOBN(0xb36a928c, 0x02e30afb), TOBN(0x9b5356ad, 0x008a88b8), - TOBN(0x4b67a5f1, 0xcf1d9e9d), TOBN(0xc6542e47, 0xa5d8d8ce), - TOBN(0x73061fe8, 0x7adfb6cc), TOBN(0xcc826fd3, 0x98678141), - TOBN(0x00e758b1, 0x3c80515a), TOBN(0x6afe3247, 0x41485083), - TOBN(0x0fcb08b9, 0xb6ae8a75), TOBN(0xb8cf388d, 0x4acf51e1), - TOBN(0x344a5560, 0x6961b9d6), TOBN(0x1a6778b8, 0x6a97fd0c), - TOBN(0xd840fdc1, 0xecc4c7e3), TOBN(0xde9fe47d, 0x16db68cc), - TOBN(0xe95f89de, 0xa3e216aa), TOBN(0x84f1a6a4, 0x9594a8be), - TOBN(0x7ddc7d72, 0x5a7b162b), TOBN(0xc5cfda19, 0xadc817a3), - TOBN(0x80a5d350, 0x78b58d46), TOBN(0x93365b13, 0x82978f19), - TOBN(0x2e44d225, 0x26a1fc90), TOBN(0x0d6d10d2, 0x4d70705d), - TOBN(0xd94b6b10, 0xd70c45f4), TOBN(0x0f201022, 0xb216c079), - TOBN(0xcec966c5, 0x658fde41), TOBN(0xa8d2bc7d, 0x7e27601d), - TOBN(0xbfcce3e1, 0xff230be7), TOBN(0x3394ff6b, 0x0033ffb5), - TOBN(0xd890c509, 0x8132c9af), TOBN(0xaac4b0eb, 0x361e7868), - TOBN(0x5194ded3, 0xe82d15aa), TOBN(0x4550bd2e, 0x23ae6b7d), - TOBN(0x3fda318e, 0xea5399d4), TOBN(0xd989bffa, 0x91638b80), - TOBN(0x5ea124d0, 0xa14aa12d), TOBN(0x1fb1b899, 0x3667b944), - TOBN(0x95ec7969, 0x44c44d6a), TOBN(0x91df144a, 0x57e86137), - TOBN(0x915fd620, 0x73adac44), TOBN(0x8f01732d, 0x59a83801), - TOBN(0xec579d25, 0x3aa0a633), TOBN(0x06de5e7c, 0xc9d6d59c), - TOBN(0xc132f958, 0xb1ef8010), TOBN(0x29476f96, 0xe65c1a02), - TOBN(0x336a77c0, 0xd34c3565), TOBN(0xef1105b2, 0x1b9f1e9e), - TOBN(0x63e6d08b, 0xf9e08002), TOBN(0x9aff2f21, 0xc613809e), - TOBN(0xb5754f85, 0x3a80e75d), TOBN(0xde71853e, 0x6bbda681), - TOBN(0x86f041df, 0x8197fd7a), TOBN(0x8b332e08, 0x127817fa), - TOBN(0x05d99be8, 0xb9c20cda), TOBN(0x89f7aad5, 0xd5cd0c98), - TOBN(0x7ef936fe, 0x5bb94183), TOBN(0x92ca0753, 0xb05cd7f2), - TOBN(0x9d65db11, 0x74a1e035), TOBN(0x02628cc8, 0x13eaea92), - TOBN(0xf2d9e242, 0x49e4fbf2), TOBN(0x94fdfd9b, 0xe384f8b7), - TOBN(0x65f56054, 0x63428c6b), TOBN(0x2f7205b2, 0x90b409a5), - TOBN(0xf778bb78, 0xff45ae11), TOBN(0xa13045be, 0xc5ee53b2), - TOBN(0xe00a14ff, 0x03ef77fe), TOBN(0x689cd59f, 0xffef8bef), - TOBN(0x3578f0ed, 0x1e9ade22), TOBN(0xe99f3ec0, 0x6268b6a8), - TOBN(0xa2057d91, 0xea1b3c3e), TOBN(0x2d1a7053, 0xb8823a4a), - TOBN(0xabbb336a, 0x2cca451e), TOBN(0xcd2466e3, 0x2218bb5d), - TOBN(0x3ac1f42f, 0xc8cb762d), TOBN(0x7e312aae, 0x7690211f), - TOBN(0xebb9bd73, 0x45d07450), TOBN(0x207c4b82, 0x46c2213f), - TOBN(0x99d425c1, 0x375913ec), TOBN(0x94e45e96, 0x67908220), - TOBN(0xc08f3087, 0xcd67dbf6), TOBN(0xa5670fbe, 0xc0887056), - TOBN(0x6717b64a, 0x66f5b8fc), TOBN(0xd5a56aea, 0x786fec28), - TOBN(0xa8c3f55f, 0xc0ff4952), TOBN(0xa77fefae, 0x457ac49b), - TOBN(0x29882d7c, 0x98379d44), TOBN(0xd000bdfb, 0x509edc8a), - TOBN(0xc6f95979, 0xe66fe464), TOBN(0x504a6115, 0xfa61bde0), - TOBN(0x56b3b871, 0xeffea31a), TOBN(0x2d3de26d, 0xf0c21a54), - TOBN(0x21dbff31, 0x834753bf), TOBN(0xe67ecf49, 0x69269d86), - TOBN(0x7a176952, 0x151fe690), TOBN(0x03515804, 0x7f2adb5f), - TOBN(0xee794b15, 0xd1b62a8d), TOBN(0xf004ceec, 0xaae454e6), - TOBN(0x0897ea7c, 0xf0386fac), TOBN(0x3b62ff12, 0xd1fca751), - TOBN(0x154181df, 0x1b7a04ec), TOBN(0x2008e04a, 0xfb5847ec), - TOBN(0xd147148e, 0x41dbd772), TOBN(0x2b419f73, 0x22942654), - TOBN(0x669f30d3, 0xe9c544f7), TOBN(0x52a2c223, 0xc8540149), - TOBN(0x5da9ee14, 0x634dfb02), TOBN(0x5f074ff0, 0xf47869f3), - TOBN(0x74ee878d, 0xa3933acc), TOBN(0xe6510651, 0x4fe35ed1), - TOBN(0xb3eb9482, 0xf1012e7a), TOBN(0x51013cc0, 0xa8a566ae), - TOBN(0xdd5e9243, 0x47c00d3b), TOBN(0x7fde089d, 0x946bb0e5), - TOBN(0x030754fe, 0xc731b4b3), TOBN(0x12a136a4, 0x99fda062), - TOBN(0x7c1064b8, 0x5a1a35bc), TOBN(0xbf1f5763, 0x446c84ef), - TOBN(0xed29a56d, 0xa16d4b34), TOBN(0x7fba9d09, 0xdca21c4f), - TOBN(0x66d7ac00, 0x6d8de486), TOBN(0x60061987, 0x73a2a5e1), - TOBN(0x8b400f86, 0x9da28ff0), TOBN(0x3133f708, 0x43c4599c), - TOBN(0x9911c9b8, 0xee28cb0d), TOBN(0xcd7e2874, 0x8e0af61d), - TOBN(0x5a85f0f2, 0x72ed91fc), TOBN(0x85214f31, 0x9cd4a373), - TOBN(0x881fe5be, 0x1925253c), TOBN(0xd8dc98e0, 0x91e8bc76), - TOBN(0x7120affe, 0x585cc3a2), TOBN(0x724952ed, 0x735bf97a), - TOBN(0x5581e7dc, 0x3eb34581), TOBN(0x5cbff4f2, 0xe52ee57d), - TOBN(0x8d320a0e, 0x87d8cc7b), TOBN(0x9beaa7f3, 0xf1d280d0), - TOBN(0x7a0b9571, 0x9beec704), TOBN(0x9126332e, 0x5b7f0057), - TOBN(0x01fbc1b4, 0x8ed3bd6d), TOBN(0x35bb2c12, 0xd945eb24), - TOBN(0x6404694e, 0x9a8ae255), TOBN(0xb6092eec, 0x8d6abfb3), - TOBN(0x4d76143f, 0xcc058865), TOBN(0x7b0a5af2, 0x6e249922), - TOBN(0x8aef9440, 0x6a50d353), TOBN(0xe11e4bcc, 0x64f0e07a), - TOBN(0x4472993a, 0xa14a90fa), TOBN(0x7706e20c, 0xba0c51d4), - TOBN(0xf403292f, 0x1532672d), TOBN(0x52573bfa, 0x21829382), - TOBN(0x6a7bb6a9, 0x3b5bdb83), TOBN(0x08da65c0, 0xa4a72318), - TOBN(0xc58d22aa, 0x63eb065f), TOBN(0x1717596c, 0x1b15d685), - TOBN(0x112df0d0, 0xb266d88b), TOBN(0xf688ae97, 0x5941945a), - TOBN(0x487386e3, 0x7c292cac), TOBN(0x42f3b50d, 0x57d6985c), - TOBN(0x6da4f998, 0x6a90fc34), TOBN(0xc8f257d3, 0x65ca8a8d), - TOBN(0xc2feabca, 0x6951f762), TOBN(0xe1bc81d0, 0x74c323ac), - TOBN(0x1bc68f67, 0x251a2a12), TOBN(0x10d86587, 0xbe8a70dc), - TOBN(0xd648af7f, 0xf0f84d2e), TOBN(0xf0aa9ebc, 0x6a43ac92), - TOBN(0x69e3be04, 0x27596893), TOBN(0xb6bb02a6, 0x45bf452b), - TOBN(0x0875c11a, 0xf4c698c8), TOBN(0x6652b5c7, 0xbece3794), - TOBN(0x7b3755fd, 0x4f5c0499), TOBN(0x6ea16558, 0xb5532b38), - TOBN(0xd1c69889, 0xa2e96ef7), TOBN(0x9c773c3a, 0x61ed8f48), - TOBN(0x2b653a40, 0x9b323abc), TOBN(0xe26605e1, 0xf0e1d791), - TOBN(0x45d41064, 0x4a87157a), TOBN(0x8f9a78b7, 0xcbbce616), - TOBN(0xcf1e44aa, 0xc407eddd), TOBN(0x81ddd1d8, 0xa35b964f), - TOBN(0x473e339e, 0xfd083999), TOBN(0x6c94bdde, 0x8e796802), - TOBN(0x5a304ada, 0x8545d185), TOBN(0x82ae44ea, 0x738bb8cb), - TOBN(0x628a35e3, 0xdf87e10e), TOBN(0xd3624f3d, 0xa15b9fe3), - TOBN(0xcc44209b, 0x14be4254), TOBN(0x7d0efcbc, 0xbdbc2ea5), - TOBN(0x1f603362, 0x04c37bbe), TOBN(0x21f363f5, 0x56a5852c), - TOBN(0xa1503d1c, 0xa8501550), TOBN(0x2251e0e1, 0xd8ab10bb), - TOBN(0xde129c96, 0x6961c51c), TOBN(0x1f7246a4, 0x81910f68), - TOBN(0x2eb744ee, 0x5f2591f2), TOBN(0x3c47d33f, 0x5e627157), - TOBN(0x4d6d62c9, 0x22f3bd68), TOBN(0x6120a64b, 0xcb8df856), - TOBN(0x3a9ac6c0, 0x7b5d07df), TOBN(0xa92b9558, 0x7ef39783), - TOBN(0xe128a134, 0xab3a9b4f), TOBN(0x41c18807, 0xb1252f05), - TOBN(0xfc7ed089, 0x80ba9b1c), TOBN(0xac8dc6de, 0xc532a9dd), - TOBN(0xbf829cef, 0x55246809), TOBN(0x101b784f, 0x5b4ee80f), - TOBN(0xc09945bb, 0xb6f11603), TOBN(0x57b09dbe, 0x41d2801e), - TOBN(0xfba5202f, 0xa97534a8), TOBN(0x7fd8ae5f, 0xc17b9614), - TOBN(0xa50ba666, 0x78308435), TOBN(0x9572f77c, 0xd3868c4d), - TOBN(0x0cef7bfd, 0x2dd7aab0), TOBN(0xe7958e08, 0x2c7c79ff), - TOBN(0x81262e42, 0x25346689), TOBN(0x716da290, 0xb07c7004), - TOBN(0x35f911ea, 0xb7950ee3), TOBN(0x6fd72969, 0x261d21b5), - TOBN(0x52389803, 0x08b640d3), TOBN(0x5b0026ee, 0x887f12a1), - TOBN(0x20e21660, 0x742e9311), TOBN(0x0ef6d541, 0x5ff77ff7), - TOBN(0x969127f0, 0xf9c41135), TOBN(0xf21d60c9, 0x68a64993), - TOBN(0x656e5d0c, 0xe541875c), TOBN(0xf1e0f84e, 0xa1d3c233), - TOBN(0x9bcca359, 0x06002d60), TOBN(0xbe2da60c, 0x06191552), - TOBN(0x5da8bbae, 0x61181ec3), TOBN(0x9f04b823, 0x65806f19), - TOBN(0xf1604a7d, 0xd4b79bb8), TOBN(0xaee806fb, 0x52c878c8), - TOBN(0x34144f11, 0x8d47b8e8), TOBN(0x72edf52b, 0x949f9054), - TOBN(0xebfca84e, 0x2127015a), TOBN(0x9051d0c0, 0x9cb7cef3), - TOBN(0x86e8fe58, 0x296deec8), TOBN(0x33b28188, 0x41010d74), - }, - { - TOBN(0x01079383, 0x171b445f), TOBN(0x9bcf21e3, 0x8131ad4c), - TOBN(0x8cdfe205, 0xc93987e8), TOBN(0xe63f4152, 0xc92e8c8f), - TOBN(0x729462a9, 0x30add43d), TOBN(0x62ebb143, 0xc980f05a), - TOBN(0x4f3954e5, 0x3b06e968), TOBN(0xfe1d75ad, 0x242cf6b1), - TOBN(0x5f95c6c7, 0xaf8685c8), TOBN(0xd4c1c8ce, 0x2f8f01aa), - TOBN(0xc44bbe32, 0x2574692a), TOBN(0xb8003478, 0xd4a4a068), - TOBN(0x7c8fc6e5, 0x2eca3cdb), TOBN(0xea1db16b, 0xec04d399), - TOBN(0xb05bc82e, 0x8f2bc5cf), TOBN(0x763d517f, 0xf44793d2), - TOBN(0x4451c1b8, 0x08bd98d0), TOBN(0x644b1cd4, 0x6575f240), - TOBN(0x6907eb33, 0x7375d270), TOBN(0x56c8bebd, 0xfa2286bd), - TOBN(0xc713d2ac, 0xc4632b46), TOBN(0x17da427a, 0xafd60242), - TOBN(0x313065b7, 0xc95c7546), TOBN(0xf8239898, 0xbf17a3de), - TOBN(0xf3b7963f, 0x4c830320), TOBN(0x842c7aa0, 0x903203e3), - TOBN(0xaf22ca0a, 0xe7327afb), TOBN(0x38e13092, 0x967609b6), - TOBN(0x73b8fb62, 0x757558f1), TOBN(0x3cc3e831, 0xf7eca8c1), - TOBN(0xe4174474, 0xf6331627), TOBN(0xa77989ca, 0xc3c40234), - TOBN(0xe5fd17a1, 0x44a081e0), TOBN(0xd797fb7d, 0xb70e296a), - TOBN(0x2b472b30, 0x481f719c), TOBN(0x0e632a98, 0xfe6f8c52), - TOBN(0x89ccd116, 0xc5f0c284), TOBN(0xf51088af, 0x2d987c62), - TOBN(0x2a2bccda, 0x4c2de6cf), TOBN(0x810f9efe, 0xf679f0f9), - TOBN(0xb0f394b9, 0x7ffe4b3e), TOBN(0x0b691d21, 0xe5fa5d21), - TOBN(0xb0bd7747, 0x9dfbbc75), TOBN(0xd2830fda, 0xfaf78b00), - TOBN(0xf78c249c, 0x52434f57), TOBN(0x4b1f7545, 0x98096dab), - TOBN(0x73bf6f94, 0x8ff8c0b3), TOBN(0x34aef03d, 0x454e134c), - TOBN(0xf8d151f4, 0xb7ac7ec5), TOBN(0xd6ceb95a, 0xe50da7d5), - TOBN(0xa1b492b0, 0xdc3a0eb8), TOBN(0x75157b69, 0xb3dd2863), - TOBN(0xe2c4c74e, 0xc5413d62), TOBN(0xbe329ff7, 0xbc5fc4c7), - TOBN(0x835a2aea, 0x60fa9dda), TOBN(0xf117f5ad, 0x7445cb87), - TOBN(0xae8317f4, 0xb0166f7a), TOBN(0xfbd3e3f7, 0xceec74e6), - TOBN(0xfdb516ac, 0xe0874bfd), TOBN(0x3d846019, 0xc681f3a3), - TOBN(0x0b12ee5c, 0x7c1620b0), TOBN(0xba68b4dd, 0x2b63c501), - TOBN(0xac03cd32, 0x6668c51e), TOBN(0x2a6279f7, 0x4e0bcb5b), - TOBN(0x17bd69b0, 0x6ae85c10), TOBN(0x72946979, 0x1dfdd3a6), - TOBN(0xd9a03268, 0x2c078bec), TOBN(0x41c6a658, 0xbfd68a52), - TOBN(0xcdea1024, 0x0e023900), TOBN(0xbaeec121, 0xb10d144d), - TOBN(0x5a600e74, 0x058ab8dc), TOBN(0x1333af21, 0xbb89ccdd), - TOBN(0xdf25eae0, 0x3aaba1f1), TOBN(0x2cada16e, 0x3b7144cf), - TOBN(0x657ee27d, 0x71ab98bc), TOBN(0x99088b4c, 0x7a6fc96e), - TOBN(0x05d5c0a0, 0x3549dbd4), TOBN(0x42cbdf8f, 0xf158c3ac), - TOBN(0x3fb6b3b0, 0x87edd685), TOBN(0x22071cf6, 0x86f064d0), - TOBN(0xd2d6721f, 0xff2811e5), TOBN(0xdb81b703, 0xfe7fae8c), - TOBN(0x3cfb74ef, 0xd3f1f7bb), TOBN(0x0cdbcd76, 0x16cdeb5d), - TOBN(0x4f39642a, 0x566a808c), TOBN(0x02b74454, 0x340064d6), - TOBN(0xfabbadca, 0x0528fa6f), TOBN(0xe4c3074c, 0xd3fc0bb6), - TOBN(0xb32cb8b0, 0xb796d219), TOBN(0xc3e95f4f, 0x34741dd9), - TOBN(0x87212125, 0x68edf6f5), TOBN(0x7a03aee4, 0xa2b9cb8e), - TOBN(0x0cd3c376, 0xf53a89aa), TOBN(0x0d8af9b1, 0x948a28dc), - TOBN(0xcf86a3f4, 0x902ab04f), TOBN(0x8aacb62a, 0x7f42002d), - TOBN(0x106985eb, 0xf62ffd52), TOBN(0xe670b54e, 0x5797bf10), - TOBN(0x4b405209, 0xc5e30aef), TOBN(0x12c97a20, 0x4365b5e9), - TOBN(0x104646ce, 0x1fe32093), TOBN(0x13cb4ff6, 0x3907a8c9), - TOBN(0x8b9f30d1, 0xd46e726b), TOBN(0xe1985e21, 0xaba0f499), - TOBN(0xc573dea9, 0x10a230cd), TOBN(0x24f46a93, 0xcd30f947), - TOBN(0xf2623fcf, 0xabe2010a), TOBN(0x3f278cb2, 0x73f00e4f), - TOBN(0xed55c67d, 0x50b920eb), TOBN(0xf1cb9a2d, 0x8e760571), - TOBN(0x7c50d109, 0x0895b709), TOBN(0x4207cf07, 0x190d4369), - TOBN(0x3b027e81, 0xc4127fe1), TOBN(0xa9f8b9ad, 0x3ae9c566), - TOBN(0x5ab10851, 0xacbfbba5), TOBN(0xa747d648, 0x569556f5), - TOBN(0xcc172b5c, 0x2ba97bf7), TOBN(0x15e0f77d, 0xbcfa3324), - TOBN(0xa345b797, 0x7686279d), TOBN(0x5a723480, 0xe38003d3), - TOBN(0xfd8e139f, 0x8f5fcda8), TOBN(0xf3e558c4, 0xbdee5bfd), - TOBN(0xd76cbaf4, 0xe33f9f77), TOBN(0x3a4c97a4, 0x71771969), - TOBN(0xda27e84b, 0xf6dce6a7), TOBN(0xff373d96, 0x13e6c2d1), - TOBN(0xf115193c, 0xd759a6e9), TOBN(0x3f9b7025, 0x63d2262c), - TOBN(0xd9764a31, 0x317cd062), TOBN(0x30779d8e, 0x199f8332), - TOBN(0xd8074106, 0x16b11b0b), TOBN(0x7917ab9f, 0x78aeaed8), - TOBN(0xb67a9cbe, 0x28fb1d8e), TOBN(0x2e313563, 0x136eda33), - TOBN(0x010b7069, 0xa371a86c), TOBN(0x44d90fa2, 0x6744e6b7), - TOBN(0x68190867, 0xd6b3e243), TOBN(0x9fe6cd9d, 0x59048c48), - TOBN(0xb900b028, 0x95731538), TOBN(0xa012062f, 0x32cae04f), - TOBN(0x8107c8bc, 0x9399d082), TOBN(0x47e8c54a, 0x41df12e2), - TOBN(0x14ba5117, 0xb6ef3f73), TOBN(0x22260bea, 0x81362f0b), - TOBN(0x90ea261e, 0x1a18cc20), TOBN(0x2192999f, 0x2321d636), - TOBN(0xef64d314, 0xe311b6a0), TOBN(0xd7401e4c, 0x3b54a1f5), - TOBN(0x19019983, 0x6fbca2ba), TOBN(0x46ad3293, 0x8fbffc4b), - TOBN(0xa142d3f6, 0x3786bf40), TOBN(0xeb5cbc26, 0xb67039fc), - TOBN(0x9cb0ae6c, 0x252bd479), TOBN(0x05e0f88a, 0x12b5848f), - TOBN(0x78f6d2b2, 0xa5c97663), TOBN(0x6f6e149b, 0xc162225c), - TOBN(0xe602235c, 0xde601a89), TOBN(0xd17bbe98, 0xf373be1f), - TOBN(0xcaf49a5b, 0xa8471827), TOBN(0x7e1a0a85, 0x18aaa116), - TOBN(0x6c833196, 0x270580c3), TOBN(0x1e233839, 0xf1c98a14), - TOBN(0x67b2f7b4, 0xae34e0a5), TOBN(0x47ac8745, 0xd8ce7289), - TOBN(0x2b74779a, 0x100dd467), TOBN(0x274a4337, 0x4ee50d09), - TOBN(0x603dcf13, 0x83608bc9), TOBN(0xcd9da6c3, 0xc89e8388), - TOBN(0x2660199f, 0x355116ac), TOBN(0xcc38bb59, 0xb6d18eed), - TOBN(0x3075f31f, 0x2f4bc071), TOBN(0x9774457f, 0x265dc57e), - TOBN(0x06a6a9c8, 0xc6db88bb), TOBN(0x6429d07f, 0x4ec98e04), - TOBN(0x8d05e57b, 0x05ecaa8b), TOBN(0x20f140b1, 0x7872ea7b), - TOBN(0xdf8c0f09, 0xca494693), TOBN(0x48d3a020, 0xf252e909), - TOBN(0x4c5c29af, 0x57b14b12), TOBN(0x7e6fa37d, 0xbf47ad1c), - TOBN(0x66e7b506, 0x49a0c938), TOBN(0xb72c0d48, 0x6be5f41f), - TOBN(0x6a6242b8, 0xb2359412), TOBN(0xcd35c774, 0x8e859480), - TOBN(0x12536fea, 0x87baa627), TOBN(0x58c1fec1, 0xf72aa680), - TOBN(0x6c29b637, 0x601e5dc9), TOBN(0x9e3c3c1c, 0xde9e01b9), - TOBN(0xefc8127b, 0x2bcfe0b0), TOBN(0x35107102, 0x2a12f50d), - TOBN(0x6ccd6cb1, 0x4879b397), TOBN(0xf792f804, 0xf8a82f21), - TOBN(0x509d4804, 0xa9b46402), TOBN(0xedddf85d, 0xc10f0850), - TOBN(0x928410dc, 0x4b6208aa), TOBN(0xf6229c46, 0x391012dc), - TOBN(0xc5a7c41e, 0x7727b9b6), TOBN(0x289e4e4b, 0xaa444842), - TOBN(0x049ba1d9, 0xe9a947ea), TOBN(0x44f9e47f, 0x83c8debc), - TOBN(0xfa77a1fe, 0x611f8b8e), TOBN(0xfd2e416a, 0xf518f427), - TOBN(0xc5fffa70, 0x114ebac3), TOBN(0xfe57c4e9, 0x5d89697b), - TOBN(0xfdd053ac, 0xb1aaf613), TOBN(0x31df210f, 0xea585a45), - TOBN(0x318cc10e, 0x24985034), TOBN(0x1a38efd1, 0x5f1d6130), - TOBN(0xbf86f237, 0x0b1e9e21), TOBN(0xb258514d, 0x1dbe88aa), - TOBN(0x1e38a588, 0x90c1baf9), TOBN(0x2936a01e, 0xbdb9b692), - TOBN(0xd576de98, 0x6dd5b20c), TOBN(0xb586bf71, 0x70f98ecf), - TOBN(0xcccf0f12, 0xc42d2fd7), TOBN(0x8717e61c, 0xfb35bd7b), - TOBN(0x8b1e5722, 0x35e6fc06), TOBN(0x3477728f, 0x0b3e13d5), - TOBN(0x150c294d, 0xaa8a7372), TOBN(0xc0291d43, 0x3bfa528a), - TOBN(0xc6c8bc67, 0xcec5a196), TOBN(0xdeeb31e4, 0x5c2e8a7c), - TOBN(0xba93e244, 0xfb6e1c51), TOBN(0xb9f8b71b, 0x2e28e156), - TOBN(0xce65a287, 0x968a2ab9), TOBN(0xe3c5ce69, 0x46bbcb1f), - TOBN(0xf8c835b9, 0xe7ae3f30), TOBN(0x16bbee26, 0xff72b82b), - TOBN(0x665e2017, 0xfd42cd22), TOBN(0x1e139970, 0xf8b1d2a0), - TOBN(0x125cda29, 0x79204932), TOBN(0x7aee94a5, 0x49c3bee5), - TOBN(0x68c70160, 0x89821a66), TOBN(0xf7c37678, 0x8f981669), - TOBN(0xd90829fc, 0x48cc3645), TOBN(0x346af049, 0xd70addfc), - TOBN(0x2057b232, 0x370bf29c), TOBN(0xf90c73ce, 0x42e650ee), - TOBN(0xe03386ea, 0xa126ab90), TOBN(0x0e266e7e, 0x975a087b), - TOBN(0x80578eb9, 0x0fca65d9), TOBN(0x7e2989ea, 0x16af45b8), - TOBN(0x7438212d, 0xcac75a4e), TOBN(0x38c7ca39, 0x4fef36b8), - TOBN(0x8650c494, 0xd402676a), TOBN(0x26ab5a66, 0xf72c7c48), - TOBN(0x4e6cb426, 0xce3a464e), TOBN(0xf8f99896, 0x2b72f841), - TOBN(0x8c318491, 0x1a335cc8), TOBN(0x563459ba, 0x6a5913e4), - TOBN(0x1b920d61, 0xc7b32919), TOBN(0x805ab8b6, 0xa02425ad), - TOBN(0x2ac512da, 0x8d006086), TOBN(0x6ca4846a, 0xbcf5c0fd), - TOBN(0xafea51d8, 0xac2138d7), TOBN(0xcb647545, 0x344cd443), - TOBN(0x0429ee8f, 0xbd7d9040), TOBN(0xee66a2de, 0x819b9c96), - TOBN(0x54f9ec25, 0xdea7d744), TOBN(0x2ffea642, 0x671721bb), - TOBN(0x4f19dbd1, 0x114344ea), TOBN(0x04304536, 0xfd0dbc8b), - TOBN(0x014b50aa, 0x29ec7f91), TOBN(0xb5fc22fe, 0xbb06014d), - TOBN(0x60d963a9, 0x1ee682e0), TOBN(0xdf48abc0, 0xfe85c727), - TOBN(0x0cadba13, 0x2e707c2d), TOBN(0xde608d3a, 0xa645aeff), - TOBN(0x05f1c28b, 0xedafd883), TOBN(0x3c362ede, 0xbd94de1f), - TOBN(0x8dd0629d, 0x13593e41), TOBN(0x0a5e736f, 0x766d6eaf), - TOBN(0xbfa92311, 0xf68cf9d1), TOBN(0xa4f9ef87, 0xc1797556), - TOBN(0x10d75a1f, 0x5601c209), TOBN(0x651c374c, 0x09b07361), - TOBN(0x49950b58, 0x88b5cead), TOBN(0x0ef00058, 0x6fa9dbaa), - TOBN(0xf51ddc26, 0x4e15f33a), TOBN(0x1f8b5ca6, 0x2ef46140), - TOBN(0x343ac0a3, 0xee9523f0), TOBN(0xbb75eab2, 0x975ea978), - TOBN(0x1bccf332, 0x107387f4), TOBN(0x790f9259, 0x9ab0062e), - TOBN(0xf1a363ad, 0x1e4f6a5f), TOBN(0x06e08b84, 0x62519a50), - TOBN(0x60915187, 0x7265f1ee), TOBN(0x6a80ca34, 0x93ae985e), - TOBN(0x81b29768, 0xaaba4864), TOBN(0xb13cabf2, 0x8d52a7d6), - TOBN(0xb5c36348, 0x8ead03f1), TOBN(0xc932ad95, 0x81c7c1c0), - TOBN(0x5452708e, 0xcae1e27b), TOBN(0x9dac4269, 0x1b0df648), - TOBN(0x233e3f0c, 0xdfcdb8bc), TOBN(0xe6ceccdf, 0xec540174), - TOBN(0xbd0d845e, 0x95081181), TOBN(0xcc8a7920, 0x699355d5), - TOBN(0x111c0f6d, 0xc3b375a8), TOBN(0xfd95bc6b, 0xfd51e0dc), - TOBN(0x4a106a26, 0x6888523a), TOBN(0x4d142bd6, 0xcb01a06d), - TOBN(0x79bfd289, 0xadb9b397), TOBN(0x0bdbfb94, 0xe9863914), - TOBN(0x29d8a229, 0x1660f6a6), TOBN(0x7f6abcd6, 0x551c042d), - TOBN(0x13039deb, 0x0ac3ffe8), TOBN(0xa01be628, 0xec8523fb), - TOBN(0x6ea34103, 0x0ca1c328), TOBN(0xc74114bd, 0xb903928e), - TOBN(0x8aa4ff4e, 0x9e9144b0), TOBN(0x7064091f, 0x7f9a4b17), - TOBN(0xa3f4f521, 0xe447f2c4), TOBN(0x81b8da7a, 0x604291f0), - TOBN(0xd680bc46, 0x7d5926de), TOBN(0x84f21fd5, 0x34a1202f), - TOBN(0x1d1e3181, 0x4e9df3d8), TOBN(0x1ca4861a, 0x39ab8d34), - TOBN(0x809ddeec, 0x5b19aa4a), TOBN(0x59f72f7e, 0x4d329366), - TOBN(0xa2f93f41, 0x386d5087), TOBN(0x40bf739c, 0xdd67d64f), - TOBN(0xb4494205, 0x66702158), TOBN(0xc33c65be, 0x73b1e178), - TOBN(0xcdcd657c, 0x38ca6153), TOBN(0x97f4519a, 0xdc791976), - TOBN(0xcc7c7f29, 0xcd6e1f39), TOBN(0x38de9cfb, 0x7e3c3932), - TOBN(0xe448eba3, 0x7b793f85), TOBN(0xe9f8dbf9, 0xf067e914), - TOBN(0xc0390266, 0xf114ae87), TOBN(0x39ed75a7, 0xcd6a8e2a), - TOBN(0xadb14848, 0x7ffba390), TOBN(0x67f8cb8b, 0x6af9bc09), - TOBN(0x322c3848, 0x9c7476db), TOBN(0xa320fecf, 0x52a538d6), - TOBN(0xe0493002, 0xb2aced2b), TOBN(0xdfba1809, 0x616bd430), - TOBN(0x531c4644, 0xc331be70), TOBN(0xbc04d32e, 0x90d2e450), - TOBN(0x1805a0d1, 0x0f9f142d), TOBN(0x2c44a0c5, 0x47ee5a23), - TOBN(0x31875a43, 0x3989b4e3), TOBN(0x6b1949fd, 0x0c063481), - TOBN(0x2dfb9e08, 0xbe0f4492), TOBN(0x3ff0da03, 0xe9d5e517), - TOBN(0x03dbe9a1, 0xf79466a8), TOBN(0x0b87bcd0, 0x15ea9932), - TOBN(0xeb64fc83, 0xab1f58ab), TOBN(0x6d9598da, 0x817edc8a), - TOBN(0x699cff66, 0x1d3b67e5), TOBN(0x645c0f29, 0x92635853), - TOBN(0x253cdd82, 0xeabaf21c), TOBN(0x82b9602a, 0x2241659e), - TOBN(0x2cae07ec, 0x2d9f7091), TOBN(0xbe4c720c, 0x8b48cd9b), - TOBN(0x6ce5bc03, 0x6f08d6c9), TOBN(0x36e8a997, 0xaf10bf40), - TOBN(0x83422d21, 0x3e10ff12), TOBN(0x7b26d3eb, 0xbcc12494), - TOBN(0xb240d2d0, 0xc9469ad6), TOBN(0xc4a11b4d, 0x30afa05b), - TOBN(0x4b604ace, 0xdd6ba286), TOBN(0x18486600, 0x3ee2864c), - TOBN(0x5869d6ba, 0x8d9ce5be), TOBN(0x0d8f68c5, 0xff4bfb0d), - TOBN(0xb69f210b, 0x5700cf73), TOBN(0x61f6653a, 0x6d37c135), - TOBN(0xff3d432b, 0x5aff5a48), TOBN(0x0d81c4b9, 0x72ba3a69), - TOBN(0xee879ae9, 0xfa1899ef), TOBN(0xbac7e2a0, 0x2d6acafd), - TOBN(0xd6d93f6c, 0x1c664399), TOBN(0x4c288de1, 0x5bcb135d), - TOBN(0x83031dab, 0x9dab7cbf), TOBN(0xfe23feb0, 0x3abbf5f0), - TOBN(0x9f1b2466, 0xcdedca85), TOBN(0x140bb710, 0x1a09538c), - TOBN(0xac8ae851, 0x5e11115d), TOBN(0x0d63ff67, 0x6f03f59e), - TOBN(0x755e5551, 0x7d234afb), TOBN(0x61c2db4e, 0x7e208fc1), - TOBN(0xaa9859ce, 0xf28a4b5d), TOBN(0xbdd6d4fc, 0x34af030f), - TOBN(0xd1c4a26d, 0x3be01cb1), TOBN(0x9ba14ffc, 0x243aa07c), - TOBN(0xf95cd3a9, 0xb2503502), TOBN(0xe379bc06, 0x7d2a93ab), - TOBN(0x3efc18e9, 0xd4ca8d68), TOBN(0x083558ec, 0x80bb412a), - TOBN(0xd903b940, 0x9645a968), TOBN(0xa499f0b6, 0x9ba6054f), - TOBN(0x208b573c, 0xb8349abe), TOBN(0x3baab3e5, 0x30b4fc1c), - TOBN(0x87e978ba, 0xcb524990), TOBN(0x3524194e, 0xccdf0e80), - TOBN(0x62711725, 0x7d4bcc42), TOBN(0xe90a3d9b, 0xb90109ba), - TOBN(0x3b1bdd57, 0x1323e1e0), TOBN(0xb78e9bd5, 0x5eae1599), - TOBN(0x0794b746, 0x9e03d278), TOBN(0x80178605, 0xd70e6297), - TOBN(0x171792f8, 0x99c97855), TOBN(0x11b393ee, 0xf5a86b5c), - TOBN(0x48ef6582, 0xd8884f27), TOBN(0xbd44737a, 0xbf19ba5f), - TOBN(0x8698de4c, 0xa42062c6), TOBN(0x8975eb80, 0x61ce9c54), - TOBN(0xd50e57c7, 0xd7fe71f3), TOBN(0x15342190, 0xbc97ce38), - TOBN(0x51bda2de, 0x4df07b63), TOBN(0xba12aeae, 0x200eb87d), - TOBN(0xabe135d2, 0xa9b4f8f6), TOBN(0x04619d65, 0xfad6d99c), - TOBN(0x4a6683a7, 0x7994937c), TOBN(0x7a778c8b, 0x6f94f09a), - TOBN(0x8c508623, 0x20a71b89), TOBN(0x241a2aed, 0x1c229165), - TOBN(0x352be595, 0xaaf83a99), TOBN(0x9fbfee7f, 0x1562bac8), - TOBN(0xeaf658b9, 0x5c4017e3), TOBN(0x1dc7f9e0, 0x15120b86), - TOBN(0xd84f13dd, 0x4c034d6f), TOBN(0x283dd737, 0xeaea3038), - TOBN(0x197f2609, 0xcd85d6a2), TOBN(0x6ebbc345, 0xfae60177), - TOBN(0xb80f031b, 0x4e12fede), TOBN(0xde55d0c2, 0x07a2186b), - TOBN(0x1fb3e37f, 0x24dcdd5a), TOBN(0x8d602da5, 0x7ed191fb), - TOBN(0x108fb056, 0x76023e0d), TOBN(0x70178c71, 0x459c20c0), - TOBN(0xfad5a386, 0x3fe54cf0), TOBN(0xa4a3ec4f, 0x02bbb475), - TOBN(0x1aa5ec20, 0x919d94d7), TOBN(0x5d3b63b5, 0xa81e4ab3), - TOBN(0x7fa733d8, 0x5ad3d2af), TOBN(0xfbc586dd, 0xd1ac7a37), - TOBN(0x282925de, 0x40779614), TOBN(0xfe0ffffb, 0xe74a242a), - TOBN(0x3f39e67f, 0x906151e5), TOBN(0xcea27f5f, 0x55e10649), - TOBN(0xdca1d4e1, 0xc17cf7b7), TOBN(0x0c326d12, 0x2fe2362d), - TOBN(0x05f7ac33, 0x7dd35df3), TOBN(0x0c3b7639, 0xc396dbdf), - TOBN(0x0912f5ac, 0x03b7db1c), TOBN(0x9dea4b70, 0x5c9ed4a9), - TOBN(0x475e6e53, 0xaae3f639), TOBN(0xfaba0e7c, 0xfc278bac), - TOBN(0x16f9e221, 0x9490375f), TOBN(0xaebf9746, 0xa5a7ed0a), - TOBN(0x45f9af3f, 0xf41ad5d6), TOBN(0x03c4623c, 0xb2e99224), - TOBN(0x82c5bb5c, 0xb3cf56aa), TOBN(0x64311819, 0x34567ed3), - TOBN(0xec57f211, 0x8be489ac), TOBN(0x2821895d, 0xb9a1104b), - TOBN(0x610dc875, 0x6064e007), TOBN(0x8e526f3f, 0x5b20d0fe), - TOBN(0x6e71ca77, 0x5b645aee), TOBN(0x3d1dcb9f, 0x800e10ff), - TOBN(0x36b51162, 0x189cf6de), TOBN(0x2c5a3e30, 0x6bb17353), - TOBN(0xc186cd3e, 0x2a6c6fbf), TOBN(0xa74516fa, 0x4bf97906), - TOBN(0x5b4b8f4b, 0x279d6901), TOBN(0x0c4e57b4, 0x2b573743), - TOBN(0x75fdb229, 0xb6e386b6), TOBN(0xb46793fd, 0x99deac27), - TOBN(0xeeec47ea, 0xcf712629), TOBN(0xe965f3c4, 0xcbc3b2dd), - TOBN(0x8dd1fb83, 0x425c6559), TOBN(0x7fc00ee6, 0x0af06fda), - TOBN(0xe98c9225, 0x33d956df), TOBN(0x0f1ef335, 0x4fbdc8a2), - TOBN(0x2abb5145, 0xb79b8ea2), TOBN(0x40fd2945, 0xbdbff288), - TOBN(0x6a814ac4, 0xd7185db7), TOBN(0xc4329d6f, 0xc084609a), - TOBN(0xc9ba7b52, 0xed1be45d), TOBN(0x891dd20d, 0xe4cd2c74), - TOBN(0x5a4d4a7f, 0x824139b1), TOBN(0x66c17716, 0xb873c710), - TOBN(0x5e5bc141, 0x2843c4e0), TOBN(0xd5ac4817, 0xb97eb5bf), - TOBN(0xc0f8af54, 0x450c95c7), TOBN(0xc91b3fa0, 0x318406c5), - TOBN(0x360c340a, 0xab9d97f8), TOBN(0xfb57bd07, 0x90a2d611), - TOBN(0x4339ae3c, 0xa6a6f7e5), TOBN(0x9c1fcd2a, 0x2feb8a10), - TOBN(0x972bcca9, 0xc7ea7432), TOBN(0x1b0b924c, 0x308076f6), - TOBN(0x80b2814a, 0x2a5b4ca5), TOBN(0x2f78f55b, 0x61ef3b29), - TOBN(0xf838744a, 0xc18a414f), TOBN(0xc611eaae, 0x903d0a86), - TOBN(0x94dabc16, 0x2a453f55), TOBN(0xe6f2e3da, 0x14efb279), - TOBN(0x5b7a6017, 0x9320dc3c), TOBN(0x692e382f, 0x8df6b5a4), - TOBN(0x3f5e15e0, 0x2d40fa90), TOBN(0xc87883ae, 0x643dd318), - TOBN(0x511053e4, 0x53544774), TOBN(0x834d0ecc, 0x3adba2bc), - TOBN(0x4215d7f7, 0xbae371f5), TOBN(0xfcfd57bf, 0x6c8663bc), - TOBN(0xded2383d, 0xd6901b1d), TOBN(0x3b49fbb4, 0xb5587dc3), - TOBN(0xfd44a08d, 0x07625f62), TOBN(0x3ee4d65b, 0x9de9b762), - }, - { - TOBN(0x64e5137d, 0x0d63d1fa), TOBN(0x658fc052, 0x02a9d89f), - TOBN(0x48894874, 0x50436309), TOBN(0xe9ae30f8, 0xd598da61), - TOBN(0x2ed710d1, 0x818baf91), TOBN(0xe27e9e06, 0x8b6a0c20), - TOBN(0x1e28dcfb, 0x1c1a6b44), TOBN(0x883acb64, 0xd6ac57dc), - TOBN(0x8735728d, 0xc2c6ff70), TOBN(0x79d6122f, 0xc5dc2235), - TOBN(0x23f5d003, 0x19e277f9), TOBN(0x7ee84e25, 0xdded8cc7), - TOBN(0x91a8afb0, 0x63cd880a), TOBN(0x3f3ea7c6, 0x3574af60), - TOBN(0x0cfcdc84, 0x02de7f42), TOBN(0x62d0792f, 0xb31aa152), - TOBN(0x8e1b4e43, 0x8a5807ce), TOBN(0xad283893, 0xe4109a7e), - TOBN(0xc30cc9cb, 0xafd59dda), TOBN(0xf65f36c6, 0x3d8d8093), - TOBN(0xdf31469e, 0xa60d32b2), TOBN(0xee93df4b, 0x3e8191c8), - TOBN(0x9c1017c5, 0x355bdeb5), TOBN(0xd2623185, 0x8616aa28), - TOBN(0xb02c83f9, 0xdec31a21), TOBN(0x988c8b23, 0x6ad9d573), - TOBN(0x53e983ae, 0xa57be365), TOBN(0xe968734d, 0x646f834e), - TOBN(0x9137ea8f, 0x5da6309b), TOBN(0x10f3a624, 0xc1f1ce16), - TOBN(0x782a9ea2, 0xca440921), TOBN(0xdf94739e, 0x5b46f1b5), - TOBN(0x9f9be006, 0xcce85c9b), TOBN(0x360e70d6, 0xa4c7c2d3), - TOBN(0x2cd5beea, 0xaefa1e60), TOBN(0x64cf63c0, 0x8c3d2b6d), - TOBN(0xfb107fa3, 0xe1cf6f90), TOBN(0xb7e937c6, 0xd5e044e6), - TOBN(0x74e8ca78, 0xce34db9f), TOBN(0x4f8b36c1, 0x3e210bd0), - TOBN(0x1df165a4, 0x34a35ea8), TOBN(0x3418e0f7, 0x4d4412f6), - TOBN(0x5af1f8af, 0x518836c3), TOBN(0x42ceef4d, 0x130e1965), - TOBN(0x5560ca0b, 0x543a1957), TOBN(0xc33761e5, 0x886cb123), - TOBN(0x66624b1f, 0xfe98ed30), TOBN(0xf772f4bf, 0x1090997d), - TOBN(0xf4e540bb, 0x4885d410), TOBN(0x7287f810, 0x9ba5f8d7), - TOBN(0x22d0d865, 0xde98dfb1), TOBN(0x49ff51a1, 0xbcfbb8a3), - TOBN(0xb6b6fa53, 0x6bc3012e), TOBN(0x3d31fd72, 0x170d541d), - TOBN(0x8018724f, 0x4b0f4966), TOBN(0x79e7399f, 0x87dbde07), - TOBN(0x56f8410e, 0xf4f8b16a), TOBN(0x97241afe, 0xc47b266a), - TOBN(0x0a406b8e, 0x6d9c87c1), TOBN(0x803f3e02, 0xcd42ab1b), - TOBN(0x7f0309a8, 0x04dbec69), TOBN(0xa83b85f7, 0x3bbad05f), - TOBN(0xc6097273, 0xad8e197f), TOBN(0xc097440e, 0x5067adc1), - TOBN(0x730eafb6, 0x3524ff16), TOBN(0xd7f9b51e, 0x823fc6ce), - TOBN(0x27bd0d32, 0x443e4ac0), TOBN(0x40c59ad9, 0x4d66f217), - TOBN(0x6c33136f, 0x17c387a4), TOBN(0x5043b8d5, 0xeb86804d), - TOBN(0x74970312, 0x675a73c9), TOBN(0x838fdb31, 0xf16669b6), - TOBN(0xc507b6dd, 0x418e7ddd), TOBN(0x39888d93, 0x472f19d6), - TOBN(0x7eae26be, 0x0c27eb4d), TOBN(0x17b53ed3, 0xfbabb884), - TOBN(0xfc27021b, 0x2b01ae4f), TOBN(0x88462e87, 0xcf488682), - TOBN(0xbee096ec, 0x215e2d87), TOBN(0xeb2fea9a, 0xd242e29b), - TOBN(0x5d985b5f, 0xb821fc28), TOBN(0x89d2e197, 0xdc1e2ad2), - TOBN(0x55b566b8, 0x9030ba62), TOBN(0xe3fd41b5, 0x4f41b1c6), - TOBN(0xb738ac2e, 0xb9a96d61), TOBN(0x7f8567ca, 0x369443f4), - TOBN(0x8698622d, 0xf803a440), TOBN(0x2b586236, 0x8fe2f4dc), - TOBN(0xbbcc00c7, 0x56b95bce), TOBN(0x5ec03906, 0x616da680), - TOBN(0x79162ee6, 0x72214252), TOBN(0x43132b63, 0x86a892d2), - TOBN(0x4bdd3ff2, 0x2f3263bf), TOBN(0xd5b3733c, 0x9cd0a142), - TOBN(0x592eaa82, 0x44415ccb), TOBN(0x663e8924, 0x8d5474ea), - TOBN(0x8058a25e, 0x5236344e), TOBN(0x82e8df9d, 0xbda76ee6), - TOBN(0xdcf6efd8, 0x11cc3d22), TOBN(0x00089cda, 0x3b4ab529), - TOBN(0x91d3a071, 0xbd38a3db), TOBN(0x4ea97fc0, 0xef72b925), - TOBN(0x0c9fc15b, 0xea3edf75), TOBN(0x5a6297cd, 0xa4348ed3), - TOBN(0x0d38ab35, 0xce7c42d4), TOBN(0x9fd493ef, 0x82feab10), - TOBN(0x46056b6d, 0x82111b45), TOBN(0xda11dae1, 0x73efc5c3), - TOBN(0xdc740278, 0x5545a7fb), TOBN(0xbdb2601c, 0x40d507e6), - TOBN(0x121dfeeb, 0x7066fa58), TOBN(0x214369a8, 0x39ae8c2a), - TOBN(0x195709cb, 0x06e0956c), TOBN(0x4c9d254f, 0x010cd34b), - TOBN(0xf51e13f7, 0x0471a532), TOBN(0xe19d6791, 0x1e73054d), - TOBN(0xf702a628, 0xdb5c7be3), TOBN(0xc7141218, 0xb24dde05), - TOBN(0xdc18233c, 0xf29b2e2e), TOBN(0x3a6bd1e8, 0x85342dba), - TOBN(0x3f747fa0, 0xb311898c), TOBN(0xe2a272e4, 0xcd0eac65), - TOBN(0x4bba5851, 0xf914d0bc), TOBN(0x7a1a9660, 0xc4a43ee3), - TOBN(0xe5a367ce, 0xa1c8cde9), TOBN(0x9d958ba9, 0x7271abe3), - TOBN(0xf3ff7eb6, 0x3d1615cd), TOBN(0xa2280dce, 0xf5ae20b0), - TOBN(0x56dba5c1, 0xcf640147), TOBN(0xea5a2e3d, 0x5e83d118), - TOBN(0x04cd6b6d, 0xda24c511), TOBN(0x1c0f4671, 0xe854d214), - TOBN(0x91a6b7a9, 0x69565381), TOBN(0xdc966240, 0xdecf1f5b), - TOBN(0x1b22d21c, 0xfcf5d009), TOBN(0x2a05f641, 0x9021dbd5), - TOBN(0x8c0ed566, 0xd4312483), TOBN(0x5179a95d, 0x643e216f), - TOBN(0xcc185fec, 0x17044493), TOBN(0xb3063339, 0x54991a21), - TOBN(0xd801ecdb, 0x0081a726), TOBN(0x0149b0c6, 0x4fa89bbb), - TOBN(0xafe9065a, 0x4391b6b9), TOBN(0xedc92786, 0xd633f3a3), - TOBN(0xe408c24a, 0xae6a8e13), TOBN(0x85833fde, 0x9f3897ab), - TOBN(0x43800e7e, 0xd81a0715), TOBN(0xde08e346, 0xb44ffc5f), - TOBN(0x7094184c, 0xcdeff2e0), TOBN(0x49f9387b, 0x165eaed1), - TOBN(0x635d6129, 0x777c468a), TOBN(0x8c0dcfd1, 0x538c2dd8), - TOBN(0xd6d9d9e3, 0x7a6a308b), TOBN(0x62375830, 0x4c2767d3), - TOBN(0x874a8bc6, 0xf38cbeb6), TOBN(0xd94d3f1a, 0xccb6fd9e), - TOBN(0x92a9735b, 0xba21f248), TOBN(0x272ad0e5, 0x6cd1efb0), - TOBN(0x7437b69c, 0x05b03284), TOBN(0xe7f04702, 0x6948c225), - TOBN(0x8a56c04a, 0xcba2ecec), TOBN(0x0c181270, 0xe3a73e41), - TOBN(0x6cb34e9d, 0x03e93725), TOBN(0xf77c8713, 0x496521a9), - TOBN(0x94569183, 0xfa7f9f90), TOBN(0xf2e7aa4c, 0x8c9707ad), - TOBN(0xced2c9ba, 0x26c1c9a3), TOBN(0x9109fe96, 0x40197507), - TOBN(0x9ae868a9, 0xe9adfe1c), TOBN(0x3984403d, 0x314e39bb), - TOBN(0xb5875720, 0xf2fe378f), TOBN(0x33f901e0, 0xba44a628), - TOBN(0xea1125fe, 0x3652438c), TOBN(0xae9ec4e6, 0x9dd1f20b), - TOBN(0x1e740d9e, 0xbebf7fbd), TOBN(0x6dbd3ddc, 0x42dbe79c), - TOBN(0x62082aec, 0xedd36776), TOBN(0xf612c478, 0xe9859039), - TOBN(0xa493b201, 0x032f7065), TOBN(0xebd4d8f2, 0x4ff9b211), - TOBN(0x3f23a0aa, 0xaac4cb32), TOBN(0xea3aadb7, 0x15ed4005), - TOBN(0xacf17ea4, 0xafa27e63), TOBN(0x56125c1a, 0xc11fd66c), - TOBN(0x266344a4, 0x3794f8dc), TOBN(0xdcca923a, 0x483c5c36), - TOBN(0x2d6b6bbf, 0x3f9d10a0), TOBN(0xb320c5ca, 0x81d9bdf3), - TOBN(0x620e28ff, 0x47b50a95), TOBN(0x933e3b01, 0xcef03371), - TOBN(0xf081bf85, 0x99100153), TOBN(0x183be9a0, 0xc3a8c8d6), - TOBN(0x4e3ddc5a, 0xd6bbe24d), TOBN(0xc6c74630, 0x53843795), - TOBN(0x78193dd7, 0x65ec2d4c), TOBN(0xb8df26cc, 0xcd3c89b2), - TOBN(0x98dbe399, 0x5a483f8d), TOBN(0x72d8a957, 0x7dd3313a), - TOBN(0x65087294, 0xab0bd375), TOBN(0xfcd89248, 0x7c259d16), - TOBN(0x8a9443d7, 0x7613aa81), TOBN(0x80100800, 0x85fe6584), - TOBN(0x70fc4dbc, 0x7fb10288), TOBN(0xf58280d3, 0xe86beee8), - TOBN(0x14fdd82f, 0x7c978c38), TOBN(0xdf1204c1, 0x0de44d7b), - TOBN(0xa08a1c84, 0x4160252f), TOBN(0x591554ca, 0xc17646a5), - TOBN(0x214a37d6, 0xa05bd525), TOBN(0x48d5f09b, 0x07957b3c), - TOBN(0x0247cdcb, 0xd7109bc9), TOBN(0x40f9e4bb, 0x30599ce7), - TOBN(0xc325fa03, 0xf46ad2ec), TOBN(0x00f766cf, 0xc3e3f9ee), - TOBN(0xab556668, 0xd43a4577), TOBN(0x68d30a61, 0x3ee03b93), - TOBN(0x7ddc81ea, 0x77b46a08), TOBN(0xcf5a6477, 0xc7480699), - TOBN(0x43a8cb34, 0x6633f683), TOBN(0x1b867e6b, 0x92363c60), - TOBN(0x43921114, 0x1f60558e), TOBN(0xcdbcdd63, 0x2f41450e), - TOBN(0x7fc04601, 0xcc630e8b), TOBN(0xea7c66d5, 0x97038b43), - TOBN(0x7259b8a5, 0x04e99fd8), TOBN(0x98a8dd12, 0x4785549a), - TOBN(0x0e459a7c, 0x840552e1), TOBN(0xcdfcf4d0, 0x4bb0909e), - TOBN(0x34a86db2, 0x53758da7), TOBN(0xe643bb83, 0xeac997e1), - TOBN(0x96400bd7, 0x530c5b7e), TOBN(0x9f97af87, 0xb41c8b52), - TOBN(0x34fc8820, 0xfbeee3f9), TOBN(0x93e53490, 0x49091afd), - TOBN(0x764b9be5, 0x9a31f35c), TOBN(0x71f37864, 0x57e3d924), - TOBN(0x02fb34e0, 0x943aa75e), TOBN(0xa18c9c58, 0xab8ff6e4), - TOBN(0x080f31b1, 0x33cf0d19), TOBN(0x5c9682db, 0x083518a7), - TOBN(0x873d4ca6, 0xb709c3de), TOBN(0x64a84262, 0x3575b8f0), - TOBN(0x6275da1f, 0x020154bb), TOBN(0x97678caa, 0xd17cf1ab), - TOBN(0x8779795f, 0x951a95c3), TOBN(0xdd35b163, 0x50fccc08), - TOBN(0x32709627, 0x33d8f031), TOBN(0x3c5ab10a, 0x498dd85c), - TOBN(0xb6c185c3, 0x41dca566), TOBN(0x7de7feda, 0xd8622aa3), - TOBN(0x99e84d92, 0x901b6dfb), TOBN(0x30a02b0e, 0x7c4ad288), - TOBN(0xc7c81daa, 0x2fd3cf36), TOBN(0xd1319547, 0xdf89e59f), - TOBN(0xb2be8184, 0xcd496733), TOBN(0xd5f449eb, 0x93d3412b), - TOBN(0x7ea41b1b, 0x25fe531d), TOBN(0xf9797432, 0x6a1d5646), - TOBN(0x86067f72, 0x2bde501a), TOBN(0xf91481c0, 0x0c85e89c), - TOBN(0xca8ee465, 0xf8b05bc6), TOBN(0x1844e1cf, 0x02e83cda), - TOBN(0xca82114a, 0xb4dbe33b), TOBN(0x0f9f8769, 0x4eabfde2), - TOBN(0x4936b1c0, 0x38b27fe2), TOBN(0x63b6359b, 0xaba402df), - TOBN(0x40c0ea2f, 0x656bdbab), TOBN(0x9c992a89, 0x6580c39c), - TOBN(0x600e8f15, 0x2a60aed1), TOBN(0xeb089ca4, 0xe0bf49df), - TOBN(0x9c233d7d, 0x2d42d99a), TOBN(0x648d3f95, 0x4c6bc2fa), - TOBN(0xdcc383a8, 0xe1add3f3), TOBN(0xf42c0c6a, 0x4f64a348), - TOBN(0x2abd176f, 0x0030dbdb), TOBN(0x4de501a3, 0x7d6c215e), - TOBN(0x4a107c1f, 0x4b9a64bc), TOBN(0xa77f0ad3, 0x2496cd59), - TOBN(0xfb78ac62, 0x7688dffb), TOBN(0x7025a2ca, 0x67937d8e), - TOBN(0xfde8b2d1, 0xd1a8f4e7), TOBN(0xf5b3da47, 0x7354927c), - TOBN(0xe48606a3, 0xd9205735), TOBN(0xac477cc6, 0xe177b917), - TOBN(0xfb1f73d2, 0xa883239a), TOBN(0xe12572f6, 0xcc8b8357), - TOBN(0x9d355e9c, 0xfb1f4f86), TOBN(0x89b795f8, 0xd9f3ec6e), - TOBN(0x27be56f1, 0xb54398dc), TOBN(0x1890efd7, 0x3fedeed5), - TOBN(0x62f77f1f, 0x9c6d0140), TOBN(0x7ef0e314, 0x596f0ee4), - TOBN(0x50ca6631, 0xcc61dab3), TOBN(0x4a39801d, 0xf4866e4f), - TOBN(0x66c8d032, 0xae363b39), TOBN(0x22c591e5, 0x2ead66aa), - TOBN(0x954ba308, 0xde02a53e), TOBN(0x2a6c060f, 0xd389f357), - TOBN(0xe6cfcde8, 0xfbf40b66), TOBN(0x8e02fc56, 0xc6340ce1), - TOBN(0xe4957795, 0x73adb4ba), TOBN(0x7b86122c, 0xa7b03805), - TOBN(0x63f83512, 0x0c8e6fa6), TOBN(0x83660ea0, 0x057d7804), - TOBN(0xbad79105, 0x21ba473c), TOBN(0xb6c50bee, 0xded5389d), - TOBN(0xee2caf4d, 0xaa7c9bc0), TOBN(0xd97b8de4, 0x8c4e98a7), - TOBN(0xa9f63e70, 0xab3bbddb), TOBN(0x3898aabf, 0x2597815a), - TOBN(0x7659af89, 0xac15b3d9), TOBN(0xedf7725b, 0x703ce784), - TOBN(0x25470fab, 0xe085116b), TOBN(0x04a43375, 0x87285310), - TOBN(0x4e39187e, 0xe2bfd52f), TOBN(0x36166b44, 0x7d9ebc74), - TOBN(0x92ad433c, 0xfd4b322c), TOBN(0x726aa817, 0xba79ab51), - TOBN(0xf96eacd8, 0xc1db15eb), TOBN(0xfaf71e91, 0x0476be63), - TOBN(0xdd69a640, 0x641fad98), TOBN(0xb7995918, 0x29622559), - TOBN(0x03c6daa5, 0xde4199dc), TOBN(0x92cadc97, 0xad545eb4), - TOBN(0x1028238b, 0x256534e4), TOBN(0x73e80ce6, 0x8595409a), - TOBN(0x690d4c66, 0xd05dc59b), TOBN(0xc95f7b8f, 0x981dee80), - TOBN(0xf4337014, 0xd856ac25), TOBN(0x441bd9dd, 0xac524dca), - TOBN(0x640b3d85, 0x5f0499f5), TOBN(0x39cf84a9, 0xd5fda182), - TOBN(0x04e7b055, 0xb2aa95a0), TOBN(0x29e33f0a, 0x0ddf1860), - TOBN(0x082e74b5, 0x423f6b43), TOBN(0x217edeb9, 0x0aaa2b0f), - TOBN(0x58b83f35, 0x83cbea55), TOBN(0xc485ee4d, 0xbc185d70), - TOBN(0x833ff03b, 0x1e5f6992), TOBN(0xb5b9b9cc, 0xcf0c0dd5), - TOBN(0x7caaee8e, 0x4e9e8a50), TOBN(0x462e907b, 0x6269dafd), - TOBN(0x6ed5cee9, 0xfbe791c6), TOBN(0x68ca3259, 0xed430790), - TOBN(0x2b72bdf2, 0x13b5ba88), TOBN(0x60294c8a, 0x35ef0ac4), - TOBN(0x9c3230ed, 0x19b99b08), TOBN(0x560fff17, 0x6c2589aa), - TOBN(0x552b8487, 0xd6770374), TOBN(0xa373202d, 0x9a56f685), - TOBN(0xd3e7f907, 0x45f175d9), TOBN(0x3c2f315f, 0xd080d810), - TOBN(0x1130e9dd, 0x7b9520e8), TOBN(0xc078f9e2, 0x0af037b5), - TOBN(0x38cd2ec7, 0x1e9c104c), TOBN(0x0f684368, 0xc472fe92), - TOBN(0xd3f1b5ed, 0x6247e7ef), TOBN(0xb32d33a9, 0x396dfe21), - TOBN(0x46f59cf4, 0x4a9aa2c2), TOBN(0x69cd5168, 0xff0f7e41), - TOBN(0x3f59da0f, 0x4b3234da), TOBN(0xcf0b0235, 0xb4579ebe), - TOBN(0x6d1cbb25, 0x6d2476c7), TOBN(0x4f0837e6, 0x9dc30f08), - TOBN(0x9a4075bb, 0x906f6e98), TOBN(0x253bb434, 0xc761e7d1), - TOBN(0xde2e645f, 0x6e73af10), TOBN(0xb89a4060, 0x0c5f131c), - TOBN(0xd12840c5, 0xb8cc037f), TOBN(0x3d093a5b, 0x7405bb47), - TOBN(0x6202c253, 0x206348b8), TOBN(0xbf5d57fc, 0xc55a3ca7), - TOBN(0x89f6c90c, 0x8c3bef48), TOBN(0x23ac7623, 0x5a0a960a), - TOBN(0xdfbd3d6b, 0x552b42ab), TOBN(0x3ef22458, 0x132061f6), - TOBN(0xd74e9bda, 0xc97e6516), TOBN(0x88779360, 0xc230f49e), - TOBN(0xa6ec1de3, 0x1e74ea49), TOBN(0x581dcee5, 0x3fb645a2), - TOBN(0xbaef2391, 0x8f483f14), TOBN(0x6d2dddfc, 0xd137d13b), - TOBN(0x54cde50e, 0xd2743a42), TOBN(0x89a34fc5, 0xe4d97e67), - TOBN(0x13f1f5b3, 0x12e08ce5), TOBN(0xa80540b8, 0xa7f0b2ca), - TOBN(0x854bcf77, 0x01982805), TOBN(0xb8653ffd, 0x233bea04), - TOBN(0x8e7b8787, 0x02b0b4c9), TOBN(0x2675261f, 0x9acb170a), - TOBN(0x061a9d90, 0x930c14e5), TOBN(0xb59b30e0, 0xdef0abea), - TOBN(0x1dc19ea6, 0x0200ec7d), TOBN(0xb6f4a3f9, 0x0bce132b), - TOBN(0xb8d5de90, 0xf13e27e0), TOBN(0xbaee5ef0, 0x1fade16f), - TOBN(0x6f406aaa, 0xe4c6cf38), TOBN(0xab4cfe06, 0xd1369815), - TOBN(0x0dcffe87, 0xefd550c6), TOBN(0x9d4f59c7, 0x75ff7d39), - TOBN(0xb02553b1, 0x51deb6ad), TOBN(0x812399a4, 0xb1877749), - TOBN(0xce90f71f, 0xca6006e1), TOBN(0xc32363a6, 0xb02b6e77), - TOBN(0x02284fbe, 0xdc36c64d), TOBN(0x86c81e31, 0xa7e1ae61), - TOBN(0x2576c7e5, 0xb909d94a), TOBN(0x8b6f7d02, 0x818b2bb0), - TOBN(0xeca3ed07, 0x56faa38a), TOBN(0xa3790e6c, 0x9305bb54), - TOBN(0xd784eeda, 0x7bc73061), TOBN(0xbd56d369, 0x6dd50614), - TOBN(0xd6575949, 0x229a8aa9), TOBN(0xdcca8f47, 0x4595ec28), - TOBN(0x814305c1, 0x06ab4fe6), TOBN(0xc8c39768, 0x24f43f16), - TOBN(0xe2a45f36, 0x523f2b36), TOBN(0x995c6493, 0x920d93bb), - TOBN(0xf8afdab7, 0x90f1632b), TOBN(0x79ebbecd, 0x1c295954), - TOBN(0xc7bb3ddb, 0x79592f48), TOBN(0x67216a7b, 0x5f88e998), - TOBN(0xd91f098b, 0xbc01193e), TOBN(0xf7d928a5, 0xb1db83fc), - TOBN(0x55e38417, 0xe991f600), TOBN(0x2a91113e, 0x2981a934), - TOBN(0xcbc9d648, 0x06b13bde), TOBN(0xb011b6ac, 0x0755ff44), - TOBN(0x6f4cb518, 0x045ec613), TOBN(0x522d2d31, 0xc2f5930a), - TOBN(0x5acae1af, 0x382e65de), TOBN(0x57643067, 0x27bc966f), - TOBN(0x5e12705d, 0x1c7193f0), TOBN(0xf0f32f47, 0x3be8858e), - TOBN(0x785c3d7d, 0x96c6dfc7), TOBN(0xd75b4a20, 0xbf31795d), - TOBN(0x91acf17b, 0x342659d4), TOBN(0xe596ea34, 0x44f0378f), - TOBN(0x4515708f, 0xce52129d), TOBN(0x17387e1e, 0x79f2f585), - TOBN(0x72cfd2e9, 0x49dee168), TOBN(0x1ae05223, 0x3e2af239), - TOBN(0x009e75be, 0x1d94066a), TOBN(0x6cca31c7, 0x38abf413), - TOBN(0xb50bd61d, 0x9bc49908), TOBN(0x4a9b4a8c, 0xf5e2bc1e), - TOBN(0xeb6cc5f7, 0x946f83ac), TOBN(0x27da93fc, 0xebffab28), - TOBN(0xea314c96, 0x4821c8c5), TOBN(0x8de49ded, 0xa83c15f4), - TOBN(0x7a64cf20, 0x7af33004), TOBN(0x45f1bfeb, 0xc9627e10), - TOBN(0x878b0626, 0x54b9df60), TOBN(0x5e4fdc3c, 0xa95c0b33), - TOBN(0xe54a37ca, 0xc2035d8e), TOBN(0x9087cda9, 0x80f20b8c), - TOBN(0x36f61c23, 0x8319ade4), TOBN(0x766f287a, 0xde8cfdf8), - TOBN(0x48821948, 0x346f3705), TOBN(0x49a7b853, 0x16e4f4a2), - TOBN(0xb9b3f8a7, 0x5cedadfd), TOBN(0x8f562815, 0x8db2a815), - TOBN(0xc0b7d554, 0x01f68f95), TOBN(0x12971e27, 0x688a208e), - TOBN(0xc9f8b696, 0xd0ff34fc), TOBN(0x20824de2, 0x1222718c), - TOBN(0x7213cf9f, 0x0c95284d), TOBN(0xe2ad741b, 0xdc158240), - TOBN(0x0ee3a6df, 0x54043ccf), TOBN(0x16ff479b, 0xd84412b3), - TOBN(0xf6c74ee0, 0xdfc98af0), TOBN(0xa78a169f, 0x52fcd2fb), - TOBN(0xd8ae8746, 0x99c930e9), TOBN(0x1d33e858, 0x49e117a5), - TOBN(0x7581fcb4, 0x6624759f), TOBN(0xde50644f, 0x5bedc01d), - TOBN(0xbeec5d00, 0xcaf3155e), TOBN(0x672d66ac, 0xbc73e75f), - TOBN(0x86b9d8c6, 0x270b01db), TOBN(0xd249ef83, 0x50f55b79), - TOBN(0x6131d6d4, 0x73978fe3), TOBN(0xcc4e4542, 0x754b00a1), - TOBN(0x4e05df05, 0x57dfcfe9), TOBN(0x94b29cdd, 0x51ef6bf0), - TOBN(0xe4530cff, 0x9bc7edf2), TOBN(0x8ac236fd, 0xd3da65f3), - TOBN(0x0faf7d5f, 0xc8eb0b48), TOBN(0x4d2de14c, 0x660eb039), - TOBN(0xc006bba7, 0x60430e54), TOBN(0x10a2d0d6, 0xda3289ab), - TOBN(0x9c037a5d, 0xd7979c59), TOBN(0x04d1f3d3, 0xa116d944), - TOBN(0x9ff22473, 0x8a0983cd), TOBN(0x28e25b38, 0xc883cabb), - TOBN(0xe968dba5, 0x47a58995), TOBN(0x2c80b505, 0x774eebdf), - TOBN(0xee763b71, 0x4a953beb), TOBN(0x502e223f, 0x1642e7f6), - TOBN(0x6fe4b641, 0x61d5e722), TOBN(0x9d37c5b0, 0xdbef5316), - TOBN(0x0115ed70, 0xf8330bc7), TOBN(0x139850e6, 0x75a72789), - TOBN(0x27d7faec, 0xffceccc2), TOBN(0x3016a860, 0x4fd9f7f6), - TOBN(0xc492ec64, 0x4cd8f64c), TOBN(0x58a2d790, 0x279d7b51), - TOBN(0x0ced1fc5, 0x1fc75256), TOBN(0x3e658aed, 0x8f433017), - TOBN(0x0b61942e, 0x05da59eb), TOBN(0xba3d60a3, 0x0ddc3722), - TOBN(0x7c311cd1, 0x742e7f87), TOBN(0x6473ffee, 0xf6b01b6e), - }, - { - TOBN(0x8303604f, 0x692ac542), TOBN(0xf079ffe1, 0x227b91d3), - TOBN(0x19f63e63, 0x15aaf9bd), TOBN(0xf99ee565, 0xf1f344fb), - TOBN(0x8a1d661f, 0xd6219199), TOBN(0x8c883bc6, 0xd48ce41c), - TOBN(0x1065118f, 0x3c74d904), TOBN(0x713889ee, 0x0faf8b1b), - TOBN(0x972b3f8f, 0x81a1b3be), TOBN(0x4f3ce145, 0xce2764a0), - TOBN(0xe2d0f1cc, 0x28c4f5f7), TOBN(0xdeee0c0d, 0xc7f3985b), - TOBN(0x7df4adc0, 0xd39e25c3), TOBN(0x40619820, 0xc467a080), - TOBN(0x440ebc93, 0x61cf5a58), TOBN(0x527729a6, 0x422ad600), - TOBN(0xca6c0937, 0xb1b76ba6), TOBN(0x1a2eab85, 0x4d2026dc), - TOBN(0xb1715e15, 0x19d9ae0a), TOBN(0xf1ad9199, 0xbac4a026), - TOBN(0x35b3dfb8, 0x07ea7b0e), TOBN(0xedf5496f, 0x3ed9eb89), - TOBN(0x8932e5ff, 0x2d6d08ab), TOBN(0xf314874e, 0x25bd2731), - TOBN(0xefb26a75, 0x3f73f449), TOBN(0x1d1c94f8, 0x8d44fc79), - TOBN(0x49f0fbc5, 0x3bc0dc4d), TOBN(0xb747ea0b, 0x3698a0d0), - TOBN(0x5218c3fe, 0x228d291e), TOBN(0x35b804b5, 0x43c129d6), - TOBN(0xfac859b8, 0xd1acc516), TOBN(0x6c10697d, 0x95d6e668), - TOBN(0xc38e438f, 0x0876fd4e), TOBN(0x45f0c307, 0x83d2f383), - TOBN(0x203cc2ec, 0xb10934cb), TOBN(0x6a8f2439, 0x2c9d46ee), - TOBN(0xf16b431b, 0x65ccde7b), TOBN(0x41e2cd18, 0x27e76a6f), - TOBN(0xb9c8cf8f, 0x4e3484d7), TOBN(0x64426efd, 0x8315244a), - TOBN(0x1c0a8e44, 0xfc94dea3), TOBN(0x34c8cdbf, 0xdad6a0b0), - TOBN(0x919c3840, 0x04113cef), TOBN(0xfd32fba4, 0x15490ffa), - TOBN(0x58d190f6, 0x795dcfb7), TOBN(0xfef01b03, 0x83588baf), - TOBN(0x9e6d1d63, 0xca1fc1c0), TOBN(0x53173f96, 0xf0a41ac9), - TOBN(0x2b1d402a, 0xba16f73b), TOBN(0x2fb31014, 0x8cf9b9fc), - TOBN(0x2d51e60e, 0x446ef7bf), TOBN(0xc731021b, 0xb91e1745), - TOBN(0x9d3b4724, 0x4fee99d4), TOBN(0x4bca48b6, 0xfac5c1ea), - TOBN(0x70f5f514, 0xbbea9af7), TOBN(0x751f55a5, 0x974c283a), - TOBN(0x6e30251a, 0xcb452fdb), TOBN(0x31ee6965, 0x50f30650), - TOBN(0xb0b3e508, 0x933548d9), TOBN(0xb8949a4f, 0xf4b0ef5b), - TOBN(0x208b8326, 0x3c88f3bd), TOBN(0xab147c30, 0xdb1d9989), - TOBN(0xed6515fd, 0x44d4df03), TOBN(0x17a12f75, 0xe72eb0c5), - TOBN(0x3b59796d, 0x36cf69db), TOBN(0x1219eee9, 0x56670c18), - TOBN(0xfe3341f7, 0x7a070d8e), TOBN(0x9b70130b, 0xa327f90c), - TOBN(0x36a32462, 0x0ae18e0e), TOBN(0x2021a623, 0x46c0a638), - TOBN(0x251b5817, 0xc62eb0d4), TOBN(0x87bfbcdf, 0x4c762293), - TOBN(0xf78ab505, 0xcdd61d64), TOBN(0x8c7a53fc, 0xc8c18857), - TOBN(0xa653ce6f, 0x16147515), TOBN(0x9c923aa5, 0xea7d52d5), - TOBN(0xc24709cb, 0x5c18871f), TOBN(0x7d53bec8, 0x73b3cc74), - TOBN(0x59264aff, 0xfdd1d4c4), TOBN(0x5555917e, 0x240da582), - TOBN(0xcae8bbda, 0x548f5a0e), TOBN(0x1910eaba, 0x3bbfbbe1), - TOBN(0xae579685, 0x7677afc3), TOBN(0x49ea61f1, 0x73ff0b5c), - TOBN(0x78655478, 0x4f7c3922), TOBN(0x95d337cd, 0x20c68eef), - TOBN(0x68f1e1e5, 0xdf779ab9), TOBN(0x14b491b0, 0xb5cf69a8), - TOBN(0x7a6cbbe0, 0x28e3fe89), TOBN(0xe7e1fee4, 0xc5aac0eb), - TOBN(0x7f47eda5, 0x697e5140), TOBN(0x4f450137, 0xb454921f), - TOBN(0xdb625f84, 0x95cd8185), TOBN(0x74be0ba1, 0xcdb2e583), - TOBN(0xaee4fd7c, 0xdd5e6de4), TOBN(0x4251437d, 0xe8101739), - TOBN(0x686d72a0, 0xac620366), TOBN(0x4be3fb9c, 0xb6d59344), - TOBN(0x6e8b44e7, 0xa1eb75b9), TOBN(0x84e39da3, 0x91a5c10c), - TOBN(0x37cc1490, 0xb38f0409), TOBN(0x02951943, 0x2c2ade82), - TOBN(0x9b688783, 0x1190a2d8), TOBN(0x25627d14, 0x231182ba), - TOBN(0x6eb550aa, 0x658a6d87), TOBN(0x1405aaa7, 0xcf9c7325), - TOBN(0xd147142e, 0x5c8748c9), TOBN(0x7f637e4f, 0x53ede0e0), - TOBN(0xf8ca2776, 0x14ffad2c), TOBN(0xe58fb1bd, 0xbafb6791), - TOBN(0x17158c23, 0xbf8f93fc), TOBN(0x7f15b373, 0x0a4a4655), - TOBN(0x39d4add2, 0xd842ca72), TOBN(0xa71e4391, 0x3ed96305), - TOBN(0x5bb09cbe, 0x6700be14), TOBN(0x68d69d54, 0xd8befcf6), - TOBN(0xa45f5367, 0x37183bcf), TOBN(0x7152b7bb, 0x3370dff7), - TOBN(0xcf887baa, 0xbf12525b), TOBN(0xe7ac7bdd, 0xd6d1e3cd), - TOBN(0x25914f78, 0x81fdad90), TOBN(0xcf638f56, 0x0d2cf6ab), - TOBN(0xb90bc03f, 0xcc054de5), TOBN(0x932811a7, 0x18b06350), - TOBN(0x2f00b330, 0x9bbd11ff), TOBN(0x76108a6f, 0xb4044974), - TOBN(0x801bb9e0, 0xa851d266), TOBN(0x0dd099be, 0xbf8990c1), - TOBN(0x58c5aaaa, 0xabe32986), TOBN(0x0fe9dd2a, 0x50d59c27), - TOBN(0x84951ff4, 0x8d307305), TOBN(0x6c23f829, 0x86529b78), - TOBN(0x50bb2218, 0x0b136a79), TOBN(0x7e2174de, 0x77a20996), - TOBN(0x6f00a4b9, 0xc0bb4da6), TOBN(0x89a25a17, 0xefdde8da), - TOBN(0xf728a27e, 0xc11ee01d), TOBN(0xf900553a, 0xe5f10dfb), - TOBN(0x189a83c8, 0x02ec893c), TOBN(0x3ca5bdc1, 0x23f66d77), - TOBN(0x98781537, 0x97eada9f), TOBN(0x59c50ab3, 0x10256230), - TOBN(0x346042d9, 0x323c69b3), TOBN(0x1b715a6d, 0x2c460449), - TOBN(0xa41dd476, 0x6ae06e0b), TOBN(0xcdd7888e, 0x9d42e25f), - TOBN(0x0f395f74, 0x56b25a20), TOBN(0xeadfe0ae, 0x8700e27e), - TOBN(0xb09d52a9, 0x69950093), TOBN(0x3525d9cb, 0x327f8d40), - TOBN(0xb8235a94, 0x67df886a), TOBN(0x77e4b0dd, 0x035faec2), - TOBN(0x115eb20a, 0x517d7061), TOBN(0x77fe3433, 0x6c2df683), - TOBN(0x6870ddc7, 0xcdc6fc67), TOBN(0xb1610588, 0x0b87de83), - TOBN(0x343584ca, 0xd9c4ddbe), TOBN(0xb3164f1c, 0x3d754be2), - TOBN(0x0731ed3a, 0xc1e6c894), TOBN(0x26327dec, 0x4f6b904c), - TOBN(0x9d49c6de, 0x97b5cd32), TOBN(0x40835dae, 0xb5eceecd), - TOBN(0xc66350ed, 0xd9ded7fe), TOBN(0x8aeebb5c, 0x7a678804), - TOBN(0x51d42fb7, 0x5b8ee9ec), TOBN(0xd7a17bdd, 0x8e3ca118), - TOBN(0x40d7511a, 0x2ef4400e), TOBN(0xc48990ac, 0x875a66f4), - TOBN(0x8de07d2a, 0x2199e347), TOBN(0xbee75556, 0x2a39e051), - TOBN(0x56918786, 0x916e51dc), TOBN(0xeb191313, 0x4a2d89ec), - TOBN(0x6679610d, 0x37d341ed), TOBN(0x434fbb41, 0x56d51c2b), - TOBN(0xe54b7ee7, 0xd7492dba), TOBN(0xaa33a79a, 0x59021493), - TOBN(0x49fc5054, 0xe4bd6d3d), TOBN(0x09540f04, 0x5ab551d0), - TOBN(0x8acc9085, 0x4942d3a6), TOBN(0x231af02f, 0x2d28323b), - TOBN(0x93458cac, 0x0992c163), TOBN(0x1fef8e71, 0x888e3bb4), - TOBN(0x27578da5, 0xbe8c268c), TOBN(0xcc8be792, 0xe805ec00), - TOBN(0x29267bae, 0xc61c3855), TOBN(0xebff429d, 0x58c1fd3b), - TOBN(0x22d886c0, 0x8c0b93b8), TOBN(0xca5e00b2, 0x2ddb8953), - TOBN(0xcf330117, 0xc3fed8b7), TOBN(0xd49ac6fa, 0x819c01f6), - TOBN(0x6ddaa6bd, 0x3c0fbd54), TOBN(0x91743068, 0x8049a2cf), - TOBN(0xd67f981e, 0xaff2ef81), TOBN(0xc3654d35, 0x2818ae80), - TOBN(0x81d05044, 0x1b2aa892), TOBN(0x2db067bf, 0x3d099328), - TOBN(0xe7c79e86, 0x703dcc97), TOBN(0xe66f9b37, 0xe133e215), - TOBN(0xcdf119a6, 0xe39a7a5c), TOBN(0x47c60de3, 0x876f1b61), - TOBN(0x6e405939, 0xd860f1b2), TOBN(0x3e9a1dbc, 0xf5ed4d4a), - TOBN(0x3f23619e, 0xc9b6bcbd), TOBN(0x5ee790cf, 0x734e4497), - TOBN(0xf0a834b1, 0x5bdaf9bb), TOBN(0x02cedda7, 0x4ca295f0), - TOBN(0x4619aa2b, 0xcb8e378c), TOBN(0xe5613244, 0xcc987ea4), - TOBN(0x0bc022cc, 0x76b23a50), TOBN(0x4a2793ad, 0x0a6c21ce), - TOBN(0x38328780, 0x89cac3f5), TOBN(0x29176f1b, 0xcba26d56), - TOBN(0x06296187, 0x4f6f59eb), TOBN(0x86e9bca9, 0x8bdc658e), - TOBN(0x2ca9c4d3, 0x57e30402), TOBN(0x5438b216, 0x516a09bb), - TOBN(0x0a6a063c, 0x7672765a), TOBN(0x37a3ce64, 0x0547b9bf), - TOBN(0x42c099c8, 0x98b1a633), TOBN(0xb5ab800d, 0x05ee6961), - TOBN(0xf1963f59, 0x11a5acd6), TOBN(0xbaee6157, 0x46201063), - TOBN(0x36d9a649, 0xa596210a), TOBN(0xaed04363, 0x1ba7138c), - TOBN(0xcf817d1c, 0xa4a82b76), TOBN(0x5586960e, 0xf3806be9), - TOBN(0x7ab67c89, 0x09dc6bb5), TOBN(0x52ace7a0, 0x114fe7eb), - TOBN(0xcd987618, 0xcbbc9b70), TOBN(0x4f06fd5a, 0x604ca5e1), - TOBN(0x90af14ca, 0x6dbde133), TOBN(0x1afe4322, 0x948a3264), - TOBN(0xa70d2ca6, 0xc44b2c6c), TOBN(0xab726799, 0x0ef87dfe), - TOBN(0x310f64dc, 0x2e696377), TOBN(0x49b42e68, 0x4c8126a0), - TOBN(0x0ea444c3, 0xcea0b176), TOBN(0x53a8ddf7, 0xcb269182), - TOBN(0xf3e674eb, 0xbbba9dcb), TOBN(0x0d2878a8, 0xd8669d33), - TOBN(0x04b935d5, 0xd019b6a3), TOBN(0xbb5cf88e, 0x406f1e46), - TOBN(0xa1912d16, 0x5b57c111), TOBN(0x9803fc21, 0x19ebfd78), - TOBN(0x4f231c9e, 0xc07764a9), TOBN(0xd93286ee, 0xb75bd055), - TOBN(0x83a9457d, 0x8ee6c9de), TOBN(0x04695915, 0x6087ec90), - TOBN(0x14c6dd8a, 0x58d6cd46), TOBN(0x9cb633b5, 0x8e6634d2), - TOBN(0xc1305047, 0xf81bc328), TOBN(0x12ede0e2, 0x26a177e5), - TOBN(0x332cca62, 0x065a6f4f), TOBN(0xc3a47ecd, 0x67be487b), - TOBN(0x741eb187, 0x0f47ed1c), TOBN(0x99e66e58, 0xe7598b14), - TOBN(0x6f0544ca, 0x63d0ff12), TOBN(0xe5efc784, 0xb610a05f), - TOBN(0xf72917b1, 0x7cad7b47), TOBN(0x3ff6ea20, 0xf2cac0c0), - TOBN(0xcc23791b, 0xf21db8b7), TOBN(0x7dac70b1, 0xd7d93565), - TOBN(0x682cda1d, 0x694bdaad), TOBN(0xeb88bb8c, 0x1023516d), - TOBN(0xc4c634b4, 0xdfdbeb1b), TOBN(0x22f5ca72, 0xb4ee4dea), - TOBN(0x1045a368, 0xe6524821), TOBN(0xed9e8a3f, 0x052b18b2), - TOBN(0x9b7f2cb1, 0xb961f49a), TOBN(0x7fee2ec1, 0x7b009670), - TOBN(0x350d8754, 0x22507a6d), TOBN(0x561bd711, 0x4db55f1d), - TOBN(0x4c189ccc, 0x320bbcaf), TOBN(0x568434cf, 0xdf1de48c), - TOBN(0x6af1b00e, 0x0fa8f128), TOBN(0xf0ba9d02, 0x8907583c), - TOBN(0x735a4004, 0x32ff9f60), TOBN(0x3dd8e4b6, 0xc25dcf33), - TOBN(0xf2230f16, 0x42c74cef), TOBN(0xd8117623, 0x013fa8ad), - TOBN(0x36822876, 0xf51fe76e), TOBN(0x8a6811cc, 0x11d62589), - TOBN(0xc3fc7e65, 0x46225718), TOBN(0xb7df2c9f, 0xc82fdbcd), - TOBN(0x3b1d4e52, 0xdd7b205b), TOBN(0xb6959478, 0x47a2e414), - TOBN(0x05e4d793, 0xefa91148), TOBN(0xb47ed446, 0xfd2e9675), - TOBN(0x1a7098b9, 0x04c9d9bf), TOBN(0x661e2881, 0x1b793048), - TOBN(0xb1a16966, 0xb01ee461), TOBN(0xbc521308, 0x2954746f), - TOBN(0xc909a0fc, 0x2477de50), TOBN(0xd80bb41c, 0x7dbd51ef), - TOBN(0xa85be7ec, 0x53294905), TOBN(0x6d465b18, 0x83958f97), - TOBN(0x16f6f330, 0xfb6840fd), TOBN(0xfaaeb214, 0x3401e6c8), - TOBN(0xaf83d30f, 0xccb5b4f8), TOBN(0x22885739, 0x266dec4b), - TOBN(0x51b4367c, 0x7bc467df), TOBN(0x926562e3, 0xd842d27a), - TOBN(0xdfcb6614, 0x0fea14a6), TOBN(0xeb394dae, 0xf2734cd9), - TOBN(0x3eeae5d2, 0x11c0be98), TOBN(0xb1e6ed11, 0x814e8165), - TOBN(0x191086bc, 0xe52bce1c), TOBN(0x14b74cc6, 0xa75a04da), - TOBN(0x63cf1186, 0x8c060985), TOBN(0x071047de, 0x2dbd7f7c), - TOBN(0x4e433b8b, 0xce0942ca), TOBN(0xecbac447, 0xd8fec61d), - TOBN(0x8f0ed0e2, 0xebf3232f), TOBN(0xfff80f9e, 0xc52a2edd), - TOBN(0xad9ab433, 0x75b55fdb), TOBN(0x73ca7820, 0xe42e0c11), - TOBN(0x6dace0a0, 0xe6251b46), TOBN(0x89bc6b5c, 0x4c0d932d), - TOBN(0x3438cd77, 0x095da19a), TOBN(0x2f24a939, 0x8d48bdfb), - TOBN(0x99b47e46, 0x766561b7), TOBN(0x736600e6, 0x0ed0322a), - TOBN(0x06a47cb1, 0x638e1865), TOBN(0x927c1c2d, 0xcb136000), - TOBN(0x29542337, 0x0cc5df69), TOBN(0x99b37c02, 0x09d649a9), - TOBN(0xc5f0043c, 0x6aefdb27), TOBN(0x6cdd9987, 0x1be95c27), - TOBN(0x69850931, 0x390420d2), TOBN(0x299c40ac, 0x0983efa4), - TOBN(0x3a05e778, 0xaf39aead), TOBN(0x84274408, 0x43a45193), - TOBN(0x6bcd0fb9, 0x91a711a0), TOBN(0x461592c8, 0x9f52ab17), - TOBN(0xb49302b4, 0xda3c6ed6), TOBN(0xc51fddc7, 0x330d7067), - TOBN(0x94babeb6, 0xda50d531), TOBN(0x521b840d, 0xa6a7b9da), - TOBN(0x5305151e, 0x404bdc89), TOBN(0x1bcde201, 0xd0d07449), - TOBN(0xf427a78b, 0x3b76a59a), TOBN(0xf84841ce, 0x07791a1b), - TOBN(0xebd314be, 0xbf91ed1c), TOBN(0x8e61d34c, 0xbf172943), - TOBN(0x1d5dc451, 0x5541b892), TOBN(0xb186ee41, 0xfc9d9e54), - TOBN(0x9d9f345e, 0xd5bf610d), TOBN(0x3e7ba65d, 0xf6acca9f), - TOBN(0x9dda787a, 0xa8369486), TOBN(0x09f9dab7, 0x8eb5ba53), - TOBN(0x5afb2033, 0xd6481bc3), TOBN(0x76f4ce30, 0xafa62104), - TOBN(0xa8fa00cf, 0xf4f066b5), TOBN(0x89ab5143, 0x461dafc2), - TOBN(0x44339ed7, 0xa3389998), TOBN(0x2ff862f1, 0xbc214903), - TOBN(0x2c88f985, 0xb05556e3), TOBN(0xcd96058e, 0x3467081e), - TOBN(0x7d6a4176, 0xedc637ea), TOBN(0xe1743d09, 0x36a5acdc), - TOBN(0x66fd72e2, 0x7eb37726), TOBN(0xf7fa264e, 0x1481a037), - TOBN(0x9fbd3bde, 0x45f4aa79), TOBN(0xed1e0147, 0x767c3e22), - TOBN(0x7621f979, 0x82e7abe2), TOBN(0x19eedc72, 0x45f633f8), - TOBN(0xe69b155e, 0x6137bf3a), TOBN(0xa0ad13ce, 0x414ee94e), - TOBN(0x93e3d524, 0x1c0e651a), TOBN(0xab1a6e2a, 0x02ce227e), - TOBN(0xe7af1797, 0x4ab27eca), TOBN(0x245446de, 0xbd444f39), - TOBN(0x59e22a21, 0x56c07613), TOBN(0x43deafce, 0xf4275498), - TOBN(0x10834ccb, 0x67fd0946), TOBN(0xa75841e5, 0x47406edf), - TOBN(0xebd6a677, 0x7b0ac93d), TOBN(0xa6e37b0d, 0x78f5e0d7), - TOBN(0x2516c096, 0x76f5492b), TOBN(0x1e4bf888, 0x9ac05f3a), - TOBN(0xcdb42ce0, 0x4df0ba2b), TOBN(0x935d5cfd, 0x5062341b), - TOBN(0x8a303333, 0x82acac20), TOBN(0x429438c4, 0x5198b00e), - TOBN(0x1d083bc9, 0x049d33fa), TOBN(0x58b82dda, 0x946f67ff), - TOBN(0xac3e2db8, 0x67a1d6a3), TOBN(0x62e6bead, 0x1798aac8), - TOBN(0xfc85980f, 0xde46c58c), TOBN(0xa7f69379, 0x69c8d7be), - TOBN(0x23557927, 0x837b35ec), TOBN(0x06a933d8, 0xe0790c0c), - TOBN(0x827c0e9b, 0x077ff55d), TOBN(0x53977798, 0xbb26e680), - TOBN(0x59530874, 0x1d9cb54f), TOBN(0xcca3f449, 0x4aac53ef), - TOBN(0x11dc5c87, 0xa07eda0f), TOBN(0xc138bccf, 0xfd6400c8), - TOBN(0x549680d3, 0x13e5da72), TOBN(0xc93eed82, 0x4540617e), - TOBN(0xfd3db157, 0x4d0b75c0), TOBN(0x9716eb42, 0x6386075b), - TOBN(0x0639605c, 0x817b2c16), TOBN(0x09915109, 0xf1e4f201), - TOBN(0x35c9a928, 0x5cca6c3b), TOBN(0xb25f7d1a, 0x3505c900), - TOBN(0xeb9f7d20, 0x630480c4), TOBN(0xc3c7b8c6, 0x2a1a501c), - TOBN(0x3f99183c, 0x5a1f8e24), TOBN(0xfdb118fa, 0x9dd255f0), - TOBN(0xb9b18b90, 0xc27f62a6), TOBN(0xe8f732f7, 0x396ec191), - TOBN(0x524a2d91, 0x0be786ab), TOBN(0x5d32adef, 0x0ac5a0f5), - TOBN(0x9b53d4d6, 0x9725f694), TOBN(0x032a76c6, 0x0510ba89), - TOBN(0x840391a3, 0xebeb1544), TOBN(0x44b7b88c, 0x3ed73ac3), - TOBN(0xd24bae7a, 0x256cb8b3), TOBN(0x7ceb151a, 0xe394cb12), - TOBN(0xbd6b66d0, 0x5bc1e6a8), TOBN(0xec70cecb, 0x090f07bf), - TOBN(0x270644ed, 0x7d937589), TOBN(0xee9e1a3d, 0x5f1dccfe), - TOBN(0xb0d40a84, 0x745b98d2), TOBN(0xda429a21, 0x2556ed40), - TOBN(0xf676eced, 0x85148cb9), TOBN(0x5a22d40c, 0xded18936), - TOBN(0x3bc4b9e5, 0x70e8a4ce), TOBN(0xbfd1445b, 0x9eae0379), - TOBN(0xf23f2c0c, 0x1a0bd47e), TOBN(0xa9c0bb31, 0xe1845531), - TOBN(0x9ddc4d60, 0x0a4c3f6b), TOBN(0xbdfaad79, 0x2c15ef44), - TOBN(0xce55a236, 0x7f484acc), TOBN(0x08653ca7, 0x055b1f15), - TOBN(0x2efa8724, 0x538873a3), TOBN(0x09299e5d, 0xace1c7e7), - TOBN(0x07afab66, 0xade332ba), TOBN(0x9be1fdf6, 0x92dd71b7), - TOBN(0xa49b5d59, 0x5758b11c), TOBN(0x0b852893, 0xc8654f40), - TOBN(0xb63ef6f4, 0x52379447), TOBN(0xd4957d29, 0x105e690c), - TOBN(0x7d484363, 0x646559b0), TOBN(0xf4a8273c, 0x49788a8e), - TOBN(0xee406cb8, 0x34ce54a9), TOBN(0x1e1c260f, 0xf86fda9b), - TOBN(0xe150e228, 0xcf6a4a81), TOBN(0x1fa3b6a3, 0x1b488772), - TOBN(0x1e6ff110, 0xc5a9c15b), TOBN(0xc6133b91, 0x8ad6aa47), - TOBN(0x8ac5d55c, 0x9dffa978), TOBN(0xba1d1c1d, 0x5f3965f2), - TOBN(0xf969f4e0, 0x7732b52f), TOBN(0xfceecdb5, 0xa5172a07), - TOBN(0xb0120a5f, 0x10f2b8f5), TOBN(0xc83a6cdf, 0x5c4c2f63), - TOBN(0x4d47a491, 0xf8f9c213), TOBN(0xd9e1cce5, 0xd3f1bbd5), - TOBN(0x0d91bc7c, 0xaba7e372), TOBN(0xfcdc74c8, 0xdfd1a2db), - TOBN(0x05efa800, 0x374618e5), TOBN(0x11216969, 0x15a7925e), - TOBN(0xd4c89823, 0xf6021c5d), TOBN(0x880d5e84, 0xeff14423), - TOBN(0x6523bc5a, 0x6dcd1396), TOBN(0xd1acfdfc, 0x113c978b), - TOBN(0xb0c164e8, 0xbbb66840), TOBN(0xf7f4301e, 0x72b58459), - TOBN(0xc29ad4a6, 0xa638e8ec), TOBN(0xf5ab8961, 0x46b78699), - TOBN(0x9dbd7974, 0x0e954750), TOBN(0x0121de88, 0x64f9d2c6), - TOBN(0x2e597b42, 0xd985232e), TOBN(0x55b6c3c5, 0x53451777), - TOBN(0xbb53e547, 0x519cb9fb), TOBN(0xf134019f, 0x8428600d), - TOBN(0x5a473176, 0xe081791a), TOBN(0x2f3e2263, 0x35fb0c08), - TOBN(0xb28c3017, 0x73d273b0), TOBN(0xccd21076, 0x7721ef9a), - TOBN(0x054cc292, 0xb650dc39), TOBN(0x662246de, 0x6188045e), - TOBN(0x904b52fa, 0x6b83c0d1), TOBN(0xa72df267, 0x97e9cd46), - TOBN(0x886b43cd, 0x899725e4), TOBN(0x2b651688, 0xd849ff22), - TOBN(0x60479b79, 0x02f34533), TOBN(0x5e354c14, 0x0c77c148), - TOBN(0xb4bb7581, 0xa8537c78), TOBN(0x188043d7, 0xefe1495f), - TOBN(0x9ba12f42, 0x8c1d5026), TOBN(0x2e0c8a26, 0x93d4aaab), - TOBN(0xbdba7b8b, 0xaa57c450), TOBN(0x140c9ad6, 0x9bbdafef), - TOBN(0x2067aa42, 0x25ac0f18), TOBN(0xf7b1295b, 0x04d1fbf3), - TOBN(0x14829111, 0xa4b04824), TOBN(0x2ce3f192, 0x33bd5e91), - TOBN(0x9c7a1d55, 0x8f2e1b72), TOBN(0xfe932286, 0x302aa243), - TOBN(0x497ca7b4, 0xd4be9554), TOBN(0xb8e821b8, 0xe0547a6e), - TOBN(0xfb2838be, 0x67e573e0), TOBN(0x05891db9, 0x4084c44b), - TOBN(0x91311373, 0x96c1c2c5), TOBN(0x6aebfa3f, 0xd958444b), - TOBN(0xac9cdce9, 0xe56e55c1), TOBN(0x7148ced3, 0x2caa46d0), - TOBN(0x2e10c7ef, 0xb61fe8eb), TOBN(0x9fd835da, 0xff97cf4d), - }, - { - TOBN(0xa36da109, 0x081e9387), TOBN(0xfb9780d7, 0x8c935828), - TOBN(0xd5940332, 0xe540b015), TOBN(0xc9d7b51b, 0xe0f466fa), - TOBN(0xfaadcd41, 0xd6d9f671), TOBN(0xba6c1e28, 0xb1a2ac17), - TOBN(0x066a7833, 0xed201e5f), TOBN(0x19d99719, 0xf90f462b), - TOBN(0xf431f462, 0x060b5f61), TOBN(0xa56f46b4, 0x7bd057c2), - TOBN(0x348dca6c, 0x47e1bf65), TOBN(0x9a38783e, 0x41bcf1ff), - TOBN(0x7a5d33a9, 0xda710718), TOBN(0x5a779987, 0x2e0aeaf6), - TOBN(0xca87314d, 0x2d29d187), TOBN(0xfa0edc3e, 0xc687d733), - TOBN(0x9df33621, 0x6a31e09b), TOBN(0xde89e44d, 0xc1350e35), - TOBN(0x29214871, 0x4ca0cf52), TOBN(0xdf379672, 0x0b88a538), - TOBN(0xc92a510a, 0x2591d61b), TOBN(0x79aa87d7, 0x585b447b), - TOBN(0xf67db604, 0xe5287f77), TOBN(0x1697c8bf, 0x5efe7a80), - TOBN(0x1c894849, 0xcb198ac7), TOBN(0xa884a93d, 0x0f264665), - TOBN(0x2da964ef, 0x9b200678), TOBN(0x3c351b87, 0x009834e6), - TOBN(0xafb2ef9f, 0xe2c4b44b), TOBN(0x580f6c47, 0x3326790c), - TOBN(0xb8480521, 0x0b02264a), TOBN(0x8ba6f9e2, 0x42a194e2), - TOBN(0xfc87975f, 0x8fb54738), TOBN(0x35160788, 0x27c3ead3), - TOBN(0x834116d2, 0xb74a085a), TOBN(0x53c99a73, 0xa62fe996), - TOBN(0x87585be0, 0x5b81c51b), TOBN(0x925bafa8, 0xbe0852b7), - TOBN(0x76a4fafd, 0xa84d19a7), TOBN(0x39a45982, 0x585206d4), - TOBN(0x499b6ab6, 0x5eb03c0e), TOBN(0xf19b7954, 0x72bc3fde), - TOBN(0xa86b5b9c, 0x6e3a80d2), TOBN(0xe4377508, 0x6d42819f), - TOBN(0xc1663650, 0xbb3ee8a3), TOBN(0x75eb14fc, 0xb132075f), - TOBN(0xa8ccc906, 0x7ad834f6), TOBN(0xea6a2474, 0xe6e92ffd), - TOBN(0x9d72fd95, 0x0f8d6758), TOBN(0xcb84e101, 0x408c07dd), - TOBN(0xb9114bfd, 0xa5e23221), TOBN(0x358b5fe2, 0xe94e742c), - TOBN(0x1c0577ec, 0x95f40e75), TOBN(0xf0155451, 0x3d73f3d6), - TOBN(0x9d55cd67, 0xbd1b9b66), TOBN(0x63e86e78, 0xaf8d63c7), - TOBN(0x39d934ab, 0xd3c095f1), TOBN(0x04b261be, 0xe4b76d71), - TOBN(0x1d2e6970, 0xe73e6984), TOBN(0x879fb23b, 0x5e5fcb11), - TOBN(0x11506c72, 0xdfd75490), TOBN(0x3a97d085, 0x61bcf1c1), - TOBN(0x43201d82, 0xbf5e7007), TOBN(0x7f0ac52f, 0x798232a7), - TOBN(0x2715cbc4, 0x6eb564d4), TOBN(0x8d6c752c, 0x9e570e29), - TOBN(0xf80247c8, 0x9ef5fd5d), TOBN(0xc3c66b46, 0xd53eb514), - TOBN(0x9666b401, 0x0f87de56), TOBN(0xce62c06f, 0xc6c603b5), - TOBN(0xae7b4c60, 0x7e4fc942), TOBN(0x38ac0b77, 0x663a9c19), - TOBN(0xcb4d20ee, 0x4b049136), TOBN(0x8b63bf12, 0x356a4613), - TOBN(0x1221aef6, 0x70e08128), TOBN(0xe62d8c51, 0x4acb6b16), - TOBN(0x71f64a67, 0x379e7896), TOBN(0xb25237a2, 0xcafd7fa5), - TOBN(0xf077bd98, 0x3841ba6a), TOBN(0xc4ac0244, 0x3cd16e7e), - TOBN(0x548ba869, 0x21fea4ca), TOBN(0xd36d0817, 0xf3dfdac1), - TOBN(0x09d8d71f, 0xf4685faf), TOBN(0x8eff66be, 0xc52c459a), - TOBN(0x182faee7, 0x0b57235e), TOBN(0xee3c39b1, 0x0106712b), - TOBN(0x5107331f, 0xc0fcdcb0), TOBN(0x669fb9dc, 0xa51054ba), - TOBN(0xb25101fb, 0x319d7682), TOBN(0xb0293129, 0x0a982fee), - TOBN(0x51c1c9b9, 0x0261b344), TOBN(0x0e008c5b, 0xbfd371fa), - TOBN(0xd866dd1c, 0x0278ca33), TOBN(0x666f76a6, 0xe5aa53b1), - TOBN(0xe5cfb779, 0x6013a2cf), TOBN(0x1d3a1aad, 0xa3521836), - TOBN(0xcedd2531, 0x73faa485), TOBN(0xc8ee6c4f, 0xc0a76878), - TOBN(0xddbccfc9, 0x2a11667d), TOBN(0x1a418ea9, 0x1c2f695a), - TOBN(0xdb11bd92, 0x51f73971), TOBN(0x3e4b3c82, 0xda2ed89f), - TOBN(0x9a44f3f4, 0xe73e0319), TOBN(0xd1e3de0f, 0x303431af), - TOBN(0x3c5604ff, 0x50f75f9c), TOBN(0x1d8eddf3, 0x7e752b22), - TOBN(0x0ef074dd, 0x3c9a1118), TOBN(0xd0ffc172, 0xccb86d7b), - TOBN(0xabd1ece3, 0x037d90f2), TOBN(0xe3f307d6, 0x6055856c), - TOBN(0x422f9328, 0x7e4c6daf), TOBN(0x902aac66, 0x334879a0), - TOBN(0xb6a1e7bf, 0x94cdfade), TOBN(0x6c97e1ed, 0x7fc6d634), - TOBN(0x662ad24d, 0xa2fb63f8), TOBN(0xf81be1b9, 0xa5928405), - TOBN(0x86d765e4, 0xd14b4206), TOBN(0xbecc2e0e, 0x8fa0db65), - TOBN(0xa28838e0, 0xb17fc76c), TOBN(0xe49a602a, 0xe37cf24e), - TOBN(0x76b4131a, 0x567193ec), TOBN(0xaf3c305a, 0xe5f6e70b), - TOBN(0x9587bd39, 0x031eebdd), TOBN(0x5709def8, 0x71bbe831), - TOBN(0x57059983, 0x0eb2b669), TOBN(0x4d80ce1b, 0x875b7029), - TOBN(0x838a7da8, 0x0364ac16), TOBN(0x2f431d23, 0xbe1c83ab), - TOBN(0xe56812a6, 0xf9294dd3), TOBN(0xb448d01f, 0x9b4b0d77), - TOBN(0xf3ae6061, 0x04e8305c), TOBN(0x2bead645, 0x94d8c63e), - TOBN(0x0a85434d, 0x84fd8b07), TOBN(0x537b983f, 0xf7a9dee5), - TOBN(0xedcc5f18, 0xef55bd85), TOBN(0x2041af62, 0x21c6cf8b), - TOBN(0x8e52874c, 0xb940c71e), TOBN(0x211935a9, 0xdb5f4b3a), - TOBN(0x94350492, 0x301b1dc3), TOBN(0x33d2646d, 0x29958620), - TOBN(0x16b0d64b, 0xef911404), TOBN(0x9d1f25ea, 0x9a3c5ef4), - TOBN(0x20f200eb, 0x4a352c78), TOBN(0x43929f2c, 0x4bd0b428), - TOBN(0xa5656667, 0xc7196e29), TOBN(0x7992c2f0, 0x9391be48), - TOBN(0xaaa97cbd, 0x9ee0cd6e), TOBN(0x51b0310c, 0x3dc8c9bf), - TOBN(0x237f8acf, 0xdd9f22cb), TOBN(0xbb1d81a1, 0xb585d584), - TOBN(0x8d5d85f5, 0x8c416388), TOBN(0x0d6e5a5a, 0x42fe474f), - TOBN(0xe7812766, 0x38235d4e), TOBN(0x1c62bd67, 0x496e3298), - TOBN(0x8378660c, 0x3f175bc8), TOBN(0x4d04e189, 0x17afdd4d), - TOBN(0x32a81601, 0x85a8068c), TOBN(0xdb58e4e1, 0x92b29a85), - TOBN(0xe8a65b86, 0xc70d8a3b), TOBN(0x5f0e6f4e, 0x98a0403b), - TOBN(0x08129684, 0x69ed2370), TOBN(0x34dc30bd, 0x0871ee26), - TOBN(0x3a5ce948, 0x7c9c5b05), TOBN(0x7d487b80, 0x43a90c87), - TOBN(0x4089ba37, 0xdd0e7179), TOBN(0x45f80191, 0xb4041811), - TOBN(0x1c3e1058, 0x98747ba5), TOBN(0x98c4e13a, 0x6e1ae592), - TOBN(0xd44636e6, 0xe82c9f9e), TOBN(0x711db87c, 0xc33a1043), - TOBN(0x6f431263, 0xaa8aec05), TOBN(0x43ff120d, 0x2744a4aa), - TOBN(0xd3bd892f, 0xae77779b), TOBN(0xf0fe0cc9, 0x8cdc9f82), - TOBN(0xca5f7fe6, 0xf1c5b1bc), TOBN(0xcc63a682, 0x44929a72), - TOBN(0xc7eaba0c, 0x09dbe19a), TOBN(0x2f3585ad, 0x6b5c73c2), - TOBN(0x8ab8924b, 0x0ae50c30), TOBN(0x17fcd27a, 0x638b30ba), - TOBN(0xaf414d34, 0x10b3d5a5), TOBN(0x09c107d2, 0x2a9accf1), - TOBN(0x15dac49f, 0x946a6242), TOBN(0xaec3df2a, 0xd707d642), - TOBN(0x2c2492b7, 0x3f894ae0), TOBN(0xf59df3e5, 0xb75f18ce), - TOBN(0x7cb740d2, 0x8f53cad0), TOBN(0x3eb585fb, 0xc4f01294), - TOBN(0x17da0c86, 0x32c7f717), TOBN(0xeb8c795b, 0xaf943f4c), - TOBN(0x4ee23fb5, 0xf67c51d2), TOBN(0xef187575, 0x68889949), - TOBN(0xa6b4bdb2, 0x0389168b), TOBN(0xc4ecd258, 0xea577d03), - TOBN(0x3a63782b, 0x55743082), TOBN(0x6f678f4c, 0xc72f08cd), - TOBN(0x553511cf, 0x65e58dd8), TOBN(0xd53b4e3e, 0xd402c0cd), - TOBN(0x37de3e29, 0xa037c14c), TOBN(0x86b6c516, 0xc05712aa), - TOBN(0x2834da3e, 0xb38dff6f), TOBN(0xbe012c52, 0xea636be8), - TOBN(0x292d238c, 0x61dd37f8), TOBN(0x0e54523f, 0x8f8142db), - TOBN(0xe31eb436, 0x036a05d8), TOBN(0x83e3cdff, 0x1e93c0ff), - TOBN(0x3fd2fe0f, 0x50821ddf), TOBN(0xc8e19b0d, 0xff9eb33b), - TOBN(0xc8cc943f, 0xb569a5fe), TOBN(0xad0090d4, 0xd4342d75), - TOBN(0x82090b4b, 0xcaeca000), TOBN(0xca39687f, 0x1bd410eb), - TOBN(0xe7bb0df7, 0x65959d77), TOBN(0x39d78218, 0x9c964999), - TOBN(0xd87f62e8, 0xb2415451), TOBN(0xe5efb774, 0xbed76108), - TOBN(0x3ea011a4, 0xe822f0d0), TOBN(0xbc647ad1, 0x5a8704f8), - TOBN(0xbb315b35, 0x50c6820f), TOBN(0x863dec3d, 0xb7e76bec), - TOBN(0x01ff5d3a, 0xf017bfc7), TOBN(0x20054439, 0x976b8229), - TOBN(0x067fca37, 0x0bbd0d3b), TOBN(0xf63dde64, 0x7f5e3d0f), - TOBN(0x22dbefb3, 0x2a4c94e9), TOBN(0xafbff0fe, 0x96f8278a), - TOBN(0x80aea0b1, 0x3503793d), TOBN(0xb2238029, 0x5f06cd29), - TOBN(0x65703e57, 0x8ec3feca), TOBN(0x06c38314, 0x393e7053), - TOBN(0xa0b751eb, 0x7c6734c4), TOBN(0xd2e8a435, 0xc59f0f1e), - TOBN(0x147d9052, 0x5e9ca895), TOBN(0x2f4dd31e, 0x972072df), - TOBN(0xa16fda8e, 0xe6c6755c), TOBN(0xc66826ff, 0xcf196558), - TOBN(0x1f1a76a3, 0x0cf43895), TOBN(0xa9d604e0, 0x83c3097b), - TOBN(0xe1908309, 0x66390e0e), TOBN(0xa50bf753, 0xb3c85eff), - TOBN(0x0696bdde, 0xf6a70251), TOBN(0x548b801b, 0x3c6ab16a), - TOBN(0x37fcf704, 0xa4d08762), TOBN(0x090b3def, 0xdff76c4e), - TOBN(0x87e8cb89, 0x69cb9158), TOBN(0x44a90744, 0x995ece43), - TOBN(0xf85395f4, 0x0ad9fbf5), TOBN(0x49b0f6c5, 0x4fb0c82d), - TOBN(0x75d9bc15, 0xadf7cccf), TOBN(0x81a3e5d6, 0xdfa1e1b0), - TOBN(0x8c39e444, 0x249bc17e), TOBN(0xf37dccb2, 0x8ea7fd43), - TOBN(0xda654873, 0x907fba12), TOBN(0x35daa6da, 0x4a372904), - TOBN(0x0564cfc6, 0x6283a6c5), TOBN(0xd09fa4f6, 0x4a9395bf), - TOBN(0x688e9ec9, 0xaeb19a36), TOBN(0xd913f1ce, 0xc7bfbfb4), - TOBN(0x797b9a3c, 0x61c2faa6), TOBN(0x2f979bec, 0x6a0a9c12), - TOBN(0xb5969d0f, 0x359679ec), TOBN(0xebcf523d, 0x079b0460), - TOBN(0xfd6b0008, 0x10fab870), TOBN(0x3f2edcda, 0x9373a39c), - TOBN(0x0d64f9a7, 0x6f568431), TOBN(0xf848c27c, 0x02f8898c), - TOBN(0xf418ade1, 0x260b5bd5), TOBN(0xc1f3e323, 0x6973dee8), - TOBN(0x46e9319c, 0x26c185dd), TOBN(0x6d85b7d8, 0x546f0ac4), - TOBN(0x427965f2, 0x247f9d57), TOBN(0xb519b636, 0xb0035f48), - TOBN(0x6b6163a9, 0xab87d59c), TOBN(0xff9f58c3, 0x39caaa11), - TOBN(0x4ac39cde, 0x3177387b), TOBN(0x5f6557c2, 0x873e77f9), - TOBN(0x67504006, 0x36a83041), TOBN(0x9b1c96ca, 0x75ef196c), - TOBN(0xf34283de, 0xb08c7940), TOBN(0x7ea09644, 0x1128c316), - TOBN(0xb510b3b5, 0x6aa39dff), TOBN(0x59b43da2, 0x9f8e4d8c), - TOBN(0xa8ce31fd, 0x9e4c4b9f), TOBN(0x0e20be26, 0xc1303c01), - TOBN(0x18187182, 0xe8ee47c9), TOBN(0xd9687cdb, 0x7db98101), - TOBN(0x7a520e4d, 0xa1e14ff6), TOBN(0x429808ba, 0x8836d572), - TOBN(0xa37ca60d, 0x4944b663), TOBN(0xf901f7a9, 0xa3f91ae5), - TOBN(0xe4e3e76e, 0x9e36e3b1), TOBN(0x9aa219cf, 0x29d93250), - TOBN(0x347fe275, 0x056a2512), TOBN(0xa4d643d9, 0xde65d95c), - TOBN(0x9669d396, 0x699fc3ed), TOBN(0xb598dee2, 0xcf8c6bbe), - TOBN(0x682ac1e5, 0xdda9e5c6), TOBN(0x4e0d3c72, 0xcaa9fc95), - TOBN(0x17faaade, 0x772bea44), TOBN(0x5ef8428c, 0xab0009c8), - TOBN(0xcc4ce47a, 0x460ff016), TOBN(0xda6d12bf, 0x725281cb), - TOBN(0x44c67848, 0x0223aad2), TOBN(0x6e342afa, 0x36256e28), - TOBN(0x1400bb0b, 0x93a37c04), TOBN(0x62b1bc9b, 0xdd10bd96), - TOBN(0x7251adeb, 0x0dac46b7), TOBN(0x7d33b92e, 0x7be4ef51), - TOBN(0x28b2a94b, 0xe61fa29a), TOBN(0x4b2be13f, 0x06422233), - TOBN(0x36d6d062, 0x330d8d37), TOBN(0x5ef80e1e, 0xb28ca005), - TOBN(0x174d4699, 0x6d16768e), TOBN(0x9fc4ff6a, 0x628bf217), - TOBN(0x77705a94, 0x154e490d), TOBN(0x9d96dd28, 0x8d2d997a), - TOBN(0x77e2d9d8, 0xce5d72c4), TOBN(0x9d06c5a4, 0xc11c714f), - TOBN(0x02aa5136, 0x79e4a03e), TOBN(0x1386b3c2, 0x030ff28b), - TOBN(0xfe82e8a6, 0xfb283f61), TOBN(0x7df203e5, 0xf3abc3fb), - TOBN(0xeec7c351, 0x3a4d3622), TOBN(0xf7d17dbf, 0xdf762761), - TOBN(0xc3956e44, 0x522055f0), TOBN(0xde3012db, 0x8fa748db), - TOBN(0xca9fcb63, 0xbf1dcc14), TOBN(0xa56d9dcf, 0xbe4e2f3a), - TOBN(0xb86186b6, 0x8bcec9c2), TOBN(0x7cf24df9, 0x680b9f06), - TOBN(0xc46b45ea, 0xc0d29281), TOBN(0xfff42bc5, 0x07b10e12), - TOBN(0x12263c40, 0x4d289427), TOBN(0x3d5f1899, 0xb4848ec4), - TOBN(0x11f97010, 0xd040800c), TOBN(0xb4c5f529, 0x300feb20), - TOBN(0xcc543f8f, 0xde94fdcb), TOBN(0xe96af739, 0xc7c2f05e), - TOBN(0xaa5e0036, 0x882692e1), TOBN(0x09c75b68, 0x950d4ae9), - TOBN(0x62f63df2, 0xb5932a7a), TOBN(0x2658252e, 0xde0979ad), - TOBN(0x2a19343f, 0xb5e69631), TOBN(0x718c7501, 0x525b666b), - TOBN(0x26a42d69, 0xea40dc3a), TOBN(0xdc84ad22, 0xaecc018f), - TOBN(0x25c36c7b, 0x3270f04a), TOBN(0x46ba6d47, 0x50fa72ed), - TOBN(0x6c37d1c5, 0x93e58a8e), TOBN(0xa2394731, 0x120c088c), - TOBN(0xc3be4263, 0xcb6e86da), TOBN(0x2c417d36, 0x7126d038), - TOBN(0x5b70f9c5, 0x8b6f8efa), TOBN(0x671a2faa, 0x37718536), - TOBN(0xd3ced3c6, 0xb539c92b), TOBN(0xe56f1bd9, 0xa31203c2), - TOBN(0x8b096ec4, 0x9ff3c8eb), TOBN(0x2deae432, 0x43491cea), - TOBN(0x2465c6eb, 0x17943794), TOBN(0x5d267e66, 0x20586843), - TOBN(0x9d3d116d, 0xb07159d0), TOBN(0xae07a67f, 0xc1896210), - TOBN(0x8fc84d87, 0xbb961579), TOBN(0x30009e49, 0x1c1f8dd6), - TOBN(0x8a8caf22, 0xe3132819), TOBN(0xcffa197c, 0xf23ab4ff), - TOBN(0x58103a44, 0x205dd687), TOBN(0x57b796c3, 0x0ded67a2), - TOBN(0x0b9c3a6c, 0xa1779ad7), TOBN(0xa33cfe2e, 0x357c09c5), - TOBN(0x2ea29315, 0x3db4a57e), TOBN(0x91959695, 0x8ebeb52e), - TOBN(0x118db9a6, 0xe546c879), TOBN(0x8e996df4, 0x6295c8d6), - TOBN(0xdd990484, 0x55ec806b), TOBN(0x24f291ca, 0x165c1035), - TOBN(0xcca523bb, 0x440e2229), TOBN(0x324673a2, 0x73ef4d04), - TOBN(0xaf3adf34, 0x3e11ec39), TOBN(0x6136d7f1, 0xdc5968d3), - TOBN(0x7a7b2899, 0xb053a927), TOBN(0x3eaa2661, 0xae067ecd), - TOBN(0x8549b9c8, 0x02779cd9), TOBN(0x061d7940, 0xc53385ea), - TOBN(0x3e0ba883, 0xf06d18bd), TOBN(0x4ba6de53, 0xb2700843), - TOBN(0xb966b668, 0x591a9e4d), TOBN(0x93f67567, 0x7f4fa0ed), - TOBN(0x5a02711b, 0x4347237b), TOBN(0xbc041e2f, 0xe794608e), - TOBN(0x55af10f5, 0x70f73d8c), TOBN(0xd2d4d4f7, 0xbb7564f7), - TOBN(0xd7d27a89, 0xb3e93ce7), TOBN(0xf7b5a875, 0x5d3a2c1b), - TOBN(0xb29e68a0, 0x255b218a), TOBN(0xb533837e, 0x8af76754), - TOBN(0xd1b05a73, 0x579fab2e), TOBN(0xb41055a1, 0xecd74385), - TOBN(0xb2369274, 0x445e9115), TOBN(0x2972a7c4, 0xf520274e), - TOBN(0x6c08334e, 0xf678e68a), TOBN(0x4e4160f0, 0x99b057ed), - TOBN(0x3cfe11b8, 0x52ccb69a), TOBN(0x2fd1823a, 0x21c8f772), - TOBN(0xdf7f072f, 0x3298f055), TOBN(0x8c0566f9, 0xfec74a6e), - TOBN(0xe549e019, 0x5bb4d041), TOBN(0x7c3930ba, 0x9208d850), - TOBN(0xe07141fc, 0xaaa2902b), TOBN(0x539ad799, 0xe4f69ad3), - TOBN(0xa6453f94, 0x813f9ffd), TOBN(0xc58d3c48, 0x375bc2f7), - TOBN(0xb3326fad, 0x5dc64e96), TOBN(0x3aafcaa9, 0xb240e354), - TOBN(0x1d1b0903, 0xaca1e7a9), TOBN(0x4ceb9767, 0x1211b8a0), - TOBN(0xeca83e49, 0xe32a858e), TOBN(0x4c32892e, 0xae907bad), - TOBN(0xd5b42ab6, 0x2eb9b494), TOBN(0x7fde3ee2, 0x1eabae1b), - TOBN(0x13b5ab09, 0xcaf54957), TOBN(0xbfb028be, 0xe5f5d5d5), - TOBN(0x928a0650, 0x2003e2c0), TOBN(0x90793aac, 0x67476843), - TOBN(0x5e942e79, 0xc81710a0), TOBN(0x557e4a36, 0x27ccadd4), - TOBN(0x72a2bc56, 0x4bcf6d0c), TOBN(0x09ee5f43, 0x26d7b80c), - TOBN(0x6b70dbe9, 0xd4292f19), TOBN(0x56f74c26, 0x63f16b18), - TOBN(0xc23db0f7, 0x35fbb42a), TOBN(0xb606bdf6, 0x6ae10040), - TOBN(0x1eb15d4d, 0x044573ac), TOBN(0x7dc3cf86, 0x556b0ba4), - TOBN(0x97af9a33, 0xc60df6f7), TOBN(0x0b1ef85c, 0xa716ce8c), - TOBN(0x2922f884, 0xc96958be), TOBN(0x7c32fa94, 0x35690963), - TOBN(0x2d7f667c, 0xeaa00061), TOBN(0xeaaf7c17, 0x3547365c), - TOBN(0x1eb4de46, 0x87032d58), TOBN(0xc54f3d83, 0x5e2c79e0), - TOBN(0x07818df4, 0x5d04ef23), TOBN(0x55faa9c8, 0x673d41b4), - TOBN(0xced64f6f, 0x89b95355), TOBN(0x4860d2ea, 0xb7415c84), - TOBN(0x5fdb9bd2, 0x050ebad3), TOBN(0xdb53e0cc, 0x6685a5bf), - TOBN(0xb830c031, 0x9feb6593), TOBN(0xdd87f310, 0x6accff17), - TOBN(0x2303ebab, 0x9f555c10), TOBN(0x94603695, 0x287e7065), - TOBN(0xf88311c3, 0x2e83358c), TOBN(0x508dd9b4, 0xeefb0178), - TOBN(0x7ca23706, 0x2dba8652), TOBN(0x62aac5a3, 0x0047abe5), - TOBN(0x9a61d2a0, 0x8b1ea7b3), TOBN(0xd495ab63, 0xae8b1485), - TOBN(0x38740f84, 0x87052f99), TOBN(0x178ebe5b, 0xb2974eea), - TOBN(0x030bbcca, 0x5b36d17f), TOBN(0xb5e4cce3, 0xaaf86eea), - TOBN(0xb51a0220, 0x68f8e9e0), TOBN(0xa4348796, 0x09eb3e75), - TOBN(0xbe592309, 0xeef1a752), TOBN(0x5d7162d7, 0x6f2aa1ed), - TOBN(0xaebfb5ed, 0x0f007dd2), TOBN(0x255e14b2, 0xc89edd22), - TOBN(0xba85e072, 0x0303b697), TOBN(0xc5d17e25, 0xf05720ff), - TOBN(0x02b58d6e, 0x5128ebb6), TOBN(0x2c80242d, 0xd754e113), - TOBN(0x919fca5f, 0xabfae1ca), TOBN(0x937afaac, 0x1a21459b), - TOBN(0x9e0ca91c, 0x1f66a4d2), TOBN(0x194cc7f3, 0x23ec1331), - TOBN(0xad25143a, 0x8aa11690), TOBN(0xbe40ad8d, 0x09b59e08), - TOBN(0x37d60d9b, 0xe750860a), TOBN(0x6c53b008, 0xc6bf434c), - TOBN(0xb572415d, 0x1356eb80), TOBN(0xb8bf9da3, 0x9578ded8), - TOBN(0x22658e36, 0x5e8fb38b), TOBN(0x9b70ce22, 0x5af8cb22), - TOBN(0x7c00018a, 0x829a8180), TOBN(0x84329f93, 0xb81ed295), - TOBN(0x7c343ea2, 0x5f3cea83), TOBN(0x38f8655f, 0x67586536), - TOBN(0xa661a0d0, 0x1d3ec517), TOBN(0x98744652, 0x512321ae), - TOBN(0x084ca591, 0xeca92598), TOBN(0xa9bb9dc9, 0x1dcb3feb), - TOBN(0x14c54355, 0x78b4c240), TOBN(0x5ed62a3b, 0x610cafdc), - TOBN(0x07512f37, 0x1b38846b), TOBN(0x571bb70a, 0xb0e38161), - TOBN(0xb556b95b, 0x2da705d2), TOBN(0x3ef8ada6, 0xb1a08f98), - TOBN(0x85302ca7, 0xddecfbe5), TOBN(0x0e530573, 0x943105cd), - TOBN(0x60554d55, 0x21a9255d), TOBN(0x63a32fa1, 0xf2f3802a), - TOBN(0x35c8c5b0, 0xcd477875), TOBN(0x97f458ea, 0x6ad42da1), - TOBN(0x832d7080, 0xeb6b242d), TOBN(0xd30bd023, 0x3b71e246), - TOBN(0x7027991b, 0xbe31139d), TOBN(0x68797e91, 0x462e4e53), - TOBN(0x423fe20a, 0x6b4e185a), TOBN(0x82f2c67e, 0x42d9b707), - TOBN(0x25c81768, 0x4cf7811b), TOBN(0xbd53005e, 0x045bb95d), - }, - { - TOBN(0xe5f649be, 0x9d8e68fd), TOBN(0xdb0f0533, 0x1b044320), - TOBN(0xf6fde9b3, 0xe0c33398), TOBN(0x92f4209b, 0x66c8cfae), - TOBN(0xe9d1afcc, 0x1a739d4b), TOBN(0x09aea75f, 0xa28ab8de), - TOBN(0x14375fb5, 0xeac6f1d0), TOBN(0x6420b560, 0x708f7aa5), - TOBN(0x9eae499c, 0x6254dc41), TOBN(0x7e293924, 0x7a837e7e), - TOBN(0x74aec08c, 0x090524a7), TOBN(0xf82b9219, 0x8d6f55f2), - TOBN(0x493c962e, 0x1402cec5), TOBN(0x9f17ca17, 0xfa2f30e7), - TOBN(0xbcd783e8, 0xe9b879cb), TOBN(0xea3d8c14, 0x5a6f145f), - TOBN(0xdede15e7, 0x5e0dee6e), TOBN(0x74f24872, 0xdc628aa2), - TOBN(0xd3e9c4fe, 0x7861bb93), TOBN(0x56d4822a, 0x6187b2e0), - TOBN(0xb66417cf, 0xc59826f9), TOBN(0xca260969, 0x2408169e), - TOBN(0xedf69d06, 0xc79ef885), TOBN(0x00031f8a, 0xdc7d138f), - TOBN(0x103c46e6, 0x0ebcf726), TOBN(0x4482b831, 0x6231470e), - TOBN(0x6f6dfaca, 0x487c2109), TOBN(0x2e0ace97, 0x62e666ef), - TOBN(0x3246a9d3, 0x1f8d1f42), TOBN(0x1b1e83f1, 0x574944d2), - TOBN(0x13dfa63a, 0xa57f334b), TOBN(0x0cf8daed, 0x9f025d81), - TOBN(0x30d78ea8, 0x00ee11c1), TOBN(0xeb053cd4, 0xb5e3dd75), - TOBN(0x9b65b13e, 0xd58c43c5), TOBN(0xc3ad49bd, 0xbd151663), - TOBN(0x99fd8e41, 0xb6427990), TOBN(0x12cf15bd, 0x707eae1e), - TOBN(0x29ad4f1b, 0x1aabb71e), TOBN(0x5143e74d, 0x07545d0e), - TOBN(0x30266336, 0xc88bdee1), TOBN(0x25f29306, 0x5876767c), - TOBN(0x9c078571, 0xc6731996), TOBN(0xc88690b2, 0xed552951), - TOBN(0x274f2c2d, 0x852705b4), TOBN(0xb0bf8d44, 0x4e09552d), - TOBN(0x7628beeb, 0x986575d1), TOBN(0x407be238, 0x7f864651), - TOBN(0x0e5e3049, 0xa639fc6b), TOBN(0xe75c35d9, 0x86003625), - TOBN(0x0cf35bd8, 0x5dcc1646), TOBN(0x8bcaced2, 0x6c26273a), - TOBN(0xe22ecf1d, 0xb5536742), TOBN(0x013dd897, 0x1a9e068b), - TOBN(0x17f411cb, 0x8a7909c5), TOBN(0x5757ac98, 0x861dd506), - TOBN(0x85de1f0d, 0x1e935abb), TOBN(0xdefd10b4, 0x154de37a), - TOBN(0xb8d9e392, 0x369cebb5), TOBN(0x54d5ef9b, 0x761324be), - TOBN(0x4d6341ba, 0x74f17e26), TOBN(0xc0a0e3c8, 0x78c1dde4), - TOBN(0xa6d77581, 0x87d918fd), TOBN(0x66876015, 0x02ca3a13), - TOBN(0xc7313e9c, 0xf36658f0), TOBN(0xc433ef1c, 0x71f8057e), - TOBN(0x85326246, 0x1b6a835a), TOBN(0xc8f05398, 0x7c86394c), - TOBN(0xff398cdf, 0xe983c4a1), TOBN(0xbf5e8162, 0x03b7b931), - TOBN(0x93193c46, 0xb7b9045b), TOBN(0x1e4ebf5d, 0xa4a6e46b), - TOBN(0xf9942a60, 0x43a24fe7), TOBN(0x29c1191e, 0xffb3492b), - TOBN(0x9f662449, 0x902fde05), TOBN(0xc792a7ac, 0x6713c32d), - TOBN(0x2fd88ad8, 0xb737982c), TOBN(0x7e3a0319, 0xa21e60e3), - TOBN(0x09b0de44, 0x7383591a), TOBN(0x6df141ee, 0x8310a456), - TOBN(0xaec1a039, 0xe6d6f471), TOBN(0x14b2ba0f, 0x1198d12e), - TOBN(0xebc1a160, 0x3aeee5ac), TOBN(0x401f4836, 0xe0b964ce), - TOBN(0x2ee43796, 0x4fd03f66), TOBN(0x3fdb4e49, 0xdd8f3f12), - TOBN(0x6ef267f6, 0x29380f18), TOBN(0x3e8e9670, 0x8da64d16), - TOBN(0xbc19180c, 0x207674f1), TOBN(0x112e09a7, 0x33ae8fdb), - TOBN(0x99667554, 0x6aaeb71e), TOBN(0x79432af1, 0xe101b1c7), - TOBN(0xd5eb558f, 0xde2ddec6), TOBN(0x81392d1f, 0x5357753f), - TOBN(0xa7a76b97, 0x3ae1158a), TOBN(0x416fbbff, 0x4a899991), - TOBN(0x9e65fdfd, 0x0d4a9dcf), TOBN(0x7bc29e48, 0x944ddf12), - TOBN(0xbc1a92d9, 0x3c856866), TOBN(0x273c6905, 0x6e98dfe2), - TOBN(0x69fce418, 0xcdfaa6b8), TOBN(0x606bd823, 0x5061c69f), - TOBN(0x42d495a0, 0x6af75e27), TOBN(0x8ed3d505, 0x6d873a1f), - TOBN(0xaf552841, 0x6ab25b6a), TOBN(0xc6c0ffc7, 0x2b1a4523), - TOBN(0xab18827b, 0x21c99e03), TOBN(0x060e8648, 0x9034691b), - TOBN(0x5207f90f, 0x93c7f398), TOBN(0x9f4a96cb, 0x82f8d10b), - TOBN(0xdd71cd79, 0x3ad0f9e3), TOBN(0x84f435d2, 0xfc3a54f5), - TOBN(0x4b03c55b, 0x8e33787f), TOBN(0xef42f975, 0xa6384673), - TOBN(0xff7304f7, 0x5051b9f0), TOBN(0x18aca1dc, 0x741c87c2), - TOBN(0x56f120a7, 0x2d4bfe80), TOBN(0xfd823b3d, 0x053e732c), - TOBN(0x11bccfe4, 0x7537ca16), TOBN(0xdf6c9c74, 0x1b5a996b), - TOBN(0xee7332c7, 0x904fc3fa), TOBN(0x14a23f45, 0xc7e3636a), - TOBN(0xc38659c3, 0xf091d9aa), TOBN(0x4a995e5d, 0xb12d8540), - TOBN(0x20a53bec, 0xf3a5598a), TOBN(0x56534b17, 0xb1eaa995), - TOBN(0x9ed3dca4, 0xbf04e03c), TOBN(0x716c563a, 0xd8d56268), - TOBN(0x27ba77a4, 0x1d6178e7), TOBN(0xe4c80c40, 0x68a1ff8e), - TOBN(0x75011099, 0x0a13f63d), TOBN(0x7bf33521, 0xa61d46f3), - TOBN(0x0aff218e, 0x10b365bb), TOBN(0x81021804, 0x0fd7ea75), - TOBN(0x05a3fd8a, 0xa4b3a925), TOBN(0xb829e75f, 0x9b3db4e6), - TOBN(0x6bdc75a5, 0x4d53e5fb), TOBN(0x04a5dc02, 0xd52717e3), - TOBN(0x86af502f, 0xe9a42ec2), TOBN(0x8867e8fb, 0x2630e382), - TOBN(0xbf845c6e, 0xbec9889b), TOBN(0x54f491f2, 0xcb47c98d), - TOBN(0xa3091fba, 0x790c2a12), TOBN(0xd7f6fd78, 0xc20f708b), - TOBN(0xa569ac30, 0xacde5e17), TOBN(0xd0f996d0, 0x6852b4d7), - TOBN(0xe51d4bb5, 0x4609ae54), TOBN(0x3fa37d17, 0x0daed061), - TOBN(0x62a88684, 0x34b8fb41), TOBN(0x99a2acbd, 0x9efb64f1), - TOBN(0xb75c1a5e, 0x6448e1f2), TOBN(0xfa99951a, 0x42b5a069), - TOBN(0x6d956e89, 0x2f3b26e7), TOBN(0xf4709860, 0xda875247), - TOBN(0x3ad15179, 0x2482dda3), TOBN(0xd64110e3, 0x017d82f0), - TOBN(0x14928d2c, 0xfad414e4), TOBN(0x2b155f58, 0x2ed02b24), - TOBN(0x481a141b, 0xcb821bf1), TOBN(0x12e3c770, 0x4f81f5da), - TOBN(0xe49c5de5, 0x9fff8381), TOBN(0x11053232, 0x5bbec894), - TOBN(0xa0d051cc, 0x454d88c4), TOBN(0x4f6db89c, 0x1f8e531b), - TOBN(0x34fe3fd6, 0xca563a44), TOBN(0x7f5c2215, 0x58da8ab9), - TOBN(0x8445016d, 0x9474f0a1), TOBN(0x17d34d61, 0xcb7d8a0a), - TOBN(0x8e9d3910, 0x1c474019), TOBN(0xcaff2629, 0xd52ceefb), - TOBN(0xf9cf3e32, 0xc1622c2b), TOBN(0xd4b95e3c, 0xe9071a05), - TOBN(0xfbbca61f, 0x1594438c), TOBN(0x1eb6e6a6, 0x04aadedf), - TOBN(0x853027f4, 0x68e14940), TOBN(0x221d322a, 0xdfabda9c), - TOBN(0xed8ea9f6, 0xb7cb179a), TOBN(0xdc7b764d, 0xb7934dcc), - TOBN(0xfcb13940, 0x5e09180d), TOBN(0x6629a6bf, 0xb47dc2dd), - TOBN(0xbfc55e4e, 0x9f5a915e), TOBN(0xb1db9d37, 0x6204441e), - TOBN(0xf82d68cf, 0x930c5f53), TOBN(0x17d3a142, 0xcbb605b1), - TOBN(0xdd5944ea, 0x308780f2), TOBN(0xdc8de761, 0x3845f5e4), - TOBN(0x6beaba7d, 0x7624d7a3), TOBN(0x1e709afd, 0x304df11e), - TOBN(0x95364376, 0x02170456), TOBN(0xbf204b3a, 0xc8f94b64), - TOBN(0x4e53af7c, 0x5680ca68), TOBN(0x0526074a, 0xe0c67574), - TOBN(0x95d8cef8, 0xecd92af6), TOBN(0xe6b9fa7a, 0x6cd1745a), - TOBN(0x3d546d3d, 0xa325c3e4), TOBN(0x1f57691d, 0x9ae93aae), - TOBN(0xe891f3fe, 0x9d2e1a33), TOBN(0xd430093f, 0xac063d35), - TOBN(0xeda59b12, 0x5513a327), TOBN(0xdc2134f3, 0x5536f18f), - TOBN(0xaa51fe2c, 0x5c210286), TOBN(0x3f68aaee, 0x1cab658c), - TOBN(0x5a23a00b, 0xf9357292), TOBN(0x9a626f39, 0x7efdabed), - TOBN(0xfe2b3bf3, 0x199d78e3), TOBN(0xb7a2af77, 0x71bbc345), - TOBN(0x3d19827a, 0x1e59802c), TOBN(0x823bbc15, 0xb487a51c), - TOBN(0x856139f2, 0x99d0a422), TOBN(0x9ac3df65, 0xf456c6fb), - TOBN(0xaddf65c6, 0x701f8bd6), TOBN(0x149f321e, 0x3758df87), - TOBN(0xb1ecf714, 0x721b7eba), TOBN(0xe17df098, 0x31a3312a), - TOBN(0xdb2fd6ec, 0xd5c4d581), TOBN(0xfd02996f, 0x8fcea1b3), - TOBN(0xe29fa63e, 0x7882f14f), TOBN(0xc9f6dc35, 0x07c6cadc), - TOBN(0x46f22d6f, 0xb882bed0), TOBN(0x1a45755b, 0xd118e52c), - TOBN(0x9f2c7c27, 0x7c4608cf), TOBN(0x7ccbdf32, 0x568012c2), - TOBN(0xfcb0aedd, 0x61729b0e), TOBN(0x7ca2ca9e, 0xf7d75dbf), - TOBN(0xf58fecb1, 0x6f640f62), TOBN(0xe274b92b, 0x39f51946), - TOBN(0x7f4dfc04, 0x6288af44), TOBN(0x0a91f32a, 0xeac329e5), - TOBN(0x43ad274b, 0xd6aaba31), TOBN(0x719a1640, 0x0f6884f9), - TOBN(0x685d29f6, 0xdaf91e20), TOBN(0x5ec1cc33, 0x27e49d52), - TOBN(0x38f4de96, 0x3b54a059), TOBN(0x0e0015e5, 0xefbcfdb3), - TOBN(0x177d23d9, 0x4dbb8da6), TOBN(0x98724aa2, 0x97a617ad), - TOBN(0x30f0885b, 0xfdb6558e), TOBN(0xf9f7a28a, 0xc7899a96), - TOBN(0xd2ae8ac8, 0x872dc112), TOBN(0xfa0642ca, 0x73c3c459), - TOBN(0x15296981, 0xe7dfc8d6), TOBN(0x67cd4450, 0x1fb5b94a), - TOBN(0x0ec71cf1, 0x0eddfd37), TOBN(0xc7e5eeb3, 0x9a8eddc7), - TOBN(0x02ac8e3d, 0x81d95028), TOBN(0x0088f172, 0x70b0e35d), - TOBN(0xec041fab, 0xe1881fe3), TOBN(0x62cf71b8, 0xd99e7faa), - TOBN(0x5043dea7, 0xe0f222c2), TOBN(0x309d42ac, 0x72e65142), - TOBN(0x94fe9ddd, 0x9216cd30), TOBN(0xd6539c7d, 0x0f87feec), - TOBN(0x03c5a57c, 0x432ac7d7), TOBN(0x72692cf0, 0x327fda10), - TOBN(0xec28c85f, 0x280698de), TOBN(0x2331fb46, 0x7ec283b1), - TOBN(0xd34bfa32, 0x2867e633), TOBN(0x78709a82, 0x0a9cc815), - TOBN(0xb7fe6964, 0x875e2fa5), TOBN(0x25cc064f, 0x9e98bfb5), - TOBN(0x9eb0151c, 0x493a65c5), TOBN(0x5fb5d941, 0x53182464), - TOBN(0x69e6f130, 0xf04618e2), TOBN(0xa8ecec22, 0xf89c8ab6), - TOBN(0xcd6ac88b, 0xb96209bd), TOBN(0x65fa8cdb, 0xb3e1c9e0), - TOBN(0xa47d22f5, 0x4a8d8eac), TOBN(0x83895cdf, 0x8d33f963), - TOBN(0xa8adca59, 0xb56cd3d1), TOBN(0x10c8350b, 0xdaf38232), - TOBN(0x2b161fb3, 0xa5080a9f), TOBN(0xbe7f5c64, 0x3af65b3a), - TOBN(0x2c754039, 0x97403a11), TOBN(0x94626cf7, 0x121b96af), - TOBN(0x431de7c4, 0x6a983ec2), TOBN(0x3780dd3a, 0x52cc3df7), - TOBN(0xe28a0e46, 0x2baf8e3b), TOBN(0xabe68aad, 0x51d299ae), - TOBN(0x603eb8f9, 0x647a2408), TOBN(0x14c61ed6, 0x5c750981), - TOBN(0x88b34414, 0xc53352e7), TOBN(0x5a34889c, 0x1337d46e), - TOBN(0x612c1560, 0xf95f2bc8), TOBN(0x8a3f8441, 0xd4807a3a), - TOBN(0x680d9e97, 0x5224da68), TOBN(0x60cd6e88, 0xc3eb00e9), - TOBN(0x3875a98e, 0x9a6bc375), TOBN(0xdc80f924, 0x4fd554c2), - TOBN(0x6c4b3415, 0x6ac77407), TOBN(0xa1e5ea8f, 0x25420681), - TOBN(0x541bfa14, 0x4607a458), TOBN(0x5dbc7e7a, 0x96d7fbf9), - TOBN(0x646a851b, 0x31590a47), TOBN(0x039e85ba, 0x15ee6df8), - TOBN(0xd19fa231, 0xd7b43fc0), TOBN(0x84bc8be8, 0x299a0e04), - TOBN(0x2b9d2936, 0xf20df03a), TOBN(0x24054382, 0x8608d472), - TOBN(0x76b6ba04, 0x9149202a), TOBN(0xb21c3831, 0x3670e7b7), - TOBN(0xddd93059, 0xd6fdee10), TOBN(0x9da47ad3, 0x78488e71), - TOBN(0x99cc1dfd, 0xa0fcfb25), TOBN(0x42abde10, 0x64696954), - TOBN(0x14cc15fc, 0x17eab9fe), TOBN(0xd6e863e4, 0xd3e70972), - TOBN(0x29a7765c, 0x6432112c), TOBN(0x88660001, 0x5b0774d8), - TOBN(0x3729175a, 0x2c088eae), TOBN(0x13afbcae, 0x8230b8d4), - TOBN(0x44768151, 0x915f4379), TOBN(0xf086431a, 0xd8d22812), - TOBN(0x37461955, 0xc298b974), TOBN(0x905fb5f0, 0xf8711e04), - TOBN(0x787abf3a, 0xfe969d18), TOBN(0x392167c2, 0x6f6a494e), - TOBN(0xfc7a0d2d, 0x28c511da), TOBN(0xf127c7dc, 0xb66a262d), - TOBN(0xf9c4bb95, 0xfd63fdf0), TOBN(0x90016589, 0x3913ef46), - TOBN(0x74d2a73c, 0x11aa600d), TOBN(0x2f5379bd, 0x9fb5ab52), - TOBN(0xe49e53a4, 0x7fb70068), TOBN(0x68dd39e5, 0x404aa9a7), - TOBN(0xb9b0cf57, 0x2ecaa9c3), TOBN(0xba0e103b, 0xe824826b), - TOBN(0x60c2198b, 0x4631a3c4), TOBN(0xc5ff84ab, 0xfa8966a2), - TOBN(0x2d6ebe22, 0xac95aff8), TOBN(0x1c9bb6db, 0xb5a46d09), - TOBN(0x419062da, 0x53ee4f8d), TOBN(0x7b9042d0, 0xbb97efef), - TOBN(0x0f87f080, 0x830cf6bd), TOBN(0x4861d19a, 0x6ec8a6c6), - TOBN(0xd3a0daa1, 0x202f01aa), TOBN(0xb0111674, 0xf25afbd5), - TOBN(0x6d00d6cf, 0x1afb20d9), TOBN(0x13695000, 0x40671bc5), - TOBN(0x913ab0dc, 0x2485ea9b), TOBN(0x1f2bed06, 0x9eef61ac), - TOBN(0x850c8217, 0x6d799e20), TOBN(0x93415f37, 0x3271c2de), - TOBN(0x5afb06e9, 0x6c4f5910), TOBN(0x688a52df, 0xc4e9e421), - TOBN(0x30495ba3, 0xe2a9a6db), TOBN(0x4601303d, 0x58f9268b), - TOBN(0xbe3b0dad, 0x7eb0f04f), TOBN(0x4ea47250, 0x4456936d), - TOBN(0x8caf8798, 0xd33fd3e7), TOBN(0x1ccd8a89, 0xeb433708), - TOBN(0x9effe3e8, 0x87fd50ad), TOBN(0xbe240a56, 0x6b29c4df), - TOBN(0xec4ffd98, 0xca0e7ebd), TOBN(0xf586783a, 0xe748616e), - TOBN(0xa5b00d8f, 0xc77baa99), TOBN(0x0acada29, 0xb4f34c9c), - TOBN(0x36dad67d, 0x0fe723ac), TOBN(0x1d8e53a5, 0x39c36c1e), - TOBN(0xe4dd342d, 0x1f4bea41), TOBN(0x64fd5e35, 0xebc9e4e0), - TOBN(0x96f01f90, 0x57908805), TOBN(0xb5b9ea3d, 0x5ed480dd), - TOBN(0x366c5dc2, 0x3efd2dd0), TOBN(0xed2fe305, 0x6e9dfa27), - TOBN(0x4575e892, 0x6e9197e2), TOBN(0x11719c09, 0xab502a5d), - TOBN(0x264c7bec, 0xe81f213f), TOBN(0x741b9241, 0x55f5c457), - TOBN(0x78ac7b68, 0x49a5f4f4), TOBN(0xf91d70a2, 0x9fc45b7d), - TOBN(0x39b05544, 0xb0f5f355), TOBN(0x11f06bce, 0xeef930d9), - TOBN(0xdb84d25d, 0x038d05e1), TOBN(0x04838ee5, 0xbacc1d51), - TOBN(0x9da3ce86, 0x9e8ee00b), TOBN(0xc3412057, 0xc36eda1f), - TOBN(0xae80b913, 0x64d9c2f4), TOBN(0x7468bac3, 0xa010a8ff), - TOBN(0xdfd20037, 0x37359d41), TOBN(0x1a0f5ab8, 0x15efeacc), - TOBN(0x7c25ad2f, 0x659d0ce0), TOBN(0x4011bcbb, 0x6785cff1), - TOBN(0x128b9912, 0x7e2192c7), TOBN(0xa549d8e1, 0x13ccb0e8), - TOBN(0x805588d8, 0xc85438b1), TOBN(0x5680332d, 0xbc25cb27), - TOBN(0xdcd1bc96, 0x1a4bfdf4), TOBN(0x779ff428, 0x706f6566), - TOBN(0x8bbee998, 0xf059987a), TOBN(0xf6ce8cf2, 0xcc686de7), - TOBN(0xf8ad3c4a, 0x953cfdb2), TOBN(0xd1d426d9, 0x2205da36), - TOBN(0xb3c0f13f, 0xc781a241), TOBN(0x3e89360e, 0xd75362a8), - TOBN(0xccd05863, 0xc8a91184), TOBN(0x9bd0c9b7, 0xefa8a7f4), - TOBN(0x97ee4d53, 0x8a912a4b), TOBN(0xde5e15f8, 0xbcf518fd), - TOBN(0x6a055bf8, 0xc467e1e0), TOBN(0x10be4b4b, 0x1587e256), - TOBN(0xd90c14f2, 0x668621c9), TOBN(0xd5518f51, 0xab9c92c1), - TOBN(0x8e6a0100, 0xd6d47b3c), TOBN(0xcbe980dd, 0x66716175), - TOBN(0x500d3f10, 0xddd83683), TOBN(0x3b6cb35d, 0x99cac73c), - TOBN(0x53730c8b, 0x6083d550), TOBN(0xcf159767, 0xdf0a1987), - TOBN(0x84bfcf53, 0x43ad73b3), TOBN(0x1b528c20, 0x4f035a94), - TOBN(0x4294edf7, 0x33eeac69), TOBN(0xb6283e83, 0x817f3240), - TOBN(0xc3fdc959, 0x0a5f25b1), TOBN(0xefaf8aa5, 0x5844ee22), - TOBN(0xde269ba5, 0xdbdde4de), TOBN(0xe3347160, 0xc56133bf), - TOBN(0xc1184219, 0x8d9ea9f8), TOBN(0x090de5db, 0xf3fc1ab5), - TOBN(0x404c37b1, 0x0bf22cda), TOBN(0x7de20ec8, 0xf5618894), - TOBN(0x754c588e, 0xecdaecab), TOBN(0x6ca4b0ed, 0x88342743), - TOBN(0x76f08bdd, 0xf4a938ec), TOBN(0xd182de89, 0x91493ccb), - TOBN(0xd652c53e, 0xc8a4186a), TOBN(0xb3e878db, 0x946d8e33), - TOBN(0x088453c0, 0x5f37663c), TOBN(0x5cd9daaa, 0xb407748b), - TOBN(0xa1f5197f, 0x586d5e72), TOBN(0x47500be8, 0xc443ca59), - TOBN(0x78ef35b2, 0xe2652424), TOBN(0x09c5d26f, 0x6dd7767d), - TOBN(0x7175a79a, 0xa74d3f7b), TOBN(0x0428fd8d, 0xcf5ea459), - TOBN(0x511cb97c, 0xa5d1746d), TOBN(0x36363939, 0xe71d1278), - TOBN(0xcf2df955, 0x10350bf4), TOBN(0xb3817439, 0x60aae782), - TOBN(0xa748c0e4, 0x3e688809), TOBN(0x98021fbf, 0xd7a5a006), - TOBN(0x9076a70c, 0x0e367a98), TOBN(0xbea1bc15, 0x0f62b7c2), - TOBN(0x2645a68c, 0x30fe0343), TOBN(0xacaffa78, 0x699dc14f), - TOBN(0xf4469964, 0x457bf9c4), TOBN(0x0db6407b, 0x0d2ead83), - TOBN(0x68d56cad, 0xb2c6f3eb), TOBN(0x3b512e73, 0xf376356c), - TOBN(0xe43b0e1f, 0xfce10408), TOBN(0x89ddc003, 0x5a5e257d), - TOBN(0xb0ae0d12, 0x0362e5b3), TOBN(0x07f983c7, 0xb0519161), - TOBN(0xc2e94d15, 0x5d5231e7), TOBN(0xcff22aed, 0x0b4f9513), - TOBN(0xb02588dd, 0x6ad0b0b5), TOBN(0xb967d1ac, 0x11d0dcd5), - TOBN(0x8dac6bc6, 0xcf777b6c), TOBN(0x0062bdbd, 0x4c6d1959), - TOBN(0x53da71b5, 0x0ef5cc85), TOBN(0x07012c7d, 0x4006f14f), - TOBN(0x4617f962, 0xac47800d), TOBN(0x53365f2b, 0xc102ed75), - TOBN(0xb422efcb, 0x4ab8c9d3), TOBN(0x195cb26b, 0x34af31c9), - TOBN(0x3a926e29, 0x05f2c4ce), TOBN(0xbd2bdecb, 0x9856966c), - TOBN(0x5d16ab3a, 0x85527015), TOBN(0x9f81609e, 0x4486c231), - TOBN(0xd8b96b2c, 0xda350002), TOBN(0xbd054690, 0xfa1b7d36), - TOBN(0xdc90ebf5, 0xe71d79bc), TOBN(0xf241b6f9, 0x08964e4e), - TOBN(0x7c838643, 0x2fe3cd4c), TOBN(0xe0f33acb, 0xb4bc633c), - TOBN(0xb4a9ecec, 0x3d139f1f), TOBN(0x05ce69cd, 0xdc4a1f49), - TOBN(0xa19d1b16, 0xf5f98aaf), TOBN(0x45bb71d6, 0x6f23e0ef), - TOBN(0x33789fcd, 0x46cdfdd3), TOBN(0x9b8e2978, 0xcee040ca), - TOBN(0x9c69b246, 0xae0a6828), TOBN(0xba533d24, 0x7078d5aa), - TOBN(0x7a2e42c0, 0x7bb4fbdb), TOBN(0xcfb4879a, 0x7035385c), - TOBN(0x8c3dd30b, 0x3281705b), TOBN(0x7e361c6c, 0x404fe081), - TOBN(0x7b21649c, 0x3f604edf), TOBN(0x5dbf6a3f, 0xe52ffe47), - TOBN(0xc41b7c23, 0x4b54d9bf), TOBN(0x1374e681, 0x3511c3d9), - TOBN(0x1863bf16, 0xc1b2b758), TOBN(0x90e78507, 0x1e9e6a96), - TOBN(0xab4bf98d, 0x5d86f174), TOBN(0xd74e0bd3, 0x85e96fe4), - TOBN(0x8afde39f, 0xcac5d344), TOBN(0x90946dbc, 0xbd91b847), - TOBN(0xf5b42358, 0xfe1a838c), TOBN(0x05aae6c5, 0x620ac9d8), - TOBN(0x8e193bd8, 0xa1ce5a0b), TOBN(0x8f710571, 0x4dabfd72), - TOBN(0x8d8fdd48, 0x182caaac), TOBN(0x8c4aeefa, 0x040745cf), - TOBN(0x73c6c30a, 0xf3b93e6d), TOBN(0x991241f3, 0x16f42011), - TOBN(0xa0158eea, 0xe457a477), TOBN(0xd19857db, 0xee6ddc05), - TOBN(0xb3265224, 0x18c41671), TOBN(0x3ffdfc7e, 0x3c2c0d58), - TOBN(0x3a3a5254, 0x26ee7cda), TOBN(0x341b0869, 0xdf02c3a8), - TOBN(0xa023bf42, 0x723bbfc8), TOBN(0x3d15002a, 0x14452691), - }, - { - TOBN(0x5ef7324c, 0x85edfa30), TOBN(0x25976554, 0x87d4f3da), - TOBN(0x352f5bc0, 0xdcb50c86), TOBN(0x8f6927b0, 0x4832a96c), - TOBN(0xd08ee1ba, 0x55f2f94c), TOBN(0x6a996f99, 0x344b45fa), - TOBN(0xe133cb8d, 0xa8aa455d), TOBN(0x5d0721ec, 0x758dc1f7), - TOBN(0x6ba7a920, 0x79e5fb67), TOBN(0xe1331feb, 0x70aa725e), - TOBN(0x5080ccf5, 0x7df5d837), TOBN(0xe4cae01d, 0x7ff72e21), - TOBN(0xd9243ee6, 0x0412a77d), TOBN(0x06ff7cac, 0xdf449025), - TOBN(0xbe75f7cd, 0x23ef5a31), TOBN(0xbc957822, 0x0ddef7a8), - TOBN(0x8cf7230c, 0xb0ce1c55), TOBN(0x5b534d05, 0x0bbfb607), - TOBN(0xee1ef113, 0x0e16363b), TOBN(0x27e0aa7a, 0xb4999e82), - TOBN(0xce1dac2d, 0x79362c41), TOBN(0x67920c90, 0x91bb6cb0), - TOBN(0x1e648d63, 0x2223df24), TOBN(0x0f7d9eef, 0xe32e8f28), - TOBN(0x6943f39a, 0xfa833834), TOBN(0x22951722, 0xa6328562), - TOBN(0x81d63dd5, 0x4170fc10), TOBN(0x9f5fa58f, 0xaecc2e6d), - TOBN(0xb66c8725, 0xe77d9a3b), TOBN(0x11235cea, 0x6384ebe0), - TOBN(0x06a8c118, 0x5845e24a), TOBN(0x0137b286, 0xebd093b1), - TOBN(0xc589e1ce, 0x44ace150), TOBN(0xe0f8d3d9, 0x4381e97c), - TOBN(0x59e99b11, 0x62c5a4b8), TOBN(0x90d262f7, 0xfd0ec9f9), - TOBN(0xfbc854c9, 0x283e13c9), TOBN(0x2d04fde7, 0xaedc7085), - TOBN(0x057d7765, 0x47dcbecb), TOBN(0x8dbdf591, 0x9a76fa5f), - TOBN(0xd0150695, 0x0de1e578), TOBN(0x2e1463e7, 0xe9f72bc6), - TOBN(0xffa68441, 0x1b39eca5), TOBN(0x673c8530, 0x7c037f2f), - TOBN(0xd0d6a600, 0x747f91da), TOBN(0xb08d43e1, 0xc9cb78e9), - TOBN(0x0fc0c644, 0x27b5cef5), TOBN(0x5c1d160a, 0xa60a2fd6), - TOBN(0xf98cae53, 0x28c8e13b), TOBN(0x375f10c4, 0xb2eddcd1), - TOBN(0xd4eb8b7f, 0x5cce06ad), TOBN(0xb4669f45, 0x80a2e1ef), - TOBN(0xd593f9d0, 0x5bbd8699), TOBN(0x5528a4c9, 0xe7976d13), - TOBN(0x3923e095, 0x1c7e28d3), TOBN(0xb9293790, 0x3f6bb577), - TOBN(0xdb567d6a, 0xc42bd6d2), TOBN(0x6df86468, 0xbb1f96ae), - TOBN(0x0efe5b1a, 0x4843b28e), TOBN(0x961bbb05, 0x6379b240), - TOBN(0xb6caf5f0, 0x70a6a26b), TOBN(0x70686c0d, 0x328e6e39), - TOBN(0x80da06cf, 0x895fc8d3), TOBN(0x804d8810, 0xb363fdc9), - TOBN(0xbe22877b, 0x207f1670), TOBN(0x9b0dd188, 0x4e615291), - TOBN(0x625ae8dc, 0x97a3c2bf), TOBN(0x08584ef7, 0x439b86e8), - TOBN(0xde7190a5, 0xdcd898ff), TOBN(0x26286c40, 0x2058ee3d), - TOBN(0x3db0b217, 0x5f87b1c1), TOBN(0xcc334771, 0x102a6db5), - TOBN(0xd99de954, 0x2f770fb1), TOBN(0x97c1c620, 0x4cd7535e), - TOBN(0xd3b6c448, 0x3f09cefc), TOBN(0xd725af15, 0x5a63b4f8), - TOBN(0x0c95d24f, 0xc01e20ec), TOBN(0xdfd37494, 0x9ae7121f), - TOBN(0x7d6ddb72, 0xec77b7ec), TOBN(0xfe079d3b, 0x0353a4ae), - TOBN(0x3066e70a, 0x2e6ac8d2), TOBN(0x9c6b5a43, 0x106e5c05), - TOBN(0x52d3c6f5, 0xede59b8c), TOBN(0x30d6a5c3, 0xfccec9ae), - TOBN(0xedec7c22, 0x4fc0a9ef), TOBN(0x190ff083, 0x95c16ced), - TOBN(0xbe12ec8f, 0x94de0fde), TOBN(0x0d131ab8, 0x852d3433), - TOBN(0x42ace07e, 0x85701291), TOBN(0x94793ed9, 0x194061a8), - TOBN(0x30e83ed6, 0xd7f4a485), TOBN(0x9eec7269, 0xf9eeff4d), - TOBN(0x90acba59, 0x0c9d8005), TOBN(0x5feca458, 0x1e79b9d1), - TOBN(0x8fbe5427, 0x1d506a1e), TOBN(0xa32b2c8e, 0x2439cfa7), - TOBN(0x1671c173, 0x73dd0b4e), TOBN(0x37a28214, 0x44a054c6), - TOBN(0x81760a1b, 0x4e8b53f1), TOBN(0xa6c04224, 0xf9f93b9e), - TOBN(0x18784b34, 0xcf671e3c), TOBN(0x81bbecd2, 0xcda9b994), - TOBN(0x38831979, 0xb2ab3848), TOBN(0xef54feb7, 0xf2e03c2d), - TOBN(0xcf197ca7, 0xfb8088fa), TOBN(0x01427247, 0x4ddc96c5), - TOBN(0xa2d2550a, 0x30777176), TOBN(0x53469898, 0x4d0cf71d), - TOBN(0x6ce937b8, 0x3a2aaac6), TOBN(0xe9f91dc3, 0x5af38d9b), - TOBN(0x2598ad83, 0xc8bf2899), TOBN(0x8e706ac9, 0xb5536c16), - TOBN(0x40dc7495, 0xf688dc98), TOBN(0x26490cd7, 0x124c4afc), - TOBN(0xe651ec84, 0x1f18775c), TOBN(0x393ea6c3, 0xb4fdaf4a), - TOBN(0x1e1f3343, 0x7f338e0d), TOBN(0x39fb832b, 0x6053e7b5), - TOBN(0x46e702da, 0x619e14d5), TOBN(0x859cacd1, 0xcdeef6e0), - TOBN(0x63b99ce7, 0x4462007d), TOBN(0xb8ab48a5, 0x4cb5f5b7), - TOBN(0x9ec673d2, 0xf55edde7), TOBN(0xd1567f74, 0x8cfaefda), - TOBN(0x46381b6b, 0x0887bcec), TOBN(0x694497ce, 0xe178f3c2), - TOBN(0x5e6525e3, 0x1e6266cb), TOBN(0x5931de26, 0x697d6413), - TOBN(0x87f8df7c, 0x0e58d493), TOBN(0xb1ae5ed0, 0x58b73f12), - TOBN(0xc368f784, 0xdea0c34d), TOBN(0x9bd0a120, 0x859a91a0), - TOBN(0xb00d88b7, 0xcc863c68), TOBN(0x3a1cc11e, 0x3d1f4d65), - TOBN(0xea38e0e7, 0x0aa85593), TOBN(0x37f13e98, 0x7dc4aee8), - TOBN(0x10d38667, 0xbc947bad), TOBN(0x738e07ce, 0x2a36ee2e), - TOBN(0xc93470cd, 0xc577fcac), TOBN(0xdee1b616, 0x2782470d), - TOBN(0x36a25e67, 0x2e793d12), TOBN(0xd6aa6cae, 0xe0f186da), - TOBN(0x474d0fd9, 0x80e07af7), TOBN(0xf7cdc47d, 0xba8a5cd4), - TOBN(0x28af6d9d, 0xab15247f), TOBN(0x7c789c10, 0x493a537f), - TOBN(0x7ac9b110, 0x23a334e7), TOBN(0x0236ac09, 0x12c9c277), - TOBN(0xa7e5bd25, 0x1d7a5144), TOBN(0x098b9c2a, 0xf13ec4ec), - TOBN(0x3639daca, 0xd3f0abca), TOBN(0x642da81a, 0xa23960f9), - TOBN(0x7d2e5c05, 0x4f7269b1), TOBN(0xfcf30777, 0xe287c385), - TOBN(0x10edc84f, 0xf2a46f21), TOBN(0x35441757, 0x4f43fa36), - TOBN(0xf1327899, 0xfd703431), TOBN(0xa438d7a6, 0x16dd587a), - TOBN(0x65c34c57, 0xe9c8352d), TOBN(0xa728edab, 0x5cc5a24e), - TOBN(0xaed78abc, 0x42531689), TOBN(0x0a51a0e8, 0x010963ef), - TOBN(0x5776fa0a, 0xd717d9b3), TOBN(0xf356c239, 0x7dd3428b), - TOBN(0x29903fff, 0x8d3a3dac), TOBN(0x409597fa, 0x3d94491f), - TOBN(0x4cd7a5ff, 0xbf4a56a4), TOBN(0xe5096474, 0x8adab462), - TOBN(0xa97b5126, 0x5c3427b0), TOBN(0x6401405c, 0xd282c9bd), - TOBN(0x3629f8d7, 0x222c5c45), TOBN(0xb1c02c16, 0xe8d50aed), - TOBN(0xbea2ed75, 0xd9635bc9), TOBN(0x226790c7, 0x6e24552f), - TOBN(0x3c33f2a3, 0x65f1d066), TOBN(0x2a43463e, 0x6dfccc2e), - TOBN(0x8cc3453a, 0xdb483761), TOBN(0xe7cc6085, 0x65d5672b), - TOBN(0x277ed6cb, 0xde3efc87), TOBN(0x19f2f368, 0x69234eaf), - TOBN(0x9aaf4317, 0x5c0b800b), TOBN(0x1f1e7c89, 0x8b6da6e2), - TOBN(0x6cfb4715, 0xb94ec75e), TOBN(0xd590dd5f, 0x453118c2), - TOBN(0x14e49da1, 0x1f17a34c), TOBN(0x5420ab39, 0x235a1456), - TOBN(0xb7637241, 0x2f50363b), TOBN(0x7b15d623, 0xc3fabb6e), - TOBN(0xa0ef40b1, 0xe274e49c), TOBN(0x5cf50744, 0x96b1860a), - TOBN(0xd6583fbf, 0x66afe5a4), TOBN(0x44240510, 0xf47e3e9a), - TOBN(0x99254343, 0x11b2d595), TOBN(0xf1367499, 0xeec8df57), - TOBN(0x3cb12c61, 0x3e73dd05), TOBN(0xd248c033, 0x7dac102a), - TOBN(0xcf154f13, 0xa77739f5), TOBN(0xbf4288cb, 0x23d2af42), - TOBN(0xaa64c9b6, 0x32e4a1cf), TOBN(0xee8c07a8, 0xc8a208f3), - TOBN(0xe10d4999, 0x6fe8393f), TOBN(0x0f809a3f, 0xe91f3a32), - TOBN(0x61096d1c, 0x802f63c8), TOBN(0x289e1462, 0x57750d3d), - TOBN(0xed06167e, 0x9889feea), TOBN(0xd5c9c0e2, 0xe0993909), - TOBN(0x46fca0d8, 0x56508ac6), TOBN(0x91826047, 0x4f1b8e83), - TOBN(0x4f2c877a, 0x9a4a2751), TOBN(0x71bd0072, 0xcae6fead), - TOBN(0x38df8dcc, 0x06aa1941), TOBN(0x5a074b4c, 0x63beeaa8), - TOBN(0xd6d65934, 0xc1cec8ed), TOBN(0xa6ecb49e, 0xaabc03bd), - TOBN(0xaade91c2, 0xde8a8415), TOBN(0xcfb0efdf, 0x691136e0), - TOBN(0x11af45ee, 0x23ab3495), TOBN(0xa132df88, 0x0b77463d), - TOBN(0x8923c15c, 0x815d06f4), TOBN(0xc3ceb3f5, 0x0d61a436), - TOBN(0xaf52291d, 0xe88fb1da), TOBN(0xea057974, 0x1da12179), - TOBN(0xb0d7218c, 0xd2fef720), TOBN(0x6c0899c9, 0x8e1d8845), - TOBN(0x98157504, 0x752ddad7), TOBN(0xd60bd74f, 0xa1a68a97), - TOBN(0x7047a3a9, 0xf658fb99), TOBN(0x1f5d86d6, 0x5f8511e4), - TOBN(0xb8a4bc42, 0x4b5a6d88), TOBN(0x69eb2c33, 0x1abefa7d), - TOBN(0x95bf39e8, 0x13c9c510), TOBN(0xf571960a, 0xd48aab43), - TOBN(0x7e8cfbcf, 0x704e23c6), TOBN(0xc71b7d22, 0x28aaa65b), - TOBN(0xa041b2bd, 0x245e3c83), TOBN(0x69b98834, 0xd21854ff), - TOBN(0x89d227a3, 0x963bfeec), TOBN(0x99947aaa, 0xde7da7cb), - TOBN(0x1d9ee9db, 0xee68a9b1), TOBN(0x0a08f003, 0x698ec368), - TOBN(0xe9ea4094, 0x78ef2487), TOBN(0xc8d2d415, 0x02cfec26), - TOBN(0xc52f9a6e, 0xb7dcf328), TOBN(0x0ed489e3, 0x85b6a937), - TOBN(0x9b94986b, 0xbef3366e), TOBN(0x0de59c70, 0xedddddb8), - TOBN(0xffdb748c, 0xeadddbe2), TOBN(0x9b9784bb, 0x8266ea40), - TOBN(0x142b5502, 0x1a93507a), TOBN(0xb4cd1187, 0x8d3c06cf), - TOBN(0xdf70e76a, 0x91ec3f40), TOBN(0x484e81ad, 0x4e7553c2), - TOBN(0x830f87b5, 0x272e9d6e), TOBN(0xea1c93e5, 0xc6ff514a), - TOBN(0x67cc2adc, 0xc4192a8e), TOBN(0xc77e27e2, 0x42f4535a), - TOBN(0x9cdbab36, 0xd2b713c5), TOBN(0x86274ea0, 0xcf7b0cd3), - TOBN(0x784680f3, 0x09af826b), TOBN(0xbfcc837a, 0x0c72dea3), - TOBN(0xa8bdfe9d, 0xd6529b73), TOBN(0x708aa228, 0x63a88002), - TOBN(0x6c7a9a54, 0xc91d45b9), TOBN(0xdf1a38bb, 0xfd004f56), - TOBN(0x2e8c9a26, 0xb8bad853), TOBN(0x2d52cea3, 0x3723eae7), - TOBN(0x054d6d81, 0x56ca2830), TOBN(0xa3317d14, 0x9a8dc411), - TOBN(0xa08662fe, 0xfd4ddeda), TOBN(0xed2a153a, 0xb55d792b), - TOBN(0x7035c16a, 0xbfc6e944), TOBN(0xb6bc5834, 0x00171cf3), - TOBN(0xe27152b3, 0x83d102b6), TOBN(0xfe695a47, 0x0646b848), - TOBN(0xa5bb09d8, 0x916e6d37), TOBN(0xb4269d64, 0x0d17015e), - TOBN(0x8d8156a1, 0x0a1d2285), TOBN(0xfeef6c51, 0x46d26d72), - TOBN(0x9dac57c8, 0x4c5434a7), TOBN(0x0282e5be, 0x59d39e31), - TOBN(0xedfff181, 0x721c486d), TOBN(0x301baf10, 0xbc58824e), - TOBN(0x8136a6aa, 0x00570031), TOBN(0x55aaf78c, 0x1cddde68), - TOBN(0x26829371, 0x59c63952), TOBN(0x3a3bd274, 0x8bc25baf), - TOBN(0xecdf8657, 0xb7e52dc3), TOBN(0x2dd8c087, 0xfd78e6c8), - TOBN(0x20553274, 0xf5531461), TOBN(0x8b4a1281, 0x5d95499b), - TOBN(0xe2c8763a, 0x1a80f9d2), TOBN(0xd1dbe32b, 0x4ddec758), - TOBN(0xaf12210d, 0x30c34169), TOBN(0xba74a953, 0x78baa533), - TOBN(0x3d133c6e, 0xa438f254), TOBN(0xa431531a, 0x201bef5b), - TOBN(0x15295e22, 0xf669d7ec), TOBN(0xca374f64, 0x357fb515), - TOBN(0x8a8406ff, 0xeaa3fdb3), TOBN(0x106ae448, 0xdf3f2da8), - TOBN(0x8f9b0a90, 0x33c8e9a1), TOBN(0x234645e2, 0x71ad5885), - TOBN(0x3d083224, 0x1c0aed14), TOBN(0xf10a7d3e, 0x7a942d46), - TOBN(0x7c11deee, 0x40d5c9be), TOBN(0xb2bae7ff, 0xba84ed98), - TOBN(0x93e97139, 0xaad58ddd), TOBN(0x3d872796, 0x3f6d1fa3), - TOBN(0x483aca81, 0x8569ff13), TOBN(0x8b89a5fb, 0x9a600f72), - TOBN(0x4cbc27c3, 0xc06f2b86), TOBN(0x22130713, 0x63ad9c0b), - TOBN(0xb5358b1e, 0x48ac2840), TOBN(0x18311294, 0xecba9477), - TOBN(0xda58f990, 0xa6946b43), TOBN(0x3098baf9, 0x9ab41819), - TOBN(0x66c4c158, 0x4198da52), TOBN(0xab4fc17c, 0x146bfd1b), - TOBN(0x2f0a4c3c, 0xbf36a908), TOBN(0x2ae9e34b, 0x58cf7838), - TOBN(0xf411529e, 0x3fa11b1f), TOBN(0x21e43677, 0x974af2b4), - TOBN(0x7c20958e, 0xc230793b), TOBN(0x710ea885, 0x16e840f3), - TOBN(0xfc0b21fc, 0xc5dc67cf), TOBN(0x08d51647, 0x88405718), - TOBN(0xd955c21f, 0xcfe49eb7), TOBN(0x9722a5d5, 0x56dd4a1f), - TOBN(0xc9ef50e2, 0xc861baa5), TOBN(0xc0c21a5d, 0x9505ac3e), - TOBN(0xaf6b9a33, 0x8b7c063f), TOBN(0xc6370339, 0x2f4779c1), - TOBN(0x22df99c7, 0x638167c3), TOBN(0xfe6ffe76, 0x795db30c), - TOBN(0x2b822d33, 0xa4854989), TOBN(0xfef031dd, 0x30563aa5), - TOBN(0x16b09f82, 0xd57c667f), TOBN(0xc70312ce, 0xcc0b76f1), - TOBN(0xbf04a9e6, 0xc9118aec), TOBN(0x82fcb419, 0x3409d133), - TOBN(0x1a8ab385, 0xab45d44d), TOBN(0xfba07222, 0x617b83a3), - TOBN(0xb05f50dd, 0x58e81b52), TOBN(0x1d8db553, 0x21ce5aff), - TOBN(0x3097b8d4, 0xe344a873), TOBN(0x7d8d116d, 0xfe36d53e), - TOBN(0x6db22f58, 0x7875e750), TOBN(0x2dc5e373, 0x43e144ea), - TOBN(0xc05f32e6, 0xe799eb95), TOBN(0xe9e5f4df, 0x6899e6ec), - TOBN(0xbdc3bd68, 0x1fab23d5), TOBN(0xb72b8ab7, 0x73af60e6), - TOBN(0x8db27ae0, 0x2cecc84a), TOBN(0x600016d8, 0x7bdb871c), - TOBN(0x42a44b13, 0xd7c46f58), TOBN(0xb8919727, 0xc3a77d39), - TOBN(0xcfc6bbbd, 0xdafd6088), TOBN(0x1a740146, 0x6bd20d39), - TOBN(0x8c747abd, 0x98c41072), TOBN(0x4c91e765, 0xbdf68ea1), - TOBN(0x7c95e5ca, 0x08819a78), TOBN(0xcf48b729, 0xc9587921), - TOBN(0x091c7c5f, 0xdebbcc7d), TOBN(0x6f287404, 0xf0e05149), - TOBN(0xf83b5ac2, 0x26cd44ec), TOBN(0x88ae32a6, 0xcfea250e), - TOBN(0x6ac5047a, 0x1d06ebc5), TOBN(0xc7e550b4, 0xd434f781), - TOBN(0x61ab1cf2, 0x5c727bd2), TOBN(0x2e4badb1, 0x1cf915b0), - TOBN(0x1b4dadec, 0xf69d3920), TOBN(0xe61b1ca6, 0xf14c1dfe), - TOBN(0x90b479cc, 0xbd6bd51f), TOBN(0x8024e401, 0x8045ec30), - TOBN(0xcab29ca3, 0x25ef0e62), TOBN(0x4f2e9416, 0x49e4ebc0), - TOBN(0x45eb40ec, 0x0ccced58), TOBN(0x25cd4b9c, 0x0da44f98), - TOBN(0x43e06458, 0x871812c6), TOBN(0x99f80d55, 0x16cef651), - TOBN(0x571340c9, 0xce6dc153), TOBN(0x138d5117, 0xd8665521), - TOBN(0xacdb45bc, 0x4e07014d), TOBN(0x2f34bb38, 0x84b60b91), - TOBN(0xf44a4fd2, 0x2ae8921e), TOBN(0xb039288e, 0x892ba1e2), - TOBN(0x9da50174, 0xb1c180b2), TOBN(0x6b70ab66, 0x1693dc87), - TOBN(0x7e9babc9, 0xe7057481), TOBN(0x4581ddef, 0x9c80dc41), - TOBN(0x0c890da9, 0x51294682), TOBN(0x0b5629d3, 0x3f4736e5), - TOBN(0x2340c79e, 0xb06f5b41), TOBN(0xa42e84ce, 0x4e243469), - TOBN(0xf9a20135, 0x045a71a9), TOBN(0xefbfb415, 0xd27b6fb6), - TOBN(0x25ebea23, 0x9d33cd6f), TOBN(0x9caedb88, 0xaa6c0af8), - TOBN(0x53dc7e9a, 0xd9ce6f96), TOBN(0x3897f9fd, 0x51e0b15a), - TOBN(0xf51cb1f8, 0x8e5d788e), TOBN(0x1aec7ba8, 0xe1d490ee), - TOBN(0x265991e0, 0xcc58cb3c), TOBN(0x9f306e8c, 0x9fc3ad31), - TOBN(0x5fed006e, 0x5040a0ac), TOBN(0xca9d5043, 0xfb476f2e), - TOBN(0xa19c06e8, 0xbeea7a23), TOBN(0xd2865801, 0x0edabb63), - TOBN(0xdb92293f, 0x6967469a), TOBN(0x2894d839, 0x8d8a8ed8), - TOBN(0x87c9e406, 0xbbc77122), TOBN(0x8671c6f1, 0x2ea3a26a), - TOBN(0xe42df8d6, 0xd7de9853), TOBN(0x2e3ce346, 0xb1f2bcc7), - TOBN(0xda601dfc, 0x899d50cf), TOBN(0xbfc913de, 0xfb1b598f), - TOBN(0x81c4909f, 0xe61f7908), TOBN(0x192e304f, 0x9bbc7b29), - TOBN(0xc3ed8738, 0xc104b338), TOBN(0xedbe9e47, 0x783f5d61), - TOBN(0x0c06e9be, 0x2db30660), TOBN(0xda3e613f, 0xc0eb7d8e), - TOBN(0xd8fa3e97, 0x322e096e), TOBN(0xfebd91e8, 0xd336e247), - TOBN(0x8f13ccc4, 0xdf655a49), TOBN(0xa9e00dfc, 0x5eb20210), - TOBN(0x84631d0f, 0xc656b6ea), TOBN(0x93a058cd, 0xd8c0d947), - TOBN(0x6846904a, 0x67bd3448), TOBN(0x4a3d4e1a, 0xf394fd5c), - TOBN(0xc102c1a5, 0xdb225f52), TOBN(0xe3455bba, 0xfc4f5e9a), - TOBN(0x6b36985b, 0x4b9ad1ce), TOBN(0xa9818536, 0x5bb7f793), - TOBN(0x6c25e1d0, 0x48b1a416), TOBN(0x1381dd53, 0x3c81bee7), - TOBN(0xd2a30d61, 0x7a4a7620), TOBN(0xc8412926, 0x39b8944c), - TOBN(0x3c1c6fbe, 0x7a97c33a), TOBN(0x941e541d, 0x938664e7), - TOBN(0x417499e8, 0x4a34f239), TOBN(0x15fdb83c, 0xb90402d5), - TOBN(0xb75f46bf, 0x433aa832), TOBN(0xb61e15af, 0x63215db1), - TOBN(0xaabe59d4, 0xa127f89a), TOBN(0x5d541e0c, 0x07e816da), - TOBN(0xaaba0659, 0xa618b692), TOBN(0x55327733, 0x17266026), - TOBN(0xaf53a0fc, 0x95f57552), TOBN(0x32947650, 0x6cacb0c9), - TOBN(0x253ff58d, 0xc821be01), TOBN(0xb0309531, 0xa06f1146), - TOBN(0x59bbbdf5, 0x05c2e54d), TOBN(0x158f27ad, 0x26e8dd22), - TOBN(0xcc5b7ffb, 0x397e1e53), TOBN(0xae03f65b, 0x7fc1e50d), - TOBN(0xa9784ebd, 0x9c95f0f9), TOBN(0x5ed9deb2, 0x24640771), - TOBN(0x31244af7, 0x035561c4), TOBN(0x87332f3a, 0x7ee857de), - TOBN(0x09e16e9e, 0x2b9e0d88), TOBN(0x52d910f4, 0x56a06049), - TOBN(0x507ed477, 0xa9592f48), TOBN(0x85cb917b, 0x2365d678), - TOBN(0xf8511c93, 0x4c8998d1), TOBN(0x2186a3f1, 0x730ea58f), - TOBN(0x50189626, 0xb2029db0), TOBN(0x9137a6d9, 0x02ceb75a), - TOBN(0x2fe17f37, 0x748bc82c), TOBN(0x87c2e931, 0x80469f8c), - TOBN(0x850f71cd, 0xbf891aa2), TOBN(0x0ca1b89b, 0x75ec3d8d), - TOBN(0x516c43aa, 0x5e1cd3cd), TOBN(0x89397808, 0x9a887c28), - TOBN(0x0059c699, 0xddea1f9f), TOBN(0x7737d6fa, 0x8e6868f7), - TOBN(0x6d93746a, 0x60f1524b), TOBN(0x36985e55, 0xba052aa7), - TOBN(0x41b1d322, 0xed923ea5), TOBN(0x3429759f, 0x25852a11), - TOBN(0xbeca6ec3, 0x092e9f41), TOBN(0x3a238c66, 0x62256bbd), - TOBN(0xd82958ea, 0x70ad487d), TOBN(0x4ac8aaf9, 0x65610d93), - TOBN(0x3fa101b1, 0x5e4ccab0), TOBN(0x9bf430f2, 0x9de14bfb), - TOBN(0xa10f5cc6, 0x6531899d), TOBN(0x590005fb, 0xea8ce17d), - TOBN(0xc437912f, 0x24544cb6), TOBN(0x9987b71a, 0xd79ac2e3), - TOBN(0x13e3d9dd, 0xc058a212), TOBN(0x00075aac, 0xd2de9606), - TOBN(0x80ab508b, 0x6cac8369), TOBN(0x87842be7, 0xf54f6c89), - TOBN(0xa7ad663d, 0x6bc532a4), TOBN(0x67813de7, 0x78a91bc8), - TOBN(0x5dcb61ce, 0xc3427239), TOBN(0x5f3c7cf0, 0xc56934d9), - TOBN(0xc079e0fb, 0xe3191591), TOBN(0xe40896bd, 0xb01aada7), - TOBN(0x8d466791, 0x0492d25f), TOBN(0x8aeb30c9, 0xe7408276), - TOBN(0xe9437495, 0x9287aacc), TOBN(0x23d4708d, 0x79fe03d4), - TOBN(0x8cda9cf2, 0xd0c05199), TOBN(0x502fbc22, 0xfae78454), - TOBN(0xc0bda9df, 0xf572a182), TOBN(0x5f9b71b8, 0x6158b372), - TOBN(0xe0f33a59, 0x2b82dd07), TOBN(0x76302735, 0x9523032e), - TOBN(0x7fe1a721, 0xc4505a32), TOBN(0x7b6e3e82, 0xf796409f), - }, - { - TOBN(0xe3417bc0, 0x35d0b34a), TOBN(0x440b386b, 0x8327c0a7), - TOBN(0x8fb7262d, 0xac0362d1), TOBN(0x2c41114c, 0xe0cdf943), - TOBN(0x2ba5cef1, 0xad95a0b1), TOBN(0xc09b37a8, 0x67d54362), - TOBN(0x26d6cdd2, 0x01e486c9), TOBN(0x20477abf, 0x42ff9297), - TOBN(0xa004dcb3, 0x292a9287), TOBN(0xddc15cf6, 0x77b092c7), - TOBN(0x083a8464, 0x806c0605), TOBN(0x4a68df70, 0x3db997b0), - TOBN(0x9c134e45, 0x05bf7dd0), TOBN(0xa4e63d39, 0x8ccf7f8c), - TOBN(0xa6e6517f, 0x41b5f8af), TOBN(0xaa8b9342, 0xad7bc1cc), - TOBN(0x126f35b5, 0x1e706ad9), TOBN(0xb99cebb4, 0xc3a9ebdf), - TOBN(0xa75389af, 0xbf608d90), TOBN(0x76113c4f, 0xc6c89858), - TOBN(0x80de8eb0, 0x97e2b5aa), TOBN(0x7e1022cc, 0x63b91304), - TOBN(0x3bdab605, 0x6ccc066c), TOBN(0x33cbb144, 0xb2edf900), - TOBN(0xc4176471, 0x7af715d2), TOBN(0xe2f7f594, 0xd0134a96), - TOBN(0x2c1873ef, 0xa41ec956), TOBN(0xe4e7b4f6, 0x77821304), - TOBN(0xe5c8ff97, 0x88d5374a), TOBN(0x2b915e63, 0x80823d5b), - TOBN(0xea6bc755, 0xb2ee8fe2), TOBN(0x6657624c, 0xe7112651), - TOBN(0x157af101, 0xdace5aca), TOBN(0xc4fdbcf2, 0x11a6a267), - TOBN(0xdaddf340, 0xc49c8609), TOBN(0x97e49f52, 0xe9604a65), - TOBN(0x9be8e790, 0x937e2ad5), TOBN(0x846e2508, 0x326e17f1), - TOBN(0x3f38007a, 0x0bbbc0dc), TOBN(0xcf03603f, 0xb11e16d6), - TOBN(0xd6f800e0, 0x7442f1d5), TOBN(0x475607d1, 0x66e0e3ab), - TOBN(0x82807f16, 0xb7c64047), TOBN(0x8858e1e3, 0xa749883d), - TOBN(0x5859120b, 0x8231ee10), TOBN(0x1b80e7eb, 0x638a1ece), - TOBN(0xcb72525a, 0xc6aa73a4), TOBN(0xa7cdea3d, 0x844423ac), - TOBN(0x5ed0c007, 0xf8ae7c38), TOBN(0x6db07a5c, 0x3d740192), - TOBN(0xbe5e9c2a, 0x5fe36db3), TOBN(0xd5b9d57a, 0x76e95046), - TOBN(0x54ac32e7, 0x8eba20f2), TOBN(0xef11ca8f, 0x71b9a352), - TOBN(0x305e373e, 0xff98a658), TOBN(0xffe5a100, 0x823eb667), - TOBN(0x57477b11, 0xe51732d2), TOBN(0xdfd6eb28, 0x2538fc0e), - TOBN(0x5c43b0cc, 0x3b39eec5), TOBN(0x6af12778, 0xcb36cc57), - TOBN(0x70b0852d, 0x06c425ae), TOBN(0x6df92f8c, 0x5c221b9b), - TOBN(0x6c8d4f9e, 0xce826d9c), TOBN(0xf59aba7b, 0xb49359c3), - TOBN(0x5c8ed8d5, 0xda64309d), TOBN(0x61a6de56, 0x91b30704), - TOBN(0xd6b52f6a, 0x2f9b5808), TOBN(0x0eee4194, 0x98c958a7), - TOBN(0xcddd9aab, 0x771e4caa), TOBN(0x83965dfd, 0x78bc21be), - TOBN(0x02affce3, 0xb3b504f5), TOBN(0x30847a21, 0x561c8291), - TOBN(0xd2eb2cf1, 0x52bfda05), TOBN(0xe0e4c4e9, 0x6197b98c), - TOBN(0x1d35076c, 0xf8a1726f), TOBN(0x6c06085b, 0x2db11e3d), - TOBN(0x15c0c4d7, 0x4463ba14), TOBN(0x9d292f83, 0x0030238c), - TOBN(0x1311ee8b, 0x3727536d), TOBN(0xfeea86ef, 0xbeaedc1e), - TOBN(0xb9d18cd3, 0x66131e2e), TOBN(0xf31d974f, 0x80fe2682), - TOBN(0xb6e49e0f, 0xe4160289), TOBN(0x7c48ec0b, 0x08e92799), - TOBN(0x818111d8, 0xd1989aa7), TOBN(0xb34fa0aa, 0xebf926f9), - TOBN(0xdb5fe2f5, 0xa245474a), TOBN(0xf80a6ebb, 0x3c7ca756), - TOBN(0xa7f96054, 0xafa05dd8), TOBN(0x26dfcf21, 0xfcaf119e), - TOBN(0xe20ef2e3, 0x0564bb59), TOBN(0xef4dca50, 0x61cb02b8), - TOBN(0xcda7838a, 0x65d30672), TOBN(0x8b08d534, 0xfd657e86), - TOBN(0x4c5b4395, 0x46d595c8), TOBN(0x39b58725, 0x425cb836), - TOBN(0x8ea61059, 0x3de9abe3), TOBN(0x40434881, 0x9cdc03be), - TOBN(0x9b261245, 0xcfedce8c), TOBN(0x78c318b4, 0xcf5234a1), - TOBN(0x510bcf16, 0xfde24c99), TOBN(0x2a77cb75, 0xa2c2ff5d), - TOBN(0x9c895c2b, 0x27960fb4), TOBN(0xd30ce975, 0xb0eda42b), - TOBN(0xfda85393, 0x1a62cc26), TOBN(0x23c69b96, 0x50c0e052), - TOBN(0xa227df15, 0xbfc633f3), TOBN(0x2ac78848, 0x1bae7d48), - TOBN(0x487878f9, 0x187d073d), TOBN(0x6c2be919, 0x967f807d), - TOBN(0x765861d8, 0x336e6d8f), TOBN(0x88b8974c, 0xce528a43), - TOBN(0x09521177, 0xff57d051), TOBN(0x2ff38037, 0xfb6a1961), - TOBN(0xfc0aba74, 0xa3d76ad4), TOBN(0x7c764803, 0x25a7ec17), - TOBN(0x7532d75f, 0x48879bc8), TOBN(0xea7eacc0, 0x58ce6bc1), - TOBN(0xc82176b4, 0x8e896c16), TOBN(0x9a30e0b2, 0x2c750fed), - TOBN(0xc37e2c2e, 0x421d3aa4), TOBN(0xf926407c, 0xe84fa840), - TOBN(0x18abc03d, 0x1454e41c), TOBN(0x26605ecd, 0x3f7af644), - TOBN(0x242341a6, 0xd6a5eabf), TOBN(0x1edb84f4, 0x216b668e), - TOBN(0xd836edb8, 0x04010102), TOBN(0x5b337ce7, 0x945e1d8c), - TOBN(0xd2075c77, 0xc055dc14), TOBN(0x2a0ffa25, 0x81d89cdf), - TOBN(0x8ce815ea, 0x6ffdcbaf), TOBN(0xa3428878, 0xfb648867), - TOBN(0x277699cf, 0x884655fb), TOBN(0xfa5b5bd6, 0x364d3e41), - TOBN(0x01f680c6, 0x441e1cb7), TOBN(0x3fd61e66, 0xb70a7d67), - TOBN(0x666ba2dc, 0xcc78cf66), TOBN(0xb3018174, 0x6fdbff77), - TOBN(0x8d4dd0db, 0x168d4668), TOBN(0x259455d0, 0x1dab3a2a), - TOBN(0xf58564c5, 0xcde3acec), TOBN(0x77141925, 0x13adb276), - TOBN(0x527d725d, 0x8a303f65), TOBN(0x55deb6c9, 0xe6f38f7b), - TOBN(0xfd5bb657, 0xb1fa70fb), TOBN(0xfa07f50f, 0xd8073a00), - TOBN(0xf72e3aa7, 0xbca02500), TOBN(0xf68f895d, 0x9975740d), - TOBN(0x30112060, 0x5cae2a6a), TOBN(0x01bd7218, 0x02874842), - TOBN(0x3d423891, 0x7ce47bd3), TOBN(0xa66663c1, 0x789544f6), - TOBN(0x864d05d7, 0x3272d838), TOBN(0xe22924f9, 0xfa6295c5), - TOBN(0x8189593f, 0x6c2fda32), TOBN(0x330d7189, 0xb184b544), - TOBN(0x79efa62c, 0xbde1f714), TOBN(0x35771c94, 0xe5cb1a63), - TOBN(0x2f4826b8, 0x641c8332), TOBN(0x00a894fb, 0xc8cee854), - TOBN(0xb4b9a39b, 0x36194d40), TOBN(0xe857a7c5, 0x77612601), - TOBN(0xf4209dd2, 0x4ecf2f58), TOBN(0x82b9e66d, 0x5a033487), - TOBN(0xc1e36934, 0xe4e8b9dd), TOBN(0xd2372c9d, 0xa42377d7), - TOBN(0x51dc94c7, 0x0e3ae43b), TOBN(0x4c57761e, 0x04474f6f), - TOBN(0xdcdacd0a, 0x1058a318), TOBN(0x369cf3f5, 0x78053a9a), - TOBN(0xc6c3de50, 0x31c68de2), TOBN(0x4653a576, 0x3c4b6d9f), - TOBN(0x1688dd5a, 0xaa4e5c97), TOBN(0x5be80aa1, 0xb7ab3c74), - TOBN(0x70cefe7c, 0xbc65c283), TOBN(0x57f95f13, 0x06867091), - TOBN(0xa39114e2, 0x4415503b), TOBN(0xc08ff7c6, 0x4cbb17e9), - TOBN(0x1eff674d, 0xd7dec966), TOBN(0x6d4690af, 0x53376f63), - TOBN(0xff6fe32e, 0xea74237b), TOBN(0xc436d17e, 0xcd57508e), - TOBN(0x15aa28e1, 0xedcc40fe), TOBN(0x0d769c04, 0x581bbb44), - TOBN(0xc240b6de, 0x34eaacda), TOBN(0xd9e116e8, 0x2ba0f1de), - TOBN(0xcbe45ec7, 0x79438e55), TOBN(0x91787c9d, 0x96f752d7), - TOBN(0x897f532b, 0xf129ac2f), TOBN(0xd307b7c8, 0x5a36e22c), - TOBN(0x91940675, 0x749fb8f3), TOBN(0xd14f95d0, 0x157fdb28), - TOBN(0xfe51d029, 0x6ae55043), TOBN(0x8931e98f, 0x44a87de1), - TOBN(0xe57f1cc6, 0x09e4fee2), TOBN(0x0d063b67, 0x4e072d92), - TOBN(0x70a998b9, 0xed0e4316), TOBN(0xe74a736b, 0x306aca46), - TOBN(0xecf0fbf2, 0x4fda97c7), TOBN(0xa40f65cb, 0x3e178d93), - TOBN(0x16253604, 0x16df4285), TOBN(0xb0c9babb, 0xd0c56ae2), - TOBN(0x73032b19, 0xcfc5cfc3), TOBN(0xe497e5c3, 0x09752056), - TOBN(0x12096bb4, 0x164bda96), TOBN(0x1ee42419, 0xa0b74da1), - TOBN(0x8fc36243, 0x403826ba), TOBN(0x0c8f0069, 0xdc09e660), - TOBN(0x8667e981, 0xc27253c9), TOBN(0x05a6aefb, 0x92b36a45), - TOBN(0xa62c4b36, 0x9cb7bb46), TOBN(0x8394f375, 0x11f7027b), - TOBN(0x747bc79c, 0x5f109d0f), TOBN(0xcad88a76, 0x5b8cc60a), - TOBN(0x80c5a66b, 0x58f09e68), TOBN(0xe753d451, 0xf6127eac), - TOBN(0xc44b74a1, 0x5b0ec6f5), TOBN(0x47989fe4, 0x5289b2b8), - TOBN(0x745f8484, 0x58d6fc73), TOBN(0xec362a6f, 0xf61c70ab), - TOBN(0x070c98a7, 0xb3a8ad41), TOBN(0x73a20fc0, 0x7b63db51), - TOBN(0xed2c2173, 0xf44c35f4), TOBN(0x8a56149d, 0x9acc9dca), - TOBN(0x98f17881, 0x9ac6e0f4), TOBN(0x360fdeaf, 0xa413b5ed), - TOBN(0x0625b8f4, 0xa300b0fd), TOBN(0xf1f4d76a, 0x5b3222d3), - TOBN(0x9d6f5109, 0x587f76b8), TOBN(0x8b4ee08d, 0x2317fdb5), - TOBN(0x88089bb7, 0x8c68b095), TOBN(0x95570e9a, 0x5808d9b9), - TOBN(0xa395c36f, 0x35d33ae7), TOBN(0x200ea123, 0x50bb5a94), - TOBN(0x20c789bd, 0x0bafe84b), TOBN(0x243ef52d, 0x0919276a), - TOBN(0x3934c577, 0xe23ae233), TOBN(0xb93807af, 0xa460d1ec), - TOBN(0xb72a53b1, 0xf8fa76a4), TOBN(0xd8914cb0, 0xc3ca4491), - TOBN(0x2e128494, 0x3fb42622), TOBN(0x3b2700ac, 0x500907d5), - TOBN(0xf370fb09, 0x1a95ec63), TOBN(0xf8f30be2, 0x31b6dfbd), - TOBN(0xf2b2f8d2, 0x69e55f15), TOBN(0x1fead851, 0xcc1323e9), - TOBN(0xfa366010, 0xd9e5eef6), TOBN(0x64d487b0, 0xe316107e), - TOBN(0x4c076b86, 0xd23ddc82), TOBN(0x03fd344c, 0x7e0143f0), - TOBN(0xa95362ff, 0x317af2c5), TOBN(0x0add3db7, 0xe18b7a4f), - TOBN(0x9c673e3f, 0x8260e01b), TOBN(0xfbeb49e5, 0x54a1cc91), - TOBN(0x91351bf2, 0x92f2e433), TOBN(0xc755e7ec, 0x851141eb), - TOBN(0xc9a95139, 0x29607745), TOBN(0x0ca07420, 0xa26f2b28), - TOBN(0xcb2790e7, 0x4bc6f9dd), TOBN(0x345bbb58, 0xadcaffc0), - TOBN(0xc65ea38c, 0xbe0f27a2), TOBN(0x67c24d7c, 0x641fcb56), - TOBN(0x2c25f0a7, 0xa9e2c757), TOBN(0x93f5cdb0, 0x16f16c49), - TOBN(0x2ca5a9d7, 0xc5ee30a1), TOBN(0xd1593635, 0xb909b729), - TOBN(0x804ce9f3, 0xdadeff48), TOBN(0xec464751, 0xb07c30c3), - TOBN(0x89d65ff3, 0x9e49af6a), TOBN(0xf2d6238a, 0x6f3d01bc), - TOBN(0x1095561e, 0x0bced843), TOBN(0x51789e12, 0xc8a13fd8), - TOBN(0xd633f929, 0x763231df), TOBN(0x46df9f7d, 0xe7cbddef), - TOBN(0x01c889c0, 0xcb265da8), TOBN(0xfce1ad10, 0xaf4336d2), - TOBN(0x8d110df6, 0xfc6a0a7e), TOBN(0xdd431b98, 0x6da425dc), - TOBN(0xcdc4aeab, 0x1834aabe), TOBN(0x84deb124, 0x8439b7fc), - TOBN(0x8796f169, 0x3c2a5998), TOBN(0x9b9247b4, 0x7947190d), - TOBN(0x55b9d9a5, 0x11597014), TOBN(0x7e9dd70d, 0x7b1566ee), - TOBN(0x94ad78f7, 0xcbcd5e64), TOBN(0x0359ac17, 0x9bd4c032), - TOBN(0x3b11baaf, 0x7cc222ae), TOBN(0xa6a6e284, 0xba78e812), - TOBN(0x8392053f, 0x24cea1a0), TOBN(0xc97bce4a, 0x33621491), - TOBN(0x7eb1db34, 0x35399ee9), TOBN(0x473f78ef, 0xece81ad1), - TOBN(0x41d72fe0, 0xf63d3d0d), TOBN(0xe620b880, 0xafab62fc), - TOBN(0x92096bc9, 0x93158383), TOBN(0x41a21357, 0x8f896f6c), - TOBN(0x1b5ee2fa, 0xc7dcfcab), TOBN(0x650acfde, 0x9546e007), - TOBN(0xc081b749, 0xb1b02e07), TOBN(0xda9e41a0, 0xf9eca03d), - TOBN(0x013ba727, 0x175a54ab), TOBN(0xca0cd190, 0xea5d8d10), - TOBN(0x85ea52c0, 0x95fd96a9), TOBN(0x2c591b9f, 0xbc5c3940), - TOBN(0x6fb4d4e4, 0x2bad4d5f), TOBN(0xfa4c3590, 0xfef0059b), - TOBN(0x6a10218a, 0xf5122294), TOBN(0x9a78a81a, 0xa85751d1), - TOBN(0x04f20579, 0xa98e84e7), TOBN(0xfe1242c0, 0x4997e5b5), - TOBN(0xe77a273b, 0xca21e1e4), TOBN(0xfcc8b1ef, 0x9411939d), - TOBN(0xe20ea302, 0x92d0487a), TOBN(0x1442dbec, 0x294b91fe), - TOBN(0x1f7a4afe, 0xbb6b0e8f), TOBN(0x1700ef74, 0x6889c318), - TOBN(0xf5bbffc3, 0x70f1fc62), TOBN(0x3b31d4b6, 0x69c79cca), - TOBN(0xe8bc2aab, 0xa7f6340d), TOBN(0xb0b08ab4, 0xa725e10a), - TOBN(0x44f05701, 0xae340050), TOBN(0xba4b3016, 0x1cf0c569), - TOBN(0x5aa29f83, 0xfbe19a51), TOBN(0x1b9ed428, 0xb71d752e), - TOBN(0x1666e54e, 0xeb4819f5), TOBN(0x616cdfed, 0x9e18b75b), - TOBN(0x112ed5be, 0x3ee27b0b), TOBN(0xfbf28319, 0x44c7de4d), - TOBN(0xd685ec85, 0xe0e60d84), TOBN(0x68037e30, 0x1db7ee78), - TOBN(0x5b65bdcd, 0x003c4d6e), TOBN(0x33e7363a, 0x93e29a6a), - TOBN(0x995b3a61, 0x08d0756c), TOBN(0xd727f85c, 0x2faf134b), - TOBN(0xfac6edf7, 0x1d337823), TOBN(0x99b9aa50, 0x0439b8b4), - TOBN(0x722eb104, 0xe2b4e075), TOBN(0x49987295, 0x437c4926), - TOBN(0xb1e4c0e4, 0x46a9b82d), TOBN(0xd0cb3197, 0x57a006f5), - TOBN(0xf3de0f7d, 0xd7808c56), TOBN(0xb5c54d8f, 0x51f89772), - TOBN(0x500a114a, 0xadbd31aa), TOBN(0x9afaaaa6, 0x295f6cab), - TOBN(0x94705e21, 0x04cf667a), TOBN(0xfc2a811b, 0x9d3935d7), - TOBN(0x560b0280, 0x6d09267c), TOBN(0xf19ed119, 0xf780e53b), - TOBN(0xf0227c09, 0x067b6269), TOBN(0x967b8533, 0x5caef599), - TOBN(0x155b9243, 0x68efeebc), TOBN(0xcd6d34f5, 0xc497bae6), - TOBN(0x1dd8d5d3, 0x6cceb370), TOBN(0x2aeac579, 0xa78d7bf9), - TOBN(0x5d65017d, 0x70b67a62), TOBN(0x70c8e44f, 0x17c53f67), - TOBN(0xd1fc0950, 0x86a34d09), TOBN(0xe0fca256, 0xe7134907), - TOBN(0xe24fa29c, 0x80fdd315), TOBN(0x2c4acd03, 0xd87499ad), - TOBN(0xbaaf7517, 0x3b5a9ba6), TOBN(0xb9cbe1f6, 0x12e51a51), - TOBN(0xd88edae3, 0x5e154897), TOBN(0xe4309c3c, 0x77b66ca0), - TOBN(0xf5555805, 0xf67f3746), TOBN(0x85fc37ba, 0xa36401ff), - TOBN(0xdf86e2ca, 0xd9499a53), TOBN(0x6270b2a3, 0xecbc955b), - TOBN(0xafae64f5, 0x974ad33b), TOBN(0x04d85977, 0xfe7b2df1), - TOBN(0x2a3db3ff, 0x4ab03f73), TOBN(0x0b87878a, 0x8702740a), - TOBN(0x6d263f01, 0x5a061732), TOBN(0xc25430ce, 0xa32a1901), - TOBN(0xf7ebab3d, 0xdb155018), TOBN(0x3a86f693, 0x63a9b78e), - TOBN(0x349ae368, 0xda9f3804), TOBN(0x470f07fe, 0xa164349c), - TOBN(0xd52f4cc9, 0x8562baa5), TOBN(0xc74a9e86, 0x2b290df3), - TOBN(0xd3a1aa35, 0x43471a24), TOBN(0x239446be, 0xb8194511), - TOBN(0xbec2dd00, 0x81dcd44d), TOBN(0xca3d7f0f, 0xc42ac82d), - TOBN(0x1f3db085, 0xfdaf4520), TOBN(0xbb6d3e80, 0x4549daf2), - TOBN(0xf5969d8a, 0x19ad5c42), TOBN(0x7052b13d, 0xdbfd1511), - TOBN(0x11890d1b, 0x682b9060), TOBN(0xa71d3883, 0xac34452c), - TOBN(0xa438055b, 0x783805b4), TOBN(0x43241277, 0x4725b23e), - TOBN(0xf20cf96e, 0x4901bbed), TOBN(0x6419c710, 0xf432a2bb), - TOBN(0x57a0fbb9, 0xdfa9cd7d), TOBN(0x589111e4, 0x00daa249), - TOBN(0x19809a33, 0x7b60554e), TOBN(0xea5f8887, 0xede283a4), - TOBN(0x2d713802, 0x503bfd35), TOBN(0x151bb0af, 0x585d2a53), - TOBN(0x40b08f74, 0x43b30ca8), TOBN(0xe10b5bba, 0xd9934583), - TOBN(0xe8a546d6, 0xb51110ad), TOBN(0x1dd50e66, 0x28e0b6c5), - TOBN(0x292e9d54, 0xcff2b821), TOBN(0x3882555d, 0x47281760), - TOBN(0x134838f8, 0x3724d6e3), TOBN(0xf2c679e0, 0x22ddcda1), - TOBN(0x40ee8815, 0x6d2a5768), TOBN(0x7f227bd2, 0x1c1e7e2d), - TOBN(0x487ba134, 0xd04ff443), TOBN(0x76e2ff3d, 0xc614e54b), - TOBN(0x36b88d6f, 0xa3177ec7), TOBN(0xbf731d51, 0x2328fff5), - TOBN(0x758caea2, 0x49ba158e), TOBN(0x5ab8ff4c, 0x02938188), - TOBN(0x33e16056, 0x35edc56d), TOBN(0x5a69d349, 0x7e940d79), - TOBN(0x6c4fd001, 0x03866dcb), TOBN(0x20a38f57, 0x4893cdef), - TOBN(0xfbf3e790, 0xfac3a15b), TOBN(0x6ed7ea2e, 0x7a4f8e6b), - TOBN(0xa663eb4f, 0xbc3aca86), TOBN(0x22061ea5, 0x080d53f7), - TOBN(0x2480dfe6, 0xf546783f), TOBN(0xd38bc6da, 0x5a0a641e), - TOBN(0xfb093cd1, 0x2ede8965), TOBN(0x89654db4, 0xacb455cf), - TOBN(0x413cbf9a, 0x26e1adee), TOBN(0x291f3764, 0x373294d4), - TOBN(0x00797257, 0x648083fe), TOBN(0x25f504d3, 0x208cc341), - TOBN(0x635a8e5e, 0xc3a0ee43), TOBN(0x70aaebca, 0x679898ff), - TOBN(0x9ee9f547, 0x5dc63d56), TOBN(0xce987966, 0xffb34d00), - TOBN(0xf9f86b19, 0x5e26310a), TOBN(0x9e435484, 0x382a8ca8), - TOBN(0x253bcb81, 0xc2352fe4), TOBN(0xa4eac8b0, 0x4474b571), - TOBN(0xc1b97512, 0xc1ad8cf8), TOBN(0x193b4e9e, 0x99e0b697), - TOBN(0x939d2716, 0x01e85df0), TOBN(0x4fb265b3, 0xcd44eafd), - TOBN(0x321e7dcd, 0xe51e1ae2), TOBN(0x8e3a8ca6, 0xe3d8b096), - TOBN(0x8de46cb0, 0x52604998), TOBN(0x91099ad8, 0x39072aa7), - TOBN(0x2617f91c, 0x93aa96b8), TOBN(0x0fc8716b, 0x7fca2e13), - TOBN(0xa7106f5e, 0x95328723), TOBN(0xd1c9c40b, 0x262e6522), - TOBN(0xb9bafe86, 0x42b7c094), TOBN(0x1873439d, 0x1543c021), - TOBN(0xe1baa5de, 0x5cbefd5d), TOBN(0xa363fc5e, 0x521e8aff), - TOBN(0xefe6320d, 0xf862eaac), TOBN(0x14419c63, 0x22c647dc), - TOBN(0x0e06707c, 0x4e46d428), TOBN(0xcb6c834f, 0x4a178f8f), - TOBN(0x0f993a45, 0xd30f917c), TOBN(0xd4c4b049, 0x9879afee), - TOBN(0xb6142a1e, 0x70500063), TOBN(0x7c9b41c3, 0xa5d9d605), - TOBN(0xbc00fc2f, 0x2f8ba2c7), TOBN(0x0966eb2f, 0x7c67aa28), - TOBN(0x13f7b516, 0x5a786972), TOBN(0x3bfb7557, 0x8a2fbba0), - TOBN(0x131c4f23, 0x5a2b9620), TOBN(0xbff3ed27, 0x6faf46be), - TOBN(0x9b4473d1, 0x7e172323), TOBN(0x421e8878, 0x339f6246), - TOBN(0x0fa8587a, 0x25a41632), TOBN(0xc0814124, 0xa35b6c93), - TOBN(0x2b18a9f5, 0x59ebb8db), TOBN(0x264e3357, 0x76edb29c), - TOBN(0xaf245ccd, 0xc87c51e2), TOBN(0x16b3015b, 0x501e6214), - TOBN(0xbb31c560, 0x0a3882ce), TOBN(0x6961bb94, 0xfec11e04), - TOBN(0x3b825b8d, 0xeff7a3a0), TOBN(0xbec33738, 0xb1df7326), - TOBN(0x68ad747c, 0x99604a1f), TOBN(0xd154c934, 0x9a3bd499), - TOBN(0xac33506f, 0x1cc7a906), TOBN(0x73bb5392, 0x6c560e8f), - TOBN(0x6428fcbe, 0x263e3944), TOBN(0xc11828d5, 0x1c387434), - TOBN(0x3cd04be1, 0x3e4b12ff), TOBN(0xc3aad9f9, 0x2d88667c), - TOBN(0xc52ddcf8, 0x248120cf), TOBN(0x985a892e, 0x2a389532), - TOBN(0xfbb4b21b, 0x3bb85fa0), TOBN(0xf95375e0, 0x8dfc6269), - TOBN(0xfb4fb06c, 0x7ee2acea), TOBN(0x6785426e, 0x309c4d1f), - TOBN(0x659b17c8, 0xd8ceb147), TOBN(0x9b649eee, 0xb70a5554), - TOBN(0x6b7fa0b5, 0xac6bc634), TOBN(0xd99fe2c7, 0x1d6e732f), - TOBN(0x30e6e762, 0x8d3abba2), TOBN(0x18fee6e7, 0xa797b799), - TOBN(0x5c9d360d, 0xc696464d), TOBN(0xe3baeb48, 0x27bfde12), - TOBN(0x2bf5db47, 0xf23206d5), TOBN(0x2f6d3420, 0x1d260152), - TOBN(0x17b87653, 0x3f8ff89a), TOBN(0x5157c30c, 0x378fa458), - TOBN(0x7517c5c5, 0x2d4fb936), TOBN(0xef22f7ac, 0xe6518cdc), - TOBN(0xdeb483e6, 0xbf847a64), TOBN(0xf5084558, 0x92e0fa89), - }, - { - TOBN(0xab9659d8, 0xdf7304d4), TOBN(0xb71bcf1b, 0xff210e8e), - TOBN(0xa9a2438b, 0xd73fbd60), TOBN(0x4595cd1f, 0x5d11b4de), - TOBN(0x9c0d329a, 0x4835859d), TOBN(0x4a0f0d2d, 0x7dbb6e56), - TOBN(0xc6038e5e, 0xdf928a4e), TOBN(0xc9429621, 0x8f5ad154), - TOBN(0x91213462, 0xf23f2d92), TOBN(0x6cab71bd, 0x60b94078), - TOBN(0x6bdd0a63, 0x176cde20), TOBN(0x54c9b20c, 0xee4d54bc), - TOBN(0x3cd2d8aa, 0x9f2ac02f), TOBN(0x03f8e617, 0x206eedb0), - TOBN(0xc7f68e16, 0x93086434), TOBN(0x831469c5, 0x92dd3db9), - TOBN(0x8521df24, 0x8f981354), TOBN(0x587e23ec, 0x3588a259), - TOBN(0xcbedf281, 0xd7a0992c), TOBN(0x06930a55, 0x38961407), - TOBN(0x09320deb, 0xbe5bbe21), TOBN(0xa7ffa5b5, 0x2491817f), - TOBN(0xe6c8b4d9, 0x09065160), TOBN(0xac4f3992, 0xfff6d2a9), - TOBN(0x7aa7a158, 0x3ae9c1bd), TOBN(0xe0af6d98, 0xe37ce240), - TOBN(0xe54342d9, 0x28ab38b4), TOBN(0xe8b75007, 0x0a1c98ca), - TOBN(0xefce86af, 0xe02358f2), TOBN(0x31b8b856, 0xea921228), - TOBN(0x052a1912, 0x0a1c67fc), TOBN(0xb4069ea4, 0xe3aead59), - TOBN(0x3232d6e2, 0x7fa03cb3), TOBN(0xdb938e5b, 0x0fdd7d88), - TOBN(0x04c1d2cd, 0x2ccbfc5d), TOBN(0xd2f45c12, 0xaf3a580f), - TOBN(0x592620b5, 0x7883e614), TOBN(0x5fd27e68, 0xbe7c5f26), - TOBN(0x139e45a9, 0x1567e1e3), TOBN(0x2cc71d2d, 0x44d8aaaf), - TOBN(0x4a9090cd, 0xe36d0757), TOBN(0xf722d7b1, 0xd9a29382), - TOBN(0xfb7fb04c, 0x04b48ddf), TOBN(0x628ad2a7, 0xebe16f43), - TOBN(0xcd3fbfb5, 0x20226040), TOBN(0x6c34ecb1, 0x5104b6c4), - TOBN(0x30c0754e, 0xc903c188), TOBN(0xec336b08, 0x2d23cab0), - TOBN(0x473d62a2, 0x1e206ee5), TOBN(0xf1e27480, 0x8c49a633), - TOBN(0x87ab956c, 0xe9f6b2c3), TOBN(0x61830b48, 0x62b606ea), - TOBN(0x67cd6846, 0xe78e815f), TOBN(0xfe40139f, 0x4c02082a), - TOBN(0x52bbbfcb, 0x952ec365), TOBN(0x74c11642, 0x6b9836ab), - TOBN(0x9f51439e, 0x558df019), TOBN(0x230da4ba, 0xac712b27), - TOBN(0x518919e3, 0x55185a24), TOBN(0x4dcefcdd, 0x84b78f50), - TOBN(0xa7d90fb2, 0xa47d4c5a), TOBN(0x55ac9abf, 0xb30e009e), - TOBN(0xfd2fc359, 0x74eed273), TOBN(0xb72d824c, 0xdbea8faf), - TOBN(0xce721a74, 0x4513e2ca), TOBN(0x0b418612, 0x38240b2c), - TOBN(0x05199968, 0xd5baa450), TOBN(0xeb1757ed, 0x2b0e8c25), - TOBN(0x6ebc3e28, 0x3dfac6d5), TOBN(0xb2431e2e, 0x48a237f5), - TOBN(0x2acb5e23, 0x52f61499), TOBN(0x5558a2a7, 0xe06c936b), - TOBN(0xd213f923, 0xcbb13d1b), TOBN(0x98799f42, 0x5bfb9bfe), - TOBN(0x1ae8ddc9, 0x701144a9), TOBN(0x0b8b3bb6, 0x4c5595ee), - TOBN(0x0ea9ef2e, 0x3ecebb21), TOBN(0x17cb6c4b, 0x3671f9a7), - TOBN(0x47ef464f, 0x726f1d1f), TOBN(0x171b9484, 0x6943a276), - TOBN(0x51a4ae2d, 0x7ef0329c), TOBN(0x08509222, 0x91c4402a), - TOBN(0x64a61d35, 0xafd45bbc), TOBN(0x38f096fe, 0x3035a851), - TOBN(0xc7468b74, 0xa1dec027), TOBN(0xe8cf10e7, 0x4fc7dcba), - TOBN(0xea35ff40, 0xf4a06353), TOBN(0x0b4c0dfa, 0x8b77dd66), - TOBN(0x779b8552, 0xde7e5c19), TOBN(0xfab28609, 0xc1c0256c), - TOBN(0x64f58eee, 0xabd4743d), TOBN(0x4e8ef838, 0x7b6cc93b), - TOBN(0xee650d26, 0x4cb1bf3d), TOBN(0x4c1f9d09, 0x73dedf61), - TOBN(0xaef7c9d7, 0xbfb70ced), TOBN(0x1ec0507e, 0x1641de1e), - TOBN(0xcd7e5cc7, 0xcde45079), TOBN(0xde173c9a, 0x516ac9e4), - TOBN(0x517a8494, 0xc170315c), TOBN(0x438fd905, 0x91d8e8fb), - TOBN(0x5145c506, 0xc7d9630b), TOBN(0x6457a87b, 0xf47d4d75), - TOBN(0xd31646bf, 0x0d9a80e8), TOBN(0x453add2b, 0xcef3aabe), - TOBN(0xc9941109, 0xa607419d), TOBN(0xfaa71e62, 0xbb6bca80), - TOBN(0x34158c13, 0x07c431f3), TOBN(0x594abebc, 0x992bc47a), - TOBN(0x6dfea691, 0xeb78399f), TOBN(0x48aafb35, 0x3f42cba4), - TOBN(0xedcd65af, 0x077c04f0), TOBN(0x1a29a366, 0xe884491a), - TOBN(0x023a40e5, 0x1c21f2bf), TOBN(0xf99a513c, 0xa5057aee), - TOBN(0xa3fe7e25, 0xbcab072e), TOBN(0x8568d2e1, 0x40e32bcf), - TOBN(0x904594eb, 0xd3f69d9f), TOBN(0x181a9733, 0x07affab1), - TOBN(0xe4d68d76, 0xb6e330f4), TOBN(0x87a6dafb, 0xc75a7fc1), - TOBN(0x549db2b5, 0xef7d9289), TOBN(0x2480d4a8, 0x197f015a), - TOBN(0x61d5590b, 0xc40493b6), TOBN(0x3a55b52e, 0x6f780331), - TOBN(0x40eb8115, 0x309eadb0), TOBN(0xdea7de5a, 0x92e5c625), - TOBN(0x64d631f0, 0xcc6a3d5a), TOBN(0x9d5e9d7c, 0x93e8dd61), - TOBN(0xf297bef5, 0x206d3ffc), TOBN(0x23d5e033, 0x7d808bd4), - TOBN(0x4a4f6912, 0xd24cf5ba), TOBN(0xe4d8163b, 0x09cdaa8a), - TOBN(0x0e0de9ef, 0xd3082e8e), TOBN(0x4fe1246c, 0x0192f360), - TOBN(0x1f900150, 0x4b8eee0a), TOBN(0x5219da81, 0xf1da391b), - TOBN(0x7bf6a5c1, 0xf7ea25aa), TOBN(0xd165e6bf, 0xfbb07d5f), - TOBN(0xe3539361, 0x89e78671), TOBN(0xa3fcac89, 0x2bac4219), - TOBN(0xdfab6fd4, 0xf0baa8ab), TOBN(0x5a4adac1, 0xe2c1c2e5), - TOBN(0x6cd75e31, 0x40d85849), TOBN(0xce263fea, 0x19b39181), - TOBN(0xcb6803d3, 0x07032c72), TOBN(0x7f40d5ce, 0x790968c8), - TOBN(0xa6de86bd, 0xdce978f0), TOBN(0x25547c4f, 0x368f751c), - TOBN(0xb1e685fd, 0x65fb2a9e), TOBN(0xce69336f, 0x1eb9179c), - TOBN(0xb15d1c27, 0x12504442), TOBN(0xb7df465c, 0xb911a06b), - TOBN(0xb8d804a3, 0x315980cd), TOBN(0x693bc492, 0xfa3bebf7), - TOBN(0x3578aeee, 0x2253c504), TOBN(0x158de498, 0xcd2474a2), - TOBN(0x1331f5c7, 0xcfda8368), TOBN(0xd2d7bbb3, 0x78d7177e), - TOBN(0xdf61133a, 0xf3c1e46e), TOBN(0x5836ce7d, 0xd30e7be8), - TOBN(0x83084f19, 0x94f834cb), TOBN(0xd35653d4, 0x429ed782), - TOBN(0xa542f16f, 0x59e58243), TOBN(0xc2b52f65, 0x0470a22d), - TOBN(0xe3b6221b, 0x18f23d96), TOBN(0xcb05abac, 0x3f5252b4), - TOBN(0xca00938b, 0x87d61402), TOBN(0x2f186cdd, 0x411933e4), - TOBN(0xe042ece5, 0x9a29a5c5), TOBN(0xb19b3c07, 0x3b6c8402), - TOBN(0xc97667c7, 0x19d92684), TOBN(0xb5624622, 0xebc66372), - TOBN(0x0cb96e65, 0x3c04fa02), TOBN(0x83a7176c, 0x8eaa39aa), - TOBN(0x2033561d, 0xeaa1633f), TOBN(0x45a9d086, 0x4533df73), - TOBN(0xe0542c1d, 0x3dc090bc), TOBN(0x82c996ef, 0xaa59c167), - TOBN(0xe3f735e8, 0x0ee7fc4d), TOBN(0x7b179393, 0x7c35db79), - TOBN(0xb6419e25, 0xf8c5dbfd), TOBN(0x4d9d7a1e, 0x1f327b04), - TOBN(0x979f6f9b, 0x298dfca8), TOBN(0xc7c5dff1, 0x8de9366a), - TOBN(0x1b7a588d, 0x04c82bdd), TOBN(0x68005534, 0xf8319dfd), - TOBN(0xde8a55b5, 0xd8eb9580), TOBN(0x5ea886da, 0x8d5bca81), - TOBN(0xe8530a01, 0x252a0b4d), TOBN(0x1bffb4fe, 0x35eaa0a1), - TOBN(0x2ad828b1, 0xd8e99563), TOBN(0x7de96ef5, 0x95f9cd87), - TOBN(0x4abb2d0c, 0xd77d970c), TOBN(0x03cfb933, 0xd33ef9cb), - TOBN(0xb0547c01, 0x8b211fe9), TOBN(0x2fe64809, 0xa56ed1c6), - TOBN(0xcb7d5624, 0xc2ac98cc), TOBN(0x2a1372c0, 0x1a393e33), - TOBN(0xc8d1ec1c, 0x29660521), TOBN(0xf3d31b04, 0xb37ac3e9), - TOBN(0xa29ae9df, 0x5ece6e7c), TOBN(0x0603ac8f, 0x0facfb55), - TOBN(0xcfe85b7a, 0xdda233a5), TOBN(0xe618919f, 0xbd75f0b8), - TOBN(0xf555a3d2, 0x99bf1603), TOBN(0x1f43afc9, 0xf184255a), - TOBN(0xdcdaf341, 0x319a3e02), TOBN(0xd3b117ef, 0x03903a39), - TOBN(0xe095da13, 0x65d1d131), TOBN(0x86f16367, 0xc37ad03e), - TOBN(0x5f37389e, 0x462cd8dd), TOBN(0xc103fa04, 0xd67a60e6), - TOBN(0x57c34344, 0xf4b478f0), TOBN(0xce91edd8, 0xe117c98d), - TOBN(0x001777b0, 0x231fc12e), TOBN(0x11ae47f2, 0xb207bccb), - TOBN(0xd983cf8d, 0x20f8a242), TOBN(0x7aff5b1d, 0xf22e1ad8), - TOBN(0x68fd11d0, 0x7fc4feb3), TOBN(0x5d53ae90, 0xb0f1c3e1), - TOBN(0x50fb7905, 0xec041803), TOBN(0x85e3c977, 0x14404888), - TOBN(0x0e67faed, 0xac628d8f), TOBN(0x2e865150, 0x6668532c), - TOBN(0x15acaaa4, 0x6a67a6b0), TOBN(0xf4cdee25, 0xb25cec41), - TOBN(0x49ee565a, 0xe4c6701e), TOBN(0x2a04ca66, 0xfc7d63d8), - TOBN(0xeb105018, 0xef0543fb), TOBN(0xf709a4f5, 0xd1b0d81d), - TOBN(0x5b906ee6, 0x2915d333), TOBN(0xf4a87412, 0x96f1f0ab), - TOBN(0xb6b82fa7, 0x4d82f4c2), TOBN(0x90725a60, 0x6804efb3), - TOBN(0xbc82ec46, 0xadc3425e), TOBN(0xb7b80581, 0x2787843e), - TOBN(0xdf46d91c, 0xdd1fc74c), TOBN(0xdc1c62cb, 0xe783a6c4), - TOBN(0x59d1b9f3, 0x1a04cbba), TOBN(0xd87f6f72, 0x95e40764), - TOBN(0x02b4cfc1, 0x317f4a76), TOBN(0x8d2703eb, 0x91036bce), - TOBN(0x98206cc6, 0xa5e72a56), TOBN(0x57be9ed1, 0xcf53fb0f), - TOBN(0x09374571, 0xef0b17ac), TOBN(0x74b2655e, 0xd9181b38), - TOBN(0xc8f80ea8, 0x89935d0e), TOBN(0xc0d9e942, 0x91529936), - TOBN(0x19686041, 0x1e84e0e5), TOBN(0xa5db84d3, 0xaea34c93), - TOBN(0xf9d5bb19, 0x7073a732), TOBN(0xb8d2fe56, 0x6bcfd7c0), - TOBN(0x45775f36, 0xf3eb82fa), TOBN(0x8cb20ccc, 0xfdff8b58), - TOBN(0x1659b65f, 0x8374c110), TOBN(0xb8b4a422, 0x330c789a), - TOBN(0x75e3c3ea, 0x6fe8208b), TOBN(0xbd74b9e4, 0x286e78fe), - TOBN(0x0be2e81b, 0xd7d93a1a), TOBN(0x7ed06e27, 0xdd0a5aae), - TOBN(0x721f5a58, 0x6be8b800), TOBN(0x428299d1, 0xd846db28), - TOBN(0x95cb8e6b, 0x5be88ed3), TOBN(0xc3186b23, 0x1c034e11), - TOBN(0xa6312c9e, 0x8977d99b), TOBN(0xbe944331, 0x83f531e7), - TOBN(0x8232c0c2, 0x18d3b1d4), TOBN(0x617aae8b, 0xe1247b73), - TOBN(0x40153fc4, 0x282aec3b), TOBN(0xc6063d2f, 0xf7b8f823), - TOBN(0x68f10e58, 0x3304f94c), TOBN(0x31efae74, 0xee676346), - TOBN(0xbadb6c6d, 0x40a9b97c), TOBN(0x14702c63, 0x4f666256), - TOBN(0xdeb954f1, 0x5184b2e3), TOBN(0x5184a526, 0x94b6ca40), - TOBN(0xfff05337, 0x003c32ea), TOBN(0x5aa374dd, 0x205974c7), - TOBN(0x9a763854, 0x4b0dd71a), TOBN(0x459cd27f, 0xdeb947ec), - TOBN(0xa6e28161, 0x459c2b92), TOBN(0x2f020fa8, 0x75ee8ef5), - TOBN(0xb132ec2d, 0x30b06310), TOBN(0xc3e15899, 0xbc6a4530), - TOBN(0xdc5f53fe, 0xaa3f451a), TOBN(0x3a3c7f23, 0xc2d9acac), - TOBN(0x2ec2f892, 0x6b27e58b), TOBN(0x68466ee7, 0xd742799f), - TOBN(0x98324dd4, 0x1fa26613), TOBN(0xa2dc6dab, 0xbdc29d63), - TOBN(0xf9675faa, 0xd712d657), TOBN(0x813994be, 0x21fd8d15), - TOBN(0x5ccbb722, 0xfd4f7553), TOBN(0x5135ff8b, 0xf3a36b20), - TOBN(0x44be28af, 0x69559df5), TOBN(0x40b65bed, 0x9d41bf30), - TOBN(0xd98bf2a4, 0x3734e520), TOBN(0x5e3abbe3, 0x209bdcba), - TOBN(0x77c76553, 0xbc945b35), TOBN(0x5331c093, 0xc6ef14aa), - TOBN(0x518ffe29, 0x76b60c80), TOBN(0x2285593b, 0x7ace16f8), - TOBN(0xab1f64cc, 0xbe2b9784), TOBN(0xe8f2c0d9, 0xab2421b6), - TOBN(0x617d7174, 0xc1df065c), TOBN(0xafeeb5ab, 0x5f6578fa), - TOBN(0x16ff1329, 0x263b54a8), TOBN(0x45c55808, 0xc990dce3), - TOBN(0x42eab6c0, 0xecc8c177), TOBN(0x799ea9b5, 0x5982ecaa), - TOBN(0xf65da244, 0xb607ef8e), TOBN(0x8ab226ce, 0x32a3fc2c), - TOBN(0x745741e5, 0x7ea973dc), TOBN(0x5c00ca70, 0x20888f2e), - TOBN(0x7cdce3cf, 0x45fd9cf1), TOBN(0x8a741ef1, 0x5507f872), - TOBN(0x47c51c2f, 0x196b4cec), TOBN(0x70d08e43, 0xc97ea618), - TOBN(0x930da15c, 0x15b18a2b), TOBN(0x33b6c678, 0x2f610514), - TOBN(0xc662e4f8, 0x07ac9794), TOBN(0x1eccf050, 0xba06cb79), - TOBN(0x1ff08623, 0xe7d954e5), TOBN(0x6ef2c5fb, 0x24cf71c3), - TOBN(0xb2c063d2, 0x67978453), TOBN(0xa0cf3796, 0x1d654af8), - TOBN(0x7cb242ea, 0x7ebdaa37), TOBN(0x206e0b10, 0xb86747e0), - TOBN(0x481dae5f, 0xd5ecfefc), TOBN(0x07084fd8, 0xc2bff8fc), - TOBN(0x8040a01a, 0xea324596), TOBN(0x4c646980, 0xd4de4036), - TOBN(0x9eb8ab4e, 0xd65abfc3), TOBN(0xe01cb91f, 0x13541ec7), - TOBN(0x8f029adb, 0xfd695012), TOBN(0x9ae28483, 0x3c7569ec), - TOBN(0xa5614c9e, 0xa66d80a1), TOBN(0x680a3e44, 0x75f5f911), - TOBN(0x0c07b14d, 0xceba4fc1), TOBN(0x891c285b, 0xa13071c1), - TOBN(0xcac67ceb, 0x799ece3c), TOBN(0x29b910a9, 0x41e07e27), - TOBN(0x66bdb409, 0xf2e43123), TOBN(0x06f8b137, 0x7ac9ecbe), - TOBN(0x5981fafd, 0x38547090), TOBN(0x19ab8b9f, 0x85e3415d), - TOBN(0xfc28c194, 0xc7e31b27), TOBN(0x843be0aa, 0x6fbcbb42), - TOBN(0xf3b1ed43, 0xa6db836c), TOBN(0x2a1330e4, 0x01a45c05), - TOBN(0x4f19f3c5, 0x95c1a377), TOBN(0xa85f39d0, 0x44b5ee33), - TOBN(0x3da18e6d, 0x4ae52834), TOBN(0x5a403b39, 0x7423dcb0), - TOBN(0xbb555e0a, 0xf2374aef), TOBN(0x2ad599c4, 0x1e8ca111), - TOBN(0x1b3a2fb9, 0x014b3bf8), TOBN(0x73092684, 0xf66d5007), - TOBN(0x079f1426, 0xc4340102), TOBN(0x1827cf81, 0x8fddf4de), - TOBN(0xc83605f6, 0xf10ff927), TOBN(0xd3871451, 0x23739fc6), - TOBN(0x6d163450, 0xcac1c2cc), TOBN(0x6b521296, 0xa2ec1ac5), - TOBN(0x0606c4f9, 0x6e3cb4a5), TOBN(0xe47d3f41, 0x778abff7), - TOBN(0x425a8d5e, 0xbe8e3a45), TOBN(0x53ea9e97, 0xa6102160), - TOBN(0x477a106e, 0x39cbb688), TOBN(0x532401d2, 0xf3386d32), - TOBN(0x8e564f64, 0xb1b9b421), TOBN(0xca9b8388, 0x81dad33f), - TOBN(0xb1422b4e, 0x2093913e), TOBN(0x533d2f92, 0x69bc8112), - TOBN(0x3fa017be, 0xebe7b2c7), TOBN(0xb2767c4a, 0xcaf197c6), - TOBN(0xc925ff87, 0xaedbae9f), TOBN(0x7daf0eb9, 0x36880a54), - TOBN(0x9284ddf5, 0x9c4d0e71), TOBN(0x1581cf93, 0x316f8cf5), - TOBN(0x3eeca887, 0x3ac1f452), TOBN(0xb417fce9, 0xfb6aeffe), - TOBN(0xa5918046, 0xeefb8dc3), TOBN(0x73d318ac, 0x02209400), - TOBN(0xe800400f, 0x728693e5), TOBN(0xe87d814b, 0x339927ed), - TOBN(0x93e94d3b, 0x57ea9910), TOBN(0xff8a35b6, 0x2245fb69), - TOBN(0x043853d7, 0x7f200d34), TOBN(0x470f1e68, 0x0f653ce1), - TOBN(0x81ac05bd, 0x59a06379), TOBN(0xa14052c2, 0x03930c29), - TOBN(0x6b72fab5, 0x26bc2797), TOBN(0x13670d16, 0x99f16771), - TOBN(0x00170052, 0x1e3e48d1), TOBN(0x978fe401, 0xb7adf678), - TOBN(0x55ecfb92, 0xd41c5dd4), TOBN(0x5ff8e247, 0xc7b27da5), - TOBN(0xe7518272, 0x013fb606), TOBN(0x5768d7e5, 0x2f547a3c), - TOBN(0xbb24eaa3, 0x60017a5f), TOBN(0x6b18e6e4, 0x9c64ce9b), - TOBN(0xc225c655, 0x103dde07), TOBN(0xfc3672ae, 0x7592f7ea), - TOBN(0x9606ad77, 0xd06283a1), TOBN(0x542fc650, 0xe4d59d99), - TOBN(0xabb57c49, 0x2a40e7c2), TOBN(0xac948f13, 0xa8db9f55), - TOBN(0x6d4c9682, 0xb04465c3), TOBN(0xe3d062fa, 0x6468bd15), - TOBN(0xa51729ac, 0x5f318d7e), TOBN(0x1fc87df6, 0x9eb6fc95), - TOBN(0x63d146a8, 0x0591f652), TOBN(0xa861b8f7, 0x589621aa), - TOBN(0x59f5f15a, 0xce31348c), TOBN(0x8f663391, 0x440da6da), - TOBN(0xcfa778ac, 0xb591ffa3), TOBN(0x027ca9c5, 0x4cdfebce), - TOBN(0xbe8e05a5, 0x444ea6b3), TOBN(0x8aab4e69, 0xa78d8254), - TOBN(0x2437f04f, 0xb474d6b8), TOBN(0x6597ffd4, 0x045b3855), - TOBN(0xbb0aea4e, 0xca47ecaa), TOBN(0x568aae83, 0x85c7ebfc), - TOBN(0x0e966e64, 0xc73b2383), TOBN(0x49eb3447, 0xd17d8762), - TOBN(0xde107821, 0x8da05dab), TOBN(0x443d8baa, 0x016b7236), - TOBN(0x163b63a5, 0xea7610d6), TOBN(0xe47e4185, 0xce1ca979), - TOBN(0xae648b65, 0x80baa132), TOBN(0xebf53de2, 0x0e0d5b64), - TOBN(0x8d3bfcb4, 0xd3c8c1ca), TOBN(0x0d914ef3, 0x5d04b309), - TOBN(0x55ef6415, 0x3de7d395), TOBN(0xbde1666f, 0x26b850e8), - TOBN(0xdbe1ca6e, 0xd449ab19), TOBN(0x8902b322, 0xe89a2672), - TOBN(0xb1674b7e, 0xdacb7a53), TOBN(0x8e9faf6e, 0xf52523ff), - TOBN(0x6ba535da, 0x9a85788b), TOBN(0xd21f03ae, 0xbd0626d4), - TOBN(0x099f8c47, 0xe873dc64), TOBN(0xcda8564d, 0x018ec97e), - TOBN(0x3e8d7a5c, 0xde92c68c), TOBN(0x78e035a1, 0x73323cc4), - TOBN(0x3ef26275, 0xf880ff7c), TOBN(0xa4ee3dff, 0x273eedaa), - TOBN(0x58823507, 0xaf4e18f8), TOBN(0x967ec9b5, 0x0672f328), - TOBN(0x9ded19d9, 0x559d3186), TOBN(0x5e2ab3de, 0x6cdce39c), - TOBN(0xabad6e4d, 0x11c226df), TOBN(0xf9783f43, 0x87723014), - TOBN(0x9a49a0cf, 0x1a885719), TOBN(0xfc0c1a5a, 0x90da9dbf), - TOBN(0x8bbaec49, 0x571d92ac), TOBN(0x569e85fe, 0x4692517f), - TOBN(0x8333b014, 0xa14ea4af), TOBN(0x32f2a62f, 0x12e5c5ad), - TOBN(0x98c2ce3a, 0x06d89b85), TOBN(0xb90741aa, 0x2ff77a08), - TOBN(0x2530defc, 0x01f795a2), TOBN(0xd6e5ba0b, 0x84b3c199), - TOBN(0x7d8e8451, 0x12e4c936), TOBN(0xae419f7d, 0xbd0be17b), - TOBN(0xa583fc8c, 0x22262bc9), TOBN(0x6b842ac7, 0x91bfe2bd), - TOBN(0x33cef4e9, 0x440d6827), TOBN(0x5f69f4de, 0xef81fb14), - TOBN(0xf16cf6f6, 0x234fbb92), TOBN(0x76ae3fc3, 0xd9e7e158), - TOBN(0x4e89f6c2, 0xe9740b33), TOBN(0x677bc85d, 0x4962d6a1), - TOBN(0x6c6d8a7f, 0x68d10d15), TOBN(0x5f9a7224, 0x0257b1cd), - TOBN(0x7096b916, 0x4ad85961), TOBN(0x5f8c47f7, 0xe657ab4a), - TOBN(0xde57d7d0, 0xf7461d7e), TOBN(0x7eb6094d, 0x80ce5ee2), - TOBN(0x0b1e1dfd, 0x34190547), TOBN(0x8a394f43, 0xf05dd150), - TOBN(0x0a9eb24d, 0x97df44e6), TOBN(0x78ca06bf, 0x87675719), - TOBN(0x6f0b3462, 0x6ffeec22), TOBN(0x9d91bcea, 0x36cdd8fb), - TOBN(0xac83363c, 0xa105be47), TOBN(0x81ba76c1, 0x069710e3), - TOBN(0x3d1b24cb, 0x28c682c6), TOBN(0x27f25228, 0x8612575b), - TOBN(0xb587c779, 0xe8e66e98), TOBN(0x7b0c03e9, 0x405eb1fe), - TOBN(0xfdf0d030, 0x15b548e7), TOBN(0xa8be76e0, 0x38b36af7), - TOBN(0x4cdab04a, 0x4f310c40), TOBN(0x6287223e, 0xf47ecaec), - TOBN(0x678e6055, 0x8b399320), TOBN(0x61fe3fa6, 0xc01e4646), - TOBN(0xc482866b, 0x03261a5e), TOBN(0xdfcf45b8, 0x5c2f244a), - TOBN(0x8fab9a51, 0x2f684b43), TOBN(0xf796c654, 0xc7220a66), - TOBN(0x1d90707e, 0xf5afa58f), TOBN(0x2c421d97, 0x4fdbe0de), - TOBN(0xc4f4cda3, 0xaf2ebc2f), TOBN(0xa0af843d, 0xcb4efe24), - TOBN(0x53b857c1, 0x9ccd10b1), TOBN(0xddc9d1eb, 0x914d3e04), - TOBN(0x7bdec8bb, 0x62771deb), TOBN(0x829277aa, 0x91c5aa81), - TOBN(0x7af18dd6, 0x832391ae), TOBN(0x1740f316, 0xc71a84ca), - }, - { - TOBN(0x8928e99a, 0xeeaf8c49), TOBN(0xee7aa73d, 0x6e24d728), - TOBN(0x4c5007c2, 0xe72b156c), TOBN(0x5fcf57c5, 0xed408a1d), - TOBN(0x9f719e39, 0xb6057604), TOBN(0x7d343c01, 0xc2868bbf), - TOBN(0x2cca254b, 0x7e103e2d), TOBN(0xe6eb38a9, 0xf131bea2), - TOBN(0xb33e624f, 0x8be762b4), TOBN(0x2a9ee4d1, 0x058e3413), - TOBN(0x968e6369, 0x67d805fa), TOBN(0x9848949b, 0x7db8bfd7), - TOBN(0x5308d7e5, 0xd23a8417), TOBN(0x892f3b1d, 0xf3e29da5), - TOBN(0xc95c139e, 0x3dee471f), TOBN(0x8631594d, 0xd757e089), - TOBN(0xe0c82a3c, 0xde918dcc), TOBN(0x2e7b5994, 0x26fdcf4b), - TOBN(0x82c50249, 0x32cb1b2d), TOBN(0xea613a9d, 0x7657ae07), - TOBN(0xc2eb5f6c, 0xf1fdc9f7), TOBN(0xb6eae8b8, 0x879fe682), - TOBN(0x253dfee0, 0x591cbc7f), TOBN(0x000da713, 0x3e1290e6), - TOBN(0x1083e2ea, 0x1f095615), TOBN(0x0a28ad77, 0x14e68c33), - TOBN(0x6bfc0252, 0x3d8818be), TOBN(0xb585113a, 0xf35850cd), - TOBN(0x7d935f0b, 0x30df8aa1), TOBN(0xaddda07c, 0x4ab7e3ac), - TOBN(0x92c34299, 0x552f00cb), TOBN(0xc33ed1de, 0x2909df6c), - TOBN(0x22c2195d, 0x80e87766), TOBN(0x9e99e6d8, 0x9ddf4ac0), - TOBN(0x09642e4e, 0x65e74934), TOBN(0x2610ffa2, 0xff1ff241), - TOBN(0x4d1d47d4, 0x751c8159), TOBN(0x697b4985, 0xaf3a9363), - TOBN(0x0318ca46, 0x87477c33), TOBN(0xa90cb565, 0x9441eff3), - TOBN(0x58bb3848, 0x36f024cb), TOBN(0x85be1f77, 0x36016168), - TOBN(0x6c59587c, 0xdc7e07f1), TOBN(0x191be071, 0xaf1d8f02), - TOBN(0xbf169fa5, 0xcca5e55c), TOBN(0x3864ba3c, 0xf7d04eac), - TOBN(0x915e367f, 0x8d7d05db), TOBN(0xb48a876d, 0xa6549e5d), - TOBN(0xef89c656, 0x580e40a2), TOBN(0xf194ed8c, 0x728068bc), - TOBN(0x74528045, 0xa47990c9), TOBN(0xf53fc7d7, 0x5e1a4649), - TOBN(0xbec5ae9b, 0x78593e7d), TOBN(0x2cac4ee3, 0x41db65d7), - TOBN(0xa8c1eb24, 0x04a3d39b), TOBN(0x53b7d634, 0x03f8f3ef), - TOBN(0x2dc40d48, 0x3e07113c), TOBN(0x6e4a5d39, 0x7d8b63ae), - TOBN(0x5582a94b, 0x79684c2b), TOBN(0x932b33d4, 0x622da26c), - TOBN(0xf534f651, 0x0dbbf08d), TOBN(0x211d07c9, 0x64c23a52), - TOBN(0x0eeece0f, 0xee5bdc9b), TOBN(0xdf178168, 0xf7015558), - TOBN(0xd4294635, 0x0a712229), TOBN(0x93cbe448, 0x09273f8c), - TOBN(0x00b095ef, 0x8f13bc83), TOBN(0xbb741972, 0x8798978c), - TOBN(0x9d7309a2, 0x56dbe6e7), TOBN(0xe578ec56, 0x5a5d39ec), - TOBN(0x3961151b, 0x851f9a31), TOBN(0x2da7715d, 0xe5709eb4), - TOBN(0x867f3017, 0x53dfabf0), TOBN(0x728d2078, 0xb8e39259), - TOBN(0x5c75a0cd, 0x815d9958), TOBN(0xf84867a6, 0x16603be1), - TOBN(0xc865b13d, 0x70e35b1c), TOBN(0x02414468, 0x19b03e2c), - TOBN(0xe46041da, 0xac1f3121), TOBN(0x7c9017ad, 0x6f028a7c), - TOBN(0xabc96de9, 0x0a482873), TOBN(0x4265d6b1, 0xb77e54d4), - TOBN(0x68c38e79, 0xa57d88e7), TOBN(0xd461d766, 0x9ce82de3), - TOBN(0x817a9ec5, 0x64a7e489), TOBN(0xcc5675cd, 0xa0def5f2), - TOBN(0x9a00e785, 0x985d494e), TOBN(0xc626833f, 0x1b03514a), - TOBN(0xabe7905a, 0x83cdd60e), TOBN(0x50602fb5, 0xa1170184), - TOBN(0x689886cd, 0xb023642a), TOBN(0xd568d090, 0xa6e1fb00), - TOBN(0x5b1922c7, 0x0259217f), TOBN(0x93831cd9, 0xc43141e4), - TOBN(0xdfca3587, 0x0c95f86e), TOBN(0xdec2057a, 0x568ae828), - TOBN(0xc44ea599, 0xf98a759a), TOBN(0x55a0a7a2, 0xf7c23c1d), - TOBN(0xd5ffb6e6, 0x94c4f687), TOBN(0x3563cce2, 0x12848478), - TOBN(0x812b3517, 0xe7b1fbe1), TOBN(0x8a7dc979, 0x4f7338e0), - TOBN(0x211ecee9, 0x52d048db), TOBN(0x2eea4056, 0xc86ea3b8), - TOBN(0xd8cb68a7, 0xba772b34), TOBN(0xe16ed341, 0x5f4e2541), - TOBN(0x9b32f6a6, 0x0fec14db), TOBN(0xeee376f7, 0x391698be), - TOBN(0xe9a7aa17, 0x83674c02), TOBN(0x65832f97, 0x5843022a), - TOBN(0x29f3a8da, 0x5ba4990f), TOBN(0x79a59c3a, 0xfb8e3216), - TOBN(0x9cdc4d2e, 0xbd19bb16), TOBN(0xc6c7cfd0, 0xb3262d86), - TOBN(0xd4ce14d0, 0x969c0b47), TOBN(0x1fa352b7, 0x13e56128), - TOBN(0x383d55b8, 0x973db6d3), TOBN(0x71836850, 0xe8e5b7bf), - TOBN(0xc7714596, 0xe6bb571f), TOBN(0x259df31f, 0x2d5b2dd2), - TOBN(0x568f8925, 0x913cc16d), TOBN(0x18bc5b6d, 0xe1a26f5a), - TOBN(0xdfa413be, 0xf5f499ae), TOBN(0xf8835dec, 0xc3f0ae84), - TOBN(0xb6e60bd8, 0x65a40ab0), TOBN(0x65596439, 0x194b377e), - TOBN(0xbcd85625, 0x92084a69), TOBN(0x5ce433b9, 0x4f23ede0), - TOBN(0xe8e8f04f, 0x6ad65143), TOBN(0x11511827, 0xd6e14af6), - TOBN(0x3d390a10, 0x8295c0c7), TOBN(0x71e29ee4, 0x621eba16), - TOBN(0xa588fc09, 0x63717b46), TOBN(0x02be02fe, 0xe06ad4a2), - TOBN(0x931558c6, 0x04c22b22), TOBN(0xbb4d4bd6, 0x12f3c849), - TOBN(0x54a4f496, 0x20efd662), TOBN(0x92ba6d20, 0xc5952d14), - TOBN(0x2db8ea1e, 0xcc9784c2), TOBN(0x81cc10ca, 0x4b353644), - TOBN(0x40b570ad, 0x4b4d7f6c), TOBN(0x5c9f1d96, 0x84a1dcd2), - TOBN(0x01379f81, 0x3147e797), TOBN(0xe5c6097b, 0x2bd499f5), - TOBN(0x40dcafa6, 0x328e5e20), TOBN(0xf7b5244a, 0x54815550), - TOBN(0xb9a4f118, 0x47bfc978), TOBN(0x0ea0e79f, 0xd25825b1), - TOBN(0xa50f96eb, 0x646c7ecf), TOBN(0xeb811493, 0x446dea9d), - TOBN(0x2af04677, 0xdfabcf69), TOBN(0xbe3a068f, 0xc713f6e8), - TOBN(0x860d523d, 0x42e06189), TOBN(0xbf077941, 0x4e3aff13), - TOBN(0x0b616dca, 0xc1b20650), TOBN(0xe66dd6d1, 0x2131300d), - TOBN(0xd4a0fd67, 0xff99abde), TOBN(0xc9903550, 0xc7aac50d), - TOBN(0x022ecf8b, 0x7c46b2d7), TOBN(0x3333b1e8, 0x3abf92af), - TOBN(0x11cc113c, 0x6c491c14), TOBN(0x05976688, 0x80dd3f88), - TOBN(0xf5b4d9e7, 0x29d932ed), TOBN(0xe982aad8, 0xa2c38b6d), - TOBN(0x6f925347, 0x8be0dcf0), TOBN(0x700080ae, 0x65ca53f2), - TOBN(0xd8131156, 0x443ca77f), TOBN(0xe92d6942, 0xec51f984), - TOBN(0xd2a08af8, 0x85dfe9ae), TOBN(0xd825d9a5, 0x4d2a86ca), - TOBN(0x2c53988d, 0x39dff020), TOBN(0xf38b135a, 0x430cdc40), - TOBN(0x0c918ae0, 0x62a7150b), TOBN(0xf31fd8de, 0x0c340e9b), - TOBN(0xafa0e7ae, 0x4dbbf02e), TOBN(0x5847fb2a, 0x5eba6239), - TOBN(0x6b1647dc, 0xdccbac8b), TOBN(0xb642aa78, 0x06f485c8), - TOBN(0x873f3765, 0x7038ecdf), TOBN(0x2ce5e865, 0xfa49d3fe), - TOBN(0xea223788, 0xc98c4400), TOBN(0x8104a8cd, 0xf1fa5279), - TOBN(0xbcf7cc7a, 0x06becfd7), TOBN(0x49424316, 0xc8f974ae), - TOBN(0xc0da65e7, 0x84d6365d), TOBN(0xbcb7443f, 0x8f759fb8), - TOBN(0x35c712b1, 0x7ae81930), TOBN(0x80428dff, 0x4c6e08ab), - TOBN(0xf19dafef, 0xa4faf843), TOBN(0xced8538d, 0xffa9855f), - TOBN(0x20ac409c, 0xbe3ac7ce), TOBN(0x358c1fb6, 0x882da71e), - TOBN(0xafa9c0e5, 0xfd349961), TOBN(0x2b2cfa51, 0x8421c2fc), - TOBN(0x2a80db17, 0xf3a28d38), TOBN(0xa8aba539, 0x5d138e7e), - TOBN(0x52012d1d, 0x6e96eb8d), TOBN(0x65d8dea0, 0xcbaf9622), - TOBN(0x57735447, 0xb264f56c), TOBN(0xbeebef3f, 0x1b6c8da2), - TOBN(0xfc346d98, 0xce785254), TOBN(0xd50e8d72, 0xbb64a161), - TOBN(0xc03567c7, 0x49794add), TOBN(0x15a76065, 0x752c7ef6), - TOBN(0x59f3a222, 0x961f23d6), TOBN(0x378e4438, 0x73ecc0b0), - TOBN(0xc74be434, 0x5a82fde4), TOBN(0xae509af2, 0xd8b9cf34), - TOBN(0x4a61ee46, 0x577f44a1), TOBN(0xe09b748c, 0xb611deeb), - TOBN(0xc0481b2c, 0xf5f7b884), TOBN(0x35626678, 0x61acfa6b), - TOBN(0x37f4c518, 0xbf8d21e6), TOBN(0x22d96531, 0xb205a76d), - TOBN(0x37fb85e1, 0x954073c0), TOBN(0xbceafe4f, 0x65b3a567), - TOBN(0xefecdef7, 0xbe42a582), TOBN(0xd3fc6080, 0x65046be6), - TOBN(0xc9af13c8, 0x09e8dba9), TOBN(0x1e6c9847, 0x641491ff), - TOBN(0x3b574925, 0xd30c31f7), TOBN(0xb7eb72ba, 0xac2a2122), - TOBN(0x776a0dac, 0xef0859e7), TOBN(0x06fec314, 0x21900942), - TOBN(0x2464bc10, 0xf8c22049), TOBN(0x9bfbcce7, 0x875ebf69), - TOBN(0xd7a88e2a, 0x4336326b), TOBN(0xda05261c, 0x5bc2acfa), - TOBN(0xc29f5bdc, 0xeba7efc8), TOBN(0x471237ca, 0x25dbbf2e), - TOBN(0xa72773f2, 0x2975f127), TOBN(0xdc744e8e, 0x04d0b326), - TOBN(0x38a7ed16, 0xa56edb73), TOBN(0x64357e37, 0x2c007e70), - TOBN(0xa167d15b, 0x5080b400), TOBN(0x07b41164, 0x23de4be1), - TOBN(0xb2d91e32, 0x74c89883), TOBN(0x3c162821, 0x2882e7ed), - TOBN(0xad6b36ba, 0x7503e482), TOBN(0x48434e8e, 0x0ea34331), - TOBN(0x79f4f24f, 0x2c7ae0b9), TOBN(0xc46fbf81, 0x1939b44a), - TOBN(0x76fefae8, 0x56595eb1), TOBN(0x417b66ab, 0xcd5f29c7), - TOBN(0x5f2332b2, 0xc5ceec20), TOBN(0xd69661ff, 0xe1a1cae2), - TOBN(0x5ede7e52, 0x9b0286e6), TOBN(0x9d062529, 0xe276b993), - TOBN(0x324794b0, 0x7e50122b), TOBN(0xdd744f8b, 0x4af07ca5), - TOBN(0x30a12f08, 0xd63fc97b), TOBN(0x39650f1a, 0x76626d9d), - TOBN(0x101b47f7, 0x1fa38477), TOBN(0x3d815f19, 0xd4dc124f), - TOBN(0x1569ae95, 0xb26eb58a), TOBN(0xc3cde188, 0x95fb1887), - TOBN(0x54e9f37b, 0xf9539a48), TOBN(0xb0100e06, 0x7408c1a5), - TOBN(0x821d9811, 0xea580cbb), TOBN(0x8af52d35, 0x86e50c56), - TOBN(0xdfbd9d47, 0xdbbf698b), TOBN(0x2961a1ea, 0x03dc1c73), - TOBN(0x203d38f8, 0xe76a5df8), TOBN(0x08a53a68, 0x6def707a), - TOBN(0x26eefb48, 0x1bee45d4), TOBN(0xb3cee346, 0x3c688036), - TOBN(0x463c5315, 0xc42f2469), TOBN(0x19d84d2e, 0x81378162), - TOBN(0x22d7c3c5, 0x1c4d349f), TOBN(0x65965844, 0x163d59c5), - TOBN(0xcf198c56, 0xb8abceae), TOBN(0x6fb1fb1b, 0x628559d5), - TOBN(0x8bbffd06, 0x07bf8fe3), TOBN(0x46259c58, 0x3467734b), - TOBN(0xd8953cea, 0x35f7f0d3), TOBN(0x1f0bece2, 0xd65b0ff1), - TOBN(0xf7d5b4b3, 0xf3c72914), TOBN(0x29e8ea95, 0x3cb53389), - TOBN(0x4a365626, 0x836b6d46), TOBN(0xe849f910, 0xea174fde), - TOBN(0x7ec62fbb, 0xf4737f21), TOBN(0xd8dba5ab, 0x6209f5ac), - TOBN(0x24b5d7a9, 0xa5f9adbe), TOBN(0x707d28f7, 0xa61dc768), - TOBN(0x7711460b, 0xcaa999ea), TOBN(0xba7b174d, 0x1c92e4cc), - TOBN(0x3c4bab66, 0x18d4bf2d), TOBN(0xb8f0c980, 0xeb8bd279), - TOBN(0x024bea9a, 0x324b4737), TOBN(0xfba9e423, 0x32a83bca), - TOBN(0x6e635643, 0xa232dced), TOBN(0x99619367, 0x2571c8ba), - TOBN(0xe8c9f357, 0x54b7032b), TOBN(0xf936b3ba, 0x2442d54a), - TOBN(0x2263f0f0, 0x8290c65a), TOBN(0x48989780, 0xee2c7fdb), - TOBN(0xadc5d55a, 0x13d4f95e), TOBN(0x737cff85, 0xad9b8500), - TOBN(0x271c557b, 0x8a73f43d), TOBN(0xbed617a4, 0xe18bc476), - TOBN(0x66245401, 0x7dfd8ab2), TOBN(0xae7b89ae, 0x3a2870aa), - TOBN(0x1b555f53, 0x23a7e545), TOBN(0x6791e247, 0xbe057e4c), - TOBN(0x860136ad, 0x324fa34d), TOBN(0xea111447, 0x4cbeae28), - TOBN(0x023a4270, 0xbedd3299), TOBN(0x3d5c3a7f, 0xc1c35c34), - TOBN(0xb0f6db67, 0x8d0412d2), TOBN(0xd92625e2, 0xfcdc6b9a), - TOBN(0x92ae5ccc, 0x4e28a982), TOBN(0xea251c36, 0x47a3ce7e), - TOBN(0x9d658932, 0x790691bf), TOBN(0xed610589, 0x06b736ae), - TOBN(0x712c2f04, 0xc0d63b6e), TOBN(0x5cf06fd5, 0xc63d488f), - TOBN(0x97363fac, 0xd9588e41), TOBN(0x1f9bf762, 0x2b93257e), - TOBN(0xa9d1ffc4, 0x667acace), TOBN(0x1cf4a1aa, 0x0a061ecf), - TOBN(0x40e48a49, 0xdc1818d0), TOBN(0x0643ff39, 0xa3621ab0), - TOBN(0x5768640c, 0xe39ef639), TOBN(0x1fc099ea, 0x04d86854), - TOBN(0x9130b9c3, 0xeccd28fd), TOBN(0xd743cbd2, 0x7eec54ab), - TOBN(0x052b146f, 0xe5b475b6), TOBN(0x058d9a82, 0x900a7d1f), - TOBN(0x65e02292, 0x91262b72), TOBN(0x96f924f9, 0xbb0edf03), - TOBN(0x5cfa59c8, 0xfe206842), TOBN(0xf6037004, 0x5eafa720), - TOBN(0x5f30699e, 0x18d7dd96), TOBN(0x381e8782, 0xcbab2495), - TOBN(0x91669b46, 0xdd8be949), TOBN(0xb40606f5, 0x26aae8ef), - TOBN(0x2812b839, 0xfc6751a4), TOBN(0x16196214, 0xfba800ef), - TOBN(0x4398d5ca, 0x4c1a2875), TOBN(0x720c00ee, 0x653d8349), - TOBN(0xc2699eb0, 0xd820007c), TOBN(0x880ee660, 0xa39b5825), - TOBN(0x70694694, 0x471f6984), TOBN(0xf7d16ea8, 0xe3dda99a), - TOBN(0x28d675b2, 0xc0519a23), TOBN(0x9ebf94fe, 0x4f6952e3), - TOBN(0xf28bb767, 0xa2294a8a), TOBN(0x85512b4d, 0xfe0af3f5), - TOBN(0x18958ba8, 0x99b16a0d), TOBN(0x95c2430c, 0xba7548a7), - TOBN(0xb30d1b10, 0xa16be615), TOBN(0xe3ebbb97, 0x85bfb74c), - TOBN(0xa3273cfe, 0x18549fdb), TOBN(0xf6e200bf, 0x4fcdb792), - TOBN(0x54a76e18, 0x83aba56c), TOBN(0x73ec66f6, 0x89ef6aa2), - TOBN(0x8d17add7, 0xd1b9a305), TOBN(0xa959c5b9, 0xb7ae1b9d), - TOBN(0x88643522, 0x6bcc094a), TOBN(0xcc5616c4, 0xd7d429b9), - TOBN(0xa6dada01, 0xe6a33f7c), TOBN(0xc6217a07, 0x9d4e70ad), - TOBN(0xd619a818, 0x09c15b7c), TOBN(0xea06b329, 0x0e80c854), - TOBN(0x174811ce, 0xa5f5e7b9), TOBN(0x66dfc310, 0x787c65f4), - TOBN(0x4ea7bd69, 0x3316ab54), TOBN(0xc12c4acb, 0x1dcc0f70), - TOBN(0xe4308d1a, 0x1e407dd9), TOBN(0xe8a3587c, 0x91afa997), - TOBN(0xea296c12, 0xab77b7a5), TOBN(0xb5ad49e4, 0x673c0d52), - TOBN(0x40f9b2b2, 0x7006085a), TOBN(0xa88ff340, 0x87bf6ec2), - TOBN(0x978603b1, 0x4e3066a6), TOBN(0xb3f99fc2, 0xb5e486e2), - TOBN(0x07b53f5e, 0xb2e63645), TOBN(0xbe57e547, 0x84c84232), - TOBN(0xd779c216, 0x7214d5cf), TOBN(0x617969cd, 0x029a3aca), - TOBN(0xd17668cd, 0x8a7017a0), TOBN(0x77b4d19a, 0xbe9b7ee8), - TOBN(0x58fd0e93, 0x9c161776), TOBN(0xa8c4f4ef, 0xd5968a72), - TOBN(0x296071cc, 0x67b3de77), TOBN(0xae3c0b8e, 0x634f7905), - TOBN(0x67e440c2, 0x8a7100c9), TOBN(0xbb8c3c1b, 0xeb4b9b42), - TOBN(0x6d71e8ea, 0xc51b3583), TOBN(0x7591f5af, 0x9525e642), - TOBN(0xf73a2f7b, 0x13f509f3), TOBN(0x618487aa, 0x5619ac9b), - TOBN(0x3a72e5f7, 0x9d61718a), TOBN(0x00413bcc, 0x7592d28c), - TOBN(0x7d9b11d3, 0x963c35cf), TOBN(0x77623bcf, 0xb90a46ed), - TOBN(0xdeef273b, 0xdcdd2a50), TOBN(0x4a741f9b, 0x0601846e), - TOBN(0x33b89e51, 0x0ec6e929), TOBN(0xcb02319f, 0x8b7f22cd), - TOBN(0xbbe1500d, 0x084bae24), TOBN(0x2f0ae8d7, 0x343d2693), - TOBN(0xacffb5f2, 0x7cdef811), TOBN(0xaa0c030a, 0x263fb94f), - TOBN(0x6eef0d61, 0xa0f442de), TOBN(0xf92e1817, 0x27b139d3), - TOBN(0x1ae6deb7, 0x0ad8bc28), TOBN(0xa89e38dc, 0xc0514130), - TOBN(0x81eeb865, 0xd2fdca23), TOBN(0x5a15ee08, 0xcc8ef895), - TOBN(0x768fa10a, 0x01905614), TOBN(0xeff5b8ef, 0x880ee19b), - TOBN(0xf0c0cabb, 0xcb1c8a0e), TOBN(0x2e1ee9cd, 0xb8c838f9), - TOBN(0x0587d8b8, 0x8a4a14c0), TOBN(0xf6f27896, 0x2ff698e5), - TOBN(0xed38ef1c, 0x89ee6256), TOBN(0xf44ee1fe, 0x6b353b45), - TOBN(0x9115c0c7, 0x70e903b3), TOBN(0xc78ec0a1, 0x818f31df), - TOBN(0x6c003324, 0xb7dccbc6), TOBN(0xd96dd1f3, 0x163bbc25), - TOBN(0x33aa82dd, 0x5cedd805), TOBN(0x123aae4f, 0x7f7eb2f1), - TOBN(0x1723fcf5, 0xa26262cd), TOBN(0x1f7f4d5d, 0x0060ebd5), - TOBN(0xf19c5c01, 0xb2eaa3af), TOBN(0x2ccb9b14, 0x9790accf), - TOBN(0x1f9c1cad, 0x52324aa6), TOBN(0x63200526, 0x7247df54), - TOBN(0x5732fe42, 0xbac96f82), TOBN(0x52fe771f, 0x01a1c384), - TOBN(0x546ca13d, 0xb1001684), TOBN(0xb56b4eee, 0xa1709f75), - TOBN(0x266545a9, 0xd5db8672), TOBN(0xed971c90, 0x1e8f3cfb), - TOBN(0x4e7d8691, 0xe3a07b29), TOBN(0x7570d9ec, 0xe4b696b9), - TOBN(0xdc5fa067, 0x7bc7e9ae), TOBN(0x68b44caf, 0xc82c4844), - TOBN(0x519d34b3, 0xbf44da80), TOBN(0x283834f9, 0x5ab32e66), - TOBN(0x6e608797, 0x6278a000), TOBN(0x1e62960e, 0x627312f6), - TOBN(0x9b87b27b, 0xe6901c55), TOBN(0x80e78538, 0x24fdbc1f), - TOBN(0xbbbc0951, 0x2facc27d), TOBN(0x06394239, 0xac143b5a), - TOBN(0x35bb4a40, 0x376c1944), TOBN(0x7cb62694, 0x63da1511), - TOBN(0xafd29161, 0xb7148a3b), TOBN(0xa6f9d9ed, 0x4e2ea2ee), - TOBN(0x15dc2ca2, 0x880dd212), TOBN(0x903c3813, 0xa61139a9), - TOBN(0x2aa7b46d, 0x6c0f8785), TOBN(0x36ce2871, 0x901c60ff), - TOBN(0xc683b028, 0xe10d9c12), TOBN(0x7573baa2, 0x032f33d3), - TOBN(0x87a9b1f6, 0x67a31b58), TOBN(0xfd3ed11a, 0xf4ffae12), - TOBN(0x83dcaa9a, 0x0cb2748e), TOBN(0x8239f018, 0x5d6fdf16), - TOBN(0xba67b49c, 0x72753941), TOBN(0x2beec455, 0xc321cb36), - TOBN(0x88015606, 0x3f8b84ce), TOBN(0x76417083, 0x8d38c86f), - TOBN(0x054f1ca7, 0x598953dd), TOBN(0xc939e110, 0x4e8e7429), - TOBN(0x9b1ac2b3, 0x5a914f2f), TOBN(0x39e35ed3, 0xe74b8f9c), - TOBN(0xd0debdb2, 0x781b2fb0), TOBN(0x1585638f, 0x2d997ba2), - TOBN(0x9c4b646e, 0x9e2fce99), TOBN(0x68a21081, 0x1e80857f), - TOBN(0x06d54e44, 0x3643b52a), TOBN(0xde8d6d63, 0x0d8eb843), - TOBN(0x70321563, 0x42146a0a), TOBN(0x8ba826f2, 0x5eaa3622), - TOBN(0x227a58bd, 0x86138787), TOBN(0x43b6c03c, 0x10281d37), - TOBN(0x6326afbb, 0xb54dde39), TOBN(0x744e5e8a, 0xdb6f2d5f), - TOBN(0x48b2a99a, 0xcff158e1), TOBN(0xa93c8fa0, 0xef87918f), - TOBN(0x2182f956, 0xde058c5c), TOBN(0x216235d2, 0x936f9e7a), - TOBN(0xace0c0db, 0xd2e31e67), TOBN(0xc96449bf, 0xf23ac3e7), - TOBN(0x7e9a2874, 0x170693bd), TOBN(0xa28e14fd, 0xa45e6335), - TOBN(0x5757f6b3, 0x56427344), TOBN(0x822e4556, 0xacf8edf9), - TOBN(0x2b7a6ee2, 0xe6a285cd), TOBN(0x5866f211, 0xa9df3af0), - TOBN(0x40dde2dd, 0xf845b844), TOBN(0x986c3726, 0x110e5e49), - TOBN(0x73680c2a, 0xf7172277), TOBN(0x57b94f0f, 0x0cccb244), - TOBN(0xbdff7267, 0x2d438ca7), TOBN(0xbad1ce11, 0xcf4663fd), - TOBN(0x9813ed9d, 0xd8f71cae), TOBN(0xf43272a6, 0x961fdaa6), - TOBN(0xbeff0119, 0xbd6d1637), TOBN(0xfebc4f91, 0x30361978), - TOBN(0x02b37a95, 0x2f41deff), TOBN(0x0e44a59a, 0xe63b89b7), - TOBN(0x673257dc, 0x143ff951), TOBN(0x19c02205, 0xd752baf4), - TOBN(0x46c23069, 0xc4b7d692), TOBN(0x2e6392c3, 0xfd1502ac), - TOBN(0x6057b1a2, 0x1b220846), TOBN(0xe51ff946, 0x0c1b5b63), - }, - { - TOBN(0x6e85cb51, 0x566c5c43), TOBN(0xcff9c919, 0x3597f046), - TOBN(0x9354e90c, 0x4994d94a), TOBN(0xe0a39332, 0x2147927d), - TOBN(0x8427fac1, 0x0dc1eb2b), TOBN(0x88cfd8c2, 0x2ff319fa), - TOBN(0xe2d4e684, 0x01965274), TOBN(0xfa2e067d, 0x67aaa746), - TOBN(0xb6d92a7f, 0x3e5f9f11), TOBN(0x9afe153a, 0xd6cb3b8e), - TOBN(0x4d1a6dd7, 0xddf800bd), TOBN(0xf6c13cc0, 0xcaf17e19), - TOBN(0x15f6c58e, 0x325fc3ee), TOBN(0x71095400, 0xa31dc3b2), - TOBN(0x168e7c07, 0xafa3d3e7), TOBN(0x3f8417a1, 0x94c7ae2d), - TOBN(0xec234772, 0x813b230d), TOBN(0x634d0f5f, 0x17344427), - TOBN(0x11548ab1, 0xd77fc56a), TOBN(0x7fab1750, 0xce06af77), - TOBN(0xb62c10a7, 0x4f7c4f83), TOBN(0xa7d2edc4, 0x220a67d9), - TOBN(0x1c404170, 0x921209a0), TOBN(0x0b9815a0, 0xface59f0), - TOBN(0x2842589b, 0x319540c3), TOBN(0x18490f59, 0xa283d6f8), - TOBN(0xa2731f84, 0xdaae9fcb), TOBN(0x3db6d960, 0xc3683ba0), - TOBN(0xc85c63bb, 0x14611069), TOBN(0xb19436af, 0x0788bf05), - TOBN(0x905459df, 0x347460d2), TOBN(0x73f6e094, 0xe11a7db1), - TOBN(0xdc7f938e, 0xb6357f37), TOBN(0xc5d00f79, 0x2bd8aa62), - TOBN(0xc878dcb9, 0x2ca979fc), TOBN(0x37e83ed9, 0xeb023a99), - TOBN(0x6b23e273, 0x1560bf3d), TOBN(0x1086e459, 0x1d0fae61), - TOBN(0x78248316, 0x9a9414bd), TOBN(0x1b956bc0, 0xf0ea9ea1), - TOBN(0x7b85bb91, 0xc31b9c38), TOBN(0x0c5aa90b, 0x48ef57b5), - TOBN(0xdedeb169, 0xaf3bab6f), TOBN(0xe610ad73, 0x2d373685), - TOBN(0xf13870df, 0x02ba8e15), TOBN(0x0337edb6, 0x8ca7f771), - TOBN(0xe4acf747, 0xb62c036c), TOBN(0xd921d576, 0xb6b94e81), - TOBN(0xdbc86439, 0x2c422f7a), TOBN(0xfb635362, 0xed348898), - TOBN(0x83084668, 0xc45bfcd1), TOBN(0xc357c9e3, 0x2b315e11), - TOBN(0xb173b540, 0x5b2e5b8c), TOBN(0x7e946931, 0xe102b9a4), - TOBN(0x17c890eb, 0x7b0fb199), TOBN(0xec225a83, 0xd61b662b), - TOBN(0xf306a3c8, 0xee3c76cb), TOBN(0x3cf11623, 0xd32a1f6e), - TOBN(0xe6d5ab64, 0x6863e956), TOBN(0x3b8a4cbe, 0x5c005c26), - TOBN(0xdcd529a5, 0x9ce6bb27), TOBN(0xc4afaa52, 0x04d4b16f), - TOBN(0xb0624a26, 0x7923798d), TOBN(0x85e56df6, 0x6b307fab), - TOBN(0x0281893c, 0x2bf29698), TOBN(0x91fc19a4, 0xd7ce7603), - TOBN(0x75a5dca3, 0xad9a558f), TOBN(0x40ceb3fa, 0x4d50bf77), - TOBN(0x1baf6060, 0xbc9ba369), TOBN(0x927e1037, 0x597888c2), - TOBN(0xd936bf19, 0x86a34c07), TOBN(0xd4cf10c1, 0xc34ae980), - TOBN(0x3a3e5334, 0x859dd614), TOBN(0x9c475b5b, 0x18d0c8ee), - TOBN(0x63080d1f, 0x07cd51d5), TOBN(0xc9c0d0a6, 0xb88b4326), - TOBN(0x1ac98691, 0xc234296f), TOBN(0x2a0a83a4, 0x94887fb6), - TOBN(0x56511427, 0x0cea9cf2), TOBN(0x5230a6e8, 0xa24802f5), - TOBN(0xf7a2bf0f, 0x72e3d5c1), TOBN(0x37717446, 0x4f21439e), - TOBN(0xfedcbf25, 0x9ce30334), TOBN(0xe0030a78, 0x7ce202f9), - TOBN(0x6f2d9ebf, 0x1202e9ca), TOBN(0xe79dde6c, 0x75e6e591), - TOBN(0xf52072af, 0xf1dac4f8), TOBN(0x6c8d087e, 0xbb9b404d), - TOBN(0xad0fc73d, 0xbce913af), TOBN(0x909e587b, 0x458a07cb), - TOBN(0x1300da84, 0xd4f00c8a), TOBN(0x425cd048, 0xb54466ac), - TOBN(0xb59cb9be, 0x90e9d8bf), TOBN(0x991616db, 0x3e431b0e), - TOBN(0xd3aa117a, 0x531aecff), TOBN(0x91af92d3, 0x59f4dc3b), - TOBN(0x9b1ec292, 0xe93fda29), TOBN(0x76bb6c17, 0xe97d91bc), - TOBN(0x7509d95f, 0xaface1e6), TOBN(0x3653fe47, 0xbe855ae3), - TOBN(0x73180b28, 0x0f680e75), TOBN(0x75eefd1b, 0xeeb6c26c), - TOBN(0xa4cdf29f, 0xb66d4236), TOBN(0x2d70a997, 0x6b5821d8), - TOBN(0x7a3ee207, 0x20445c36), TOBN(0x71d1ac82, 0x59877174), - TOBN(0x0fc539f7, 0x949f73e9), TOBN(0xd05cf3d7, 0x982e3081), - TOBN(0x8758e20b, 0x7b1c7129), TOBN(0xffadcc20, 0x569e61f2), - TOBN(0xb05d3a2f, 0x59544c2d), TOBN(0xbe16f5c1, 0x9fff5e53), - TOBN(0x73cf65b8, 0xaad58135), TOBN(0x622c2119, 0x037aa5be), - TOBN(0x79373b3f, 0x646fd6a0), TOBN(0x0e029db5, 0x0d3978cf), - TOBN(0x8bdfc437, 0x94fba037), TOBN(0xaefbd687, 0x620797a6), - TOBN(0x3fa5382b, 0xbd30d38e), TOBN(0x7627cfbf, 0x585d7464), - TOBN(0xb2330fef, 0x4e4ca463), TOBN(0xbcef7287, 0x3566cc63), - TOBN(0xd161d2ca, 0xcf780900), TOBN(0x135dc539, 0x5b54827d), - TOBN(0x638f052e, 0x27bf1bc6), TOBN(0x10a224f0, 0x07dfa06c), - TOBN(0xe973586d, 0x6d3321da), TOBN(0x8b0c5738, 0x26152c8f), - TOBN(0x07ef4f2a, 0x34606074), TOBN(0x80fe7fe8, 0xa0f7047a), - TOBN(0x3d1a8152, 0xe1a0e306), TOBN(0x32cf43d8, 0x88da5222), - TOBN(0xbf89a95f, 0x5f02ffe6), TOBN(0x3d9eb9a4, 0x806ad3ea), - TOBN(0x012c17bb, 0x79c8e55e), TOBN(0xfdcd1a74, 0x99c81dac), - TOBN(0x7043178b, 0xb9556098), TOBN(0x4090a1df, 0x801c3886), - TOBN(0x759800ff, 0x9b67b912), TOBN(0x3e5c0304, 0x232620c8), - TOBN(0x4b9d3c4b, 0x70dceeca), TOBN(0xbb2d3c15, 0x181f648e), - TOBN(0xf981d837, 0x6e33345c), TOBN(0xb626289b, 0x0cf2297a), - TOBN(0x766ac659, 0x8baebdcf), TOBN(0x1a28ae09, 0x75df01e5), - TOBN(0xb71283da, 0x375876d8), TOBN(0x4865a96d, 0x607b9800), - TOBN(0x25dd1bcd, 0x237936b2), TOBN(0x332f4f4b, 0x60417494), - TOBN(0xd0923d68, 0x370a2147), TOBN(0x497f5dfb, 0xdc842203), - TOBN(0x9dc74cbd, 0x32be5e0f), TOBN(0x7475bcb7, 0x17a01375), - TOBN(0x438477c9, 0x50d872b1), TOBN(0xcec67879, 0xffe1d63d), - TOBN(0x9b006014, 0xd8578c70), TOBN(0xc9ad99a8, 0x78bb6b8b), - TOBN(0x6799008e, 0x11fb3806), TOBN(0xcfe81435, 0xcd44cab3), - TOBN(0xa2ee1582, 0x2f4fb344), TOBN(0xb8823450, 0x483fa6eb), - TOBN(0x622d323d, 0x652c7749), TOBN(0xd8474a98, 0xbeb0a15b), - TOBN(0xe43c154d, 0x5d1c00d0), TOBN(0x7fd581d9, 0x0e3e7aac), - TOBN(0x2b44c619, 0x2525ddf8), TOBN(0x67a033eb, 0xb8ae9739), - TOBN(0x113ffec1, 0x9ef2d2e4), TOBN(0x1bf6767e, 0xd5a0ea7f), - TOBN(0x57fff75e, 0x03714c0a), TOBN(0xa23c422e, 0x0a23e9ee), - TOBN(0xdd5f6b2d, 0x540f83af), TOBN(0xc2c2c27e, 0x55ea46a7), - TOBN(0xeb6b4246, 0x672a1208), TOBN(0xd13599f7, 0xae634f7a), - TOBN(0xcf914b5c, 0xd7b32c6e), TOBN(0x61a5a640, 0xeaf61814), - TOBN(0x8dc3df8b, 0x208a1bbb), TOBN(0xef627fd6, 0xb6d79aa5), - TOBN(0x44232ffc, 0xc4c86bc8), TOBN(0xe6f9231b, 0x061539fe), - TOBN(0x1d04f25a, 0x958b9533), TOBN(0x180cf934, 0x49e8c885), - TOBN(0x89689595, 0x9884aaf7), TOBN(0xb1959be3, 0x07b348a6), - TOBN(0x96250e57, 0x3c147c87), TOBN(0xae0efb3a, 0xdd0c61f8), - TOBN(0xed00745e, 0xca8c325e), TOBN(0x3c911696, 0xecff3f70), - TOBN(0x73acbc65, 0x319ad41d), TOBN(0x7b01a020, 0xf0b1c7ef), - TOBN(0xea32b293, 0x63a1483f), TOBN(0x89eabe71, 0x7a248f96), - TOBN(0x9c6231d3, 0x343157e5), TOBN(0x93a375e5, 0xdf3c546d), - TOBN(0xe76e9343, 0x6a2afe69), TOBN(0xc4f89100, 0xe166c88e), - TOBN(0x248efd0d, 0x4f872093), TOBN(0xae0eb3ea, 0x8fe0ea61), - TOBN(0xaf89790d, 0x9d79046e), TOBN(0x4d650f2d, 0x6cee0976), - TOBN(0xa3935d9a, 0x43071eca), TOBN(0x66fcd2c9, 0x283b0bfe), - TOBN(0x0e665eb5, 0x696605f1), TOBN(0xe77e5d07, 0xa54cd38d), - TOBN(0x90ee050a, 0x43d950cf), TOBN(0x86ddebda, 0xd32e69b5), - TOBN(0x6ad94a3d, 0xfddf7415), TOBN(0xf7fa1309, 0x3f6e8d5a), - TOBN(0xc4831d1d, 0xe9957f75), TOBN(0x7de28501, 0xd5817447), - TOBN(0x6f1d7078, 0x9e2aeb6b), TOBN(0xba2b9ff4, 0xf67a53c2), - TOBN(0x36963767, 0xdf9defc3), TOBN(0x479deed3, 0x0d38022c), - TOBN(0xd2edb89b, 0x3a8631e8), TOBN(0x8de855de, 0x7a213746), - TOBN(0xb2056cb7, 0xb00c5f11), TOBN(0xdeaefbd0, 0x2c9b85e4), - TOBN(0x03f39a8d, 0xd150892d), TOBN(0x37b84686, 0x218b7985), - TOBN(0x36296dd8, 0xb7375f1a), TOBN(0x472cd4b1, 0xb78e898e), - TOBN(0x15dff651, 0xe9f05de9), TOBN(0xd4045069, 0x2ce98ba9), - TOBN(0x8466a7ae, 0x9b38024c), TOBN(0xb910e700, 0xe5a6b5ef), - TOBN(0xae1c56ea, 0xb3aa8f0d), TOBN(0xbab2a507, 0x7eee74a6), - TOBN(0x0dca11e2, 0x4b4c4620), TOBN(0xfd896e2e, 0x4c47d1f4), - TOBN(0xeb45ae53, 0x308fbd93), TOBN(0x46cd5a2e, 0x02c36fda), - TOBN(0x6a3d4e90, 0xbaa48385), TOBN(0xdd55e62e, 0x9dbe9960), - TOBN(0xa1406aa0, 0x2a81ede7), TOBN(0x6860dd14, 0xf9274ea7), - TOBN(0xcfdcb0c2, 0x80414f86), TOBN(0xff410b10, 0x22f94327), - TOBN(0x5a33cc38, 0x49ad467b), TOBN(0xefb48b6c, 0x0a7335f1), - TOBN(0x14fb54a4, 0xb153a360), TOBN(0x604aa9d2, 0xb52469cc), - TOBN(0x5e9dc486, 0x754e48e9), TOBN(0x693cb455, 0x37471e8e), - TOBN(0xfb2fd7cd, 0x8d3b37b6), TOBN(0x63345e16, 0xcf09ff07), - TOBN(0x9910ba6b, 0x23a5d896), TOBN(0x1fe19e35, 0x7fe4364e), - TOBN(0x6e1da8c3, 0x9a33c677), TOBN(0x15b4488b, 0x29fd9fd0), - TOBN(0x1f439254, 0x1a1f22bf), TOBN(0x920a8a70, 0xab8163e8), - TOBN(0x3fd1b249, 0x07e5658e), TOBN(0xf2c4f79c, 0xb6ec839b), - TOBN(0x1abbc3d0, 0x4aa38d1b), TOBN(0x3b0db35c, 0xb5d9510e), - TOBN(0x1754ac78, 0x3e60dec0), TOBN(0x53272fd7, 0xea099b33), - TOBN(0x5fb0494f, 0x07a8e107), TOBN(0x4a89e137, 0x6a8191fa), - TOBN(0xa113b7f6, 0x3c4ad544), TOBN(0x88a2e909, 0x6cb9897b), - TOBN(0x17d55de3, 0xb44a3f84), TOBN(0xacb2f344, 0x17c6c690), - TOBN(0x32088168, 0x10232390), TOBN(0xf2e8a61f, 0x6c733bf7), - TOBN(0xa774aab6, 0x9c2d7652), TOBN(0xfb5307e3, 0xed95c5bc), - TOBN(0xa05c73c2, 0x4981f110), TOBN(0x1baae31c, 0xa39458c9), - TOBN(0x1def185b, 0xcbea62e7), TOBN(0xe8ac9eae, 0xeaf63059), - TOBN(0x098a8cfd, 0x9921851c), TOBN(0xd959c3f1, 0x3abe2f5b), - TOBN(0xa4f19525, 0x20e40ae5), TOBN(0x320789e3, 0x07a24aa1), - TOBN(0x259e6927, 0x7392b2bc), TOBN(0x58f6c667, 0x1918668b), - TOBN(0xce1db2bb, 0xc55d2d8b), TOBN(0x41d58bb7, 0xf4f6ca56), - TOBN(0x7650b680, 0x8f877614), TOBN(0x905e16ba, 0xf4c349ed), - TOBN(0xed415140, 0xf661acac), TOBN(0x3b8784f0, 0xcb2270af), - TOBN(0x3bc280ac, 0x8a402cba), TOBN(0xd53f7146, 0x0937921a), - TOBN(0xc03c8ee5, 0xe5681e83), TOBN(0x62126105, 0xf6ac9e4a), - TOBN(0x9503a53f, 0x936b1a38), TOBN(0x3d45e2d4, 0x782fecbd), - TOBN(0x69a5c439, 0x76e8ae98), TOBN(0xb53b2eeb, 0xbfb4b00e), - TOBN(0xf1674712, 0x72386c89), TOBN(0x30ca34a2, 0x4268bce4), - TOBN(0x7f1ed86c, 0x78341730), TOBN(0x8ef5beb8, 0xb525e248), - TOBN(0xbbc489fd, 0xb74fbf38), TOBN(0x38a92a0e, 0x91a0b382), - TOBN(0x7a77ba3f, 0x22433ccf), TOBN(0xde8362d6, 0xa29f05a9), - TOBN(0x7f6a30ea, 0x61189afc), TOBN(0x693b5505, 0x59ef114f), - TOBN(0x50266bc0, 0xcd1797a1), TOBN(0xea17b47e, 0xf4b7af2d), - TOBN(0xd6c4025c, 0x3df9483e), TOBN(0x8cbb9d9f, 0xa37b18c9), - TOBN(0x91cbfd9c, 0x4d8424cf), TOBN(0xdb7048f1, 0xab1c3506), - TOBN(0x9eaf641f, 0x028206a3), TOBN(0xf986f3f9, 0x25bdf6ce), - TOBN(0x262143b5, 0x224c08dc), TOBN(0x2bbb09b4, 0x81b50c91), - TOBN(0xc16ed709, 0xaca8c84f), TOBN(0xa6210d9d, 0xb2850ca8), - TOBN(0x6d8df67a, 0x09cb54d6), TOBN(0x91eef6e0, 0x500919a4), - TOBN(0x90f61381, 0x0f132857), TOBN(0x9acede47, 0xf8d5028b), - TOBN(0x844d1b71, 0x90b771c3), TOBN(0x563b71e4, 0xba6426be), - TOBN(0x2efa2e83, 0xbdb802ff), TOBN(0x3410cbab, 0xab5b4a41), - TOBN(0x555b2d26, 0x30da84dd), TOBN(0xd0711ae9, 0xee1cc29a), - TOBN(0xcf3e8c60, 0x2f547792), TOBN(0x03d7d5de, 0xdc678b35), - TOBN(0x071a2fa8, 0xced806b8), TOBN(0x222e6134, 0x697f1478), - TOBN(0xdc16fd5d, 0xabfcdbbf), TOBN(0x44912ebf, 0x121b53b8), - TOBN(0xac943674, 0x2496c27c), TOBN(0x8ea3176c, 0x1ffc26b0), - TOBN(0xb6e224ac, 0x13debf2c), TOBN(0x524cc235, 0xf372a832), - TOBN(0xd706e1d8, 0x9f6f1b18), TOBN(0x2552f005, 0x44cce35b), - TOBN(0x8c8326c2, 0xa88e31fc), TOBN(0xb5468b2c, 0xf9552047), - TOBN(0xce683e88, 0x3ff90f2b), TOBN(0x77947bdf, 0x2f0a5423), - TOBN(0xd0a1b28b, 0xed56e328), TOBN(0xaee35253, 0xc20134ac), - TOBN(0x7e98367d, 0x3567962f), TOBN(0x379ed61f, 0x8188bffb), - TOBN(0x73bba348, 0xfaf130a1), TOBN(0x6c1f75e1, 0x904ed734), - TOBN(0x18956642, 0x3b4a79fc), TOBN(0xf20bc83d, 0x54ef4493), - TOBN(0x836d425d, 0x9111eca1), TOBN(0xe5b5c318, 0x009a8dcf), - TOBN(0x3360b25d, 0x13221bc5), TOBN(0x707baad2, 0x6b3eeaf7), - TOBN(0xd7279ed8, 0x743a95a1), TOBN(0x7450a875, 0x969e809f), - TOBN(0x32b6bd53, 0xe5d0338f), TOBN(0x1e77f7af, 0x2b883bbc), - TOBN(0x90da12cc, 0x1063ecd0), TOBN(0xe2697b58, 0xc315be47), - TOBN(0x2771a5bd, 0xda85d534), TOBN(0x53e78c1f, 0xff980eea), - TOBN(0xadf1cf84, 0x900385e7), TOBN(0x7d3b14f6, 0xc9387b62), - TOBN(0x170e74b0, 0xcb8f2bd2), TOBN(0x2d50b486, 0x827fa993), - TOBN(0xcdbe8c9a, 0xf6f32bab), TOBN(0x55e906b0, 0xc3b93ab8), - TOBN(0x747f22fc, 0x8fe280d1), TOBN(0xcd8e0de5, 0xb2e114ab), - TOBN(0x5ab7dbeb, 0xe10b68b0), TOBN(0x9dc63a9c, 0xa480d4b2), - TOBN(0x78d4bc3b, 0x4be1495f), TOBN(0x25eb3db8, 0x9359122d), - TOBN(0x3f8ac05b, 0x0809cbdc), TOBN(0xbf4187bb, 0xd37c702f), - TOBN(0x84cea069, 0x1416a6a5), TOBN(0x8f860c79, 0x43ef881c), - TOBN(0x41311f8a, 0x38038a5d), TOBN(0xe78c2ec0, 0xfc612067), - TOBN(0x494d2e81, 0x5ad73581), TOBN(0xb4cc9e00, 0x59604097), - TOBN(0xff558aec, 0xf3612cba), TOBN(0x35beef7a, 0x9e36c39e), - TOBN(0x1845c7cf, 0xdbcf41b9), TOBN(0x5703662a, 0xaea997c0), - TOBN(0x8b925afe, 0xe402f6d8), TOBN(0xd0a1b1ae, 0x4dd72162), - TOBN(0x9f47b375, 0x03c41c4b), TOBN(0xa023829b, 0x0391d042), - TOBN(0x5f5045c3, 0x503b8b0a), TOBN(0x123c2688, 0x98c010e5), - TOBN(0x324ec0cc, 0x36ba06ee), TOBN(0xface3115, 0x3dd2cc0c), - TOBN(0xb364f3be, 0xf333e91f), TOBN(0xef8aff73, 0x28e832b0), - TOBN(0x1e9bad04, 0x2d05841b), TOBN(0x42f0e3df, 0x356a21e2), - TOBN(0xa3270bcb, 0x4add627e), TOBN(0xb09a8158, 0xd322e711), - TOBN(0x86e326a1, 0x0fee104a), TOBN(0xad7788f8, 0x3703f65d), - TOBN(0x7e765430, 0x47bc4833), TOBN(0x6cee582b, 0x2b9b893a), - TOBN(0x9cd2a167, 0xe8f55a7b), TOBN(0xefbee3c6, 0xd9e4190d), - TOBN(0x33ee7185, 0xd40c2e9d), TOBN(0x844cc9c5, 0xa380b548), - TOBN(0x323f8ecd, 0x66926e04), TOBN(0x0001e38f, 0x8110c1ba), - TOBN(0x8dbcac12, 0xfc6a7f07), TOBN(0xd65e1d58, 0x0cec0827), - TOBN(0xd2cd4141, 0xbe76ca2d), TOBN(0x7895cf5c, 0xe892f33a), - TOBN(0x956d230d, 0x367139d2), TOBN(0xa91abd3e, 0xd012c4c1), - TOBN(0x34fa4883, 0x87eb36bf), TOBN(0xc5f07102, 0x914b8fb4), - TOBN(0x90f0e579, 0xadb9c95f), TOBN(0xfe6ea8cb, 0x28888195), - TOBN(0x7b9b5065, 0xedfa9284), TOBN(0x6c510bd2, 0x2b8c8d65), - TOBN(0xd7b8ebef, 0xcbe8aafd), TOBN(0xedb3af98, 0x96b1da07), - TOBN(0x28ff779d, 0x6295d426), TOBN(0x0c4f6ac7, 0x3fa3ad7b), - TOBN(0xec44d054, 0x8b8e2604), TOBN(0x9b32a66d, 0x8b0050e1), - TOBN(0x1f943366, 0xf0476ce2), TOBN(0x7554d953, 0xa602c7b4), - TOBN(0xbe35aca6, 0x524f2809), TOBN(0xb6881229, 0xfd4edbea), - TOBN(0xe8cd0c8f, 0x508efb63), TOBN(0x9eb5b5c8, 0x6abcefc7), - TOBN(0xf5621f5f, 0xb441ab4f), TOBN(0x79e6c046, 0xb76a2b22), - TOBN(0x74a4792c, 0xe37a1f69), TOBN(0xcbd252cb, 0x03542b60), - TOBN(0x785f65d5, 0xb3c20bd3), TOBN(0x8dea6143, 0x4fabc60c), - TOBN(0x45e21446, 0xde673629), TOBN(0x57f7aa1e, 0x703c2d21), - TOBN(0xa0e99b7f, 0x98c868c7), TOBN(0x4e42f66d, 0x8b641676), - TOBN(0x602884dc, 0x91077896), TOBN(0xa0d690cf, 0xc2c9885b), - TOBN(0xfeb4da33, 0x3b9a5187), TOBN(0x5f789598, 0x153c87ee), - TOBN(0x2192dd47, 0x52b16dba), TOBN(0xdeefc0e6, 0x3524c1b1), - TOBN(0x465ea76e, 0xe4383693), TOBN(0x79401711, 0x361b8d98), - TOBN(0xa5f9ace9, 0xf21a15cb), TOBN(0x73d26163, 0xefee9aeb), - TOBN(0xcca844b3, 0xe677016c), TOBN(0x6c122b07, 0x57eaee06), - TOBN(0xb782dce7, 0x15f09690), TOBN(0x508b9b12, 0x2dfc0fc9), - TOBN(0x9015ab4b, 0x65d89fc6), TOBN(0x5e79dab7, 0xd6d5bb0f), - TOBN(0x64f021f0, 0x6c775aa2), TOBN(0xdf09d8cc, 0x37c7eca1), - TOBN(0x9a761367, 0xef2fa506), TOBN(0xed4ca476, 0x5b81eec6), - TOBN(0x262ede36, 0x10bbb8b5), TOBN(0x0737ce83, 0x0641ada3), - TOBN(0x4c94288a, 0xe9831ccc), TOBN(0x487fc1ce, 0x8065e635), - TOBN(0xb13d7ab3, 0xb8bb3659), TOBN(0xdea5df3e, 0x855e4120), - TOBN(0xb9a18573, 0x85eb0244), TOBN(0x1a1b8ea3, 0xa7cfe0a3), - TOBN(0x3b837119, 0x67b0867c), TOBN(0x8d5e0d08, 0x9d364520), - TOBN(0x52dccc1e, 0xd930f0e3), TOBN(0xefbbcec7, 0xbf20bbaf), - TOBN(0x99cffcab, 0x0263ad10), TOBN(0xd8199e6d, 0xfcd18f8a), - TOBN(0x64e2773f, 0xe9f10617), TOBN(0x0079e8e1, 0x08704848), - TOBN(0x1169989f, 0x8a342283), TOBN(0x8097799c, 0xa83012e6), - TOBN(0xece966cb, 0x8a6a9001), TOBN(0x93b3afef, 0x072ac7fc), - TOBN(0xe6893a2a, 0x2db3d5ba), TOBN(0x263dc462, 0x89bf4fdc), - TOBN(0x8852dfc9, 0xe0396673), TOBN(0x7ac70895, 0x3af362b6), - TOBN(0xbb9cce4d, 0x5c2f342b), TOBN(0xbf80907a, 0xb52d7aae), - TOBN(0x97f3d3cd, 0x2161bcd0), TOBN(0xb25b0834, 0x0962744d), - TOBN(0xc5b18ea5, 0x6c3a1dda), TOBN(0xfe4ec7eb, 0x06c92317), - TOBN(0xb787b890, 0xad1c4afe), TOBN(0xdccd9a92, 0x0ede801a), - TOBN(0x9ac6ddda, 0xdb58da1f), TOBN(0x22bbc12f, 0xb8cae6ee), - TOBN(0xc6f8bced, 0x815c4a43), TOBN(0x8105a92c, 0xf96480c7), - TOBN(0x0dc3dbf3, 0x7a859d51), TOBN(0xe3ec7ce6, 0x3041196b), - TOBN(0xd9f64b25, 0x0d1067c9), TOBN(0xf2321321, 0x3d1f8dd8), - TOBN(0x8b5c619c, 0x76497ee8), TOBN(0x5d2b0ac6, 0xc717370e), - TOBN(0x98204cb6, 0x4fcf68e1), TOBN(0x0bdec211, 0x62bc6792), - TOBN(0x6973ccef, 0xa63b1011), TOBN(0xf9e3fa97, 0xe0de1ac5), - TOBN(0x5efb693e, 0x3d0e0c8b), TOBN(0x037248e9, 0xd2d4fcb4), - }, + {TOBN(0x80f9bdef, 0x694db7e0), TOBN(0xedca8787, 0xb9fcddc6), + TOBN(0x51981c34, 0x03b8dce1), TOBN(0x4274dcf1, 0x70e10ba1), + TOBN(0xf72743b8, 0x6def6d1a), TOBN(0xd25b1670, 0xebdb1866), + TOBN(0xc4491e8c, 0x050c6f58), TOBN(0x2be2b2ab, 0x87fbd7f5), + TOBN(0x3e0e5c9d, 0xd111f8ec), TOBN(0xbcc33f8d, 0xb7c4e760), + TOBN(0x702f9a91, 0xbd392a51), TOBN(0x7da4a795, 0xc132e92d), + TOBN(0x1a0b0ae3, 0x0bb1151b), TOBN(0x54febac8, 0x02e32251), + TOBN(0xea3a5082, 0x694e9e78), TOBN(0xe58ffec1, 0xe4fe40b8), + TOBN(0xf85592fc, 0xd1e0cf9e), TOBN(0xdea75f0d, 0xc0e7b2e8), + TOBN(0xc04215cf, 0xc135584e), TOBN(0x174fc727, 0x2f57092a), + TOBN(0xe7277877, 0xeb930bea), TOBN(0x504caccb, 0x5eb02a5a), + TOBN(0xf9fe08f7, 0xf5241b9b), TOBN(0xe7fb62f4, 0x8d5ca954), + TOBN(0xfbb8349d, 0x29c4120b), TOBN(0x9f94391f, 0xc0d0d915), + TOBN(0xc4074fa7, 0x5410ba51), TOBN(0xa66adbf6, 0x150a5911), + TOBN(0xc164543c, 0x34bfca38), TOBN(0xe0f27560, 0xb9e1ccfc), + TOBN(0x99da0f53, 0xe820219c), TOBN(0xe8234498, 0xc6b4997a), + TOBN(0xcfb88b76, 0x9d4c5423), TOBN(0x9e56eb10, 0xb0521c49), + TOBN(0x418e0b5e, 0xbe8700a1), TOBN(0x00cbaad6, 0xf93cb58a), + TOBN(0xe923fbde, 0xd92a5e67), TOBN(0xca4979ac, 0x1f347f11), + TOBN(0x89162d85, 0x6bc0585b), TOBN(0xdd6254af, 0xac3c70e3), + TOBN(0x7b23c513, 0x516e19e4), TOBN(0x56e2e847, 0xc5c4d593), + TOBN(0x9f727d73, 0x5ce71ef6), TOBN(0x5b6304a6, 0xf79a44c5), + TOBN(0x6638a736, 0x3ab7e433), TOBN(0x1adea470, 0xfe742f83), + TOBN(0xe054b854, 0x5b7fc19f), TOBN(0xf935381a, 0xba1d0698), + TOBN(0x546eab2d, 0x799e9a74), TOBN(0x96239e0e, 0xa949f729), + TOBN(0xca274c6b, 0x7090055a), TOBN(0x835142c3, 0x9020c9b0), + TOBN(0xa405667a, 0xa2e8807f), TOBN(0x29f2c085, 0x1aa3d39e), + TOBN(0xcc555d64, 0x42fc72f5), TOBN(0xe856e0e7, 0xfbeacb3c), + TOBN(0xb5504f9d, 0x918e4936), TOBN(0x65035ef6, 0xb2513982), + TOBN(0x0553a0c2, 0x6f4d9cb9), TOBN(0x6cb10d56, 0xbea85509), + TOBN(0x48d957b7, 0xa242da11), TOBN(0x16a4d3dd, 0x672b7268), + TOBN(0x3d7e637c, 0x8502a96b), TOBN(0x27c7032b, 0x730d463b), + TOBN(0xbdc02b18, 0xe4136a14), TOBN(0xbacf969d, 0x678e32bf), + TOBN(0xc98d89a3, 0xdd9c3c03), TOBN(0x7b92420a, 0x23becc4f), + TOBN(0xd4b41f78, 0xc64d565c), TOBN(0x9f969d00, 0x10f28295), + TOBN(0xec7f7f76, 0xb13d051a), TOBN(0x08945e1e, 0xa92da585), + TOBN(0x55366b7d, 0x5846426f), TOBN(0xe7d09e89, 0x247d441d), + TOBN(0x510b404d, 0x736fbf48), TOBN(0x7fa003d0, 0xe784bd7d), + TOBN(0x25f7614f, 0x17fd9596), TOBN(0x49e0e0a1, 0x35cb98db), + TOBN(0x2c65957b, 0x2e83a76a), TOBN(0x5d40da8d, 0xcddbe0f8), + TOBN(0xf2b8c405, 0x050bad24), TOBN(0x8918426d, 0xc2aa4823), + TOBN(0x2aeab3dd, 0xa38365a7), TOBN(0x72031717, 0x7c91b690), + TOBN(0x8b00d699, 0x60a94120), TOBN(0x478a255d, 0xe99eaeec), + TOBN(0xbf656a5f, 0x6f60aafd), TOBN(0xdfd7cb75, 0x5dee77b3), + TOBN(0x37f68bb4, 0xa595939d), TOBN(0x03556479, 0x28740217), + TOBN(0x8e740e7c, 0x84ad7612), TOBN(0xd89bc843, 0x9044695f), + TOBN(0xf7f3da5d, 0x85a9184d), TOBN(0x562563bb, 0x9fc0b074), + TOBN(0x06d2e6aa, 0xf88a888e), TOBN(0x612d8643, 0x161fbe7c), + TOBN(0x465edba7, 0xf64085e7), TOBN(0xb230f304, 0x29aa8511), + TOBN(0x53388426, 0xcda2d188), TOBN(0x90885735, 0x4b666649), + TOBN(0x6f02ff9a, 0x652f54f6), TOBN(0x65c82294, 0x5fae2bf0), + TOBN(0x7816ade0, 0x62f5eee3), TOBN(0xdcdbdf43, 0xfcc56d70), + TOBN(0x9fb3bba3, 0x54530bb2), TOBN(0xbde3ef77, 0xcb0869ea), + TOBN(0x89bc9046, 0x0b431163), TOBN(0x4d03d7d2, 0xe4819a35), + TOBN(0x33ae4f9e, 0x43b6a782), TOBN(0x216db307, 0x9c88a686), + TOBN(0x91dd88e0, 0x00ffedd9), TOBN(0xb280da9f, 0x12bd4840), + TOBN(0x32a7cb8a, 0x1635e741), TOBN(0xfe14008a, 0x78be02a7), + TOBN(0x3fafb334, 0x1b7ae030), TOBN(0x7fd508e7, 0x5add0ce9), + TOBN(0x72c83219, 0xd607ad51), TOBN(0x0f229c0a, 0x8d40964a), + TOBN(0x1be2c336, 0x1c878da2), TOBN(0xe0c96742, 0xeab2ab86), + TOBN(0x458f8691, 0x3e538cd7), TOBN(0xa7001f6c, 0x8e08ad53), + TOBN(0x52b8c6e6, 0xbf5d15ff), TOBN(0x548234a4, 0x011215dd), + TOBN(0xff5a9d2d, 0x3d5b4045), TOBN(0xb0ffeeb6, 0x4a904190), + TOBN(0x55a3aca4, 0x48607f8b), TOBN(0x8cbd665c, 0x30a0672a), + TOBN(0x87f834e0, 0x42583068), TOBN(0x02da2aeb, 0xf3f6e683), + TOBN(0x6b763e5d, 0x05c12248), TOBN(0x7230378f, 0x65a8aefc), + TOBN(0x93bd80b5, 0x71e8e5ca), TOBN(0x53ab041c, 0xb3b62524), + TOBN(0x1b860513, 0x6c9c552e), TOBN(0xe84d402c, 0xd5524e66), + TOBN(0xa37f3573, 0xf37f5937), TOBN(0xeb0f6c7d, 0xd1e4fca5), + TOBN(0x2965a554, 0xac8ab0fc), TOBN(0x17fbf56c, 0x274676ac), + TOBN(0x2e2f6bd9, 0xacf7d720), TOBN(0x41fc8f88, 0x10224766), + TOBN(0x517a14b3, 0x85d53bef), TOBN(0xdae327a5, 0x7d76a7d1), + TOBN(0x6ad0a065, 0xc4818267), TOBN(0x33aa189b, 0x37c1bbc1), + TOBN(0x64970b52, 0x27392a92), TOBN(0x21699a1c, 0x2d1535ea), + TOBN(0xcd20779c, 0xc2d7a7fd), TOBN(0xe3186059, 0x99c83cf2), + TOBN(0x9b69440b, 0x72c0b8c7), TOBN(0xa81497d7, 0x7b9e0e4d), + TOBN(0x515d5c89, 0x1f5f82dc), TOBN(0x9a7f67d7, 0x6361079e), + TOBN(0xa8da81e3, 0x11a35330), TOBN(0xe44990c4, 0x4b18be1b), + TOBN(0xc7d5ed95, 0xaf103e59), TOBN(0xece8aba7, 0x8dac9261), + TOBN(0xbe82b099, 0x9394b8d3), TOBN(0x6830f09a, 0x16adfe83), + TOBN(0x250a29b4, 0x88172d01), TOBN(0x8b20bd65, 0xcaff9e02), + TOBN(0xb8a7661e, 0xe8a6329a), TOBN(0x4520304d, 0xd3fce920), + TOBN(0xae45da1f, 0x2b47f7ef), TOBN(0xe07f5288, 0x5bffc540), + TOBN(0xf7997009, 0x3464f874), TOBN(0x2244c2cd, 0xa6fa1f38), + TOBN(0x43c41ac1, 0x94d7d9b1), TOBN(0x5bafdd82, 0xc82e7f17), + TOBN(0xdf0614c1, 0x5fda0fca), TOBN(0x74b043a7, 0xa8ae37ad), + TOBN(0x3ba6afa1, 0x9e71734c), TOBN(0x15d5437e, 0x9c450f2e), + TOBN(0x4a5883fe, 0x67e242b1), TOBN(0x5143bdc2, 0x2c1953c2), + TOBN(0x542b8b53, 0xfc5e8920), TOBN(0x363bf9a8, 0x9a9cee08), + TOBN(0x02375f10, 0xc3486e08), TOBN(0x2037543b, 0x8c5e70d2), + TOBN(0x7109bccc, 0x625640b4), TOBN(0xcbc1051e, 0x8bc62c3b), + TOBN(0xf8455fed, 0x803f26ea), TOBN(0x6badceab, 0xeb372424), + TOBN(0xa2a9ce7c, 0x6b53f5f9), TOBN(0x64246595, 0x1b176d99), + TOBN(0xb1298d36, 0xb95c081b), TOBN(0x53505bb8, 0x1d9a9ee6), + TOBN(0x3f6f9e61, 0xf2ba70b0), TOBN(0xd07e16c9, 0x8afad453), + TOBN(0x9f1694bb, 0xe7eb4a6a), TOBN(0xdfebced9, 0x3cb0bc8e), + TOBN(0x92d3dcdc, 0x53868c8b), TOBN(0x174311a2, 0x386107a6), + TOBN(0x4109e07c, 0x689b4e64), TOBN(0x30e4587f, 0x2df3dcb6), + TOBN(0x841aea31, 0x0811b3b2), TOBN(0x6144d41d, 0x0cce43ea), + TOBN(0x464c4581, 0x2a9a7803), TOBN(0xd03d371f, 0x3e158930), + TOBN(0xc676d7f2, 0xb1f3390b), TOBN(0x9f7a1b8c, 0xa5b61272), + TOBN(0x4ebebfc9, 0xc2e127a9), TOBN(0x4602500c, 0x5dd997bf), + TOBN(0x7f09771c, 0x4711230f), TOBN(0x058eb37c, 0x020f09c1), + TOBN(0xab693d4b, 0xfee5e38b), TOBN(0x9289eb1f, 0x4653cbc0), + TOBN(0xbecf46ab, 0xd51b9cf5), TOBN(0xd2aa9c02, 0x9f0121af), + TOBN(0x36aaf7d2, 0xe90dc274), TOBN(0x909e4ea0, 0x48b95a3c), + TOBN(0xe6b70496, 0x6f32dbdb), TOBN(0x672188a0, 0x8b030b3e), + TOBN(0xeeffe5b3, 0xcfb617e2), TOBN(0x87e947de, 0x7c82709e), + TOBN(0xa44d2b39, 0x1770f5a7), TOBN(0xe4d4d791, 0x0e44eb82), + TOBN(0x42e69d1e, 0x3f69712a), TOBN(0xbf11c4d6, 0xac6a820e), + TOBN(0xb5e7f3e5, 0x42c4224c), TOBN(0xd6b4e81c, 0x449d941c), + TOBN(0x5d72bd16, 0x5450e878), TOBN(0x6a61e28a, 0xee25ac54), + TOBN(0x33272094, 0xe6f1cd95), TOBN(0x7512f30d, 0x0d18673f), + TOBN(0x32f7a4ca, 0x5afc1464), TOBN(0x2f095656, 0x6bbb977b), + TOBN(0x586f47ca, 0xa8226200), TOBN(0x02c868ad, 0x1ac07369), + TOBN(0x4ef2b845, 0xc613acbe), TOBN(0x43d7563e, 0x0386054c), + TOBN(0x54da9dc7, 0xab952578), TOBN(0xb5423df2, 0x26e84d0b), + TOBN(0xa8b64eeb, 0x9b872042), TOBN(0xac205782, 0x5990f6df), + TOBN(0x4ff696eb, 0x21f4c77a), TOBN(0x1a79c3e4, 0xaab273af), + TOBN(0x29bc922e, 0x9436b3f1), TOBN(0xff807ef8, 0xd6d9a27a), + TOBN(0x82acea3d, 0x778f22a0), TOBN(0xfb10b2e8, 0x5b5e7469), + TOBN(0xc0b16980, 0x2818ee7d), TOBN(0x011afff4, 0xc91c1a2f), + TOBN(0x95a6d126, 0xad124418), TOBN(0x31c081a5, 0xe72e295f), + TOBN(0x36bb283a, 0xf2f4db75), TOBN(0xd115540f, 0x7acef462), + TOBN(0xc7f3a8f8, 0x33f6746c), TOBN(0x21e46f65, 0xfea990ca), + TOBN(0x915fd5c5, 0xcaddb0a9), TOBN(0xbd41f016, 0x78614555), + TOBN(0x346f4434, 0x426ffb58), TOBN(0x80559436, 0x14dbc204), + TOBN(0xf3dd20fe, 0x5a969b7f), TOBN(0x9d59e956, 0xe899a39a), + TOBN(0xf1b0971c, 0x8ad4cf4b), TOBN(0x03448860, 0x2ffb8fb8), + TOBN(0xf071ac3c, 0x65340ba4), TOBN(0x408d0596, 0xb27fd758), + TOBN(0xe7c78ea4, 0x98c364b0), TOBN(0xa4aac4a5, 0x051e8ab5), + TOBN(0xb9e1d560, 0x485d9002), TOBN(0x9acd518a, 0x88844455), + TOBN(0xe4ca688f, 0xd06f56c0), TOBN(0xa48af70d, 0xdf027972), + TOBN(0x691f0f04, 0x5e9a609d), TOBN(0xa9dd82cd, 0xee61270e), + TOBN(0x8903ca63, 0xa0ef18d3), TOBN(0x9fb7ee35, 0x3d6ca3bd), + TOBN(0xa7b4a09c, 0xabf47d03), TOBN(0x4cdada01, 0x1c67de8e), + TOBN(0x52003749, 0x9355a244), TOBN(0xe77fd2b6, 0x4f2151a9), + TOBN(0x695d6cf6, 0x66b4efcb), TOBN(0xc5a0cacf, 0xda2cfe25), + TOBN(0x104efe5c, 0xef811865), TOBN(0xf52813e8, 0x9ea5cc3d), + TOBN(0x855683dc, 0x40b58dbc), TOBN(0x0338ecde, 0x175fcb11), + TOBN(0xf9a05637, 0x74921592), TOBN(0xb4f1261d, 0xb9bb9d31), + TOBN(0x551429b7, 0x4e9c5459), TOBN(0xbe182e6f, 0x6ea71f53), + TOBN(0xd3a3b07c, 0xdfc50573), TOBN(0x9ba1afda, 0x62be8d44), + TOBN(0x9bcfd2cb, 0x52ab65d3), TOBN(0xdf11d547, 0xa9571802), + TOBN(0x099403ee, 0x02a2404a), TOBN(0x497406f4, 0x21088a71), + TOBN(0x99479409, 0x5004ae71), TOBN(0xbdb42078, 0xa812c362), + TOBN(0x2b72a30f, 0xd8828442), TOBN(0x283add27, 0xfcb5ed1c), + TOBN(0xf7c0e200, 0x66a40015), TOBN(0x3e3be641, 0x08b295ef), + TOBN(0xac127dc1, 0xe038a675), TOBN(0x729deff3, 0x8c5c6320), + TOBN(0xb7df8fd4, 0xa90d2c53), TOBN(0x9b74b0ec, 0x681e7cd3), + TOBN(0x5cb5a623, 0xdab407e5), TOBN(0xcdbd3615, 0x76b340c6), + TOBN(0xa184415a, 0x7d28392c), TOBN(0xc184c1d8, 0xe96f7830), + TOBN(0xc3204f19, 0x81d3a80f), TOBN(0xfde0c841, 0xc8e02432), + TOBN(0x78203b3e, 0x8149e0c1), TOBN(0x5904bdbb, 0x08053a73), + TOBN(0x30fc1dd1, 0x101b6805), TOBN(0x43c223bc, 0x49aa6d49), + TOBN(0x9ed67141, 0x7a174087), TOBN(0x311469a0, 0xd5997008), + TOBN(0xb189b684, 0x5e43fc61), TOBN(0xf3282375, 0xe0d3ab57), + TOBN(0x4fa34b67, 0xb1181da8), TOBN(0x621ed0b2, 0x99ee52b8), + TOBN(0x9b178de1, 0xad990676), TOBN(0xd51de67b, 0x56d54065), + TOBN(0x2a2c27c4, 0x7538c201), TOBN(0x33856ec8, 0x38a40f5c), + TOBN(0x2522fc15, 0xbe6cdcde), TOBN(0x1e603f33, 0x9f0c6f89), + TOBN(0x7994edc3, 0x103e30a6), TOBN(0x033a00db, 0x220c853e), + TOBN(0xd3cfa409, 0xf7bb7fd7), TOBN(0x70f8781e, 0x462d18f6), + TOBN(0xbbd82980, 0x687fe295), TOBN(0x6eef4c32, 0x595669f3), + TOBN(0x86a9303b, 0x2f7e85c3), TOBN(0x5fce4621, 0x71988f9b), + TOBN(0x5b935bf6, 0xc138acb5), TOBN(0x30ea7d67, 0x25661212), + TOBN(0xef1eb5f4, 0xe51ab9a2), TOBN(0x0587c98a, 0xae067c78), + TOBN(0xb3ce1b3c, 0x77ca9ca6), TOBN(0x2a553d4d, 0x54b5f057), + TOBN(0xc7898236, 0x4da29ec2), TOBN(0xdbdd5d13, 0xb9c57316), + TOBN(0xc57d6e6b, 0x2cd80d47), TOBN(0x80b460cf, 0xfe9e7391), + TOBN(0x98648cab, 0xf963c31e), TOBN(0x67f9f633, 0xcc4d32fd), + TOBN(0x0af42a9d, 0xfdf7c687), TOBN(0x55f292a3, 0x0b015ea7), + TOBN(0x89e468b2, 0xcd21ab3d), TOBN(0xe504f022, 0xc393d392), + TOBN(0xab21e1d4, 0xa5013af9), TOBN(0xe3283f78, 0xc2c28acb), + TOBN(0xf38b35f6, 0x226bf99f), TOBN(0xe8354274, 0x0e291e69), + TOBN(0x61673a15, 0xb20c162d), TOBN(0xc101dc75, 0xb04fbdbe), + TOBN(0x8323b4c2, 0x255bd617), TOBN(0x6c969693, 0x6c2a9154), + TOBN(0xc6e65860, 0x62679387), TOBN(0x8e01db0c, 0xb8c88e23), + TOBN(0x33c42873, 0x893a5559), TOBN(0x7630f04b, 0x47a3e149), + TOBN(0xb5d80805, 0xddcf35f8), TOBN(0x582ca080, 0x77dfe732), + TOBN(0x2c7156e1, 0x0b1894a0), TOBN(0x92034001, 0xd81c68c0), + TOBN(0xed225d00, 0xc8b115b5), TOBN(0x237f9c22, 0x83b907f2), + TOBN(0x0ea2f32f, 0x4470e2c0), TOBN(0xb725f7c1, 0x58be4e95), + TOBN(0x0f1dcafa, 0xb1ae5463), TOBN(0x59ed5187, 0x1ba2fc04), + TOBN(0xf6e0f316, 0xd0115d4d), TOBN(0x5180b12f, 0xd3691599), + TOBN(0x157e32c9, 0x527f0a41), TOBN(0x7b0b081d, 0xa8e0ecc0), + TOBN(0x6dbaaa8a, 0xbf4f0dd0), TOBN(0x99b289c7, 0x4d252696), + TOBN(0x79b7755e, 0xdbf864fe), TOBN(0x6974e2b1, 0x76cad3ab), + TOBN(0x35dbbee2, 0x06ddd657), TOBN(0xe7cbdd11, 0x2ff3a96d), + TOBN(0x88381968, 0x076be758), TOBN(0x2d737e72, 0x08c91f5d), + TOBN(0x5f83ab62, 0x86ec3776), TOBN(0x98aa649d, 0x945fa7a1), + TOBN(0xf477ec37, 0x72ef0933), TOBN(0x66f52b1e, 0x098c17b1), + TOBN(0x9eec58fb, 0xd803738b), TOBN(0x91aaade7, 0xe4e86aa4), + TOBN(0x6b1ae617, 0xa5b51492), TOBN(0x63272121, 0xbbc45974), + TOBN(0x7e0e28f0, 0x862c5129), TOBN(0x0a8f79a9, 0x3321a4a0), + TOBN(0xe26d1664, 0x5041c88f), TOBN(0x0571b805, 0x53233e3a), + TOBN(0xd1b0ccde, 0xc9520711), TOBN(0x55a9e4ed, 0x3c8b84bf), + TOBN(0x9426bd39, 0xa1fef314), TOBN(0x4f5f638e, 0x6eb93f2b), + TOBN(0xba2a1ed3, 0x2bf9341b), TOBN(0xd63c1321, 0x4d42d5a9), + TOBN(0xd2964a89, 0x316dc7c5), TOBN(0xd1759606, 0xca511851), + TOBN(0xd8a9201f, 0xf9e6ed35), TOBN(0xb7b5ee45, 0x6736925a), + TOBN(0x0a83fbbc, 0x99581af7), TOBN(0x3076bc40, 0x64eeb051), + TOBN(0x5511c98c, 0x02dec312), TOBN(0x270de898, 0x238dcb78), + TOBN(0x2cf4cf9c, 0x539c08c9), TOBN(0xa70cb65e, 0x38d3b06e), + TOBN(0xb12ec10e, 0xcfe57bbd), TOBN(0x82c7b656, 0x35a0c2b5), + TOBN(0xddc7d5cd, 0x161c67bd), TOBN(0xe32e8985, 0xae3a32cc), + TOBN(0x7aba9444, 0xd11a5529), TOBN(0xe964ed02, 0x2427fa1a), + TOBN(0x1528392d, 0x24a1770a), TOBN(0xa152ce2c, 0x12c72fcd), + TOBN(0x714553a4, 0x8ec07649), TOBN(0x18b4c290, 0x459dd453), + TOBN(0xea32b714, 0x7b64b110), TOBN(0xb871bfa5, 0x2e6f07a2), + TOBN(0xb67112e5, 0x9e2e3c9b), TOBN(0xfbf250e5, 0x44aa90f6), + TOBN(0xf77aedb8, 0xbd539006), TOBN(0x3b0cdf9a, 0xd172a66f), + TOBN(0xedf69fea, 0xf8c51187), TOBN(0x05bb67ec, 0x741e4da7), + TOBN(0x47df0f32, 0x08114345), TOBN(0x56facb07, 0xbb9792b1), + TOBN(0xf3e007e9, 0x8f6229e4), TOBN(0x62d103f4, 0x526fba0f), + TOBN(0x4f33bef7, 0xb0339d79), TOBN(0x9841357b, 0xb59bfec1), + TOBN(0xfa8dbb59, 0xc34e6705), TOBN(0xc3c7180b, 0x7fdaa84c), + TOBN(0xf95872fc, 0xa4108537), TOBN(0x8750cc3b, 0x932a3e5a), + TOBN(0xb61cc69d, 0xb7275d7d), TOBN(0xffa0168b, 0x2e59b2e9), + TOBN(0xca032abc, 0x6ecbb493), TOBN(0x1d86dbd3, 0x2c9082d8), + TOBN(0xae1e0b67, 0xe28ef5ba), TOBN(0x2c9a4699, 0xcb18e169), + TOBN(0x0ecd0e33, 0x1e6bbd20), TOBN(0x571b360e, 0xaf5e81d2), + TOBN(0xcd9fea58, 0x101c1d45), TOBN(0x6651788e, 0x18880452), + TOBN(0xa9972635, 0x1f8dd446), TOBN(0x44bed022, 0xe37281d0), + TOBN(0x094b2b2d, 0x33da525d), TOBN(0xf193678e, 0x13144fd8), + TOBN(0xb8ab5ba4, 0xf4c1061d), TOBN(0x4343b5fa, 0xdccbe0f4), + TOBN(0xa8702371, 0x63812713), TOBN(0x47bf6d2d, 0xf7611d93), + TOBN(0x46729b8c, 0xbd21e1d7), TOBN(0x7484d4e0, 0xd629e77d), + TOBN(0x830e6eea, 0x60dbac1f), TOBN(0x23d8c484, 0xda06a2f7), + TOBN(0x896714b0, 0x50ca535b), TOBN(0xdc8d3644, 0xebd97a9b), + TOBN(0x106ef9fa, 0xb12177b4), TOBN(0xf79bf464, 0x534d5d9c), + TOBN(0x2537a349, 0xa6ab360b), TOBN(0xc7c54253, 0xa00c744f), + TOBN(0xb3c7a047, 0xe5911a76), TOBN(0x61ffa5c8, 0x647f1ee7), + TOBN(0x15aed36f, 0x8f56ab42), TOBN(0x6a0d41b0, 0xa3ff9ac9), + TOBN(0x68f469f5, 0xcc30d357), TOBN(0xbe9adf81, 0x6b72be96), + TOBN(0x1cd926fe, 0x903ad461), TOBN(0x7e89e38f, 0xcaca441b), + TOBN(0xf0f82de5, 0xfacf69d4), TOBN(0x363b7e76, 0x4775344c), + TOBN(0x6894f312, 0xb2e36d04), TOBN(0x3c6cb4fe, 0x11d1c9a5), + TOBN(0x85d9c339, 0x4008e1f2), TOBN(0x5e9a85ea, 0x249f326c), + TOBN(0xdc35c60a, 0x678c5e06), TOBN(0xc08b944f, 0x9f86fba9), + TOBN(0xde40c02c, 0x89f71f0f), TOBN(0xad8f3e31, 0xff3da3c0), + TOBN(0x3ea5096b, 0x42125ded), TOBN(0x13879cbf, 0xa7379183), + TOBN(0x6f4714a5, 0x6b306a0b), TOBN(0x359c2ea6, 0x67646c5e), + TOBN(0xfacf8943, 0x07726368), TOBN(0x07a58935, 0x65ff431e), + TOBN(0x24d661d1, 0x68754ab0), TOBN(0x801fce1d, 0x6f429a76), + TOBN(0xc068a85f, 0xa58ce769), TOBN(0xedc35c54, 0x5d5eca2b), + TOBN(0xea31276f, 0xa3f660d1), TOBN(0xa0184ebe, 0xb8fc7167), + TOBN(0x0f20f21a, 0x1d8db0ae), TOBN(0xd96d095f, 0x56c35e12), + TOBN(0xedf402b5, 0xf8c2a25b), TOBN(0x1bb772b9, 0x059204b6), + TOBN(0x50cbeae2, 0x19b4e34c), TOBN(0x93109d80, 0x3fa0845a), + TOBN(0x54f7ccf7, 0x8ef59fb5), TOBN(0x3b438fe2, 0x88070963), + TOBN(0x9e28c659, 0x31f3ba9b), TOBN(0x9cc31b46, 0xead9da92), + TOBN(0x3c2f0ba9, 0xb733aa5f), TOBN(0xdece47cb, 0xf05af235), + TOBN(0xf8e3f715, 0xa2ac82a5), TOBN(0xc97ba641, 0x2203f18a), + TOBN(0xc3af5504, 0x09c11060), TOBN(0x56ea2c05, 0x46af512d), + TOBN(0xfac28daf, 0xf3f28146), TOBN(0x87fab43a, 0x959ef494)}, + {TOBN(0x09891641, 0xd4c5105f), TOBN(0x1ae80f8e, 0x6d7fbd65), + TOBN(0x9d67225f, 0xbee6bdb0), TOBN(0x3b433b59, 0x7fc4d860), + TOBN(0x44e66db6, 0x93e85638), TOBN(0xf7b59252, 0xe3e9862f), + TOBN(0xdb785157, 0x665c32ec), TOBN(0x702fefd7, 0xae362f50), + TOBN(0x3754475d, 0x0fefb0c3), TOBN(0xd48fb56b, 0x46d7c35d), + TOBN(0xa070b633, 0x363798a4), TOBN(0xae89f3d2, 0x8fdb98e6), + TOBN(0x970b89c8, 0x6363d14c), TOBN(0x89817521, 0x67abd27d), + TOBN(0x9bf7d474, 0x44d5a021), TOBN(0xb3083baf, 0xcac72aee), + TOBN(0x389741de, 0xbe949a44), TOBN(0x638e9388, 0x546a4fa5), + TOBN(0x3fe6419c, 0xa0047bdc), TOBN(0x7047f648, 0xaaea57ca), + TOBN(0x54e48a90, 0x41fbab17), TOBN(0xda8e0b28, 0x576bdba2), + TOBN(0xe807eebc, 0xc72afddc), TOBN(0x07d3336d, 0xf42577bf), + TOBN(0x62a8c244, 0xbfe20925), TOBN(0x91c19ac3, 0x8fdce867), + TOBN(0x5a96a5d5, 0xdd387063), TOBN(0x61d587d4, 0x21d324f6), + TOBN(0xe87673a2, 0xa37173ea), TOBN(0x23848008, 0x53778b65), + TOBN(0x10f8441e, 0x05bab43e), TOBN(0xfa11fe12, 0x4621efbe), + TOBN(0x047b772e, 0x81685d7b), TOBN(0x23f27d81, 0xbf34a976), + TOBN(0xc27608e2, 0x915f48ef), TOBN(0x3b0b43fa, 0xa521d5c3), + TOBN(0x7613fb26, 0x63ca7284), TOBN(0x7f5729b4, 0x1d4db837), + TOBN(0x87b14898, 0x583b526b), TOBN(0x00b732a6, 0xbbadd3d1), + TOBN(0x8e02f426, 0x2048e396), TOBN(0x436b50b6, 0x383d9de4), + TOBN(0xf78d3481, 0x471e85ad), TOBN(0x8b01ea6a, 0xd005c8d6), + TOBN(0xd3c7afee, 0x97015c07), TOBN(0x46cdf1a9, 0x4e3ba2ae), + TOBN(0x7a42e501, 0x83d3a1d2), TOBN(0xd54b5268, 0xb541dff4), + TOBN(0x3f24cf30, 0x4e23e9bc), TOBN(0x4387f816, 0x126e3624), + TOBN(0x26a46a03, 0x3b0b6d61), TOBN(0xaf1bc845, 0x8b2d777c), + TOBN(0x25c401ba, 0x527de79c), TOBN(0x0e1346d4, 0x4261bbb6), + TOBN(0x4b96c44b, 0x287b4bc7), TOBN(0x658493c7, 0x5254562f), + TOBN(0x23f949fe, 0xb8a24a20), TOBN(0x17ebfed1, 0xf52ca53f), + TOBN(0x9b691bbe, 0xbcfb4853), TOBN(0x5617ff6b, 0x6278a05d), + TOBN(0x241b34c5, 0xe3c99ebd), TOBN(0xfc64242e, 0x1784156a), + TOBN(0x4206482f, 0x695d67df), TOBN(0xb967ce0e, 0xee27c011), + TOBN(0x65db3751, 0x21c80b5d), TOBN(0x2e7a563c, 0xa31ecca0), + TOBN(0xe56ffc4e, 0x5238a07e), TOBN(0x3d6c2966, 0x32ced854), + TOBN(0xe99d7d1a, 0xaf70b885), TOBN(0xafc3bad9, 0x2d686459), + TOBN(0x9c78bf46, 0x0cc8ba5b), TOBN(0x5a439519, 0x18955aa3), + TOBN(0xf8b517a8, 0x5fe4e314), TOBN(0xe60234d0, 0xfcb8906f), + TOBN(0xffe542ac, 0xf2061b23), TOBN(0x287e191f, 0x6b4cb59c), + TOBN(0x21857ddc, 0x09d877d8), TOBN(0x1c23478c, 0x14678941), + TOBN(0xbbf0c056, 0xb6e05ea4), TOBN(0x82da4b53, 0xb01594fe), + TOBN(0xf7526791, 0xfadb8608), TOBN(0x049e832d, 0x7b74cdf6), + TOBN(0xa43581cc, 0xc2b90a34), TOBN(0x73639eb8, 0x9360b10c), + TOBN(0x4fba331f, 0xe1e4a71b), TOBN(0x6ffd6b93, 0x8072f919), + TOBN(0x6e53271c, 0x65679032), TOBN(0x67206444, 0xf14272ce), + TOBN(0xc0f734a3, 0xb2335834), TOBN(0x9526205a, 0x90ef6860), + TOBN(0xcb8be717, 0x04e2bb0d), TOBN(0x2418871e, 0x02f383fa), + TOBN(0xd7177681, 0x4082c157), TOBN(0xcc914ad0, 0x29c20073), + TOBN(0xf186c1eb, 0xe587e728), TOBN(0x6fdb3c22, 0x61bcd5fd), + TOBN(0x30d014a6, 0xf2f9f8e9), TOBN(0x963ece23, 0x4fec49d2), + TOBN(0x862025c5, 0x9605a8d9), TOBN(0x39874445, 0x19f8929a), + TOBN(0x01b6ff65, 0x12bf476a), TOBN(0x598a64d8, 0x09cf7d91), + TOBN(0xd7ec7749, 0x93be56ca), TOBN(0x10899785, 0xcbb33615), + TOBN(0xb8a092fd, 0x02eee3ad), TOBN(0xa86b3d35, 0x30145270), + TOBN(0x323d98c6, 0x8512b675), TOBN(0x4b8bc785, 0x62ebb40f), + TOBN(0x7d301f54, 0x413f9cde), TOBN(0xa5e4fb4f, 0x2bab5664), + TOBN(0x1d2b252d, 0x1cbfec23), TOBN(0xfcd576bb, 0xe177120d), + TOBN(0x04427d3e, 0x83731a34), TOBN(0x2bb9028e, 0xed836e8e), + TOBN(0xb36acff8, 0xb612ca7c), TOBN(0xb88fe5ef, 0xd3d9c73a), + TOBN(0xbe2a6bc6, 0xedea4eb3), TOBN(0x43b93133, 0x488eec77), + TOBN(0xf41ff566, 0xb17106e1), TOBN(0x469e9172, 0x654efa32), + TOBN(0xb4480f04, 0x41c23fa3), TOBN(0xb4712eb0, 0xc1989a2e), + TOBN(0x3ccbba0f, 0x93a29ca7), TOBN(0x6e205c14, 0xd619428c), + TOBN(0x90db7957, 0xb3641686), TOBN(0x0432691d, 0x45ac8b4e), + TOBN(0x07a759ac, 0xf64e0350), TOBN(0x0514d89c, 0x9c972517), + TOBN(0x1701147f, 0xa8e67fc3), TOBN(0x9e2e0b8b, 0xab2085be), + TOBN(0xd5651824, 0xac284e57), TOBN(0x890d4325, 0x74893664), + TOBN(0x8a7c5e6e, 0xc55e68a3), TOBN(0xbf12e90b, 0x4339c85a), + TOBN(0x31846b85, 0xf922b655), TOBN(0x9a54ce4d, 0x0bf4d700), + TOBN(0xd7f4e83a, 0xf1a14295), TOBN(0x916f955c, 0xb285d4f9), + TOBN(0xe57bb0e0, 0x99ffdaba), TOBN(0x28a43034, 0xeab0d152), + TOBN(0x0a36ffa2, 0xb8a9cef8), TOBN(0x5517407e, 0xb9ec051a), + TOBN(0x9c796096, 0xea68e672), TOBN(0x853db5fb, 0xfb3c77fb), + TOBN(0x21474ba9, 0xe864a51a), TOBN(0x6c267699, 0x6e8a1b8b), + TOBN(0x7c823626, 0x94120a28), TOBN(0xe61e9a48, 0x8383a5db), + TOBN(0x7dd75003, 0x9f84216d), TOBN(0xab020d07, 0xad43cd85), + TOBN(0x9437ae48, 0xda12c659), TOBN(0x6449c2eb, 0xe65452ad), + TOBN(0xcc7c4c1c, 0x2cf9d7c1), TOBN(0x1320886a, 0xee95e5ab), + TOBN(0xbb7b9056, 0xbeae170c), TOBN(0xc8a5b250, 0xdbc0d662), + TOBN(0x4ed81432, 0xc11d2303), TOBN(0x7da66912, 0x1f03769f), + TOBN(0x3ac7a5fd, 0x84539828), TOBN(0x14dada94, 0x3bccdd02), + TOBN(0x8b84c321, 0x7ef6b0d1), TOBN(0x52a9477a, 0x7c933f22), + TOBN(0x5ef6728a, 0xfd440b82), TOBN(0x5c3bd859, 0x6ce4bd5e), + TOBN(0x918b80f5, 0xf22c2d3e), TOBN(0x368d5040, 0xb7bb6cc5), + TOBN(0xb66142a1, 0x2695a11c), TOBN(0x60ac583a, 0xeb19ea70), + TOBN(0x317cbb98, 0x0eab2437), TOBN(0x8cc08c55, 0x5e2654c8), + TOBN(0xfe2d6520, 0xe6d8307f), TOBN(0xe9f147f3, 0x57428993), + TOBN(0x5f9c7d14, 0xd2fd6cf1), TOBN(0xa3ecd064, 0x2d4fcbb0), + TOBN(0xad83fef0, 0x8e7341f7), TOBN(0x643f23a0, 0x3a63115c), + TOBN(0xd38a78ab, 0xe65ab743), TOBN(0xbf7c75b1, 0x35edc89c), + TOBN(0x3dd8752e, 0x530df568), TOBN(0xf85c4a76, 0xe308c682), + TOBN(0x4c9955b2, 0xe68acf37), TOBN(0xa544df3d, 0xab32af85), + TOBN(0x4b8ec3f5, 0xa25cf493), TOBN(0x4d8f2764, 0x1a622feb), + TOBN(0x7bb4f7aa, 0xf0dcbc49), TOBN(0x7de551f9, 0x70bbb45b), + TOBN(0xcfd0f3e4, 0x9f2ca2e5), TOBN(0xece58709, 0x1f5c76ef), + TOBN(0x32920edd, 0x167d79ae), TOBN(0x039df8a2, 0xfa7d7ec1), + TOBN(0xf46206c0, 0xbb30af91), TOBN(0x1ff5e2f5, 0x22676b59), + TOBN(0x11f4a039, 0x6ea51d66), TOBN(0x506c1445, 0x807d7a26), + TOBN(0x60da5705, 0x755a9b24), TOBN(0x8fc8cc32, 0x1f1a319e), + TOBN(0x83642d4d, 0x9433d67d), TOBN(0x7fa5cb8f, 0x6a7dd296), + TOBN(0x576591db, 0x9b7bde07), TOBN(0x13173d25, 0x419716fb), + TOBN(0xea30599d, 0xd5b340ff), TOBN(0xfc6b5297, 0xb0fe76c5), + TOBN(0x1c6968c8, 0xab8f5adc), TOBN(0xf723c7f5, 0x901c928d), + TOBN(0x4203c321, 0x9773d402), TOBN(0xdf7c6aa3, 0x1b51dd47), + TOBN(0x3d49e37a, 0x552be23c), TOBN(0x57febee8, 0x0b5a6e87), + TOBN(0xc5ecbee4, 0x7bd8e739), TOBN(0x79d44994, 0xae63bf75), + TOBN(0x168bd00f, 0x38fb8923), TOBN(0x75d48ee4, 0xd0533130), + TOBN(0x554f77aa, 0xdb5cdf33), TOBN(0x3396e896, 0x3c696769), + TOBN(0x2fdddbf2, 0xd3fd674e), TOBN(0xbbb8f6ee, 0x99d0e3e5), + TOBN(0x51b90651, 0xcbae2f70), TOBN(0xefc4bc05, 0x93aaa8eb), + TOBN(0x8ecd8689, 0xdd1df499), TOBN(0x1aee99a8, 0x22f367a5), + TOBN(0x95d485b9, 0xae8274c5), TOBN(0x6c14d445, 0x7d30b39c), + TOBN(0xbafea90b, 0xbcc1ef81), TOBN(0x7c5f317a, 0xa459a2ed), + TOBN(0x01211075, 0x4ef44227), TOBN(0xa17bed6e, 0xdc20f496), + TOBN(0x0cdfe424, 0x819853cd), TOBN(0x13793298, 0xf71e2ce7), + TOBN(0x3c1f3078, 0xdbbe307b), TOBN(0x6dd1c20e, 0x76ee9936), + TOBN(0x23ee4b57, 0x423caa20), TOBN(0x4ac3793b, 0x8efb840e), + TOBN(0x934438eb, 0xed1f8ca0), TOBN(0x3e546658, 0x4ebb25a2), + TOBN(0xc415af0e, 0xc069896f), TOBN(0xc13eddb0, 0x9a5aa43d), + TOBN(0x7a04204f, 0xd49eb8f6), TOBN(0xd0d5bdfc, 0xd74f1670), + TOBN(0x3697e286, 0x56fc0558), TOBN(0x10207371, 0x01cebade), + TOBN(0x5f87e690, 0x0647a82b), TOBN(0x908e0ed4, 0x8f40054f), + TOBN(0xa9f633d4, 0x79853803), TOBN(0x8ed13c9a, 0x4a28b252), + TOBN(0x3e2ef676, 0x1f460f64), TOBN(0x53930b9b, 0x36d06336), + TOBN(0x347073ac, 0x8fc4979b), TOBN(0x84380e0e, 0x5ecd5597), + TOBN(0xe3b22c6b, 0xc4fe3c39), TOBN(0xba4a8153, 0x6c7bebdf), + TOBN(0xf23ab6b7, 0x25693459), TOBN(0x53bc3770, 0x14922b11), + TOBN(0x4645c8ab, 0x5afc60db), TOBN(0xaa022355, 0x20b9f2a3), + TOBN(0x52a2954c, 0xce0fc507), TOBN(0x8c2731bb, 0x7ce1c2e7), + TOBN(0xf39608ab, 0x18a0339d), TOBN(0xac7a658d, 0x3735436c), + TOBN(0xb22c2b07, 0xcd992b4f), TOBN(0x4e83daec, 0xf40dcfd4), + TOBN(0x8a34c7be, 0x2f39ea3e), TOBN(0xef0c005f, 0xb0a56d2e), + TOBN(0x62731f6a, 0x6edd8038), TOBN(0x5721d740, 0x4e3cb075), + TOBN(0x1ea41511, 0xfbeeee1b), TOBN(0xd1ef5e73, 0xef1d0c05), + TOBN(0x42feefd1, 0x73c07d35), TOBN(0xe530a00a, 0x8a329493), + TOBN(0x5d55b7fe, 0xf15ebfb0), TOBN(0x549de03c, 0xd322491a), + TOBN(0xf7b5f602, 0x745b3237), TOBN(0x3632a3a2, 0x1ab6e2b6), + TOBN(0x0d3bba89, 0x0ef59f78), TOBN(0x0dfc6443, 0xc9e52b9a), + TOBN(0x1dc79699, 0x72631447), TOBN(0xef033917, 0xb3be20b1), + TOBN(0x0c92735d, 0xb1383948), TOBN(0xc1fc29a2, 0xc0dd7d7d), + TOBN(0x6485b697, 0x403ed068), TOBN(0x13bfaab3, 0xaac93bdc), + TOBN(0x410dc6a9, 0x0deeaf52), TOBN(0xb003fb02, 0x4c641c15), + TOBN(0x1384978c, 0x5bc504c4), TOBN(0x37640487, 0x864a6a77), + TOBN(0x05991bc6, 0x222a77da), TOBN(0x62260a57, 0x5e47eb11), + TOBN(0xc7af6613, 0xf21b432c), TOBN(0x22f3acc9, 0xab4953e9), + TOBN(0x52934922, 0x8e41d155), TOBN(0x4d024568, 0x3ac059ef), + TOBN(0xb0201755, 0x4d884411), TOBN(0xce8055cf, 0xa59a178f), + TOBN(0xcd77d1af, 0xf6204549), TOBN(0xa0a00a3e, 0xc7066759), + TOBN(0x471071ef, 0x0272c229), TOBN(0x009bcf6b, 0xd3c4b6b0), + TOBN(0x2a2638a8, 0x22305177), TOBN(0xd51d59df, 0x41645bbf), + TOBN(0xa81142fd, 0xc0a7a3c0), TOBN(0xa17eca6d, 0x4c7063ee), + TOBN(0x0bb887ed, 0x60d9dcec), TOBN(0xd6d28e51, 0x20ad2455), + TOBN(0xebed6308, 0xa67102ba), TOBN(0x042c3114, 0x8bffa408), + TOBN(0xfd099ac5, 0x8aa68e30), TOBN(0x7a6a3d7c, 0x1483513e), + TOBN(0xffcc6b75, 0xba2d8f0c), TOBN(0x54dacf96, 0x1e78b954), + TOBN(0xf645696f, 0xa4a9af89), TOBN(0x3a411940, 0x06ac98ec), + TOBN(0x41b8b3f6, 0x22a67a20), TOBN(0x2d0b1e0f, 0x99dec626), + TOBN(0x27c89192, 0x40be34e8), TOBN(0xc7162b37, 0x91907f35), + TOBN(0x90188ec1, 0xa956702b), TOBN(0xca132f7d, 0xdf93769c), + TOBN(0x3ece44f9, 0x0e2025b4), TOBN(0x67aaec69, 0x0c62f14c), + TOBN(0xad741418, 0x22e3cc11), TOBN(0xcf9b75c3, 0x7ff9a50e), + TOBN(0x02fa2b16, 0x4d348272), TOBN(0xbd99d61a, 0x9959d56d), + TOBN(0xbc4f19db, 0x18762916), TOBN(0xcc7cce50, 0x49c1ac80), + TOBN(0x4d59ebaa, 0xd846bd83), TOBN(0x8775a9dc, 0xa9202849), + TOBN(0x07ec4ae1, 0x6e1f4ca9), TOBN(0x27eb5875, 0xba893f11), + TOBN(0x00284d51, 0x662cc565), TOBN(0x82353a6b, 0x0db4138d), + TOBN(0xd9c7aaaa, 0xaa32a594), TOBN(0xf5528b5e, 0xa5669c47), + TOBN(0xf3220231, 0x2f23c5ff), TOBN(0xe3e8147a, 0x6affa3a1), + TOBN(0xfb423d5c, 0x202ddda0), TOBN(0x3d6414ac, 0x6b871bd4), + TOBN(0x586f82e1, 0xa51a168a), TOBN(0xb712c671, 0x48ae5448), + TOBN(0x9a2e4bd1, 0x76233eb8), TOBN(0x0188223a, 0x78811ca9), + TOBN(0x553c5e21, 0xf7c18de1), TOBN(0x7682e451, 0xb27bb286), + TOBN(0x3ed036b3, 0x0e51e929), TOBN(0xf487211b, 0xec9cb34f), + TOBN(0x0d094277, 0x0c24efc8), TOBN(0x0349fd04, 0xbef737a4), + TOBN(0x6d1c9dd2, 0x514cdd28), TOBN(0x29c135ff, 0x30da9521), + TOBN(0xea6e4508, 0xf78b0b6f), TOBN(0x176f5dd2, 0x678c143c), + TOBN(0x08148418, 0x4be21e65), TOBN(0x27f7525c, 0xe7df38c4), + TOBN(0x1fb70e09, 0x748ab1a4), TOBN(0x9cba50a0, 0x5efe4433), + TOBN(0x7846c7a6, 0x15f75af2), TOBN(0x2a7c2c57, 0x5ee73ea8), + TOBN(0x42e566a4, 0x3f0a449a), TOBN(0x45474c3b, 0xad90fc3d), + TOBN(0x7447be3d, 0x8b61d057), TOBN(0x3e9d1cf1, 0x3a4ec092), + TOBN(0x1603e453, 0xf380a6e6), TOBN(0x0b86e431, 0x9b1437c2), + TOBN(0x7a4173f2, 0xef29610a), TOBN(0x8fa729a7, 0xf03d57f7), + TOBN(0x3e186f6e, 0x6c9c217e), TOBN(0xbe1d3079, 0x91919524), + TOBN(0x92a62a70, 0x153d4fb1), TOBN(0x32ed3e34, 0xd68c2f71), + TOBN(0xd785027f, 0x9eb1a8b7), TOBN(0xbc37eb77, 0xc5b22fe8), + TOBN(0x466b34f0, 0xb9d6a191), TOBN(0x008a89af, 0x9a05f816), + TOBN(0x19b028fb, 0x7d42c10a), TOBN(0x7fe8c92f, 0x49b3f6b8), + TOBN(0x58907cc0, 0xa5a0ade3), TOBN(0xb3154f51, 0x559d1a7c), + TOBN(0x5066efb6, 0xd9790ed6), TOBN(0xa77a0cbc, 0xa6aa793b), + TOBN(0x1a915f3c, 0x223e042e), TOBN(0x1c5def04, 0x69c5874b), + TOBN(0x0e830078, 0x73b6c1da), TOBN(0x55cf85d2, 0xfcd8557a), + TOBN(0x0f7c7c76, 0x0460f3b1), TOBN(0x87052acb, 0x46e58063), + TOBN(0x09212b80, 0x907eae66), TOBN(0x3cb068e0, 0x4d721c89), + TOBN(0xa87941ae, 0xdd45ac1c), TOBN(0xde8d5c0d, 0x0daa0dbb), + TOBN(0xda421fdc, 0xe3502e6e), TOBN(0xc8944201, 0x4d89a084), + TOBN(0x7307ba5e, 0xf0c24bfb), TOBN(0xda212beb, 0x20bde0ef), + TOBN(0xea2da24b, 0xf82ce682), TOBN(0x058d3816, 0x07f71fe4), + TOBN(0x35a02462, 0x5ffad8de), TOBN(0xcd7b05dc, 0xaadcefab), + TOBN(0xd442f8ed, 0x1d9f54ec), TOBN(0x8be3d618, 0xb2d3b5ca), + TOBN(0xe2220ed0, 0xe06b2ce2), TOBN(0x82699a5f, 0x1b0da4c0), + TOBN(0x3ff106f5, 0x71c0c3a7), TOBN(0x8f580f5a, 0x0d34180c), + TOBN(0x4ebb120e, 0x22d7d375), TOBN(0x5e5782cc, 0xe9513675), + TOBN(0x2275580c, 0x99c82a70), TOBN(0xe8359fbf, 0x15ea8c4c), + TOBN(0x53b48db8, 0x7b415e70), TOBN(0xaacf2240, 0x100c6014), + TOBN(0x9faaccf5, 0xe4652f1d), TOBN(0xbd6fdd2a, 0xd56157b2), + TOBN(0xa4f4fb1f, 0x6261ec50), TOBN(0x244e55ad, 0x476bcd52), + TOBN(0x881c9305, 0x047d320b), TOBN(0x1ca983d5, 0x6181263f), + TOBN(0x354e9a44, 0x278fb8ee), TOBN(0xad2dbc0f, 0x396e4964), + TOBN(0x723f3aa2, 0x9268b3de), TOBN(0x0d1ca29a, 0xe6e0609a), + TOBN(0x794866aa, 0x6cf44252), TOBN(0x0b59f3e3, 0x01af87ed), + TOBN(0xe234e5ff, 0x7f4a6c51), TOBN(0xa8768fd2, 0x61dc2f7e), + TOBN(0xdafc7332, 0x0a94d81f), TOBN(0xd7f84282, 0x06938ce1), + TOBN(0xae0b3c0e, 0x0546063e), TOBN(0x7fbadcb2, 0x5d61abc6), + TOBN(0xd5d7a2c9, 0x369ac400), TOBN(0xa5978d09, 0xae67d10c), + TOBN(0x290f211e, 0x4f85eaac), TOBN(0xe61e2ad1, 0xfacac681), + TOBN(0xae125225, 0x388384cd), TOBN(0xa7fb68e9, 0xccfde30f), + TOBN(0x7a59b936, 0x3daed4c2), TOBN(0x80a9aa40, 0x2606f789), + TOBN(0xb40c1ea5, 0xf6a6d90a), TOBN(0x948364d3, 0x514d5885), + TOBN(0x062ebc60, 0x70985182), TOBN(0xa6db5b0e, 0x33310895), + TOBN(0x64a12175, 0xe329c2f5), TOBN(0xc5f25bd2, 0x90ea237e), + TOBN(0x7915c524, 0x2d0a4c23), TOBN(0xeb5d26e4, 0x6bb3cc52), + TOBN(0x369a9116, 0xc09e2c92), TOBN(0x0c527f92, 0xcf182cf8), + TOBN(0x9e591938, 0x2aede0ac), TOBN(0xb2922208, 0x6cc34939), + TOBN(0x3c9d8962, 0x99a34361), TOBN(0x3c81836d, 0xc1905fe6), + TOBN(0x4bfeb57f, 0xa001ec5a), TOBN(0xe993f5bb, 0xa0dc5dba), + TOBN(0x47884109, 0x724a1380), TOBN(0x8a0369ab, 0x32fe9a04), + TOBN(0xea068d60, 0x8c927db8), TOBN(0xbf5f37cf, 0x94655741), + TOBN(0x47d402a2, 0x04b6c7ea), TOBN(0x4551c295, 0x6af259cb), + TOBN(0x698b71e7, 0xed77ee8b), TOBN(0xbddf7bd0, 0xf309d5c7), + TOBN(0x6201c22c, 0x34e780ca), TOBN(0xab04f7d8, 0x4c295ef4), + TOBN(0x1c947294, 0x4313a8ce), TOBN(0xe532e4ac, 0x92ca4cfe), + TOBN(0x89738f80, 0xd0a7a97a), TOBN(0xec088c88, 0xa580fd5b), + TOBN(0x612b1ecc, 0x42ce9e51), TOBN(0x8f9840fd, 0xb25fdd2a), + TOBN(0x3cda78c0, 0x01e7f839), TOBN(0x546b3d3a, 0xece05480), + TOBN(0x271719a9, 0x80d30916), TOBN(0x45497107, 0x584c20c4), + TOBN(0xaf8f9478, 0x5bc78608), TOBN(0x28c7d484, 0x277e2a4c), + TOBN(0xfce01767, 0x88a2ffe4), TOBN(0xdc506a35, 0x28e169a5), + TOBN(0x0ea10861, 0x7af9c93a), TOBN(0x1ed24361, 0x03fa0e08), + TOBN(0x96eaaa92, 0xa3d694e7), TOBN(0xc0f43b4d, 0xef50bc74), + TOBN(0xce6aa58c, 0x64114db4), TOBN(0x8218e8ea, 0x7c000fd4), + TOBN(0xac815dfb, 0x185f8844), TOBN(0xcd7e90cb, 0x1557abfb), + TOBN(0x23d16655, 0xafbfecdf), TOBN(0x80f3271f, 0x085cac4a), + TOBN(0x7fc39aa7, 0xd0e62f47), TOBN(0x88d519d1, 0x460a48e5), + TOBN(0x59559ac4, 0xd28f101e), TOBN(0x7981d9e9, 0xca9ae816), + TOBN(0x5c38652c, 0x9ac38203), TOBN(0x86eaf87f, 0x57657fe5), + TOBN(0x568fc472, 0xe21f5416), TOBN(0x2afff39c, 0xe7e597b5), + TOBN(0x3adbbb07, 0x256d4eab), TOBN(0x22598692, 0x8285ab89), + TOBN(0x35f8112a, 0x041caefe), TOBN(0x95df02e3, 0xa5064c8b), + TOBN(0x4d63356e, 0xc7004bf3), TOBN(0x230a08f4, 0xdb83c7de), + TOBN(0xca27b270, 0x8709a7b7), TOBN(0x0d1c4cc4, 0xcb9abd2d), + TOBN(0x8a0bc66e, 0x7550fee8), TOBN(0x369cd4c7, 0x9cf7247e), + TOBN(0x75562e84, 0x92b5b7e7), TOBN(0x8fed0da0, 0x5802af7b), + TOBN(0x6a7091c2, 0xe48fb889), TOBN(0x26882c13, 0x7b8a9d06), + TOBN(0xa2498663, 0x1b82a0e2), TOBN(0x844ed736, 0x3518152d), + TOBN(0x282f476f, 0xd86e27c7), TOBN(0xa04edaca, 0x04afefdc), + TOBN(0x8b256ebc, 0x6119e34d), TOBN(0x56a413e9, 0x0787d78b)}, + {TOBN(0x82ee061d, 0x5a74be50), TOBN(0xe41781c4, 0xdea16ff5), + TOBN(0xe0b0c81e, 0x99bfc8a2), TOBN(0x624f4d69, 0x0b547e2d), + TOBN(0x3a83545d, 0xbdcc9ae4), TOBN(0x2573dbb6, 0x409b1e8e), + TOBN(0x482960c4, 0xa6c93539), TOBN(0xf01059ad, 0x5ae18798), + TOBN(0x715c9f97, 0x3112795f), TOBN(0xe8244437, 0x984e6ee1), + TOBN(0x55cb4858, 0xecb66bcd), TOBN(0x7c136735, 0xabaffbee), + TOBN(0x54661595, 0x5dbec38e), TOBN(0x51c0782c, 0x388ad153), + TOBN(0x9ba4c53a, 0xc6e0952f), TOBN(0x27e6782a, 0x1b21dfa8), + TOBN(0x682f903d, 0x4ed2dbc2), TOBN(0x0eba59c8, 0x7c3b2d83), + TOBN(0x8e9dc84d, 0x9c7e9335), TOBN(0x5f9b21b0, 0x0eb226d7), + TOBN(0xe33bd394, 0xaf267bae), TOBN(0xaa86cc25, 0xbe2e15ae), + TOBN(0x4f0bf67d, 0x6a8ec500), TOBN(0x5846aa44, 0xf9630658), + TOBN(0xfeb09740, 0xe2c2bf15), TOBN(0x627a2205, 0xa9e99704), + TOBN(0xec8d73d0, 0xc2fbc565), TOBN(0x223eed8f, 0xc20c8de8), + TOBN(0x1ee32583, 0xa8363b49), TOBN(0x1a0b6cb9, 0xc9c2b0a6), + TOBN(0x49f7c3d2, 0x90dbc85c), TOBN(0xa8dfbb97, 0x1ef4c1ac), + TOBN(0xafb34d4c, 0x65c7c2ab), TOBN(0x1d4610e7, 0xe2c5ea84), + TOBN(0x893f6d1b, 0x973c4ab5), TOBN(0xa3cdd7e9, 0x945ba5c4), + TOBN(0x60514983, 0x064417ee), TOBN(0x1459b23c, 0xad6bdf2b), + TOBN(0x23b2c341, 0x5cf726c3), TOBN(0x3a829635, 0x32d6354a), + TOBN(0x294f901f, 0xab192c18), TOBN(0xec5fcbfe, 0x7030164f), + TOBN(0xe2e2fcb7, 0xe2246ba6), TOBN(0x1e7c88b3, 0x221a1a0c), + TOBN(0x72c7dd93, 0xc92d88c5), TOBN(0x41c2148e, 0x1106fb59), + TOBN(0x547dd4f5, 0xa0f60f14), TOBN(0xed9b52b2, 0x63960f31), + TOBN(0x6c8349eb, 0xb0a5b358), TOBN(0xb154c5c2, 0x9e7e2ed6), + TOBN(0xcad5eccf, 0xeda462db), TOBN(0xf2d6dbe4, 0x2de66b69), + TOBN(0x426aedf3, 0x8665e5b2), TOBN(0x488a8513, 0x7b7f5723), + TOBN(0x15cc43b3, 0x8bcbb386), TOBN(0x27ad0af3, 0xd791d879), + TOBN(0xc16c236e, 0x846e364f), TOBN(0x7f33527c, 0xdea50ca0), + TOBN(0xc4810775, 0x0926b86d), TOBN(0x6c2a3609, 0x0598e70c), + TOBN(0xa6755e52, 0xf024e924), TOBN(0xe0fa07a4, 0x9db4afca), + TOBN(0x15c3ce7d, 0x66831790), TOBN(0x5b4ef350, 0xa6cbb0d6), + TOBN(0x2c4aafc4, 0xb6205969), TOBN(0x42563f02, 0xf6c7854f), + TOBN(0x016aced5, 0x1d983b48), TOBN(0xfeb356d8, 0x99949755), + TOBN(0x8c2a2c81, 0xd1a39bd7), TOBN(0x8f44340f, 0xe6934ae9), + TOBN(0x148cf91c, 0x447904da), TOBN(0x7340185f, 0x0f51a926), + TOBN(0x2f8f00fb, 0x7409ab46), TOBN(0x057e78e6, 0x80e289b2), + TOBN(0x03e5022c, 0xa888e5d1), TOBN(0x3c87111a, 0x9dede4e2), + TOBN(0x5b9b0e1c, 0x7809460b), TOBN(0xe751c852, 0x71c9abc7), + TOBN(0x8b944e28, 0xc7cc1dc9), TOBN(0x4f201ffa, 0x1d3cfa08), + TOBN(0x02fc905c, 0x3e6721ce), TOBN(0xd52d70da, 0xd0b3674c), + TOBN(0x5dc2e5ca, 0x18810da4), TOBN(0xa984b273, 0x5c69dd99), + TOBN(0x63b92527, 0x84de5ca4), TOBN(0x2f1c9872, 0xc852dec4), + TOBN(0x18b03593, 0xc2e3de09), TOBN(0x19d70b01, 0x9813dc2f), + TOBN(0x42806b2d, 0xa6dc1d29), TOBN(0xd3030009, 0xf871e144), + TOBN(0xa1feb333, 0xaaf49276), TOBN(0xb5583b9e, 0xc70bc04b), + TOBN(0x1db0be78, 0x95695f20), TOBN(0xfc841811, 0x89d012b5), + TOBN(0x6409f272, 0x05f61643), TOBN(0x40d34174, 0xd5883128), + TOBN(0xd79196f5, 0x67419833), TOBN(0x6059e252, 0x863b7b08), + TOBN(0x84da1817, 0x1c56700c), TOBN(0x5758ee56, 0xb28d3ec4), + TOBN(0x7da2771d, 0x013b0ea6), TOBN(0xfddf524b, 0x54c5e9b9), + TOBN(0x7df4faf8, 0x24305d80), TOBN(0x58f5c1bf, 0x3a97763f), + TOBN(0xa5af37f1, 0x7c696042), TOBN(0xd4cba22c, 0x4a2538de), + TOBN(0x211cb995, 0x9ea42600), TOBN(0xcd105f41, 0x7b069889), + TOBN(0xb1e1cf19, 0xddb81e74), TOBN(0x472f2d89, 0x5157b8ca), + TOBN(0x086fb008, 0xee9db885), TOBN(0x365cd570, 0x0f26d131), + TOBN(0x284b02bb, 0xa2be7053), TOBN(0xdcbbf7c6, 0x7ab9a6d6), + TOBN(0x4425559c, 0x20f7a530), TOBN(0x961f2dfa, 0x188767c8), + TOBN(0xe2fd9435, 0x70dc80c4), TOBN(0x104d6b63, 0xf0784120), + TOBN(0x7f592bc1, 0x53567122), TOBN(0xf6bc1246, 0xf688ad77), + TOBN(0x05214c05, 0x0f15dde9), TOBN(0xa47a76a8, 0x0d5f2b82), + TOBN(0xbb254d30, 0x62e82b62), TOBN(0x11a05fe0, 0x3ec955ee), + TOBN(0x7eaff46e, 0x9d529b36), TOBN(0x55ab1301, 0x8f9e3df6), + TOBN(0xc463e371, 0x99317698), TOBN(0xfd251438, 0xccda47ad), + TOBN(0xca9c3547, 0x23d695ea), TOBN(0x48ce626e, 0x16e589b5), + TOBN(0x6b5b64c7, 0xb187d086), TOBN(0xd02e1794, 0xb2207948), + TOBN(0x8b58e98f, 0x7198111d), TOBN(0x90ca6305, 0xdcf9c3cc), + TOBN(0x5691fe72, 0xf34089b0), TOBN(0x60941af1, 0xfc7c80ff), + TOBN(0xa09bc0a2, 0x22eb51e5), TOBN(0xc0bb7244, 0xaa9cf09a), + TOBN(0x36a8077f, 0x80159f06), TOBN(0x8b5c989e, 0xdddc560e), + TOBN(0x19d2f316, 0x512e1f43), TOBN(0x02eac554, 0xad08ff62), + TOBN(0x012ab84c, 0x07d20b4e), TOBN(0x37d1e115, 0xd6d4e4e1), + TOBN(0xb6443e1a, 0xab7b19a8), TOBN(0xf08d067e, 0xdef8cd45), + TOBN(0x63adf3e9, 0x685e03da), TOBN(0xcf15a10e, 0x4792b916), + TOBN(0xf44bcce5, 0xb738a425), TOBN(0xebe131d5, 0x9636b2fd), + TOBN(0x94068841, 0x7850d605), TOBN(0x09684eaa, 0xb40d749d), + TOBN(0x8c3c669c, 0x72ba075b), TOBN(0x89f78b55, 0xba469015), + TOBN(0x5706aade, 0x3e9f8ba8), TOBN(0x6d8bd565, 0xb32d7ed7), + TOBN(0x25f4e63b, 0x805f08d6), TOBN(0x7f48200d, 0xc3bcc1b5), + TOBN(0x4e801968, 0xb025d847), TOBN(0x74afac04, 0x87cbe0a8), + TOBN(0x43ed2c2b, 0x7e63d690), TOBN(0xefb6bbf0, 0x0223cdb8), + TOBN(0x4fec3cae, 0x2884d3fe), TOBN(0x065ecce6, 0xd75e25a4), + TOBN(0x6c2294ce, 0x69f79071), TOBN(0x0d9a8e5f, 0x044b8666), + TOBN(0x5009f238, 0x17b69d8f), TOBN(0x3c29f8fe, 0xc5dfdaf7), + TOBN(0x9067528f, 0xebae68c4), TOBN(0x5b385632, 0x30c5ba21), + TOBN(0x540df119, 0x1fdd1aec), TOBN(0xcf37825b, 0xcfba4c78), + TOBN(0x77eff980, 0xbeb11454), TOBN(0x40a1a991, 0x60c1b066), + TOBN(0xe8018980, 0xf889a1c7), TOBN(0xb9c52ae9, 0x76c24be0), + TOBN(0x05fbbcce, 0x45650ef4), TOBN(0xae000f10, 0x8aa29ac7), + TOBN(0x884b7172, 0x4f04c470), TOBN(0x7cd4fde2, 0x19bb5c25), + TOBN(0x6477b22a, 0xe8840869), TOBN(0xa8868859, 0x5fbd0686), + TOBN(0xf23cc02e, 0x1116dfba), TOBN(0x76cd563f, 0xd87d7776), + TOBN(0xe2a37598, 0xa9d82abf), TOBN(0x5f188ccb, 0xe6c170f5), + TOBN(0x81682200, 0x5066b087), TOBN(0xda22c212, 0xc7155ada), + TOBN(0x151e5d3a, 0xfbddb479), TOBN(0x4b606b84, 0x6d715b99), + TOBN(0x4a73b54b, 0xf997cb2e), TOBN(0x9a1bfe43, 0x3ecd8b66), + TOBN(0x1c312809, 0x2a67d48a), TOBN(0xcd6a671e, 0x031fa9e2), + TOBN(0xbec3312a, 0x0e43a34a), TOBN(0x1d935639, 0x55ef47d3), + TOBN(0x5ea02489, 0x8fea73ea), TOBN(0x8247b364, 0xa035afb2), + TOBN(0xb58300a6, 0x5265b54c), TOBN(0x3286662f, 0x722c7148), + TOBN(0xb77fd76b, 0xb4ec4c20), TOBN(0xf0a12fa7, 0x0f3fe3fd), + TOBN(0xf845bbf5, 0x41d8c7e8), TOBN(0xe4d969ca, 0x5ec10aa8), + TOBN(0x4c0053b7, 0x43e232a3), TOBN(0xdc7a3fac, 0x37f8a45a), + TOBN(0x3c4261c5, 0x20d81c8f), TOBN(0xfd4b3453, 0xb00eab00), + TOBN(0x76d48f86, 0xd36e3062), TOBN(0x626c5277, 0xa143ff02), + TOBN(0x538174de, 0xaf76f42e), TOBN(0x2267aa86, 0x6407ceac), + TOBN(0xfad76351, 0x72e572d5), TOBN(0xab861af7, 0xba7330eb), + TOBN(0xa0a1c8c7, 0x418d8657), TOBN(0x988821cb, 0x20289a52), + TOBN(0x79732522, 0xcccc18ad), TOBN(0xaadf3f8d, 0xf1a6e027), + TOBN(0xf7382c93, 0x17c2354d), TOBN(0x5ce1680c, 0xd818b689), + TOBN(0x359ebbfc, 0xd9ecbee9), TOBN(0x4330689c, 0x1cae62ac), + TOBN(0xb55ce5b4, 0xc51ac38a), TOBN(0x7921dfea, 0xfe238ee8), + TOBN(0x3972bef8, 0x271d1ca5), TOBN(0x3e423bc7, 0xe8aabd18), + TOBN(0x57b09f3f, 0x44a3e5e3), TOBN(0x5da886ae, 0x7b444d66), + TOBN(0x68206634, 0xa9964375), TOBN(0x356a2fa3, 0x699cd0ff), + TOBN(0xaf0faa24, 0xdba515e9), TOBN(0x536e1f5c, 0xb321d79a), + TOBN(0xd3b9913a, 0x5c04e4ea), TOBN(0xd549dcfe, 0xd6f11513), + TOBN(0xee227bf5, 0x79fd1d94), TOBN(0x9f35afee, 0xb43f2c67), + TOBN(0xd2638d24, 0xf1314f53), TOBN(0x62baf948, 0xcabcd822), + TOBN(0x5542de29, 0x4ef48db0), TOBN(0xb3eb6a04, 0xfc5f6bb2), + TOBN(0x23c110ae, 0x1208e16a), TOBN(0x1a4d15b5, 0xf8363e24), + TOBN(0x30716844, 0x164be00b), TOBN(0xa8e24824, 0xf6f4690d), + TOBN(0x548773a2, 0x90b170cf), TOBN(0xa1bef331, 0x42f191f4), + TOBN(0x70f418d0, 0x9247aa97), TOBN(0xea06028e, 0x48be9147), + TOBN(0xe13122f3, 0xdbfb894e), TOBN(0xbe9b79f6, 0xce274b18), + TOBN(0x85a49de5, 0xca58aadf), TOBN(0x24957758, 0x11487351), + TOBN(0x111def61, 0xbb939099), TOBN(0x1d6a974a, 0x26d13694), + TOBN(0x4474b4ce, 0xd3fc253b), TOBN(0x3a1485e6, 0x4c5db15e), + TOBN(0xe79667b4, 0x147c15b4), TOBN(0xe34f553b, 0x7bc61301), + TOBN(0x032b80f8, 0x17094381), TOBN(0x55d8bafd, 0x723eaa21), + TOBN(0x5a987995, 0xf1c0e74e), TOBN(0x5a9b292e, 0xebba289c), + TOBN(0x413cd4b2, 0xeb4c8251), TOBN(0x98b5d243, 0xd162db0a), + TOBN(0xbb47bf66, 0x68342520), TOBN(0x08d68949, 0xbaa862d1), + TOBN(0x11f349c7, 0xe906abcd), TOBN(0x454ce985, 0xed7bf00e), + TOBN(0xacab5c9e, 0xb55b803b), TOBN(0xb03468ea, 0x31e3c16d), + TOBN(0x5c24213d, 0xd273bf12), TOBN(0x211538eb, 0x71587887), + TOBN(0x198e4a2f, 0x731dea2d), TOBN(0xd5856cf2, 0x74ed7b2a), + TOBN(0x86a632eb, 0x13a664fe), TOBN(0x932cd909, 0xbda41291), + TOBN(0x850e95d4, 0xc0c4ddc0), TOBN(0xc0f422f8, 0x347fc2c9), + TOBN(0xe68cbec4, 0x86076bcb), TOBN(0xf9e7c0c0, 0xcd6cd286), + TOBN(0x65994ddb, 0x0f5f27ca), TOBN(0xe85461fb, 0xa80d59ff), + TOBN(0xff05481a, 0x66601023), TOBN(0xc665427a, 0xfc9ebbfb), + TOBN(0xb0571a69, 0x7587fd52), TOBN(0x935289f8, 0x8d49efce), + TOBN(0x61becc60, 0xea420688), TOBN(0xb22639d9, 0x13a786af), + TOBN(0x1a8e6220, 0x361ecf90), TOBN(0x001f23e0, 0x25506463), + TOBN(0xe4ae9b5d, 0x0a5c2b79), TOBN(0xebc9cdad, 0xd8149db5), + TOBN(0xb33164a1, 0x934aa728), TOBN(0x750eb00e, 0xae9b60f3), + TOBN(0x5a91615b, 0x9b9cfbfd), TOBN(0x97015cbf, 0xef45f7f6), + TOBN(0xb462c4a5, 0xbf5151df), TOBN(0x21adcc41, 0xb07118f2), + TOBN(0xd60c545b, 0x043fa42c), TOBN(0xfc21aa54, 0xe96be1ab), + TOBN(0xe84bc32f, 0x4e51ea80), TOBN(0x3dae45f0, 0x259b5d8d), + TOBN(0xbb73c7eb, 0xc38f1b5e), TOBN(0xe405a74a, 0xe8ae617d), + TOBN(0xbb1ae9c6, 0x9f1c56bd), TOBN(0x8c176b98, 0x49f196a4), + TOBN(0xc448f311, 0x6875092b), TOBN(0xb5afe3de, 0x9f976033), + TOBN(0xa8dafd49, 0x145813e5), TOBN(0x687fc4d9, 0xe2b34226), + TOBN(0xf2dfc92d, 0x4c7ff57f), TOBN(0x004e3fc1, 0x401f1b46), + TOBN(0x5afddab6, 0x1430c9ab), TOBN(0x0bdd41d3, 0x2238e997), + TOBN(0xf0947430, 0x418042ae), TOBN(0x71f9adda, 0xcdddc4cb), + TOBN(0x7090c016, 0xc52dd907), TOBN(0xd9bdf44d, 0x29e2047f), + TOBN(0xe6f1fe80, 0x1b1011a6), TOBN(0xb63accbc, 0xd9acdc78), + TOBN(0xcfc7e235, 0x1272a95b), TOBN(0x0c667717, 0xa6276ac8), + TOBN(0x3c0d3709, 0xe2d7eef7), TOBN(0x5add2b06, 0x9a685b3e), + TOBN(0x363ad32d, 0x14ea5d65), TOBN(0xf8e01f06, 0x8d7dd506), + TOBN(0xc9ea2213, 0x75b4aac6), TOBN(0xed2a2bf9, 0x0d353466), + TOBN(0x439d79b5, 0xe9d3a7c3), TOBN(0x8e0ee5a6, 0x81b7f34b), + TOBN(0xcf3dacf5, 0x1dc4ba75), TOBN(0x1d3d1773, 0xeb3310c7), + TOBN(0xa8e67112, 0x7747ae83), TOBN(0x31f43160, 0x197d6b40), + TOBN(0x0521ccee, 0xcd961400), TOBN(0x67246f11, 0xf6535768), + TOBN(0x702fcc5a, 0xef0c3133), TOBN(0x247cc45d, 0x7e16693b), + TOBN(0xfd484e49, 0xc729b749), TOBN(0x522cef7d, 0xb218320f), + TOBN(0xe56ef405, 0x59ab93b3), TOBN(0x225fba11, 0x9f181071), + TOBN(0x33bd6595, 0x15330ed0), TOBN(0xc4be69d5, 0x1ddb32f7), + TOBN(0x264c7668, 0x0448087c), TOBN(0xac30903f, 0x71432dae), + TOBN(0x3851b266, 0x00f9bf47), TOBN(0x400ed311, 0x6cdd6d03), + TOBN(0x045e79fe, 0xf8fd2424), TOBN(0xfdfd974a, 0xfa6da98b), + TOBN(0x45c9f641, 0x0c1e673a), TOBN(0x76f2e733, 0x5b2c5168), + TOBN(0x1adaebb5, 0x2a601753), TOBN(0xb286514c, 0xc57c2d49), + TOBN(0xd8769670, 0x1e0bfd24), TOBN(0x950c547e, 0x04478922), + TOBN(0xd1d41969, 0xe5d32bfe), TOBN(0x30bc1472, 0x750d6c3e), + TOBN(0x8f3679fe, 0xe0e27f3a), TOBN(0x8f64a7dc, 0xa4a6ee0c), + TOBN(0x2fe59937, 0x633dfb1f), TOBN(0xea82c395, 0x977f2547), + TOBN(0xcbdfdf1a, 0x661ea646), TOBN(0xc7ccc591, 0xb9085451), + TOBN(0x82177962, 0x81761e13), TOBN(0xda57596f, 0x9196885c), + TOBN(0xbc17e849, 0x28ffbd70), TOBN(0x1e6e0a41, 0x2671d36f), + TOBN(0x61ae872c, 0x4152fcf5), TOBN(0x441c87b0, 0x9e77e754), + TOBN(0xd0799dd5, 0xa34dff09), TOBN(0x766b4e44, 0x88a6b171), + TOBN(0xdc06a512, 0x11f1c792), TOBN(0xea02ae93, 0x4be35c3e), + TOBN(0xe5ca4d6d, 0xe90c469e), TOBN(0x4df4368e, 0x56e4ff5c), + TOBN(0x7817acab, 0x4baef62e), TOBN(0x9f5a2202, 0xa85b91e8), + TOBN(0x9666ebe6, 0x6ce57610), TOBN(0x32ad31f3, 0xf73bfe03), + TOBN(0x628330a4, 0x25bcf4d6), TOBN(0xea950593, 0x515056e6), + TOBN(0x59811c89, 0xe1332156), TOBN(0xc89cf1fe, 0x8c11b2d7), + TOBN(0x75b63913, 0x04e60cc0), TOBN(0xce811e8d, 0x4625d375), + TOBN(0x030e43fc, 0x2d26e562), TOBN(0xfbb30b4b, 0x608d36a0), + TOBN(0x634ff82c, 0x48528118), TOBN(0x7c6fe085, 0xcd285911), + TOBN(0x7f2830c0, 0x99358f28), TOBN(0x2e60a95e, 0x665e6c09), + TOBN(0x08407d3d, 0x9b785dbf), TOBN(0x530889ab, 0xa759bce7), + TOBN(0xf228e0e6, 0x52f61239), TOBN(0x2b6d1461, 0x6879be3c), + TOBN(0xe6902c04, 0x51a7bbf7), TOBN(0x30ad99f0, 0x76f24a64), + TOBN(0x66d9317a, 0x98bc6da0), TOBN(0xf4f877f3, 0xcb596ac0), + TOBN(0xb05ff62d, 0x4c44f119), TOBN(0x4555f536, 0xe9b77416), + TOBN(0xc7c0d059, 0x8caed63b), TOBN(0x0cd2b7ce, 0xc358b2a9), + TOBN(0x3f33287b, 0x46945fa3), TOBN(0xf8785b20, 0xd67c8791), + TOBN(0xc54a7a61, 0x9637bd08), TOBN(0x54d4598c, 0x18be79d7), + TOBN(0x889e5acb, 0xc46d7ce1), TOBN(0x9a515bb7, 0x8b085877), + TOBN(0xfac1a03d, 0x0b7a5050), TOBN(0x7d3e738a, 0xf2926035), + TOBN(0x861cc2ce, 0x2a6cb0eb), TOBN(0x6f2e2955, 0x8f7adc79), + TOBN(0x61c4d451, 0x33016376), TOBN(0xd9fd2c80, 0x5ad59090), + TOBN(0xe5a83738, 0xb2b836a1), TOBN(0x855b41a0, 0x7c0d6622), + TOBN(0x186fe317, 0x7cc19af1), TOBN(0x6465c1ff, 0xfdd99acb), + TOBN(0x46e5c23f, 0x6974b99e), TOBN(0x75a7cf8b, 0xa2717cbe), + TOBN(0x4d2ebc3f, 0x062be658), TOBN(0x094b4447, 0x5f209c98), + TOBN(0x4af285ed, 0xb940cb5a), TOBN(0x6706d792, 0x7cc82f10), + TOBN(0xc8c8776c, 0x030526fa), TOBN(0xfa8e6f76, 0xa0da9140), + TOBN(0x77ea9d34, 0x591ee4f0), TOBN(0x5f46e337, 0x40274166), + TOBN(0x1bdf98bb, 0xea671457), TOBN(0xd7c08b46, 0x862a1fe2), + TOBN(0x46cc303c, 0x1c08ad63), TOBN(0x99543440, 0x4c845e7b), + TOBN(0x1b8fbdb5, 0x48f36bf7), TOBN(0x5b82c392, 0x8c8273a7), + TOBN(0x08f712c4, 0x928435d5), TOBN(0x071cf0f1, 0x79330380), + TOBN(0xc74c2d24, 0xa8da054a), TOBN(0xcb0e7201, 0x43c46b5c), + TOBN(0x0ad7337a, 0xc0b7eff3), TOBN(0x8552225e, 0xc5e48b3c), + TOBN(0xe6f78b0c, 0x73f13a5f), TOBN(0x5e70062e, 0x82349cbe), + TOBN(0x6b8d5048, 0xe7073969), TOBN(0x392d2a29, 0xc33cb3d2), + TOBN(0xee4f727c, 0x4ecaa20f), TOBN(0xa068c99e, 0x2ccde707), + TOBN(0xfcd5651f, 0xb87a2913), TOBN(0xea3e3c15, 0x3cc252f0), + TOBN(0x777d92df, 0x3b6cd3e4), TOBN(0x7a414143, 0xc5a732e7), + TOBN(0xa895951a, 0xa71ff493), TOBN(0xfe980c92, 0xbbd37cf6), + TOBN(0x45bd5e64, 0xdecfeeff), TOBN(0x910dc2a9, 0xa44c43e9), + TOBN(0xcb403f26, 0xcca9f54d), TOBN(0x928bbdfb, 0x9303f6db), + TOBN(0x3c37951e, 0xa9eee67c), TOBN(0x3bd61a52, 0xf79961c3), + TOBN(0x09a238e6, 0x395c9a79), TOBN(0x6940ca2d, 0x61eb352d), + TOBN(0x7d1e5c5e, 0xc1875631), TOBN(0x1e19742c, 0x1e1b20d1), + TOBN(0x4633d908, 0x23fc2e6e), TOBN(0xa76e29a9, 0x08959149), + TOBN(0x61069d9c, 0x84ed7da5), TOBN(0x0baa11cf, 0x5dbcad51), + TOBN(0xd01eec64, 0x961849da), TOBN(0x93b75f1f, 0xaf3d8c28), + TOBN(0x57bc4f9f, 0x1ca2ee44), TOBN(0x5a26322d, 0x00e00558), + TOBN(0x1888d658, 0x61a023ef), TOBN(0x1d72aab4, 0xb9e5246e), + TOBN(0xa9a26348, 0xe5563ec0), TOBN(0xa0971963, 0xc3439a43), + TOBN(0x567dd54b, 0xadb9b5b7), TOBN(0x73fac1a1, 0xc45a524b), + TOBN(0x8fe97ef7, 0xfe38e608), TOBN(0x608748d2, 0x3f384f48), + TOBN(0xb0571794, 0xc486094f), TOBN(0x869254a3, 0x8bf3a8d6), + TOBN(0x148a8dd1, 0x310b0e25), TOBN(0x99ab9f3f, 0x9aa3f7d8), + TOBN(0x0927c68a, 0x6706c02e), TOBN(0x22b5e76c, 0x69790e6c), + TOBN(0x6c325260, 0x6c71376c), TOBN(0x53a57690, 0x09ef6657), + TOBN(0x8d63f852, 0xedffcf3a), TOBN(0xb4d2ed04, 0x3c0a6f55), + TOBN(0xdb3aa8de, 0x12519b9e), TOBN(0x5d38e9c4, 0x1e0a569a), + TOBN(0x871528bf, 0x303747e2), TOBN(0xa208e77c, 0xf5b5c18d), + TOBN(0x9d129c88, 0xca6bf923), TOBN(0xbcbf197f, 0xbf02839f), + TOBN(0x9b9bf030, 0x27323194), TOBN(0x3b055a8b, 0x339ca59d), + TOBN(0xb46b2312, 0x0f669520), TOBN(0x19789f1f, 0x497e5f24), + TOBN(0x9c499468, 0xaaf01801), TOBN(0x72ee1190, 0x8b69d59c), + TOBN(0x8bd39595, 0xacf4c079), TOBN(0x3ee11ece, 0x8e0cd048), + TOBN(0xebde86ec, 0x1ed66f18), TOBN(0x225d906b, 0xd61fce43), + TOBN(0x5cab07d6, 0xe8bed74d), TOBN(0x16e4617f, 0x27855ab7), + TOBN(0x6568aadd, 0xb2fbc3dd), TOBN(0xedb5484f, 0x8aeddf5b), + TOBN(0x878f20e8, 0x6dcf2fad), TOBN(0x3516497c, 0x615f5699)}, + {TOBN(0xef0a3fec, 0xfa181e69), TOBN(0x9ea02f81, 0x30d69a98), + TOBN(0xb2e9cf8e, 0x66eab95d), TOBN(0x520f2beb, 0x24720021), + TOBN(0x621c540a, 0x1df84361), TOBN(0x12037721, 0x71fa6d5d), + TOBN(0x6e3c7b51, 0x0ff5f6ff), TOBN(0x817a069b, 0xabb2bef3), + TOBN(0x83572fb6, 0xb294cda6), TOBN(0x6ce9bf75, 0xb9039f34), + TOBN(0x20e012f0, 0x095cbb21), TOBN(0xa0aecc1b, 0xd063f0da), + TOBN(0x57c21c3a, 0xf02909e5), TOBN(0xc7d59ecf, 0x48ce9cdc), + TOBN(0x2732b844, 0x8ae336f8), TOBN(0x056e3723, 0x3f4f85f4), + TOBN(0x8a10b531, 0x89e800ca), TOBN(0x50fe0c17, 0x145208fd), + TOBN(0x9e43c0d3, 0xb714ba37), TOBN(0x427d200e, 0x34189acc), + TOBN(0x05dee24f, 0xe616e2c0), TOBN(0x9c25f4c8, 0xee1854c1), + TOBN(0x4d3222a5, 0x8f342a73), TOBN(0x0807804f, 0xa027c952), + TOBN(0xc222653a, 0x4f0d56f3), TOBN(0x961e4047, 0xca28b805), + TOBN(0x2c03f8b0, 0x4a73434b), TOBN(0x4c966787, 0xab712a19), + TOBN(0xcc196c42, 0x864fee42), TOBN(0xc1be93da, 0x5b0ece5c), + TOBN(0xa87d9f22, 0xc131c159), TOBN(0x2bb6d593, 0xdce45655), + TOBN(0x22c49ec9, 0xb809b7ce), TOBN(0x8a41486b, 0xe2c72c2c), + TOBN(0x813b9420, 0xfea0bf36), TOBN(0xb3d36ee9, 0xa66dac69), + TOBN(0x6fddc08a, 0x328cc987), TOBN(0x0a3bcd2c, 0x3a326461), + TOBN(0x7103c49d, 0xd810dbba), TOBN(0xf9d81a28, 0x4b78a4c4), + TOBN(0x3de865ad, 0xe4d55941), TOBN(0xdedafa5e, 0x30384087), + TOBN(0x6f414abb, 0x4ef18b9b), TOBN(0x9ee9ea42, 0xfaee5268), + TOBN(0x260faa16, 0x37a55a4a), TOBN(0xeb19a514, 0x015f93b9), + TOBN(0x51d7ebd2, 0x9e9c3598), TOBN(0x523fc56d, 0x1932178e), + TOBN(0x501d070c, 0xb98fe684), TOBN(0xd60fbe9a, 0x124a1458), + TOBN(0xa45761c8, 0x92bc6b3f), TOBN(0xf5384858, 0xfe6f27cb), + TOBN(0x4b0271f7, 0xb59e763b), TOBN(0x3d4606a9, 0x5b5a8e5e), + TOBN(0x1eda5d9b, 0x05a48292), TOBN(0xda7731d0, 0xe6fec446), + TOBN(0xa3e33693, 0x90d45871), TOBN(0xe9764040, 0x06166d8d), + TOBN(0xb5c33682, 0x89a90403), TOBN(0x4bd17983, 0x72f1d637), + TOBN(0xa616679e, 0xd5d2c53a), TOBN(0x5ec4bcd8, 0xfdcf3b87), + TOBN(0xae6d7613, 0xb66a694e), TOBN(0x7460fc76, 0xe3fc27e5), + TOBN(0x70469b82, 0x95caabee), TOBN(0xde024ca5, 0x889501e3), + TOBN(0x6bdadc06, 0x076ed265), TOBN(0x0cb1236b, 0x5a0ef8b2), + TOBN(0x4065ddbf, 0x0972ebf9), TOBN(0xf1dd3875, 0x22aca432), + TOBN(0xa88b97cf, 0x744aff76), TOBN(0xd1359afd, 0xfe8e3d24), + TOBN(0x52a3ba2b, 0x91502cf3), TOBN(0x2c3832a8, 0x084db75d), + TOBN(0x04a12ddd, 0xde30b1c9), TOBN(0x7802eabc, 0xe31fd60c), + TOBN(0x33707327, 0xa37fddab), TOBN(0x65d6f2ab, 0xfaafa973), + TOBN(0x3525c5b8, 0x11e6f91a), TOBN(0x76aeb0c9, 0x5f46530b), + TOBN(0xe8815ff6, 0x2f93a675), TOBN(0xa6ec9684, 0x05f48679), + TOBN(0x6dcbb556, 0x358ae884), TOBN(0x0af61472, 0xe19e3873), + TOBN(0x72334372, 0xa5f696be), TOBN(0xc65e57ea, 0x6f22fb70), + TOBN(0x268da30c, 0x946cea90), TOBN(0x136a8a87, 0x65681b2a), + TOBN(0xad5e81dc, 0x0f9f44d4), TOBN(0xf09a6960, 0x2c46585a), + TOBN(0xd1649164, 0xc447d1b1), TOBN(0x3b4b36c8, 0x879dc8b1), + TOBN(0x20d4177b, 0x3b6b234c), TOBN(0x096a2505, 0x1730d9d0), + TOBN(0x0611b9b8, 0xef80531d), TOBN(0xba904b3b, 0x64bb495d), + TOBN(0x1192d9d4, 0x93a3147a), TOBN(0x9f30a5dc, 0x9a565545), + TOBN(0x90b1f9cb, 0x6ef07212), TOBN(0x29958546, 0x0d87fc13), + TOBN(0xd3323eff, 0xc17db9ba), TOBN(0xcb18548c, 0xcb1644a8), + TOBN(0x18a306d4, 0x4f49ffbc), TOBN(0x28d658f1, 0x4c2e8684), + TOBN(0x44ba60cd, 0xa99f8c71), TOBN(0x67b7abdb, 0x4bf742ff), + TOBN(0x66310f9c, 0x914b3f99), TOBN(0xae430a32, 0xf412c161), + TOBN(0x1e6776d3, 0x88ace52f), TOBN(0x4bc0fa24, 0x52d7067d), + TOBN(0x03c286aa, 0x8f07cd1b), TOBN(0x4cb8f38c, 0xa985b2c1), + TOBN(0x83ccbe80, 0x8c3bff36), TOBN(0x005a0bd2, 0x5263e575), + TOBN(0x460d7dda, 0x259bdcd1), TOBN(0x4a1c5642, 0xfa5cab6b), + TOBN(0x2b7bdbb9, 0x9fe4fc88), TOBN(0x09418e28, 0xcc97bbb5), + TOBN(0xd8274fb4, 0xa12321ae), TOBN(0xb137007d, 0x5c87b64e), + TOBN(0x80531fe1, 0xc63c4962), TOBN(0x50541e89, 0x981fdb25), + TOBN(0xdc1291a1, 0xfd4c2b6b), TOBN(0xc0693a17, 0xa6df4fca), + TOBN(0xb2c4604e, 0x0117f203), TOBN(0x245f1963, 0x0a99b8d0), + TOBN(0xaedc20aa, 0xc6212c44), TOBN(0xb1ed4e56, 0x520f52a8), + TOBN(0xfe48f575, 0xf8547be3), TOBN(0x0a7033cd, 0xa9e45f98), + TOBN(0x4b45d3a9, 0x18c50100), TOBN(0xb2a6cd6a, 0xa61d41da), + TOBN(0x60bbb4f5, 0x57933c6b), TOBN(0xa7538ebd, 0x2b0d7ffc), + TOBN(0x9ea3ab8d, 0x8cd626b6), TOBN(0x8273a484, 0x3601625a), + TOBN(0x88859845, 0x0168e508), TOBN(0x8cbc9bb2, 0x99a94abd), + TOBN(0x713ac792, 0xfab0a671), TOBN(0xa3995b19, 0x6c9ebffc), + TOBN(0xe711668e, 0x1239e152), TOBN(0x56892558, 0xbbb8dff4), + TOBN(0x8bfc7dab, 0xdbf17963), TOBN(0x5b59fe5a, 0xb3de1253), + TOBN(0x7e3320eb, 0x34a9f7ae), TOBN(0xe5e8cf72, 0xd751efe4), + TOBN(0x7ea003bc, 0xd9be2f37), TOBN(0xc0f551a0, 0xb6c08ef7), + TOBN(0x56606268, 0x038f6725), TOBN(0x1dd38e35, 0x6d92d3b6), + TOBN(0x07dfce7c, 0xc3cbd686), TOBN(0x4e549e04, 0x651c5da8), + TOBN(0x4058f93b, 0x08b19340), TOBN(0xc2fae6f4, 0xcac6d89d), + TOBN(0x4bad8a8c, 0x8f159cc7), TOBN(0x0ddba4b3, 0xcb0b601c), + TOBN(0xda4fc7b5, 0x1dd95f8c), TOBN(0x1d163cd7, 0xcea5c255), + TOBN(0x30707d06, 0x274a8c4c), TOBN(0x79d9e008, 0x2802e9ce), + TOBN(0x02a29ebf, 0xe6ddd505), TOBN(0x37064e74, 0xb50bed1a), + TOBN(0x3f6bae65, 0xa7327d57), TOBN(0x3846f5f1, 0xf83920bc), + TOBN(0x87c37491, 0x60df1b9b), TOBN(0x4cfb2895, 0x2d1da29f), + TOBN(0x10a478ca, 0x4ed1743c), TOBN(0x390c6030, 0x3edd47c6), + TOBN(0x8f3e5312, 0x8c0a78de), TOBN(0xccd02bda, 0x1e85df70), + TOBN(0xd6c75c03, 0xa61b6582), TOBN(0x0762921c, 0xfc0eebd1), + TOBN(0xd34d0823, 0xd85010c0), TOBN(0xd73aaacb, 0x0044cf1f), + TOBN(0xfb4159bb, 0xa3b5e78a), TOBN(0x2287c7f7, 0xe5826f3f), + TOBN(0x4aeaf742, 0x580b1a01), TOBN(0xf080415d, 0x60423b79), + TOBN(0xe12622cd, 0xa7dea144), TOBN(0x49ea4996, 0x59d62472), + TOBN(0xb42991ef, 0x571f3913), TOBN(0x0610f214, 0xf5b25a8a), + TOBN(0x47adc585, 0x30b79e8f), TOBN(0xf90e3df6, 0x07a065a2), + TOBN(0x5d0a5deb, 0x43e2e034), TOBN(0x53fb5a34, 0x444024aa), + TOBN(0xa8628c68, 0x6b0c9f7f), TOBN(0x9c69c29c, 0xac563656), + TOBN(0x5a231feb, 0xbace47b6), TOBN(0xbdce0289, 0x9ea5a2ec), + TOBN(0x05da1fac, 0x9463853e), TOBN(0x96812c52, 0x509e78aa), + TOBN(0xd3fb5771, 0x57151692), TOBN(0xeb2721f8, 0xd98e1c44), + TOBN(0xc0506087, 0x32399be1), TOBN(0xda5a5511, 0xd979d8b8), + TOBN(0x737ed55d, 0xc6f56780), TOBN(0xe20d3004, 0x0dc7a7f4), + TOBN(0x02ce7301, 0xf5941a03), TOBN(0x91ef5215, 0xed30f83a), + TOBN(0x28727fc1, 0x4092d85f), TOBN(0x72d223c6, 0x5c49e41a), + TOBN(0xa7cf30a2, 0xba6a4d81), TOBN(0x7c086209, 0xb030d87d), + TOBN(0x04844c7d, 0xfc588b09), TOBN(0x728cd499, 0x5874bbb0), + TOBN(0xcc1281ee, 0xe84c0495), TOBN(0x0769b5ba, 0xec31958f), + TOBN(0x665c228b, 0xf99c2471), TOBN(0xf2d8a11b, 0x191eb110), + TOBN(0x4594f494, 0xd36d7024), TOBN(0x482ded8b, 0xcdcb25a1), + TOBN(0xc958a9d8, 0xdadd4885), TOBN(0x7004477e, 0xf1d2b547), + TOBN(0x0a45f6ef, 0x2a0af550), TOBN(0x4fc739d6, 0x2f8d6351), + TOBN(0x75cdaf27, 0x786f08a9), TOBN(0x8700bb26, 0x42c2737f), + TOBN(0x855a7141, 0x1c4e2670), TOBN(0x810188c1, 0x15076fef), + TOBN(0xc251d0c9, 0xabcd3297), TOBN(0xae4c8967, 0xf48108eb), + TOBN(0xbd146de7, 0x18ceed30), TOBN(0xf9d4f07a, 0xc986bced), + TOBN(0x5ad98ed5, 0x83fa1e08), TOBN(0x7780d33e, 0xbeabd1fb), + TOBN(0xe330513c, 0x903b1196), TOBN(0xba11de9e, 0xa47bc8c4), + TOBN(0x684334da, 0x02c2d064), TOBN(0x7ecf360d, 0xa48de23b), + TOBN(0x57a1b474, 0x0a9089d8), TOBN(0xf28fa439, 0xff36734c), + TOBN(0xf2a482cb, 0xea4570b3), TOBN(0xee65d68b, 0xa5ebcee9), + TOBN(0x988d0036, 0xb9694cd5), TOBN(0x53edd0e9, 0x37885d32), + TOBN(0xe37e3307, 0xbeb9bc6d), TOBN(0xe9abb907, 0x9f5c6768), + TOBN(0x4396ccd5, 0x51f2160f), TOBN(0x2500888c, 0x47336da6), + TOBN(0x383f9ed9, 0x926fce43), TOBN(0x809dd1c7, 0x04da2930), + TOBN(0x30f6f596, 0x8a4cb227), TOBN(0x0d700c7f, 0x73a56b38), + TOBN(0x1825ea33, 0xab64a065), TOBN(0xaab9b735, 0x1338df80), + TOBN(0x1516100d, 0x9b63f57f), TOBN(0x2574395a, 0x27a6a634), + TOBN(0xb5560fb6, 0x700a1acd), TOBN(0xe823fd73, 0xfd999681), + TOBN(0xda915d1f, 0x6cb4e1ba), TOBN(0x0d030118, 0x6ebe00a3), + TOBN(0x744fb0c9, 0x89fca8cd), TOBN(0x970d01db, 0xf9da0e0b), + TOBN(0x0ad8c564, 0x7931d76f), TOBN(0xb15737bf, 0xf659b96a), + TOBN(0xdc9933e8, 0xa8b484e7), TOBN(0xb2fdbdf9, 0x7a26dec7), + TOBN(0x2349e9a4, 0x9f1f0136), TOBN(0x7860368e, 0x70fddddb), + TOBN(0xd93d2c1c, 0xf9ad3e18), TOBN(0x6d6c5f17, 0x689f4e79), + TOBN(0x7a544d91, 0xb24ff1b6), TOBN(0x3e12a5eb, 0xfe16cd8c), + TOBN(0x543574e9, 0xa56b872f), TOBN(0xa1ad550c, 0xfcf68ea2), + TOBN(0x689e37d2, 0x3f560ef7), TOBN(0x8c54b9ca, 0xc9d47a8b), + TOBN(0x46d40a4a, 0x088ac342), TOBN(0xec450c7c, 0x1576c6d0), + TOBN(0xb589e31c, 0x1f9689e9), TOBN(0xdacf2602, 0xb8781718), + TOBN(0xa89237c6, 0xc8cb6b42), TOBN(0x1326fc93, 0xb96ef381), + TOBN(0x55d56c6d, 0xb5f07825), TOBN(0xacba2eea, 0x7449e22d), + TOBN(0x74e0887a, 0x633c3000), TOBN(0xcb6cd172, 0xd7cbcf71), + TOBN(0x309e81de, 0xc36cf1be), TOBN(0x07a18a6d, 0x60ae399b), + TOBN(0xb36c2679, 0x9edce57e), TOBN(0x52b892f4, 0xdf001d41), + TOBN(0xd884ae5d, 0x16a1f2c6), TOBN(0x9b329424, 0xefcc370a), + TOBN(0x3120daf2, 0xbd2e21df), TOBN(0x55298d2d, 0x02470a99), + TOBN(0x0b78af6c, 0xa05db32e), TOBN(0x5c76a331, 0x601f5636), + TOBN(0xaae861ff, 0xf8a4f29c), TOBN(0x70dc9240, 0xd68f8d49), + TOBN(0x960e649f, 0x81b1321c), TOBN(0x3d2c801b, 0x8792e4ce), + TOBN(0xf479f772, 0x42521876), TOBN(0x0bed93bc, 0x416c79b1), + TOBN(0xa67fbc05, 0x263e5bc9), TOBN(0x01e8e630, 0x521db049), + TOBN(0x76f26738, 0xc6f3431e), TOBN(0xe609cb02, 0xe3267541), + TOBN(0xb10cff2d, 0x818c877c), TOBN(0x1f0e75ce, 0x786a13cb), + TOBN(0xf4fdca64, 0x1158544d), TOBN(0x5d777e89, 0x6cb71ed0), + TOBN(0x3c233737, 0xa9aa4755), TOBN(0x7b453192, 0xe527ab40), + TOBN(0xdb59f688, 0x39f05ffe), TOBN(0x8f4f4be0, 0x6d82574e), + TOBN(0xcce3450c, 0xee292d1b), TOBN(0xaa448a12, 0x61ccd086), + TOBN(0xabce91b3, 0xf7914967), TOBN(0x4537f09b, 0x1908a5ed), + TOBN(0xa812421e, 0xf51042e7), TOBN(0xfaf5cebc, 0xec0b3a34), + TOBN(0x730ffd87, 0x4ca6b39a), TOBN(0x70fb72ed, 0x02efd342), + TOBN(0xeb4735f9, 0xd75c8edb), TOBN(0xc11f2157, 0xc278aa51), + TOBN(0xc459f635, 0xbf3bfebf), TOBN(0x3a1ff0b4, 0x6bd9601f), + TOBN(0xc9d12823, 0xc420cb73), TOBN(0x3e9af3e2, 0x3c2915a3), + TOBN(0xe0c82c72, 0xb41c3440), TOBN(0x175239e5, 0xe3039a5f), + TOBN(0xe1084b8a, 0x558795a3), TOBN(0x328d0a1d, 0xd01e5c60), + TOBN(0x0a495f2e, 0xd3788a04), TOBN(0x25d8ff16, 0x66c11a9f), + TOBN(0xf5155f05, 0x9ed692d6), TOBN(0x954fa107, 0x4f425fe4), + TOBN(0xd16aabf2, 0xe98aaa99), TOBN(0x90cd8ba0, 0x96b0f88a), + TOBN(0x957f4782, 0xc154026a), TOBN(0x54ee0734, 0x52af56d2), + TOBN(0xbcf89e54, 0x45b4147a), TOBN(0x3d102f21, 0x9a52816c), + TOBN(0x6808517e, 0x39b62e77), TOBN(0x92e25421, 0x69169ad8), + TOBN(0xd721d871, 0xbb608558), TOBN(0x60e4ebae, 0xf6d4ff9b), + TOBN(0x0ba10819, 0x41f2763e), TOBN(0xca2e45be, 0x51ee3247), + TOBN(0x66d172ec, 0x2bfd7a5f), TOBN(0x528a8f2f, 0x74d0b12d), + TOBN(0xe17f1e38, 0xdabe70dc), TOBN(0x1d5d7316, 0x9f93983c), + TOBN(0x51b2184a, 0xdf423e31), TOBN(0xcb417291, 0xaedb1a10), + TOBN(0x2054ca93, 0x625bcab9), TOBN(0x54396860, 0xa98998f0), + TOBN(0x4e53f6c4, 0xa54ae57e), TOBN(0x0ffeb590, 0xee648e9d), + TOBN(0xfbbdaadc, 0x6afaf6bc), TOBN(0xf88ae796, 0xaa3bfb8a), + TOBN(0x209f1d44, 0xd2359ed9), TOBN(0xac68dd03, 0xf3544ce2), + TOBN(0xf378da47, 0xfd51e569), TOBN(0xe1abd860, 0x2cc80097), + TOBN(0x23ca18d9, 0x343b6e3a), TOBN(0x480797e8, 0xb40a1bae), + TOBN(0xd1f0c717, 0x533f3e67), TOBN(0x44896970, 0x06e6cdfc), + TOBN(0x8ca21055, 0x52a82e8d), TOBN(0xb2caf785, 0x78460cdc), + TOBN(0x4c1b7b62, 0xe9037178), TOBN(0xefc09d2c, 0xdb514b58), + TOBN(0x5f2df9ee, 0x9113be5c), TOBN(0x2fbda78f, 0xb3f9271c), + TOBN(0xe09a81af, 0x8f83fc54), TOBN(0x06b13866, 0x8afb5141), + TOBN(0x38f6480f, 0x43e3865d), TOBN(0x72dd77a8, 0x1ddf47d9), + TOBN(0xf2a8e971, 0x4c205ff7), TOBN(0x46d449d8, 0x9d088ad8), + TOBN(0x926619ea, 0x185d706f), TOBN(0xe47e02eb, 0xc7dd7f62), + TOBN(0xe7f120a7, 0x8cbc2031), TOBN(0xc18bef00, 0x998d4ac9), + TOBN(0x18f37a9c, 0x6bdf22da), TOBN(0xefbc432f, 0x90dc82df), + TOBN(0xc52cef8e, 0x5d703651), TOBN(0x82887ba0, 0xd99881a5), + TOBN(0x7cec9dda, 0xb920ec1d), TOBN(0xd0d7e8c3, 0xec3e8d3b), + TOBN(0x445bc395, 0x4ca88747), TOBN(0xedeaa2e0, 0x9fd53535), + TOBN(0x461b1d93, 0x6cc87475), TOBN(0xd92a52e2, 0x6d2383bd), + TOBN(0xfabccb59, 0xd7903546), TOBN(0x6111a761, 0x3d14b112), + TOBN(0x0ae584fe, 0xb3d5f612), TOBN(0x5ea69b8d, 0x60e828ec), + TOBN(0x6c078985, 0x54087030), TOBN(0x649cab04, 0xac4821fe), + TOBN(0x25ecedcf, 0x8bdce214), TOBN(0xb5622f72, 0x86af7361), + TOBN(0x0e1227aa, 0x7038b9e2), TOBN(0xd0efb273, 0xac20fa77), + TOBN(0x817ff88b, 0x79df975b), TOBN(0x856bf286, 0x1999503e), + TOBN(0xb4d5351f, 0x5038ec46), TOBN(0x740a52c5, 0xfc42af6e), + TOBN(0x2e38bb15, 0x2cbb1a3f), TOBN(0xc3eb99fe, 0x17a83429), + TOBN(0xca4fcbf1, 0xdd66bb74), TOBN(0x880784d6, 0xcde5e8fc), + TOBN(0xddc84c1c, 0xb4e7a0be), TOBN(0x8780510d, 0xbd15a72f), + TOBN(0x44bcf1af, 0x81ec30e1), TOBN(0x141e50a8, 0x0a61073e), + TOBN(0x0d955718, 0x47be87ae), TOBN(0x68a61417, 0xf76a4372), + TOBN(0xf57e7e87, 0xc607c3d3), TOBN(0x043afaf8, 0x5252f332), + TOBN(0xcc14e121, 0x1552a4d2), TOBN(0xb6dee692, 0xbb4d4ab4), + TOBN(0xb6ab74c8, 0xa03816a4), TOBN(0x84001ae4, 0x6f394a29), + TOBN(0x5bed8344, 0xd795fb45), TOBN(0x57326e7d, 0xb79f55a5), + TOBN(0xc9533ce0, 0x4accdffc), TOBN(0x53473caf, 0x3993fa04), + TOBN(0x7906eb93, 0xa13df4c8), TOBN(0xa73e51f6, 0x97cbe46f), + TOBN(0xd1ab3ae1, 0x0ae4ccf8), TOBN(0x25614508, 0x8a5b3dbc), + TOBN(0x61eff962, 0x11a71b27), TOBN(0xdf71412b, 0x6bb7fa39), + TOBN(0xb31ba6b8, 0x2bd7f3ef), TOBN(0xb0b9c415, 0x69180d29), + TOBN(0xeec14552, 0x014cdde5), TOBN(0x702c624b, 0x227b4bbb), + TOBN(0x2b15e8c2, 0xd3e988f3), TOBN(0xee3bcc6d, 0xa4f7fd04), + TOBN(0x9d00822a, 0x42ac6c85), TOBN(0x2db0cea6, 0x1df9f2b7), + TOBN(0xd7cad2ab, 0x42de1e58), TOBN(0x346ed526, 0x2d6fbb61), + TOBN(0xb3962995, 0x1a2faf09), TOBN(0x2fa8a580, 0x7c25612e), + TOBN(0x30ae04da, 0x7cf56490), TOBN(0x75662908, 0x0eea3961), + TOBN(0x3609f5c5, 0x3d080847), TOBN(0xcb081d39, 0x5241d4f6), + TOBN(0xb4fb3810, 0x77961a63), TOBN(0xc20c5984, 0x2abb66fc), + TOBN(0x3d40aa7c, 0xf902f245), TOBN(0x9cb12736, 0x4e536b1e), + TOBN(0x5eda24da, 0x99b3134f), TOBN(0xafbd9c69, 0x5cd011af), + TOBN(0x9a16e30a, 0xc7088c7d), TOBN(0x5ab65710, 0x3207389f), + TOBN(0x1b09547f, 0xe7407a53), TOBN(0x2322f9d7, 0x4fdc6eab), + TOBN(0xc0f2f22d, 0x7430de4d), TOBN(0x19382696, 0xe68ca9a9), + TOBN(0x17f1eff1, 0x918e5868), TOBN(0xe3b5b635, 0x586f4204), + TOBN(0x146ef980, 0x3fbc4341), TOBN(0x359f2c80, 0x5b5eed4e), + TOBN(0x9f35744e, 0x7482e41d), TOBN(0x9a9ac3ec, 0xf3b224c2), + TOBN(0x9161a6fe, 0x91fc50ae), TOBN(0x89ccc66b, 0xc613fa7c), + TOBN(0x89268b14, 0xc732f15a), TOBN(0x7cd6f4e2, 0xb467ed03), + TOBN(0xfbf79869, 0xce56b40e), TOBN(0xf93e094c, 0xc02dde98), + TOBN(0xefe0c3a8, 0xedee2cd7), TOBN(0x90f3ffc0, 0xb268fd42), + TOBN(0x81a7fd56, 0x08241aed), TOBN(0x95ab7ad8, 0x00b1afe8), + TOBN(0x40127056, 0x3e310d52), TOBN(0xd3ffdeb1, 0x09d9fc43), + TOBN(0xc8f85c91, 0xd11a8594), TOBN(0x2e74d258, 0x31cf6db8), + TOBN(0x829c7ca3, 0x02b5dfd0), TOBN(0xe389cfbe, 0x69143c86), + TOBN(0xd01b6405, 0x941768d8), TOBN(0x45103995, 0x03bf825d), + TOBN(0xcc4ee166, 0x56cd17e2), TOBN(0xbea3c283, 0xba037e79), + TOBN(0x4e1ac06e, 0xd9a47520), TOBN(0xfbfe18aa, 0xaf852404), + TOBN(0x5615f8e2, 0x8087648a), TOBN(0x7301e47e, 0xb9d150d9), + TOBN(0x79f9f9dd, 0xb299b977), TOBN(0x76697a7b, 0xa5b78314), + TOBN(0x10d67468, 0x7d7c90e7), TOBN(0x7afffe03, 0x937210b5), + TOBN(0x5aef3e4b, 0x28c22cee), TOBN(0xefb0ecd8, 0x09fd55ae), + TOBN(0x4cea7132, 0x0d2a5d6a), TOBN(0x9cfb5fa1, 0x01db6357), + TOBN(0x395e0b57, 0xf36e1ac5), TOBN(0x008fa9ad, 0x36cafb7d), + TOBN(0x8f6cdf70, 0x5308c4db), TOBN(0x51527a37, 0x95ed2477), + TOBN(0xba0dee30, 0x5bd21311), TOBN(0x6ed41b22, 0x909c90d7), + TOBN(0xc5f6b758, 0x7c8696d3), TOBN(0x0db8eaa8, 0x3ce83a80), + TOBN(0xd297fe37, 0xb24b4b6f), TOBN(0xfe58afe8, 0x522d1f0d), + TOBN(0x97358736, 0x8c98dbd9), TOBN(0x6bc226ca, 0x9454a527), + TOBN(0xa12b384e, 0xce53c2d0), TOBN(0x779d897d, 0x5e4606da), + TOBN(0xa53e47b0, 0x73ec12b0), TOBN(0x462dbbba, 0x5756f1ad), + TOBN(0x69fe09f2, 0xcafe37b6), TOBN(0x273d1ebf, 0xecce2e17), + TOBN(0x8ac1d538, 0x3cf607fd), TOBN(0x8035f7ff, 0x12e10c25)}, + {TOBN(0x854d34c7, 0x7e6c5520), TOBN(0xc27df9ef, 0xdcb9ea58), + TOBN(0x405f2369, 0xd686666d), TOBN(0x29d1febf, 0x0417aa85), + TOBN(0x9846819e, 0x93470afe), TOBN(0x3e6a9669, 0xe2a27f9e), + TOBN(0x24d008a2, 0xe31e6504), TOBN(0xdba7cecf, 0x9cb7680a), + TOBN(0xecaff541, 0x338d6e43), TOBN(0x56f7dd73, 0x4541d5cc), + TOBN(0xb5d426de, 0x96bc88ca), TOBN(0x48d94f6b, 0x9ed3a2c3), + TOBN(0x6354a3bb, 0x2ef8279c), TOBN(0xd575465b, 0x0b1867f2), + TOBN(0xef99b0ff, 0x95225151), TOBN(0xf3e19d88, 0xf94500d8), + TOBN(0x92a83268, 0xe32dd620), TOBN(0x913ec99f, 0x627849a2), + TOBN(0xedd8fdfa, 0x2c378882), TOBN(0xaf96f33e, 0xee6f8cfe), + TOBN(0xc06737e5, 0xdc3fa8a5), TOBN(0x236bb531, 0xb0b03a1d), + TOBN(0x33e59f29, 0x89f037b0), TOBN(0x13f9b5a7, 0xd9a12a53), + TOBN(0x0d0df6ce, 0x51efb310), TOBN(0xcb5b2eb4, 0x958df5be), + TOBN(0xd6459e29, 0x36158e59), TOBN(0x82aae2b9, 0x1466e336), + TOBN(0xfb658a39, 0x411aa636), TOBN(0x7152ecc5, 0xd4c0a933), + TOBN(0xf10c758a, 0x49f026b7), TOBN(0xf4837f97, 0xcb09311f), + TOBN(0xddfb02c4, 0xc753c45f), TOBN(0x18ca81b6, 0xf9c840fe), + TOBN(0x846fd09a, 0xb0f8a3e6), TOBN(0xb1162add, 0xe7733dbc), + TOBN(0x7070ad20, 0x236e3ab6), TOBN(0xf88cdaf5, 0xb2a56326), + TOBN(0x05fc8719, 0x997cbc7a), TOBN(0x442cd452, 0x4b665272), + TOBN(0x7807f364, 0xb71698f5), TOBN(0x6ba418d2, 0x9f7b605e), + TOBN(0xfd20b00f, 0xa03b2cbb), TOBN(0x883eca37, 0xda54386f), + TOBN(0xff0be43f, 0xf3437f24), TOBN(0xe910b432, 0xa48bb33c), + TOBN(0x4963a128, 0x329df765), TOBN(0xac1dd556, 0xbe2fe6f7), + TOBN(0x557610f9, 0x24a0a3fc), TOBN(0x38e17bf4, 0xe881c3f9), + TOBN(0x6ba84faf, 0xed0dac99), TOBN(0xd4a222c3, 0x59eeb918), + TOBN(0xc79c1dbe, 0x13f542b6), TOBN(0x1fc65e0d, 0xe425d457), + TOBN(0xeffb754f, 0x1debb779), TOBN(0x638d8fd0, 0x9e08af60), + TOBN(0x994f523a, 0x626332d5), TOBN(0x7bc38833, 0x5561bb44), + TOBN(0x005ed4b0, 0x3d845ea2), TOBN(0xd39d3ee1, 0xc2a1f08a), + TOBN(0x6561fdd3, 0xe7676b0d), TOBN(0x620e35ff, 0xfb706017), + TOBN(0x36ce424f, 0xf264f9a8), TOBN(0xc4c3419f, 0xda2681f7), + TOBN(0xfb6afd2f, 0x69beb6e8), TOBN(0x3a50b993, 0x6d700d03), + TOBN(0xc840b2ad, 0x0c83a14f), TOBN(0x573207be, 0x54085bef), + TOBN(0x5af882e3, 0x09fe7e5b), TOBN(0x957678a4, 0x3b40a7e1), + TOBN(0x172d4bdd, 0x543056e2), TOBN(0x9c1b26b4, 0x0df13c0a), + TOBN(0x1c30861c, 0xf405ff06), TOBN(0xebac86bd, 0x486e828b), + TOBN(0xe791a971, 0x636933fc), TOBN(0x50e7c2be, 0x7aeee947), + TOBN(0xc3d4a095, 0xfa90d767), TOBN(0xae60eb7b, 0xe670ab7b), + TOBN(0x17633a64, 0x397b056d), TOBN(0x93a21f33, 0x105012aa), + TOBN(0x663c370b, 0xabb88643), TOBN(0x91df36d7, 0x22e21599), + TOBN(0x183ba835, 0x8b761671), TOBN(0x381eea1d, 0x728f3bf1), + TOBN(0xb9b2f1ba, 0x39966e6c), TOBN(0x7c464a28, 0xe7295492), + TOBN(0x0fd5f70a, 0x09b26b7f), TOBN(0xa9aba1f9, 0xfbe009df), + TOBN(0x857c1f22, 0x369b87ad), TOBN(0x3c00e5d9, 0x32fca556), + TOBN(0x1ad74cab, 0x90b06466), TOBN(0xa7112386, 0x550faaf2), + TOBN(0x7435e198, 0x6d9bd5f5), TOBN(0x2dcc7e38, 0x59c3463f), + TOBN(0xdc7df748, 0xca7bd4b2), TOBN(0x13cd4c08, 0x9dec2f31), + TOBN(0x0d3b5df8, 0xe3237710), TOBN(0x0dadb26e, 0xcbd2f7b0), + TOBN(0x9f5966ab, 0xe4aa082b), TOBN(0x666ec8de, 0x350e966e), + TOBN(0x1bfd1ed5, 0xee524216), TOBN(0xcd93c59b, 0x41dab0b6), + TOBN(0x658a8435, 0xd186d6ba), TOBN(0x1b7d34d2, 0x159d1195), + TOBN(0x5936e460, 0x22caf46b), TOBN(0x6a45dd8f, 0x9a96fe4f), + TOBN(0xf7925434, 0xb98f474e), TOBN(0x41410412, 0x0053ef15), + TOBN(0x71cf8d12, 0x41de97bf), TOBN(0xb8547b61, 0xbd80bef4), + TOBN(0xb47d3970, 0xc4db0037), TOBN(0xf1bcd328, 0xfef20dff), + TOBN(0x31a92e09, 0x10caad67), TOBN(0x1f591960, 0x5531a1e1), + TOBN(0x3bb852e0, 0x5f4fc840), TOBN(0x63e297ca, 0x93a72c6c), + TOBN(0x3c2b0b2e, 0x49abad67), TOBN(0x6ec405fc, 0xed3db0d9), + TOBN(0xdc14a530, 0x7fef1d40), TOBN(0xccd19846, 0x280896fc), + TOBN(0x00f83176, 0x9bb81648), TOBN(0xd69eb485, 0x653120d0), + TOBN(0xd17d75f4, 0x4ccabc62), TOBN(0x34a07f82, 0xb749fcb1), + TOBN(0x2c3af787, 0xbbfb5554), TOBN(0xb06ed4d0, 0x62e283f8), + TOBN(0x5722889f, 0xa19213a0), TOBN(0x162b085e, 0xdcf3c7b4), + TOBN(0xbcaecb31, 0xe0dd3eca), TOBN(0xc6237fbc, 0xe52f13a5), + TOBN(0xcc2b6b03, 0x27bac297), TOBN(0x2ae1cac5, 0xb917f54a), + TOBN(0x474807d4, 0x7845ae4f), TOBN(0xfec7dd92, 0xce5972e0), + TOBN(0xc3bd2541, 0x1d7915bb), TOBN(0x66f85dc4, 0xd94907ca), + TOBN(0xd981b888, 0xbdbcf0ca), TOBN(0xd75f5da6, 0xdf279e9f), + TOBN(0x128bbf24, 0x7054e934), TOBN(0x3c6ff6e5, 0x81db134b), + TOBN(0x795b7cf4, 0x047d26e4), TOBN(0xf370f7b8, 0x5049ec37), + TOBN(0xc6712d4d, 0xced945af), TOBN(0xdf30b5ec, 0x095642bc), + TOBN(0x9b034c62, 0x4896246e), TOBN(0x5652c016, 0xee90bbd1), + TOBN(0xeb38636f, 0x87fedb73), TOBN(0x5e32f847, 0x0135a613), + TOBN(0x0703b312, 0xcf933c83), TOBN(0xd05bb76e, 0x1a7f47e6), + TOBN(0x825e4f0c, 0x949c2415), TOBN(0x569e5622, 0x7250d6f8), + TOBN(0xbbe9eb3a, 0x6568013e), TOBN(0x8dbd203f, 0x22f243fc), + TOBN(0x9dbd7694, 0xb342734a), TOBN(0x8f6d12f8, 0x46afa984), + TOBN(0xb98610a2, 0xc9eade29), TOBN(0xbab4f323, 0x47dd0f18), + TOBN(0x5779737b, 0x671c0d46), TOBN(0x10b6a7c6, 0xd3e0a42a), + TOBN(0xfb19ddf3, 0x3035b41c), TOBN(0xd336343f, 0x99c45895), + TOBN(0x61fe4938, 0x54c857e5), TOBN(0xc4d506be, 0xae4e57d5), + TOBN(0x3cd8c8cb, 0xbbc33f75), TOBN(0x7281f08a, 0x9262c77d), + TOBN(0x083f4ea6, 0xf11a2823), TOBN(0x8895041e, 0x9fba2e33), + TOBN(0xfcdfea49, 0x9c438edf), TOBN(0x7678dcc3, 0x91edba44), + TOBN(0xf07b3b87, 0xe2ba50f0), TOBN(0xc13888ef, 0x43948c1b), + TOBN(0xc2135ad4, 0x1140af42), TOBN(0x8e5104f3, 0x926ed1a7), + TOBN(0xf24430cb, 0x88f6695f), TOBN(0x0ce0637b, 0x6d73c120), + TOBN(0xb2db01e6, 0xfe631e8f), TOBN(0x1c5563d7, 0xd7bdd24b), + TOBN(0x8daea3ba, 0x369ad44f), TOBN(0x000c81b6, 0x8187a9f9), + TOBN(0x5f48a951, 0xaae1fd9a), TOBN(0xe35626c7, 0x8d5aed8a), + TOBN(0x20952763, 0x0498c622), TOBN(0x76d17634, 0x773aa504), + TOBN(0x36d90dda, 0xeb300f7a), TOBN(0x9dcf7dfc, 0xedb5e801), + TOBN(0x645cb268, 0x74d5244c), TOBN(0xa127ee79, 0x348e3aa2), + TOBN(0x488acc53, 0x575f1dbb), TOBN(0x95037e85, 0x80e6161e), + TOBN(0x57e59283, 0x292650d0), TOBN(0xabe67d99, 0x14938216), + TOBN(0x3c7f944b, 0x3f8e1065), TOBN(0xed908cb6, 0x330e8924), + TOBN(0x08ee8fd5, 0x6f530136), TOBN(0x2227b7d5, 0xd7ffc169), + TOBN(0x4f55c893, 0xb5cd6dd5), TOBN(0x82225e11, 0xa62796e8), + TOBN(0x5c6cead1, 0xcb18e12c), TOBN(0x4381ae0c, 0x84f5a51a), + TOBN(0x345913d3, 0x7fafa4c8), TOBN(0x3d918082, 0x0491aac0), + TOBN(0x9347871f, 0x3e69264c), TOBN(0xbea9dd3c, 0xb4f4f0cd), + TOBN(0xbda5d067, 0x3eadd3e7), TOBN(0x0033c1b8, 0x0573bcd8), + TOBN(0x25589379, 0x5da2486c), TOBN(0xcb89ee5b, 0x86abbee7), + TOBN(0x8fe0a8f3, 0x22532e5d), TOBN(0xb6410ff0, 0x727dfc4c), + TOBN(0x619b9d58, 0x226726db), TOBN(0x5ec25669, 0x7a2b2dc7), + TOBN(0xaf4d2e06, 0x4c3beb01), TOBN(0x852123d0, 0x7acea556), + TOBN(0x0e9470fa, 0xf783487a), TOBN(0x75a7ea04, 0x5664b3eb), + TOBN(0x4ad78f35, 0x6798e4ba), TOBN(0x9214e6e5, 0xc7d0e091), + TOBN(0xc420b488, 0xb1290403), TOBN(0x64049e0a, 0xfc295749), + TOBN(0x03ef5af1, 0x3ae9841f), TOBN(0xdbe4ca19, 0xb0b662a6), + TOBN(0x46845c5f, 0xfa453458), TOBN(0xf8dabf19, 0x10b66722), + TOBN(0xb650f0aa, 0xcce2793b), TOBN(0x71db851e, 0xc5ec47c1), + TOBN(0x3eb78f3e, 0x3b234fa9), TOBN(0xb0c60f35, 0xfc0106ce), + TOBN(0x05427121, 0x774eadbd), TOBN(0x25367faf, 0xce323863), + TOBN(0x7541b5c9, 0xcd086976), TOBN(0x4ff069e2, 0xdc507ad1), + TOBN(0x74145256, 0x8776e667), TOBN(0x6e76142c, 0xb23c6bb5), + TOBN(0xdbf30712, 0x1b3a8a87), TOBN(0x60e7363e, 0x98450836), + TOBN(0x5741450e, 0xb7366d80), TOBN(0xe4ee14ca, 0x4837dbdf), + TOBN(0xa765eb9b, 0x69d4316f), TOBN(0x04548dca, 0x8ef43825), + TOBN(0x9c9f4e4c, 0x5ae888eb), TOBN(0x733abb51, 0x56e9ac99), + TOBN(0xdaad3c20, 0xba6ac029), TOBN(0x9b8dd3d3, 0x2ba3e38e), + TOBN(0xa9bb4c92, 0x0bc5d11a), TOBN(0xf20127a7, 0x9c5f88a3), + TOBN(0x4f52b06e, 0x161d3cb8), TOBN(0x26c1ff09, 0x6afaf0a6), + TOBN(0x32670d2f, 0x7189e71f), TOBN(0xc6438748, 0x5ecf91e7), + TOBN(0x15758e57, 0xdb757a21), TOBN(0x427d09f8, 0x290a9ce5), + TOBN(0x846a308f, 0x38384a7a), TOBN(0xaac3acb4, 0xb0732b99), + TOBN(0x9e941009, 0x17845819), TOBN(0x95cba111, 0xa7ce5e03), + TOBN(0x6f3d4f7f, 0xb00009c4), TOBN(0xb8396c27, 0x8ff28b5f), + TOBN(0xb1a9ae43, 0x1c97975d), TOBN(0x9d7ba8af, 0xe5d9fed5), + TOBN(0x338cf09f, 0x34f485b6), TOBN(0xbc0ddacc, 0x64122516), + TOBN(0xa450da12, 0x05d471fe), TOBN(0x4c3a6250, 0x628dd8c9), + TOBN(0x69c7d103, 0xd1295837), TOBN(0xa2893e50, 0x3807eb2f), + TOBN(0xd6e1e1de, 0xbdb41491), TOBN(0xc630745b, 0x5e138235), + TOBN(0xc892109e, 0x48661ae1), TOBN(0x8d17e7eb, 0xea2b2674), + TOBN(0x00ec0f87, 0xc328d6b5), TOBN(0x6d858645, 0xf079ff9e), + TOBN(0x6cdf243e, 0x19115ead), TOBN(0x1ce1393e, 0x4bac4fcf), + TOBN(0x2c960ed0, 0x9c29f25b), TOBN(0x59be4d8e, 0x9d388a05), + TOBN(0x0d46e06c, 0xd0def72b), TOBN(0xb923db5d, 0xe0342748), + TOBN(0xf7d3aacd, 0x936d4a3d), TOBN(0x558519cc, 0x0b0b099e), + TOBN(0x3ea8ebf8, 0x827097ef), TOBN(0x259353db, 0xd054f55d), + TOBN(0x84c89abc, 0x6d2ed089), TOBN(0x5c548b69, 0x8e096a7c), + TOBN(0xd587f616, 0x994b995d), TOBN(0x4d1531f6, 0xa5845601), + TOBN(0x792ab31e, 0x451fd9f0), TOBN(0xc8b57bb2, 0x65adf6ca), + TOBN(0x68440fcb, 0x1cd5ad73), TOBN(0xb9c860e6, 0x6144da4f), + TOBN(0x2ab286aa, 0x8462beb8), TOBN(0xcc6b8fff, 0xef46797f), + TOBN(0xac820da4, 0x20c8a471), TOBN(0x69ae05a1, 0x77ff7faf), + TOBN(0xb9163f39, 0xbfb5da77), TOBN(0xbd03e590, 0x2c73ab7a), + TOBN(0x7e862b5e, 0xb2940d9e), TOBN(0x3c663d86, 0x4b9af564), + TOBN(0xd8309031, 0xbde3033d), TOBN(0x298231b2, 0xd42c5bc6), + TOBN(0x42090d2c, 0x552ad093), TOBN(0xa4799d1c, 0xff854695), + TOBN(0x0a88b5d6, 0xd31f0d00), TOBN(0xf8b40825, 0xa2f26b46), + TOBN(0xec29b1ed, 0xf1bd7218), TOBN(0xd491c53b, 0x4b24c86e), + TOBN(0xd2fe588f, 0x3395ea65), TOBN(0x6f3764f7, 0x4456ef15), + TOBN(0xdb43116d, 0xcdc34800), TOBN(0xcdbcd456, 0xc1e33955), + TOBN(0xefdb5540, 0x74ab286b), TOBN(0x948c7a51, 0xd18c5d7c), + TOBN(0xeb81aa37, 0x7378058e), TOBN(0x41c746a1, 0x04411154), + TOBN(0xa10c73bc, 0xfb828ac7), TOBN(0x6439be91, 0x9d972b29), + TOBN(0x4bf3b4b0, 0x43a2fbad), TOBN(0x39e6dadf, 0x82b5e840), + TOBN(0x4f716408, 0x6397bd4c), TOBN(0x0f7de568, 0x7f1eeccb), + TOBN(0x5865c5a1, 0xd2ffbfc1), TOBN(0xf74211fa, 0x4ccb6451), + TOBN(0x66368a88, 0xc0b32558), TOBN(0x5b539dc2, 0x9ad7812e), + TOBN(0x579483d0, 0x2f3af6f6), TOBN(0x52132078, 0x99934ece), + TOBN(0x50b9650f, 0xdcc9e983), TOBN(0xca989ec9, 0xaee42b8a), + TOBN(0x6a44c829, 0xd6f62f99), TOBN(0x8f06a309, 0x4c2a7c0c), + TOBN(0x4ea2b3a0, 0x98a0cb0a), TOBN(0x5c547b70, 0xbeee8364), + TOBN(0x461d40e1, 0x682afe11), TOBN(0x9e0fc77a, 0x7b41c0a8), + TOBN(0x79e4aefd, 0xe20d5d36), TOBN(0x2916e520, 0x32dd9f63), + TOBN(0xf59e52e8, 0x3f883faf), TOBN(0x396f9639, 0x2b868d35), + TOBN(0xc902a9df, 0x4ca19881), TOBN(0x0fc96822, 0xdb2401a6), + TOBN(0x41237587, 0x66f1c68d), TOBN(0x10fc6de3, 0xfb476c0d), + TOBN(0xf8b6b579, 0x841f5d90), TOBN(0x2ba8446c, 0xfa24f44a), + TOBN(0xa237b920, 0xef4a9975), TOBN(0x60bb6004, 0x2330435f), + TOBN(0xd6f4ab5a, 0xcfb7e7b5), TOBN(0xb2ac5097, 0x83435391), + TOBN(0xf036ee2f, 0xb0d1ea67), TOBN(0xae779a6a, 0x74c56230), + TOBN(0x59bff8c8, 0xab838ae6), TOBN(0xcd83ca99, 0x9b38e6f0), + TOBN(0xbb27bef5, 0xe33deed3), TOBN(0xe6356f6f, 0x001892a8), + TOBN(0xbf3be6cc, 0x7adfbd3e), TOBN(0xaecbc81c, 0x33d1ac9d), + TOBN(0xe4feb909, 0xe6e861dc), TOBN(0x90a247a4, 0x53f5f801), + TOBN(0x01c50acb, 0x27346e57), TOBN(0xce29242e, 0x461acc1b), + TOBN(0x04dd214a, 0x2f998a91), TOBN(0x271ee9b1, 0xd4baf27b), + TOBN(0x7e3027d1, 0xe8c26722), TOBN(0x21d1645c, 0x1820dce5), + TOBN(0x086f242c, 0x7501779c), TOBN(0xf0061407, 0xfa0e8009), + TOBN(0xf23ce477, 0x60187129), TOBN(0x05bbdedb, 0x0fde9bd0), + TOBN(0x682f4832, 0x25d98473), TOBN(0xf207fe85, 0x5c658427), + TOBN(0xb6fdd7ba, 0x4166ffa1), TOBN(0x0c314056, 0x9eed799d), + TOBN(0x0db8048f, 0x4107e28f), TOBN(0x74ed3871, 0x41216840), + TOBN(0x74489f8f, 0x56a3c06e), TOBN(0x1e1c005b, 0x12777134), + TOBN(0xdb332a73, 0xf37ec3c3), TOBN(0xc65259bd, 0xdd59eba0), + TOBN(0x2291709c, 0xdb4d3257), TOBN(0x9a793b25, 0xbd389390), + TOBN(0xf39fe34b, 0xe43756f0), TOBN(0x2f76bdce, 0x9afb56c9), + TOBN(0x9f37867a, 0x61208b27), TOBN(0xea1d4307, 0x089972c3), + TOBN(0x8c595330, 0x8bdf623a), TOBN(0x5f5accda, 0x8441fb7d), + TOBN(0xfafa9418, 0x32ddfd95), TOBN(0x6ad40c5a, 0x0fde9be7), + TOBN(0x43faba89, 0xaeca8709), TOBN(0xc64a7cf1, 0x2c248a9d), + TOBN(0x16620252, 0x72637a76), TOBN(0xaee1c791, 0x22b8d1bb), + TOBN(0xf0f798fd, 0x21a843b2), TOBN(0x56e4ed4d, 0x8d005cb1), + TOBN(0x355f7780, 0x1f0d8abe), TOBN(0x197b04cf, 0x34522326), + TOBN(0x41f9b31f, 0xfd42c13f), TOBN(0x5ef7feb2, 0xb40f933d), + TOBN(0x27326f42, 0x5d60bad4), TOBN(0x027ecdb2, 0x8c92cf89), + TOBN(0x04aae4d1, 0x4e3352fe), TOBN(0x08414d2f, 0x73591b90), + TOBN(0x5ed6124e, 0xb7da7d60), TOBN(0xb985b931, 0x4d13d4ec), + TOBN(0xa592d3ab, 0x96bf36f9), TOBN(0x012dbed5, 0xbbdf51df), + TOBN(0xa57963c0, 0xdf6c177d), TOBN(0x010ec869, 0x87ca29cf), + TOBN(0xba1700f6, 0xbf926dff), TOBN(0x7c9fdbd1, 0xf4bf6bc2), + TOBN(0xdc18dc8f, 0x64da11f5), TOBN(0xa6074b7a, 0xd938ae75), + TOBN(0x14270066, 0xe84f44a4), TOBN(0x99998d38, 0xd27b954e), + TOBN(0xc1be8ab2, 0xb4f38e9a), TOBN(0x8bb55bbf, 0x15c01016), + TOBN(0xf73472b4, 0x0ea2ab30), TOBN(0xd365a340, 0xf73d68dd), + TOBN(0xc01a7168, 0x19c2e1eb), TOBN(0x32f49e37, 0x34061719), + TOBN(0xb73c57f1, 0x01d8b4d6), TOBN(0x03c8423c, 0x26b47700), + TOBN(0x321d0bc8, 0xa4d8826a), TOBN(0x6004213c, 0x4bc0e638), + TOBN(0xf78c64a1, 0xc1c06681), TOBN(0x16e0a16f, 0xef018e50), + TOBN(0x31cbdf91, 0xdb42b2b3), TOBN(0xf8f4ffce, 0xe0d36f58), + TOBN(0xcdcc71cd, 0x4cc5e3e0), TOBN(0xd55c7cfa, 0xa129e3e0), + TOBN(0xccdb6ba0, 0x0fb2cbf1), TOBN(0x6aba0005, 0xc4bce3cb), + TOBN(0x501cdb30, 0xd232cfc4), TOBN(0x9ddcf12e, 0xd58a3cef), + TOBN(0x02d2cf9c, 0x87e09149), TOBN(0xdc5d7ec7, 0x2c976257), + TOBN(0x6447986e, 0x0b50d7dd), TOBN(0x88fdbaf7, 0x807f112a), + TOBN(0x58c9822a, 0xb00ae9f6), TOBN(0x6abfb950, 0x6d3d27e0), + TOBN(0xd0a74487, 0x8a429f4f), TOBN(0x0649712b, 0xdb516609), + TOBN(0xb826ba57, 0xe769b5df), TOBN(0x82335df2, 0x1fc7aaf2), + TOBN(0x2389f067, 0x5c93d995), TOBN(0x59ac367a, 0x68677be6), + TOBN(0xa77985ff, 0x21d9951b), TOBN(0x038956fb, 0x85011cce), + TOBN(0x608e48cb, 0xbb734e37), TOBN(0xc08c0bf2, 0x2be5b26f), + TOBN(0x17bbdd3b, 0xf9b1a0d9), TOBN(0xeac7d898, 0x10483319), + TOBN(0xc95c4baf, 0xbc1a6dea), TOBN(0xfdd0e2bf, 0x172aafdb), + TOBN(0x40373cbc, 0x8235c41a), TOBN(0x14303f21, 0xfb6f41d5), + TOBN(0xba063621, 0x0408f237), TOBN(0xcad3b09a, 0xecd2d1ed), + TOBN(0x4667855a, 0x52abb6a2), TOBN(0xba9157dc, 0xaa8b417b), + TOBN(0xfe7f3507, 0x4f013efb), TOBN(0x1b112c4b, 0xaa38c4a2), + TOBN(0xa1406a60, 0x9ba64345), TOBN(0xe53cba33, 0x6993c80b), + TOBN(0x45466063, 0xded40d23), TOBN(0x3d5f1f4d, 0x54908e25), + TOBN(0x9ebefe62, 0x403c3c31), TOBN(0x274ea0b5, 0x0672a624), + TOBN(0xff818d99, 0x451d1b71), TOBN(0x80e82643, 0x8f79cf79), + TOBN(0xa165df13, 0x73ce37f5), TOBN(0xa744ef4f, 0xfe3a21fd), + TOBN(0x73f1e7f5, 0xcf551396), TOBN(0xc616898e, 0x868c676b), + TOBN(0x671c28c7, 0x8c442c36), TOBN(0xcfe5e558, 0x5e0a317d), + TOBN(0x1242d818, 0x7051f476), TOBN(0x56fad2a6, 0x14f03442), + TOBN(0x262068bc, 0x0a44d0f6), TOBN(0xdfa2cd6e, 0xce6edf4e), + TOBN(0x0f43813a, 0xd15d1517), TOBN(0x61214cb2, 0x377d44f5), + TOBN(0xd399aa29, 0xc639b35f), TOBN(0x42136d71, 0x54c51c19), + TOBN(0x9774711b, 0x08417221), TOBN(0x0a5546b3, 0x52545a57), + TOBN(0x80624c41, 0x1150582d), TOBN(0x9ec5c418, 0xfbc555bc), + TOBN(0x2c87dcad, 0x771849f1), TOBN(0xb0c932c5, 0x01d7bf6f), + TOBN(0x6aa5cd3e, 0x89116eb2), TOBN(0xd378c25a, 0x51ca7bd3), + TOBN(0xc612a0da, 0x9e6e3e31), TOBN(0x0417a54d, 0xb68ad5d0), + TOBN(0x00451e4a, 0x22c6edb8), TOBN(0x9fbfe019, 0xb42827ce), + TOBN(0x2fa92505, 0xba9384a2), TOBN(0x21b8596e, 0x64ad69c1), + TOBN(0x8f4fcc49, 0x983b35a6), TOBN(0xde093760, 0x72754672), + TOBN(0x2f14ccc8, 0xf7bffe6d), TOBN(0x27566bff, 0x5d94263d), + TOBN(0xb5b4e9c6, 0x2df3ec30), TOBN(0x94f1d7d5, 0x3e6ea6ba), + TOBN(0x97b7851a, 0xaaca5e9b), TOBN(0x518aa521, 0x56713b97), + TOBN(0x3357e8c7, 0x150a61f6), TOBN(0x7842e7e2, 0xec2c2b69), + TOBN(0x8dffaf65, 0x6868a548), TOBN(0xd963bd82, 0xe068fc81), + TOBN(0x64da5c8b, 0x65917733), TOBN(0x927090ff, 0x7b247328)}, + {TOBN(0x214bc9a7, 0xd298c241), TOBN(0xe3b697ba, 0x56807cfd), + TOBN(0xef1c7802, 0x4564eadb), TOBN(0xdde8cdcf, 0xb48149c5), + TOBN(0x946bf0a7, 0x5a4d2604), TOBN(0x27154d7f, 0x6c1538af), + TOBN(0x95cc9230, 0xde5b1fcc), TOBN(0xd88519e9, 0x66864f82), + TOBN(0xb828dd1a, 0x7cb1282c), TOBN(0xa08d7626, 0xbe46973a), + TOBN(0x6baf8d40, 0xe708d6b2), TOBN(0x72571fa1, 0x4daeb3f3), + TOBN(0x85b1732f, 0xf22dfd98), TOBN(0x87ab01a7, 0x0087108d), + TOBN(0xaaaafea8, 0x5988207a), TOBN(0xccc832f8, 0x69f00755), + TOBN(0x964d950e, 0x36ff3bf0), TOBN(0x8ad20f6f, 0xf0b34638), + TOBN(0x4d9177b3, 0xb5d7585f), TOBN(0xcf839760, 0xef3f019f), + TOBN(0x582fc5b3, 0x8288c545), TOBN(0x2f8e4e9b, 0x13116bd1), + TOBN(0xf91e1b2f, 0x332120ef), TOBN(0xcf568724, 0x2a17dd23), + TOBN(0x488f1185, 0xca8d9d1a), TOBN(0xadf2c77d, 0xd987ded2), + TOBN(0x5f3039f0, 0x60c46124), TOBN(0xe5d70b75, 0x71e095f4), + TOBN(0x82d58650, 0x6260e70f), TOBN(0x39d75ea7, 0xf750d105), + TOBN(0x8cf3d0b1, 0x75bac364), TOBN(0xf3a7564d, 0x21d01329), + TOBN(0x182f04cd, 0x2f52d2a7), TOBN(0x4fde149a, 0xe2df565a), + TOBN(0xb80c5eec, 0xa79fb2f7), TOBN(0xab491d7b, 0x22ddc897), + TOBN(0x99d76c18, 0xc6312c7f), TOBN(0xca0d5f3d, 0x6aa41a57), + TOBN(0x71207325, 0xd15363a0), TOBN(0xe82aa265, 0xbeb252c2), + TOBN(0x94ab4700, 0xec3128c2), TOBN(0x6c76d862, 0x8e383f49), + TOBN(0xdc36b150, 0xc03024eb), TOBN(0xfb439477, 0x53daac69), + TOBN(0xfc68764a, 0x8dc79623), TOBN(0x5b86995d, 0xb440fbb2), + TOBN(0xd66879bf, 0xccc5ee0d), TOBN(0x05228942, 0x95aa8bd3), + TOBN(0xb51a40a5, 0x1e6a75c1), TOBN(0x24327c76, 0x0ea7d817), + TOBN(0x06630182, 0x07774597), TOBN(0xd6fdbec3, 0x97fa7164), + TOBN(0x20c99dfb, 0x13c90f48), TOBN(0xd6ac5273, 0x686ef263), + TOBN(0xc6a50bdc, 0xfef64eeb), TOBN(0xcd87b281, 0x86fdfc32), + TOBN(0xb24aa43e, 0x3fcd3efc), TOBN(0xdd26c034, 0xb8088e9a), + TOBN(0xa5ef4dc9, 0xbd3d46ea), TOBN(0xa2f99d58, 0x8a4c6a6f), + TOBN(0xddabd355, 0x2f1da46c), TOBN(0x72c3f8ce, 0x1afacdd1), + TOBN(0xd90c4eee, 0x92d40578), TOBN(0xd28bb41f, 0xca623b94), + TOBN(0x50fc0711, 0x745edc11), TOBN(0x9dd9ad7d, 0x3dc87558), + TOBN(0xce6931fb, 0xb49d1e64), TOBN(0x6c77a0a2, 0xc98bd0f9), + TOBN(0x62b9a629, 0x6baf7cb1), TOBN(0xcf065f91, 0xccf72d22), + TOBN(0x7203cce9, 0x79639071), TOBN(0x09ae4885, 0xf9cb732f), + TOBN(0x5e7c3bec, 0xee8314f3), TOBN(0x1c068aed, 0xdbea298f), + TOBN(0x08d381f1, 0x7c80acec), TOBN(0x03b56be8, 0xe330495b), + TOBN(0xaeffb8f2, 0x9222882d), TOBN(0x95ff38f6, 0xc4af8bf7), + TOBN(0x50e32d35, 0x1fc57d8c), TOBN(0x6635be52, 0x17b444f0), + TOBN(0x04d15276, 0xa5177900), TOBN(0x4e1dbb47, 0xf6858752), + TOBN(0x5b475622, 0xc615796c), TOBN(0xa6fa0387, 0x691867bf), + TOBN(0xed7f5d56, 0x2844c6d0), TOBN(0xc633cf9b, 0x03a2477d), + TOBN(0xf6be5c40, 0x2d3721d6), TOBN(0xaf312eb7, 0xe9fd68e6), + TOBN(0x242792d2, 0xe7417ce1), TOBN(0xff42bc71, 0x970ee7f5), + TOBN(0x1ff4dc6d, 0x5c67a41e), TOBN(0x77709b7b, 0x20882a58), + TOBN(0x3554731d, 0xbe217f2c), TOBN(0x2af2a8cd, 0x5bb72177), + TOBN(0x58eee769, 0x591dd059), TOBN(0xbb2930c9, 0x4bba6477), + TOBN(0x863ee047, 0x7d930cfc), TOBN(0x4c262ad1, 0x396fd1f4), + TOBN(0xf4765bc8, 0x039af7e1), TOBN(0x2519834b, 0x5ba104f6), + TOBN(0x7cd61b4c, 0xd105f961), TOBN(0xa5415da5, 0xd63bca54), + TOBN(0x778280a0, 0x88a1f17c), TOBN(0xc4968949, 0x2329512c), + TOBN(0x174a9126, 0xcecdaa7a), TOBN(0xfc8c7e0e, 0x0b13247b), + TOBN(0x29c110d2, 0x3484c1c4), TOBN(0xf8eb8757, 0x831dfc3b), + TOBN(0x022f0212, 0xc0067452), TOBN(0x3f6f69ee, 0x7b9b926c), + TOBN(0x09032da0, 0xef42daf4), TOBN(0x79f00ade, 0x83f80de4), + TOBN(0x6210db71, 0x81236c97), TOBN(0x74f7685b, 0x3ee0781f), + TOBN(0x4df7da7b, 0xa3e41372), TOBN(0x2aae38b1, 0xb1a1553e), + TOBN(0x1688e222, 0xf6dd9d1b), TOBN(0x57695448, 0x5b8b6487), + TOBN(0x478d2127, 0x4b2edeaa), TOBN(0xb2818fa5, 0x1e85956a), + TOBN(0x1e6addda, 0xf176f2c0), TOBN(0x01ca4604, 0xe2572658), + TOBN(0x0a404ded, 0x85342ffb), TOBN(0x8cf60f96, 0x441838d6), + TOBN(0x9bbc691c, 0xc9071c4a), TOBN(0xfd588744, 0x34442803), + TOBN(0x97101c85, 0x809c0d81), TOBN(0xa7fb754c, 0x8c456f7f), + TOBN(0xc95f3c5c, 0xd51805e1), TOBN(0xab4ccd39, 0xb299dca8), + TOBN(0x3e03d20b, 0x47eaf500), TOBN(0xfa3165c1, 0xd7b80893), + TOBN(0x005e8b54, 0xe160e552), TOBN(0xdc4972ba, 0x9019d11f), + TOBN(0x21a6972e, 0x0c9a4a7a), TOBN(0xa52c258f, 0x37840fd7), + TOBN(0xf8559ff4, 0xc1e99d81), TOBN(0x08e1a7d6, 0xa3c617c0), + TOBN(0xb398fd43, 0x248c6ba7), TOBN(0x6ffedd91, 0xd1283794), + TOBN(0x8a6a59d2, 0xd629d208), TOBN(0xa9d141d5, 0x3490530e), + TOBN(0x42f6fc18, 0x38505989), TOBN(0x09bf250d, 0x479d94ee), + TOBN(0x223ad3b1, 0xb3822790), TOBN(0x6c5926c0, 0x93b8971c), + TOBN(0x609efc7e, 0x75f7fa62), TOBN(0x45d66a6d, 0x1ec2d989), + TOBN(0x4422d663, 0x987d2792), TOBN(0x4a73caad, 0x3eb31d2b), + TOBN(0xf06c2ac1, 0xa32cb9e6), TOBN(0xd9445c5f, 0x91aeba84), + TOBN(0x6af7a1d5, 0xaf71013f), TOBN(0xe68216e5, 0x0bedc946), + TOBN(0xf4cba30b, 0xd27370a0), TOBN(0x7981afbf, 0x870421cc), + TOBN(0x02496a67, 0x9449f0e1), TOBN(0x86cfc4be, 0x0a47edae), + TOBN(0x3073c936, 0xb1feca22), TOBN(0xf5694612, 0x03f8f8fb), + TOBN(0xd063b723, 0x901515ea), TOBN(0x4c6c77a5, 0x749cf038), + TOBN(0x6361e360, 0xab9e5059), TOBN(0x596cf171, 0xa76a37c0), + TOBN(0x800f53fa, 0x6530ae7a), TOBN(0x0f5e631e, 0x0792a7a6), + TOBN(0x5cc29c24, 0xefdb81c9), TOBN(0xa269e868, 0x3f9c40ba), + TOBN(0xec14f9e1, 0x2cb7191e), TOBN(0x78ea1bd8, 0xe5b08ea6), + TOBN(0x3c65aa9b, 0x46332bb9), TOBN(0x84cc22b3, 0xbf80ce25), + TOBN(0x0098e9e9, 0xd49d5bf1), TOBN(0xcd4ec1c6, 0x19087da4), + TOBN(0x3c9d07c5, 0xaef6e357), TOBN(0x839a0268, 0x9f8f64b8), + TOBN(0xc5e9eb62, 0xc6d8607f), TOBN(0x759689f5, 0x6aa995e4), + TOBN(0x70464669, 0xbbb48317), TOBN(0x921474bf, 0xe402417d), + TOBN(0xcabe135b, 0x2a354c8c), TOBN(0xd51e52d2, 0x812fa4b5), + TOBN(0xec741096, 0x53311fe8), TOBN(0x4f774535, 0xb864514b), + TOBN(0xbcadd671, 0x5bde48f8), TOBN(0xc9703873, 0x2189bc7d), + TOBN(0x5d45299e, 0xc709ee8a), TOBN(0xd1287ee2, 0x845aaff8), + TOBN(0x7d1f8874, 0xdb1dbf1f), TOBN(0xea46588b, 0x990c88d6), + TOBN(0x60ba649a, 0x84368313), TOBN(0xd5fdcbce, 0x60d543ae), + TOBN(0x90b46d43, 0x810d5ab0), TOBN(0x6739d8f9, 0x04d7e5cc), + TOBN(0x021c1a58, 0x0d337c33), TOBN(0x00a61162, 0x68e67c40), + TOBN(0x95ef413b, 0x379f0a1f), TOBN(0xfe126605, 0xe9e2ab95), + TOBN(0x67578b85, 0x2f5f199c), TOBN(0xf5c00329, 0x2cb84913), + TOBN(0xf7956430, 0x37577dd8), TOBN(0x83b82af4, 0x29c5fe88), + TOBN(0x9c1bea26, 0xcdbdc132), TOBN(0x589fa086, 0x9c04339e), + TOBN(0x033e9538, 0xb13799df), TOBN(0x85fa8b21, 0xd295d034), + TOBN(0xdf17f73f, 0xbd9ddcca), TOBN(0xf32bd122, 0xddb66334), + TOBN(0x55ef88a7, 0x858b044c), TOBN(0x1f0d69c2, 0x5aa9e397), + TOBN(0x55fd9cc3, 0x40d85559), TOBN(0xc774df72, 0x7785ddb2), + TOBN(0x5dcce9f6, 0xd3bd2e1c), TOBN(0xeb30da20, 0xa85dfed0), + TOBN(0x5ed7f5bb, 0xd3ed09c4), TOBN(0x7d42a35c, 0x82a9c1bd), + TOBN(0xcf3de995, 0x9890272d), TOBN(0x75f3432a, 0x3e713a10), + TOBN(0x5e13479f, 0xe28227b8), TOBN(0xb8561ea9, 0xfefacdc8), + TOBN(0xa6a297a0, 0x8332aafd), TOBN(0x9b0d8bb5, 0x73809b62), + TOBN(0xd2fa1cfd, 0x0c63036f), TOBN(0x7a16eb55, 0xbd64bda8), + TOBN(0x3f5cf5f6, 0x78e62ddc), TOBN(0x2267c454, 0x07fd752b), + TOBN(0x5e361b6b, 0x5e437bbe), TOBN(0x95c59501, 0x8354e075), + TOBN(0xec725f85, 0xf2b254d9), TOBN(0x844b617d, 0x2cb52b4e), + TOBN(0xed8554f5, 0xcf425fb5), TOBN(0xab67703e, 0x2af9f312), + TOBN(0x4cc34ec1, 0x3cf48283), TOBN(0xb09daa25, 0x9c8a705e), + TOBN(0xd1e9d0d0, 0x5b7d4f84), TOBN(0x4df6ef64, 0xdb38929d), + TOBN(0xe16b0763, 0xaa21ba46), TOBN(0xc6b1d178, 0xa293f8fb), + TOBN(0x0ff5b602, 0xd520aabf), TOBN(0x94d671bd, 0xc339397a), + TOBN(0x7c7d98cf, 0x4f5792fa), TOBN(0x7c5e0d67, 0x11215261), + TOBN(0x9b19a631, 0xa7c5a6d4), TOBN(0xc8511a62, 0x7a45274d), + TOBN(0x0c16621c, 0xa5a60d99), TOBN(0xf7fbab88, 0xcf5e48cb), + TOBN(0xab1e6ca2, 0xf7ddee08), TOBN(0x83bd08ce, 0xe7867f3c), + TOBN(0xf7e48e8a, 0x2ac13e27), TOBN(0x4494f6df, 0x4eb1a9f5), + TOBN(0xedbf84eb, 0x981f0a62), TOBN(0x49badc32, 0x536438f0), + TOBN(0x50bea541, 0x004f7571), TOBN(0xbac67d10, 0xdf1c94ee), + TOBN(0x253d73a1, 0xb727bc31), TOBN(0xb3d01cf2, 0x30686e28), + TOBN(0x51b77b1b, 0x55fd0b8b), TOBN(0xa099d183, 0xfeec3173), + TOBN(0x202b1fb7, 0x670e72b7), TOBN(0xadc88b33, 0xa8e1635f), + TOBN(0x34e8216a, 0xf989d905), TOBN(0xc2e68d20, 0x29b58d01), + TOBN(0x11f81c92, 0x6fe55a93), TOBN(0x15f1462a, 0x8f296f40), + TOBN(0x1915d375, 0xea3d62f2), TOBN(0xa17765a3, 0x01c8977d), + TOBN(0x7559710a, 0xe47b26f6), TOBN(0xe0bd29c8, 0x535077a5), + TOBN(0x615f976d, 0x08d84858), TOBN(0x370dfe85, 0x69ced5c1), + TOBN(0xbbc7503c, 0xa734fa56), TOBN(0xfbb9f1ec, 0x91ac4574), + TOBN(0x95d7ec53, 0x060dd7ef), TOBN(0xeef2dacd, 0x6e657979), + TOBN(0x54511af3, 0xe2a08235), TOBN(0x1e324aa4, 0x1f4aea3d), + TOBN(0x550e7e71, 0xe6e67671), TOBN(0xbccd5190, 0xbf52faf7), + TOBN(0xf880d316, 0x223cc62a), TOBN(0x0d402c7e, 0x2b32eb5d), + TOBN(0xa40bc039, 0x306a5a3b), TOBN(0x4e0a41fd, 0x96783a1b), + TOBN(0xa1e8d39a, 0x0253cdd4), TOBN(0x6480be26, 0xc7388638), + TOBN(0xee365e1d, 0x2285f382), TOBN(0x188d8d8f, 0xec0b5c36), + TOBN(0x34ef1a48, 0x1f0f4d82), TOBN(0x1a8f43e1, 0xa487d29a), + TOBN(0x8168226d, 0x77aefb3a), TOBN(0xf69a751e, 0x1e72c253), + TOBN(0x8e04359a, 0xe9594df1), TOBN(0x475ffd7d, 0xd14c0467), + TOBN(0xb5a2c2b1, 0x3844e95c), TOBN(0x85caf647, 0xdd12ef94), + TOBN(0x1ecd2a9f, 0xf1063d00), TOBN(0x1dd2e229, 0x23843311), + TOBN(0x38f0e09d, 0x73d17244), TOBN(0x3ede7746, 0x8fc653f1), + TOBN(0xae4459f5, 0xdc20e21c), TOBN(0x00db2ffa, 0x6a8599ea), + TOBN(0x11682c39, 0x30cfd905), TOBN(0x4934d074, 0xa5c112a6), + TOBN(0xbdf063c5, 0x568bfe95), TOBN(0x779a440a, 0x016c441a), + TOBN(0x0c23f218, 0x97d6fbdc), TOBN(0xd3a5cd87, 0xe0776aac), + TOBN(0xcee37f72, 0xd712e8db), TOBN(0xfb28c70d, 0x26f74e8d), + TOBN(0xffe0c728, 0xb61301a0), TOBN(0xa6282168, 0xd3724354), + TOBN(0x7ff4cb00, 0x768ffedc), TOBN(0xc51b3088, 0x03b02de9), + TOBN(0xa5a8147c, 0x3902dda5), TOBN(0x35d2f706, 0xfe6973b4), + TOBN(0x5ac2efcf, 0xc257457e), TOBN(0x933f48d4, 0x8700611b), + TOBN(0xc365af88, 0x4912beb2), TOBN(0x7f5a4de6, 0x162edf94), + TOBN(0xc646ba7c, 0x0c32f34b), TOBN(0x632c6af3, 0xb2091074), + TOBN(0x58d4f2e3, 0x753e43a9), TOBN(0x70e1d217, 0x24d4e23f), + TOBN(0xb24bf729, 0xafede6a6), TOBN(0x7f4a94d8, 0x710c8b60), + TOBN(0xaad90a96, 0x8d4faa6a), TOBN(0xd9ed0b32, 0xb066b690), + TOBN(0x52fcd37b, 0x78b6dbfd), TOBN(0x0b64615e, 0x8bd2b431), + TOBN(0x228e2048, 0xcfb9fad5), TOBN(0xbeaa386d, 0x240b76bd), + TOBN(0x2d6681c8, 0x90dad7bc), TOBN(0x3e553fc3, 0x06d38f5e), + TOBN(0xf27cdb9b, 0x9d5f9750), TOBN(0x3e85c52a, 0xd28c5b0e), + TOBN(0x190795af, 0x5247c39b), TOBN(0x547831eb, 0xbddd6828), + TOBN(0xf327a227, 0x4a82f424), TOBN(0x36919c78, 0x7e47f89d), + TOBN(0xe4783919, 0x43c7392c), TOBN(0xf101b9aa, 0x2316fefe), + TOBN(0xbcdc9e9c, 0x1c5009d2), TOBN(0xfb55ea13, 0x9cd18345), + TOBN(0xf5b5e231, 0xa3ce77c7), TOBN(0xde6b4527, 0xd2f2cb3d), + TOBN(0x10f6a333, 0x9bb26f5f), TOBN(0x1e85db8e, 0x044d85b6), + TOBN(0xc3697a08, 0x94197e54), TOBN(0x65e18cc0, 0xa7cb4ea8), + TOBN(0xa38c4f50, 0xa471fe6e), TOBN(0xf031747a, 0x2f13439c), + TOBN(0x53c4a6ba, 0xc007318b), TOBN(0xa8da3ee5, 0x1deccb3d), + TOBN(0x0555b31c, 0x558216b1), TOBN(0x90c7810c, 0x2f79e6c2), + TOBN(0x9b669f4d, 0xfe8eed3c), TOBN(0x70398ec8, 0xe0fac126), + TOBN(0xa96a449e, 0xf701b235), TOBN(0x0ceecdb3, 0xeb94f395), + TOBN(0x285fc368, 0xd0cb7431), TOBN(0x0d37bb52, 0x16a18c64), + TOBN(0x05110d38, 0xb880d2dd), TOBN(0xa60f177b, 0x65930d57), + TOBN(0x7da34a67, 0xf36235f5), TOBN(0x47f5e17c, 0x183816b9), + TOBN(0xc7664b57, 0xdb394af4), TOBN(0x39ba215d, 0x7036f789), + TOBN(0x46d2ca0e, 0x2f27b472), TOBN(0xc42647ee, 0xf73a84b7), + TOBN(0x44bc7545, 0x64488f1d), TOBN(0xaa922708, 0xf4cf85d5), + TOBN(0x721a01d5, 0x53e4df63), TOBN(0x649c0c51, 0x5db46ced), + TOBN(0x6bf0d64e, 0x3cffcb6c), TOBN(0xe3bf93fe, 0x50f71d96), + TOBN(0x75044558, 0xbcc194a0), TOBN(0x16ae3372, 0x6afdc554), + TOBN(0xbfc01adf, 0x5ca48f3f), TOBN(0x64352f06, 0xe22a9b84), + TOBN(0xcee54da1, 0xc1099e4a), TOBN(0xbbda54e8, 0xfa1b89c0), + TOBN(0x166a3df5, 0x6f6e55fb), TOBN(0x1ca44a24, 0x20176f88), + TOBN(0x936afd88, 0xdfb7b5ff), TOBN(0xe34c2437, 0x8611d4a0), + TOBN(0x7effbb75, 0x86142103), TOBN(0x6704ba1b, 0x1f34fc4d), + TOBN(0x7c2a468f, 0x10c1b122), TOBN(0x36b3a610, 0x8c6aace9), + TOBN(0xabfcc0a7, 0x75a0d050), TOBN(0x066f9197, 0x3ce33e32), + TOBN(0xce905ef4, 0x29fe09be), TOBN(0x89ee25ba, 0xa8376351), + TOBN(0x2a3ede22, 0xfd29dc76), TOBN(0x7fd32ed9, 0x36f17260), + TOBN(0x0cadcf68, 0x284b4126), TOBN(0x63422f08, 0xa7951fc8), + TOBN(0x562b24f4, 0x0807e199), TOBN(0xfe9ce5d1, 0x22ad4490), + TOBN(0xc2f51b10, 0x0db2b1b4), TOBN(0xeb3613ff, 0xe4541d0d), + TOBN(0xbd2c4a05, 0x2680813b), TOBN(0x527aa55d, 0x561b08d6), + TOBN(0xa9f8a40e, 0xa7205558), TOBN(0xe3eea56f, 0x243d0bec), + TOBN(0x7b853817, 0xa0ff58b3), TOBN(0xb67d3f65, 0x1a69e627), + TOBN(0x0b76bbb9, 0xa869b5d6), TOBN(0xa3afeb82, 0x546723ed), + TOBN(0x5f24416d, 0x3e554892), TOBN(0x8413b53d, 0x430e2a45), + TOBN(0x99c56aee, 0x9032a2a0), TOBN(0x09432bf6, 0xeec367b1), + TOBN(0x552850c6, 0xdaf0ecc1), TOBN(0x49ebce55, 0x5bc92048), + TOBN(0xdfb66ba6, 0x54811307), TOBN(0x1b84f797, 0x6f298597), + TOBN(0x79590481, 0x8d1d7a0d), TOBN(0xd9fabe03, 0x3a6fa556), + TOBN(0xa40f9c59, 0xba9e5d35), TOBN(0xcb1771c1, 0xf6247577), + TOBN(0x542a47ca, 0xe9a6312b), TOBN(0xa34b3560, 0x552dd8c5), + TOBN(0xfdf94de0, 0x0d794716), TOBN(0xd46124a9, 0x9c623094), + TOBN(0x56b7435d, 0x68afe8b4), TOBN(0x27f20540, 0x6c0d8ea1), + TOBN(0x12b77e14, 0x73186898), TOBN(0xdbc3dd46, 0x7479490f), + TOBN(0x951a9842, 0xc03b0c05), TOBN(0x8b1b3bb3, 0x7921bc96), + TOBN(0xa573b346, 0x2b202e0a), TOBN(0x77e4665d, 0x47254d56), + TOBN(0x08b70dfc, 0xd23e3984), TOBN(0xab86e8bc, 0xebd14236), + TOBN(0xaa3e07f8, 0x57114ba7), TOBN(0x5ac71689, 0xab0ef4f2), + TOBN(0x88fca384, 0x0139d9af), TOBN(0x72733f88, 0x76644af0), + TOBN(0xf122f72a, 0x65d74f4a), TOBN(0x13931577, 0xa5626c7a), + TOBN(0xd5b5d9eb, 0x70f8d5a4), TOBN(0x375adde7, 0xd7bbb228), + TOBN(0x31e88b86, 0x0c1c0b32), TOBN(0xd1f568c4, 0x173edbaa), + TOBN(0x1592fc83, 0x5459df02), TOBN(0x2beac0fb, 0x0fcd9a7e), + TOBN(0xb0a6fdb8, 0x1b473b0a), TOBN(0xe3224c6f, 0x0fe8fc48), + TOBN(0x680bd00e, 0xe87edf5b), TOBN(0x30385f02, 0x20e77cf5), + TOBN(0xe9ab98c0, 0x4d42d1b2), TOBN(0x72d191d2, 0xd3816d77), + TOBN(0x1564daca, 0x0917d9e5), TOBN(0x394eab59, 0x1f8fed7f), + TOBN(0xa209aa8d, 0x7fbb3896), TOBN(0x5564f3b9, 0xbe6ac98e), + TOBN(0xead21d05, 0xd73654ef), TOBN(0x68d1a9c4, 0x13d78d74), + TOBN(0x61e01708, 0x6d4973a0), TOBN(0x83da3500, 0x46e6d32a), + TOBN(0x6a3dfca4, 0x68ae0118), TOBN(0xa1b9a4c9, 0xd02da069), + TOBN(0x0b2ff9c7, 0xebab8302), TOBN(0x98af07c3, 0x944ba436), + TOBN(0x85997326, 0x995f0f9f), TOBN(0x467fade0, 0x71b58bc6), + TOBN(0x47e4495a, 0xbd625a2b), TOBN(0xfdd2d01d, 0x33c3b8cd), + TOBN(0x2c38ae28, 0xc693f9fa), TOBN(0x48622329, 0x348f7999), + TOBN(0x97bf738e, 0x2161f583), TOBN(0x15ee2fa7, 0x565e8cc9), + TOBN(0xa1a5c845, 0x5777e189), TOBN(0xcc10bee0, 0x456f2829), + TOBN(0x8ad95c56, 0xda762bd5), TOBN(0x152e2214, 0xe9d91da8), + TOBN(0x975b0e72, 0x7cb23c74), TOBN(0xfd5d7670, 0xa90c66df), + TOBN(0xb5b5b8ad, 0x225ffc53), TOBN(0xab6dff73, 0xfaded2ae), + TOBN(0xebd56781, 0x6f4cbe9d), TOBN(0x0ed8b249, 0x6a574bd7), + TOBN(0x41c246fe, 0x81a881fa), TOBN(0x91564805, 0xc3db9c70), + TOBN(0xd7c12b08, 0x5b862809), TOBN(0x1facd1f1, 0x55858d7b), + TOBN(0x7693747c, 0xaf09e92a), TOBN(0x3b69dcba, 0x189a425f), + TOBN(0x0be28e9f, 0x967365ef), TOBN(0x57300eb2, 0xe801f5c9), + TOBN(0x93b8ac6a, 0xd583352f), TOBN(0xa2cf1f89, 0xcd05b2b7), + TOBN(0x7c0c9b74, 0x4dcc40cc), TOBN(0xfee38c45, 0xada523fb), + TOBN(0xb49a4dec, 0x1099cc4d), TOBN(0x325c377f, 0x69f069c6), + TOBN(0xe12458ce, 0x476cc9ff), TOBN(0x580e0b6c, 0xc6d4cb63), + TOBN(0xd561c8b7, 0x9072289b), TOBN(0x0377f264, 0xa619e6da), + TOBN(0x26685362, 0x88e591a5), TOBN(0xa453a7bd, 0x7523ca2b), + TOBN(0x8a9536d2, 0xc1df4533), TOBN(0xc8e50f2f, 0xbe972f79), + TOBN(0xd433e50f, 0x6d3549cf), TOBN(0x6f33696f, 0xfacd665e), + TOBN(0x695bfdac, 0xce11fcb4), TOBN(0x810ee252, 0xaf7c9860), + TOBN(0x65450fe1, 0x7159bb2c), TOBN(0xf7dfbebe, 0x758b357b), + TOBN(0x2b057e74, 0xd69fea72), TOBN(0xd485717a, 0x92731745)}, + {TOBN(0x896c42e8, 0xee36860c), TOBN(0xdaf04dfd, 0x4113c22d), + TOBN(0x1adbb7b7, 0x44104213), TOBN(0xe5fd5fa1, 0x1fd394ea), + TOBN(0x68235d94, 0x1a4e0551), TOBN(0x6772cfbe, 0x18d10151), + TOBN(0x276071e3, 0x09984523), TOBN(0xe4e879de, 0x5a56ba98), + TOBN(0xaaafafb0, 0x285b9491), TOBN(0x01a0be88, 0x1e4c705e), + TOBN(0xff1d4f5d, 0x2ad9caab), TOBN(0x6e349a4a, 0xc37a233f), + TOBN(0xcf1c1246, 0x4a1c6a16), TOBN(0xd99e6b66, 0x29383260), + TOBN(0xea3d4366, 0x5f6d5471), TOBN(0x36974d04, 0xff8cc89b), + TOBN(0xc26c49a1, 0xcfe89d80), TOBN(0xb42c026d, 0xda9c8371), + TOBN(0xca6c013a, 0xdad066d2), TOBN(0xfb8f7228, 0x56a4f3ee), + TOBN(0x08b579ec, 0xd850935b), TOBN(0x34c1a74c, 0xd631e1b3), + TOBN(0xcb5fe596, 0xac198534), TOBN(0x39ff21f6, 0xe1f24f25), + TOBN(0x27f29e14, 0x8f929057), TOBN(0x7a64ae06, 0xc0c853df), + TOBN(0x256cd183, 0x58e9c5ce), TOBN(0x9d9cce82, 0xded092a5), + TOBN(0xcc6e5979, 0x6e93b7c7), TOBN(0xe1e47092, 0x31bb9e27), + TOBN(0xb70b3083, 0xaa9e29a0), TOBN(0xbf181a75, 0x3785e644), + TOBN(0xf53f2c65, 0x8ead09f7), TOBN(0x1335e1d5, 0x9780d14d), + TOBN(0x69cc20e0, 0xcd1b66bc), TOBN(0x9b670a37, 0xbbe0bfc8), + TOBN(0xce53dc81, 0x28efbeed), TOBN(0x0c74e77c, 0x8326a6e5), + TOBN(0x3604e0d2, 0xb88e9a63), TOBN(0xbab38fca, 0x13dc2248), + TOBN(0x8ed6e8c8, 0x5c0a3f1e), TOBN(0xbcad2492, 0x7c87c37f), + TOBN(0xfdfb62bb, 0x9ee3b78d), TOBN(0xeba8e477, 0xcbceba46), + TOBN(0x37d38cb0, 0xeeaede4b), TOBN(0x0bc498e8, 0x7976deb6), + TOBN(0xb2944c04, 0x6b6147fb), TOBN(0x8b123f35, 0xf71f9609), + TOBN(0xa155dcc7, 0xde79dc24), TOBN(0xf1168a32, 0x558f69cd), + TOBN(0xbac21595, 0x0d1850df), TOBN(0x15c8295b, 0xb204c848), + TOBN(0xf661aa36, 0x7d8184ff), TOBN(0xc396228e, 0x30447bdb), + TOBN(0x11cd5143, 0xbde4a59e), TOBN(0xe3a26e3b, 0x6beab5e6), + TOBN(0xd3b3a13f, 0x1402b9d0), TOBN(0x573441c3, 0x2c7bc863), + TOBN(0x4b301ec4, 0x578c3e6e), TOBN(0xc26fc9c4, 0x0adaf57e), + TOBN(0x96e71bfd, 0x7493cea3), TOBN(0xd05d4b3f, 0x1af81456), + TOBN(0xdaca2a8a, 0x6a8c608f), TOBN(0x53ef07f6, 0x0725b276), + TOBN(0x07a5fbd2, 0x7824fc56), TOBN(0x34675218, 0x13289077), + TOBN(0x5bf69fd5, 0xe0c48349), TOBN(0xa613ddd3, 0xb6aa7875), + TOBN(0x7f78c19c, 0x5450d866), TOBN(0x46f4409c, 0x8f84a481), + TOBN(0x9f1d1928, 0x90fce239), TOBN(0x016c4168, 0xb2ce44b9), + TOBN(0xbae023f0, 0xc7435978), TOBN(0xb152c888, 0x20e30e19), + TOBN(0x9c241645, 0xe3fa6faf), TOBN(0x735d95c1, 0x84823e60), + TOBN(0x03197573, 0x03955317), TOBN(0x0b4b02a9, 0xf03b4995), + TOBN(0x076bf559, 0x70274600), TOBN(0x32c5cc53, 0xaaf57508), + TOBN(0xe8af6d1f, 0x60624129), TOBN(0xb7bc5d64, 0x9a5e2b5e), + TOBN(0x3814b048, 0x5f082d72), TOBN(0x76f267f2, 0xce19677a), + TOBN(0x626c630f, 0xb36eed93), TOBN(0x55230cd7, 0x3bf56803), + TOBN(0x78837949, 0xce2736a0), TOBN(0x0d792d60, 0xaa6c55f1), + TOBN(0x0318dbfd, 0xd5c7c5d2), TOBN(0xb38f8da7, 0x072b342d), + TOBN(0x3569bddc, 0x7b8de38a), TOBN(0xf25b5887, 0xa1c94842), + TOBN(0xb2d5b284, 0x2946ad60), TOBN(0x854f29ad, 0xe9d1707e), + TOBN(0xaa5159dc, 0x2c6a4509), TOBN(0x899f94c0, 0x57189837), + TOBN(0xcf6adc51, 0xf4a55b03), TOBN(0x261762de, 0x35e3b2d5), + TOBN(0x4cc43012, 0x04827b51), TOBN(0xcd22a113, 0xc6021442), + TOBN(0xce2fd61a, 0x247c9569), TOBN(0x59a50973, 0xd152beca), + TOBN(0x6c835a11, 0x63a716d4), TOBN(0xc26455ed, 0x187dedcf), + TOBN(0x27f536e0, 0x49ce89e7), TOBN(0x18908539, 0xcc890cb5), + TOBN(0x308909ab, 0xd83c2aa1), TOBN(0xecd3142b, 0x1ab73bd3), + TOBN(0x6a85bf59, 0xb3f5ab84), TOBN(0x3c320a68, 0xf2bea4c6), + TOBN(0xad8dc538, 0x6da4541f), TOBN(0xeaf34eb0, 0xb7c41186), + TOBN(0x1c780129, 0x977c97c4), TOBN(0x5ff9beeb, 0xc57eb9fa), + TOBN(0xa24d0524, 0xc822c478), TOBN(0xfd8eec2a, 0x461cd415), + TOBN(0xfbde194e, 0xf027458c), TOBN(0xb4ff5319, 0x1d1be115), + TOBN(0x63f874d9, 0x4866d6f4), TOBN(0x35c75015, 0xb21ad0c9), + TOBN(0xa6b5c9d6, 0x46ac49d2), TOBN(0x42c77c0b, 0x83137aa9), + TOBN(0x24d000fc, 0x68225a38), TOBN(0x0f63cfc8, 0x2fe1e907), + TOBN(0x22d1b01b, 0xc6441f95), TOBN(0x7d38f719, 0xec8e448f), + TOBN(0x9b33fa5f, 0x787fb1ba), TOBN(0x94dcfda1, 0x190158df), + TOBN(0xc47cb339, 0x5f6d4a09), TOBN(0x6b4f355c, 0xee52b826), + TOBN(0x3d100f5d, 0xf51b930a), TOBN(0xf4512fac, 0x9f668f69), + TOBN(0x546781d5, 0x206c4c74), TOBN(0xd021d4d4, 0xcb4d2e48), + TOBN(0x494a54c2, 0xca085c2d), TOBN(0xf1dbaca4, 0x520850a8), + TOBN(0x63c79326, 0x490a1aca), TOBN(0xcb64dd9c, 0x41526b02), + TOBN(0xbb772591, 0xa2979258), TOBN(0x3f582970, 0x48d97846), + TOBN(0xd66b70d1, 0x7c213ba7), TOBN(0xc28febb5, 0xe8a0ced4), + TOBN(0x6b911831, 0xc10338c1), TOBN(0x0d54e389, 0xbf0126f3), + TOBN(0x7048d460, 0x4af206ee), TOBN(0x786c88f6, 0x77e97cb9), + TOBN(0xd4375ae1, 0xac64802e), TOBN(0x469bcfe1, 0xd53ec11c), + TOBN(0xfc9b340d, 0x47062230), TOBN(0xe743bb57, 0xc5b4a3ac), + TOBN(0xfe00b4aa, 0x59ef45ac), TOBN(0x29a4ef23, 0x59edf188), + TOBN(0x40242efe, 0xb483689b), TOBN(0x2575d3f6, 0x513ac262), + TOBN(0xf30037c8, 0x0ca6db72), TOBN(0xc9fcce82, 0x98864be2), + TOBN(0x84a112ff, 0x0149362d), TOBN(0x95e57582, 0x1c4ae971), + TOBN(0x1fa4b1a8, 0x945cf86c), TOBN(0x4525a734, 0x0b024a2f), + TOBN(0xe76c8b62, 0x8f338360), TOBN(0x483ff593, 0x28edf32b), + TOBN(0x67e8e90a, 0x298b1aec), TOBN(0x9caab338, 0x736d9a21), + TOBN(0x5c09d2fd, 0x66892709), TOBN(0x2496b4dc, 0xb55a1d41), + TOBN(0x93f5fb1a, 0xe24a4394), TOBN(0x08c75049, 0x6fa8f6c1), + TOBN(0xcaead1c2, 0xc905d85f), TOBN(0xe9d7f790, 0x0733ae57), + TOBN(0x24c9a65c, 0xf07cdd94), TOBN(0x7389359c, 0xa4b55931), + TOBN(0xf58709b7, 0x367e45f7), TOBN(0x1f203067, 0xcb7e7adc), + TOBN(0x82444bff, 0xc7b72818), TOBN(0x07303b35, 0xbaac8033), + TOBN(0x1e1ee4e4, 0xd13b7ea1), TOBN(0xe6489b24, 0xe0e74180), + TOBN(0xa5f2c610, 0x7e70ef70), TOBN(0xa1655412, 0xbdd10894), + TOBN(0x555ebefb, 0x7af4194e), TOBN(0x533c1c3c, 0x8e89bd9c), + TOBN(0x735b9b57, 0x89895856), TOBN(0x15fb3cd2, 0x567f5c15), + TOBN(0x057fed45, 0x526f09fd), TOBN(0xe8a4f10c, 0x8128240a), + TOBN(0x9332efc4, 0xff2bfd8d), TOBN(0x214e77a0, 0xbd35aa31), + TOBN(0x32896d73, 0x14faa40e), TOBN(0x767867ec, 0x01e5f186), + TOBN(0xc9adf8f1, 0x17a1813e), TOBN(0xcb6cda78, 0x54741795), + TOBN(0xb7521b6d, 0x349d51aa), TOBN(0xf56b5a9e, 0xe3c7b8e9), + TOBN(0xc6f1e5c9, 0x32a096df), TOBN(0x083667c4, 0xa3635024), + TOBN(0x365ea135, 0x18087f2f), TOBN(0xf1b8eaac, 0xd136e45d), + TOBN(0xc8a0e484, 0x73aec989), TOBN(0xd75a324b, 0x142c9259), + TOBN(0xb7b4d001, 0x01dae185), TOBN(0x45434e0b, 0x9b7a94bc), + TOBN(0xf54339af, 0xfbd8cb0b), TOBN(0xdcc4569e, 0xe98ef49e), + TOBN(0x7789318a, 0x09a51299), TOBN(0x81b4d206, 0xb2b025d8), + TOBN(0xf64aa418, 0xfae85792), TOBN(0x3e50258f, 0xacd7baf7), + TOBN(0xdce84cdb, 0x2996864b), TOBN(0xa2e67089, 0x1f485fa4), + TOBN(0xb28b2bb6, 0x534c6a5a), TOBN(0x31a7ec6b, 0xc94b9d39), + TOBN(0x1d217766, 0xd6bc20da), TOBN(0x4acdb5ec, 0x86761190), + TOBN(0x68726328, 0x73701063), TOBN(0x4d24ee7c, 0x2128c29b), + TOBN(0xc072ebd3, 0xa19fd868), TOBN(0x612e481c, 0xdb8ddd3b), + TOBN(0xb4e1d754, 0x1a64d852), TOBN(0x00ef95ac, 0xc4c6c4ab), + TOBN(0x1536d2ed, 0xaa0a6c46), TOBN(0x61294086, 0x43774790), + TOBN(0x54af25e8, 0x343fda10), TOBN(0x9ff9d98d, 0xfd25d6f2), + TOBN(0x0746af7c, 0x468b8835), TOBN(0x977a31cb, 0x730ecea7), + TOBN(0xa5096b80, 0xc2cf4a81), TOBN(0xaa986833, 0x6458c37a), + TOBN(0x6af29bf3, 0xa6bd9d34), TOBN(0x6a62fe9b, 0x33c5d854), + TOBN(0x50e6c304, 0xb7133b5e), TOBN(0x04b60159, 0x7d6e6848), + TOBN(0x4cd296df, 0x5579bea4), TOBN(0x10e35ac8, 0x5ceedaf1), + TOBN(0x04c4c5fd, 0xe3bcc5b1), TOBN(0x95f9ee8a, 0x89412cf9), + TOBN(0x2c9459ee, 0x82b6eb0f), TOBN(0x2e845765, 0x95c2aadd), + TOBN(0x774a84ae, 0xd327fcfe), TOBN(0xd8c93722, 0x0368d476), + TOBN(0x0dbd5748, 0xf83e8a3b), TOBN(0xa579aa96, 0x8d2495f3), + TOBN(0x535996a0, 0xae496e9b), TOBN(0x07afbfe9, 0xb7f9bcc2), + TOBN(0x3ac1dc6d, 0x5b7bd293), TOBN(0x3b592cff, 0x7022323d), + TOBN(0xba0deb98, 0x9c0a3e76), TOBN(0x18e78e9f, 0x4b197acb), + TOBN(0x211cde10, 0x296c36ef), TOBN(0x7ee89672, 0x82c4da77), + TOBN(0xb617d270, 0xa57836da), TOBN(0xf0cd9c31, 0x9cb7560b), + TOBN(0x01fdcbf7, 0xe455fe90), TOBN(0x3fb53cbb, 0x7e7334f3), + TOBN(0x781e2ea4, 0x4e7de4ec), TOBN(0x8adab3ad, 0x0b384fd0), + TOBN(0x129eee2f, 0x53d64829), TOBN(0x7a471e17, 0xa261492b), + TOBN(0xe4f9adb9, 0xe4cb4a2c), TOBN(0x3d359f6f, 0x97ba2c2d), + TOBN(0x346c6786, 0x0aacd697), TOBN(0x92b444c3, 0x75c2f8a8), + TOBN(0xc79fa117, 0xd85df44e), TOBN(0x56782372, 0x398ddf31), + TOBN(0x60e690f2, 0xbbbab3b8), TOBN(0x4851f8ae, 0x8b04816b), + TOBN(0xc72046ab, 0x9c92e4d2), TOBN(0x518c74a1, 0x7cf3136b), + TOBN(0xff4eb50a, 0xf9877d4c), TOBN(0x14578d90, 0xa919cabb), + TOBN(0x8218f8c4, 0xac5eb2b6), TOBN(0xa3ccc547, 0x542016e4), + TOBN(0x025bf48e, 0x327f8349), TOBN(0xf3e97346, 0xf43cb641), + TOBN(0xdc2bafdf, 0x500f1085), TOBN(0x57167876, 0x2f063055), + TOBN(0x5bd914b9, 0x411925a6), TOBN(0x7c078d48, 0xa1123de5), + TOBN(0xee6bf835, 0x182b165d), TOBN(0xb11b5e5b, 0xba519727), + TOBN(0xe33ea76c, 0x1eea7b85), TOBN(0x2352b461, 0x92d4f85e), + TOBN(0xf101d334, 0xafe115bb), TOBN(0xfabc1294, 0x889175a3), + TOBN(0x7f6bcdc0, 0x5233f925), TOBN(0xe0a802db, 0xe77fec55), + TOBN(0xbdb47b75, 0x8069b659), TOBN(0x1c5e12de, 0xf98fbd74), + TOBN(0x869c58c6, 0x4b8457ee), TOBN(0xa5360f69, 0x4f7ea9f7), + TOBN(0xe576c09f, 0xf460b38f), TOBN(0x6b70d548, 0x22b7fb36), + TOBN(0x3fd237f1, 0x3bfae315), TOBN(0x33797852, 0xcbdff369), + TOBN(0x97df25f5, 0x25b516f9), TOBN(0x46f388f2, 0xba38ad2d), + TOBN(0x656c4658, 0x89d8ddbb), TOBN(0x8830b26e, 0x70f38ee8), + TOBN(0x4320fd5c, 0xde1212b0), TOBN(0xc34f30cf, 0xe4a2edb2), + TOBN(0xabb131a3, 0x56ab64b8), TOBN(0x7f77f0cc, 0xd99c5d26), + TOBN(0x66856a37, 0xbf981d94), TOBN(0x19e76d09, 0x738bd76e), + TOBN(0xe76c8ac3, 0x96238f39), TOBN(0xc0a482be, 0xa830b366), + TOBN(0xb7b8eaff, 0x0b4eb499), TOBN(0x8ecd83bc, 0x4bfb4865), + TOBN(0x971b2cb7, 0xa2f3776f), TOBN(0xb42176a4, 0xf4b88adf), + TOBN(0xb9617df5, 0xbe1fa446), TOBN(0x8b32d508, 0xcd031bd2), + TOBN(0x1c6bd47d, 0x53b618c0), TOBN(0xc424f46c, 0x6a227923), + TOBN(0x7303ffde, 0xdd92d964), TOBN(0xe9712878, 0x71b5abf2), + TOBN(0x8f48a632, 0xf815561d), TOBN(0x85f48ff5, 0xd3c055d1), + TOBN(0x222a1427, 0x7525684f), TOBN(0xd0d841a0, 0x67360cc3), + TOBN(0x4245a926, 0x0b9267c6), TOBN(0xc78913f1, 0xcf07f863), + TOBN(0xaa844c8e, 0x4d0d9e24), TOBN(0xa42ad522, 0x3d5f9017), + TOBN(0xbd371749, 0xa2c989d5), TOBN(0x928292df, 0xe1f5e78e), + TOBN(0x493b383e, 0x0a1ea6da), TOBN(0x5136fd8d, 0x13aee529), + TOBN(0x860c44b1, 0xf2c34a99), TOBN(0x3b00aca4, 0xbf5855ac), + TOBN(0xabf6aaa0, 0xfaaf37be), TOBN(0x65f43682, 0x2a53ec08), + TOBN(0x1d9a5801, 0xa11b12e1), TOBN(0x78a7ab2c, 0xe20ed475), + TOBN(0x0de1067e, 0x9a41e0d5), TOBN(0x30473f5f, 0x305023ea), + TOBN(0xdd3ae09d, 0x169c7d97), TOBN(0x5cd5baa4, 0xcfaef9cd), + TOBN(0x5cd7440b, 0x65a44803), TOBN(0xdc13966a, 0x47f364de), + TOBN(0x077b2be8, 0x2b8357c1), TOBN(0x0cb1b4c5, 0xe9d57c2a), + TOBN(0x7a4ceb32, 0x05ff363e), TOBN(0xf310fa4d, 0xca35a9ef), + TOBN(0xdbb7b352, 0xf97f68c6), TOBN(0x0c773b50, 0x0b02cf58), + TOBN(0xea2e4821, 0x3c1f96d9), TOBN(0xffb357b0, 0xeee01815), + TOBN(0xb9c924cd, 0xe0f28039), TOBN(0x0b36c95a, 0x46a3fbe4), + TOBN(0x1faaaea4, 0x5e46db6c), TOBN(0xcae575c3, 0x1928aaff), + TOBN(0x7f671302, 0xa70dab86), TOBN(0xfcbd12a9, 0x71c58cfc), + TOBN(0xcbef9acf, 0xbee0cb92), TOBN(0x573da0b9, 0xf8c1b583), + TOBN(0x4752fcfe, 0x0d41d550), TOBN(0xe7eec0e3, 0x2155cffe), + TOBN(0x0fc39fcb, 0x545ae248), TOBN(0x522cb8d1, 0x8065f44e), + TOBN(0x263c962a, 0x70cbb96c), TOBN(0xe034362a, 0xbcd124a9), + TOBN(0xf120db28, 0x3c2ae58d), TOBN(0xb9a38d49, 0xfef6d507), + TOBN(0xb1fd2a82, 0x1ff140fd), TOBN(0xbd162f30, 0x20aee7e0), + TOBN(0x4e17a5d4, 0xcb251949), TOBN(0x2aebcb83, 0x4f7e1c3d), + TOBN(0x608eb25f, 0x937b0527), TOBN(0xf42e1e47, 0xeb7d9997), + TOBN(0xeba699c4, 0xb8a53a29), TOBN(0x1f921c71, 0xe091b536), + TOBN(0xcce29e7b, 0x5b26bbd5), TOBN(0x7a8ef5ed, 0x3b61a680), + TOBN(0xe5ef8043, 0xba1f1c7e), TOBN(0x16ea8217, 0x18158dda), + TOBN(0x01778a2b, 0x599ff0f9), TOBN(0x68a923d7, 0x8104fc6b), + TOBN(0x5bfa44df, 0xda694ff3), TOBN(0x4f7199db, 0xf7667f12), + TOBN(0xc06d8ff6, 0xe46f2a79), TOBN(0x08b5dead, 0xe9f8131d), + TOBN(0x02519a59, 0xabb4ce7c), TOBN(0xc4f710bc, 0xb42aec3e), + TOBN(0x3d77b057, 0x78bde41a), TOBN(0x6474bf80, 0xb4186b5a), + TOBN(0x048b3f67, 0x88c65741), TOBN(0xc64519de, 0x03c7c154), + TOBN(0xdf073846, 0x0edfcc4f), TOBN(0x319aa737, 0x48f1aa6b), + TOBN(0x8b9f8a02, 0xca909f77), TOBN(0x90258139, 0x7580bfef), + TOBN(0xd8bfd3ca, 0xc0c22719), TOBN(0xc60209e4, 0xc9ca151e), + TOBN(0x7a744ab5, 0xd9a1a69c), TOBN(0x6de5048b, 0x14937f8f), + TOBN(0x171938d8, 0xe115ac04), TOBN(0x7df70940, 0x1c6b16d2), + TOBN(0xa6aeb663, 0x7f8e94e7), TOBN(0xc130388e, 0x2a2cf094), + TOBN(0x1850be84, 0x77f54e6e), TOBN(0x9f258a72, 0x65d60fe5), + TOBN(0xff7ff0c0, 0x6c9146d6), TOBN(0x039aaf90, 0xe63a830b), + TOBN(0x38f27a73, 0x9460342f), TOBN(0x4703148c, 0x3f795f8a), + TOBN(0x1bb5467b, 0x9681a97e), TOBN(0x00931ba5, 0xecaeb594), + TOBN(0xcdb6719d, 0x786f337c), TOBN(0xd9c01cd2, 0xe704397d), + TOBN(0x0f4a3f20, 0x555c2fef), TOBN(0x00452509, 0x7c0af223), + TOBN(0x54a58047, 0x84db8e76), TOBN(0x3bacf1aa, 0x93c8aa06), + TOBN(0x11ca957c, 0xf7919422), TOBN(0x50641053, 0x78cdaa40), + TOBN(0x7a303874, 0x9f7144ae), TOBN(0x170c963f, 0x43d4acfd), + TOBN(0x5e148149, 0x58ddd3ef), TOBN(0xa7bde582, 0x9e72dba8), + TOBN(0x0769da8b, 0x6fa68750), TOBN(0xfa64e532, 0x572e0249), + TOBN(0xfcaadf9d, 0x2619ad31), TOBN(0x87882daa, 0xa7b349cd), + TOBN(0x9f6eb731, 0x6c67a775), TOBN(0xcb10471a, 0xefc5d0b1), + TOBN(0xb433750c, 0xe1b806b2), TOBN(0x19c5714d, 0x57b1ae7e), + TOBN(0xc0dc8b7b, 0xed03fd3f), TOBN(0xdd03344f, 0x31bc194e), + TOBN(0xa66c52a7, 0x8c6320b5), TOBN(0x8bc82ce3, 0xd0b6fd93), + TOBN(0xf8e13501, 0xb35f1341), TOBN(0xe53156dd, 0x25a43e42), + TOBN(0xd3adf27e, 0x4daeb85c), TOBN(0xb81d8379, 0xbbeddeb5), + TOBN(0x1b0b546e, 0x2e435867), TOBN(0x9020eb94, 0xeba5dd60), + TOBN(0x37d91161, 0x8210cb9d), TOBN(0x4c596b31, 0x5c91f1cf), + TOBN(0xb228a90f, 0x0e0b040d), TOBN(0xbaf02d82, 0x45ff897f), + TOBN(0x2aac79e6, 0x00fa6122), TOBN(0x24828817, 0x8e36f557), + TOBN(0xb9521d31, 0x113ec356), TOBN(0x9e48861e, 0x15eff1f8), + TOBN(0x2aa1d412, 0xe0d41715), TOBN(0x71f86203, 0x53f131b8), + TOBN(0xf60da8da, 0x3fd19408), TOBN(0x4aa716dc, 0x278d9d99), + TOBN(0x394531f7, 0xa8c51c90), TOBN(0xb560b0e8, 0xf59db51c), + TOBN(0xa28fc992, 0xfa34bdad), TOBN(0xf024fa14, 0x9cd4f8bd), + TOBN(0x5cf530f7, 0x23a9d0d3), TOBN(0x615ca193, 0xe28c9b56), + TOBN(0x6d2a483d, 0x6f73c51e), TOBN(0xa4cb2412, 0xea0dc2dd), + TOBN(0x50663c41, 0x1eb917ff), TOBN(0x3d3a74cf, 0xeade299e), + TOBN(0x29b3990f, 0x4a7a9202), TOBN(0xa9bccf59, 0xa7b15c3d), + TOBN(0x66a3ccdc, 0xa5df9208), TOBN(0x48027c14, 0x43f2f929), + TOBN(0xd385377c, 0x40b557f0), TOBN(0xe001c366, 0xcd684660), + TOBN(0x1b18ed6b, 0xe2183a27), TOBN(0x879738d8, 0x63210329), + TOBN(0xa687c74b, 0xbda94882), TOBN(0xd1bbcc48, 0xa684b299), + TOBN(0xaf6f1112, 0x863b3724), TOBN(0x6943d1b4, 0x2c8ce9f8), + TOBN(0xe044a3bb, 0x098cafb4), TOBN(0x27ed2310, 0x60d48caf), + TOBN(0x542b5675, 0x3a31b84d), TOBN(0xcbf3dd50, 0xfcddbed7), + TOBN(0x25031f16, 0x41b1d830), TOBN(0xa7ec851d, 0xcb0c1e27), + TOBN(0xac1c8fe0, 0xb5ae75db), TOBN(0xb24c7557, 0x08c52120), + TOBN(0x57f811dc, 0x1d4636c3), TOBN(0xf8436526, 0x681a9939), + TOBN(0x1f6bc6d9, 0x9c81adb3), TOBN(0x840f8ac3, 0x5b7d80d4), + TOBN(0x731a9811, 0xf4387f1a), TOBN(0x7c501cd3, 0xb5156880), + TOBN(0xa5ca4a07, 0xdfe68867), TOBN(0xf123d8f0, 0x5fcea120), + TOBN(0x1fbb0e71, 0xd607039e), TOBN(0x2b70e215, 0xcd3a4546), + TOBN(0x32d2f01d, 0x53324091), TOBN(0xb796ff08, 0x180ab19b), + TOBN(0x32d87a86, 0x3c57c4aa), TOBN(0x2aed9caf, 0xb7c49a27), + TOBN(0x9fb35eac, 0x31630d98), TOBN(0x338e8cdf, 0x5c3e20a3), + TOBN(0x80f16182, 0x66cde8db), TOBN(0x4e159980, 0x2d72fd36), + TOBN(0xd7b8f13b, 0x9b6e5072), TOBN(0xf5213907, 0x3b7b5dc1), + TOBN(0x4d431f1d, 0x8ce4396e), TOBN(0x37a1a680, 0xa7ed2142), + TOBN(0xbf375696, 0xd01aaf6b), TOBN(0xaa1c0c54, 0xe63aab66), + TOBN(0x3014368b, 0x4ed80940), TOBN(0x67e6d056, 0x7a6fcedd), + TOBN(0x7c208c49, 0xca97579f), TOBN(0xfe3d7a81, 0xa23597f6), + TOBN(0x5e203202, 0x7e096ae2), TOBN(0xb1f3e1e7, 0x24b39366), + TOBN(0x26da26f3, 0x2fdcdffc), TOBN(0x79422f1d, 0x6097be83)}, + {TOBN(0x263a2cfb, 0x9db3b381), TOBN(0x9c3a2dee, 0xd4df0a4b), + TOBN(0x728d06e9, 0x7d04e61f), TOBN(0x8b1adfbc, 0x42449325), + TOBN(0x6ec1d939, 0x7e053a1b), TOBN(0xee2be5c7, 0x66daf707), + TOBN(0x80ba1e14, 0x810ac7ab), TOBN(0xdd2ae778, 0xf530f174), + TOBN(0x0435d97a, 0x205b9d8b), TOBN(0x6eb8f064, 0x056756d4), + TOBN(0xd5e88a8b, 0xb6f8210e), TOBN(0x070ef12d, 0xec9fd9ea), + TOBN(0x4d849505, 0x3bcc876a), TOBN(0x12a75338, 0xa7404ce3), + TOBN(0xd22b49e1, 0xb8a1db5e), TOBN(0xec1f2051, 0x14bfa5ad), + TOBN(0xadbaeb79, 0xb6828f36), TOBN(0x9d7a0258, 0x01bd5b9e), + TOBN(0xeda01e0d, 0x1e844b0c), TOBN(0x4b625175, 0x887edfc9), + TOBN(0x14109fdd, 0x9669b621), TOBN(0x88a2ca56, 0xf6f87b98), + TOBN(0xfe2eb788, 0x170df6bc), TOBN(0x0cea06f4, 0xffa473f9), + TOBN(0x43ed81b5, 0xc4e83d33), TOBN(0xd9f35879, 0x5efd488b), + TOBN(0x164a620f, 0x9deb4d0f), TOBN(0xc6927bdb, 0xac6a7394), + TOBN(0x45c28df7, 0x9f9e0f03), TOBN(0x2868661e, 0xfcd7e1a9), + TOBN(0x7cf4e8d0, 0xffa348f1), TOBN(0x6bd4c284, 0x398538e0), + TOBN(0x2618a091, 0x289a8619), TOBN(0xef796e60, 0x6671b173), + TOBN(0x664e46e5, 0x9090c632), TOBN(0xa38062d4, 0x1e66f8fb), + TOBN(0x6c744a20, 0x0573274e), TOBN(0xd07b67e4, 0xa9271394), + TOBN(0x391223b2, 0x6bdc0e20), TOBN(0xbe2d93f1, 0xeb0a05a7), + TOBN(0xf23e2e53, 0x3f36d141), TOBN(0xe84bb3d4, 0x4dfca442), + TOBN(0xb804a48d, 0x6b7c023a), TOBN(0x1e16a8fa, 0x76431c3b), + TOBN(0x1b5452ad, 0xddd472e0), TOBN(0x7d405ee7, 0x0d1ee127), + TOBN(0x50fc6f1d, 0xffa27599), TOBN(0x351ac53c, 0xbf391b35), + TOBN(0x7efa14b8, 0x4444896b), TOBN(0x64974d2f, 0xf94027fb), + TOBN(0xefdcd0e8, 0xde84487d), TOBN(0x8c45b260, 0x2b48989b), + TOBN(0xa8fcbbc2, 0xd8463487), TOBN(0xd1b2b3f7, 0x3fbc476c), + TOBN(0x21d005b7, 0xc8f443c0), TOBN(0x518f2e67, 0x40c0139c), + TOBN(0x56036e8c, 0x06d75fc1), TOBN(0x2dcf7bb7, 0x3249a89f), + TOBN(0x81dd1d3d, 0xe245e7dd), TOBN(0xf578dc4b, 0xebd6e2a7), + TOBN(0x4c028903, 0xdf2ce7a0), TOBN(0xaee36288, 0x9c39afac), + TOBN(0xdc847c31, 0x146404ab), TOBN(0x6304c0d8, 0xa4e97818), + TOBN(0xae51dca2, 0xa91f6791), TOBN(0x2abe4190, 0x9baa9efc), + TOBN(0xd9d2e2f4, 0x559c7ac1), TOBN(0xe82f4b51, 0xfc9f773a), + TOBN(0xa7713027, 0x4073e81c), TOBN(0xc0276fac, 0xfbb596fc), + TOBN(0x1d819fc9, 0xa684f70c), TOBN(0x29b47fdd, 0xc9f7b1e0), + TOBN(0x358de103, 0x459b1940), TOBN(0xec881c59, 0x5b013e93), + TOBN(0x51574c93, 0x49532ad3), TOBN(0x2db1d445, 0xb37b46de), + TOBN(0xc6445b87, 0xdf239fd8), TOBN(0xc718af75, 0x151d24ee), + TOBN(0xaea1c4a4, 0xf43c6259), TOBN(0x40c0e5d7, 0x70be02f7), + TOBN(0x6a4590f4, 0x721b33f2), TOBN(0x2124f1fb, 0xfedf04ea), + TOBN(0xf8e53cde, 0x9745efe7), TOBN(0xe7e10432, 0x65f046d9), + TOBN(0xc3fca28e, 0xe4d0c7e6), TOBN(0x847e339a, 0x87253b1b), + TOBN(0x9b595348, 0x3743e643), TOBN(0xcb6a0a0b, 0x4fd12fc5), + TOBN(0xfb6836c3, 0x27d02dcc), TOBN(0x5ad00982, 0x7a68bcc2), + TOBN(0x1b24b44c, 0x005e912d), TOBN(0xcc83d20f, 0x811fdcfe), + TOBN(0x36527ec1, 0x666fba0c), TOBN(0x69948197, 0x14754635), + TOBN(0xfcdcb1a8, 0x556da9c2), TOBN(0xa5934267, 0x81a732b2), + TOBN(0xec1214ed, 0xa714181d), TOBN(0x609ac13b, 0x6067b341), + TOBN(0xff4b4c97, 0xa545df1f), TOBN(0xa1240501, 0x34d2076b), + TOBN(0x6efa0c23, 0x1409ca97), TOBN(0x254cc1a8, 0x20638c43), + TOBN(0xd4e363af, 0xdcfb46cd), TOBN(0x62c2adc3, 0x03942a27), + TOBN(0xc67b9df0, 0x56e46483), TOBN(0xa55abb20, 0x63736356), + TOBN(0xab93c098, 0xc551bc52), TOBN(0x382b49f9, 0xb15fe64b), + TOBN(0x9ec221ad, 0x4dff8d47), TOBN(0x79caf615, 0x437df4d6), + TOBN(0x5f13dc64, 0xbb456509), TOBN(0xe4c589d9, 0x191f0714), + TOBN(0x27b6a8ab, 0x3fd40e09), TOBN(0xe455842e, 0x77313ea9), + TOBN(0x8b51d1e2, 0x1f55988b), TOBN(0x5716dd73, 0x062bbbfc), + TOBN(0x633c11e5, 0x4e8bf3de), TOBN(0x9a0e77b6, 0x1b85be3b), + TOBN(0x56510729, 0x0911cca6), TOBN(0x27e76495, 0xefa6590f), + TOBN(0xe4ac8b33, 0x070d3aab), TOBN(0x2643672b, 0x9a2cd5e5), + TOBN(0x52eff79b, 0x1cfc9173), TOBN(0x665ca49b, 0x90a7c13f), + TOBN(0x5a8dda59, 0xb3efb998), TOBN(0x8a5b922d, 0x052f1341), + TOBN(0xae9ebbab, 0x3cf9a530), TOBN(0x35986e7b, 0xf56da4d7), + TOBN(0x3a636b5c, 0xff3513cc), TOBN(0xbb0cf8ba, 0x3198f7dd), + TOBN(0xb8d40522, 0x41f16f86), TOBN(0x760575d8, 0xde13a7bf), + TOBN(0x36f74e16, 0x9f7aa181), TOBN(0x163a3ecf, 0xf509ed1c), + TOBN(0x6aead61f, 0x3c40a491), TOBN(0x158c95fc, 0xdfe8fcaa), + TOBN(0xa3991b6e, 0x13cda46f), TOBN(0x79482415, 0x342faed0), + TOBN(0xf3ba5bde, 0x666b5970), TOBN(0x1d52e6bc, 0xb26ab6dd), + TOBN(0x768ba1e7, 0x8608dd3d), TOBN(0x4930db2a, 0xea076586), + TOBN(0xd9575714, 0xe7dc1afa), TOBN(0x1fc7bf7d, 0xf7c58817), + TOBN(0x6b47accd, 0xd9eee96c), TOBN(0x0ca277fb, 0xe58cec37), + TOBN(0x113fe413, 0xe702c42a), TOBN(0xdd1764ee, 0xc47cbe51), + TOBN(0x041e7cde, 0x7b3ed739), TOBN(0x50cb7459, 0x5ce9e1c0), + TOBN(0x35568513, 0x2925b212), TOBN(0x7cff95c4, 0x001b081c), + TOBN(0x63ee4cbd, 0x8088b454), TOBN(0xdb7f32f7, 0x9a9e0c8a), + TOBN(0xb377d418, 0x6b2447cb), TOBN(0xe3e982aa, 0xd370219b), + TOBN(0x06ccc1e4, 0xc2a2a593), TOBN(0x72c36865, 0x0773f24f), + TOBN(0xa13b4da7, 0x95859423), TOBN(0x8bbf1d33, 0x75040c8f), + TOBN(0x726f0973, 0xda50c991), TOBN(0x48afcd5b, 0x822d6ee2), + TOBN(0xe5fc718b, 0x20fd7771), TOBN(0xb9e8e77d, 0xfd0807a1), + TOBN(0x7f5e0f44, 0x99a7703d), TOBN(0x6972930e, 0x618e36f3), + TOBN(0x2b7c77b8, 0x23807bbe), TOBN(0xe5b82405, 0xcb27ff50), + TOBN(0xba8b8be3, 0xbd379062), TOBN(0xd64b7a1d, 0x2dce4a92), + TOBN(0x040a73c5, 0xb2952e37), TOBN(0x0a9e252e, 0xd438aeca), + TOBN(0xdd43956b, 0xc39d3bcb), TOBN(0x1a31ca00, 0xb32b2d63), + TOBN(0xd67133b8, 0x5c417a18), TOBN(0xd08e4790, 0x2ef442c8), + TOBN(0x98cb1ae9, 0x255c0980), TOBN(0x4bd86381, 0x2b4a739f), + TOBN(0x5a5c31e1, 0x1e4a45a1), TOBN(0x1e5d55fe, 0x9cb0db2f), + TOBN(0x74661b06, 0x8ff5cc29), TOBN(0x026b389f, 0x0eb8a4f4), + TOBN(0x536b21a4, 0x58848c24), TOBN(0x2e5bf8ec, 0x81dc72b0), + TOBN(0x03c187d0, 0xad886aac), TOBN(0x5c16878a, 0xb771b645), + TOBN(0xb07dfc6f, 0xc74045ab), TOBN(0x2c6360bf, 0x7800caed), + TOBN(0x24295bb5, 0xb9c972a3), TOBN(0xc9e6f88e, 0x7c9a6dba), + TOBN(0x90ffbf24, 0x92a79aa6), TOBN(0xde29d50a, 0x41c26ac2), + TOBN(0x9f0af483, 0xd309cbe6), TOBN(0x5b020d8a, 0xe0bced4f), + TOBN(0x606e986d, 0xb38023e3), TOBN(0xad8f2c9d, 0x1abc6933), + TOBN(0x19292e1d, 0xe7400e93), TOBN(0xfe3e18a9, 0x52be5e4d), + TOBN(0xe8e9771d, 0x2e0680bf), TOBN(0x8c5bec98, 0xc54db063), + TOBN(0x2af9662a, 0x74a55d1f), TOBN(0xe3fbf28f, 0x046f66d8), + TOBN(0xa3a72ab4, 0xd4dc4794), TOBN(0x09779f45, 0x5c7c2dd8), + TOBN(0xd893bdaf, 0xc3d19d8d), TOBN(0xd5a75094, 0x57d6a6df), + TOBN(0x8cf8fef9, 0x952e6255), TOBN(0x3da67cfb, 0xda9a8aff), + TOBN(0x4c23f62a, 0x2c160dcd), TOBN(0x34e6c5e3, 0x8f90eaef), + TOBN(0x35865519, 0xa9a65d5a), TOBN(0x07c48aae, 0x8fd38a3d), + TOBN(0xb7e7aeda, 0x50068527), TOBN(0x2c09ef23, 0x1c90936a), + TOBN(0x31ecfeb6, 0xe879324c), TOBN(0xa0871f6b, 0xfb0ec938), + TOBN(0xb1f0fb68, 0xd84d835d), TOBN(0xc90caf39, 0x861dc1e6), + TOBN(0x12e5b046, 0x7594f8d7), TOBN(0x26897ae2, 0x65012b92), + TOBN(0xbcf68a08, 0xa4d6755d), TOBN(0x403ee41c, 0x0991fbda), + TOBN(0x733e343e, 0x3bbf17e8), TOBN(0xd2c7980d, 0x679b3d65), + TOBN(0x33056232, 0xd2e11305), TOBN(0x966be492, 0xf3c07a6f), + TOBN(0x6a8878ff, 0xbb15509d), TOBN(0xff221101, 0x0a9b59a4), + TOBN(0x6c9f564a, 0xabe30129), TOBN(0xc6f2c940, 0x336e64cf), + TOBN(0x0fe75262, 0x8b0c8022), TOBN(0xbe0267e9, 0x6ae8db87), + TOBN(0x22e192f1, 0x93bc042b), TOBN(0xf085b534, 0xb237c458), + TOBN(0xa0d192bd, 0x832c4168), TOBN(0x7a76e9e3, 0xbdf6271d), + TOBN(0x52a882fa, 0xb88911b5), TOBN(0xc85345e4, 0xb4db0eb5), + TOBN(0xa3be02a6, 0x81a7c3ff), TOBN(0x51889c8c, 0xf0ec0469), + TOBN(0x9d031369, 0xa5e829e5), TOBN(0xcbb4c6fc, 0x1607aa41), + TOBN(0x75ac59a6, 0x241d84c1), TOBN(0xc043f2bf, 0x8829e0ee), + TOBN(0x82a38f75, 0x8ea5e185), TOBN(0x8bda40b9, 0xd87cbd9f), + TOBN(0x9e65e75e, 0x2d8fc601), TOBN(0x3d515f74, 0xa35690b3), + TOBN(0x534acf4f, 0xda79e5ac), TOBN(0x68b83b3a, 0x8630215f), + TOBN(0x5c748b2e, 0xd085756e), TOBN(0xb0317258, 0xe5d37cb2), + TOBN(0x6735841a, 0xc5ccc2c4), TOBN(0x7d7dc96b, 0x3d9d5069), + TOBN(0xa147e410, 0xfd1754bd), TOBN(0x65296e94, 0xd399ddd5), + TOBN(0xf6b5b2d0, 0xbc8fa5bc), TOBN(0x8a5ead67, 0x500c277b), + TOBN(0x214625e6, 0xdfa08a5d), TOBN(0x51fdfedc, 0x959cf047), + TOBN(0x6bc9430b, 0x289fca32), TOBN(0xe36ff0cf, 0x9d9bdc3f), + TOBN(0x2fe187cb, 0x58ea0ede), TOBN(0xed66af20, 0x5a900b3f), + TOBN(0x00e0968b, 0x5fa9f4d6), TOBN(0x2d4066ce, 0x37a362e7), + TOBN(0xa99a9748, 0xbd07e772), TOBN(0x710989c0, 0x06a4f1d0), + TOBN(0xd5dedf35, 0xce40cbd8), TOBN(0xab55c5f0, 0x1743293d), + TOBN(0x766f1144, 0x8aa24e2c), TOBN(0x94d874f8, 0x605fbcb4), + TOBN(0xa365f0e8, 0xa518001b), TOBN(0xee605eb6, 0x9d04ef0f), + TOBN(0x5a3915cd, 0xba8d4d25), TOBN(0x44c0e1b8, 0xb5113472), + TOBN(0xcbb024e8, 0x8b6740dc), TOBN(0x89087a53, 0xee1d4f0c), + TOBN(0xa88fa05c, 0x1fc4e372), TOBN(0x8bf395cb, 0xaf8b3af2), + TOBN(0x1e71c9a1, 0xdeb8568b), TOBN(0xa35daea0, 0x80fb3d32), + TOBN(0xe8b6f266, 0x2cf8fb81), TOBN(0x6d51afe8, 0x9490696a), + TOBN(0x81beac6e, 0x51803a19), TOBN(0xe3d24b7f, 0x86219080), + TOBN(0x727cfd9d, 0xdf6f463c), TOBN(0x8c6865ca, 0x72284ee8), + TOBN(0x32c88b7d, 0xb743f4ef), TOBN(0x3793909b, 0xe7d11dce), + TOBN(0xd398f922, 0x2ff2ebe8), TOBN(0x2c70ca44, 0xe5e49796), + TOBN(0xdf4d9929, 0xcb1131b1), TOBN(0x7826f298, 0x25888e79), + TOBN(0x4d3a112c, 0xf1d8740a), TOBN(0x00384cb6, 0x270afa8b), + TOBN(0xcb64125b, 0x3ab48095), TOBN(0x3451c256, 0x62d05106), + TOBN(0xd73d577d, 0xa4955845), TOBN(0x39570c16, 0xbf9f4433), + TOBN(0xd7dfaad3, 0xadecf263), TOBN(0xf1c3d8d1, 0xdc76e102), + TOBN(0x5e774a58, 0x54c6a836), TOBN(0xdad4b672, 0x3e92d47b), + TOBN(0xbe7e990f, 0xf0d796a0), TOBN(0x5fc62478, 0xdf0e8b02), + TOBN(0x8aae8bf4, 0x030c00ad), TOBN(0x3d2db93b, 0x9004ba0f), + TOBN(0xe48c8a79, 0xd85d5ddc), TOBN(0xe907caa7, 0x6bb07f34), + TOBN(0x58db343a, 0xa39eaed5), TOBN(0x0ea6e007, 0xadaf5724), + TOBN(0xe00df169, 0xd23233f3), TOBN(0x3e322796, 0x77cb637f), + TOBN(0x1f897c0e, 0x1da0cf6c), TOBN(0xa651f5d8, 0x31d6bbdd), + TOBN(0xdd61af19, 0x1a230c76), TOBN(0xbd527272, 0xcdaa5e4a), + TOBN(0xca753636, 0xd0abcd7e), TOBN(0x78bdd37c, 0x370bd8dc), + TOBN(0xc23916c2, 0x17cd93fe), TOBN(0x65b97a4d, 0xdadce6e2), + TOBN(0xe04ed4eb, 0x174e42f8), TOBN(0x1491ccaa, 0xbb21480a), + TOBN(0x145a8280, 0x23196332), TOBN(0x3c3862d7, 0x587b479a), + TOBN(0x9f4a88a3, 0x01dcd0ed), TOBN(0x4da2b7ef, 0x3ea12f1f), + TOBN(0xf8e7ae33, 0xb126e48e), TOBN(0x404a0b32, 0xf494e237), + TOBN(0x9beac474, 0xc55acadb), TOBN(0x4ee5cf3b, 0xcbec9fd9), + TOBN(0x336b33b9, 0x7df3c8c3), TOBN(0xbd905fe3, 0xb76808fd), + TOBN(0x8f436981, 0xaa45c16a), TOBN(0x255c5bfa, 0x3dd27b62), + TOBN(0x71965cbf, 0xc3dd9b4d), TOBN(0xce23edbf, 0xfc068a87), + TOBN(0xb78d4725, 0x745b029b), TOBN(0x74610713, 0xcefdd9bd), + TOBN(0x7116f75f, 0x1266bf52), TOBN(0x02046722, 0x18e49bb6), + TOBN(0xdf43df9f, 0x3d6f19e3), TOBN(0xef1bc7d0, 0xe685cb2f), + TOBN(0xcddb27c1, 0x7078c432), TOBN(0xe1961b9c, 0xb77fedb7), + TOBN(0x1edc2f5c, 0xc2290570), TOBN(0x2c3fefca, 0x19cbd886), + TOBN(0xcf880a36, 0xc2af389a), TOBN(0x96c610fd, 0xbda71cea), + TOBN(0xf03977a9, 0x32aa8463), TOBN(0x8eb7763f, 0x8586d90a), + TOBN(0x3f342454, 0x2a296e77), TOBN(0xc8718683, 0x42837a35), + TOBN(0x7dc71090, 0x6a09c731), TOBN(0x54778ffb, 0x51b816db), + TOBN(0x6b33bfec, 0xaf06defd), TOBN(0xfe3c105f, 0x8592b70b), + TOBN(0xf937fda4, 0x61da6114), TOBN(0x3c13e651, 0x4c266ad7), + TOBN(0xe363a829, 0x855938e8), TOBN(0x2eeb5d9e, 0x9de54b72), + TOBN(0xbeb93b0e, 0x20ccfab9), TOBN(0x3dffbb5f, 0x25e61a25), + TOBN(0x7f655e43, 0x1acc093d), TOBN(0x0cb6cc3d, 0x3964ce61), + TOBN(0x6ab283a1, 0xe5e9b460), TOBN(0x55d787c5, 0xa1c7e72d), + TOBN(0x4d2efd47, 0xdeadbf02), TOBN(0x11e80219, 0xac459068), + TOBN(0x810c7626, 0x71f311f0), TOBN(0xfa17ef8d, 0x4ab6ef53), + TOBN(0xaf47fd25, 0x93e43bff), TOBN(0x5cb5ff3f, 0x0be40632), + TOBN(0x54687106, 0x8ee61da3), TOBN(0x7764196e, 0xb08afd0f), + TOBN(0x831ab3ed, 0xf0290a8f), TOBN(0xcae81966, 0xcb47c387), + TOBN(0xaad7dece, 0x184efb4f), TOBN(0xdcfc53b3, 0x4749110e), + TOBN(0x6698f23c, 0x4cb632f9), TOBN(0xc42a1ad6, 0xb91f8067), + TOBN(0xb116a81d, 0x6284180a), TOBN(0xebedf5f8, 0xe901326f), + TOBN(0xf2274c9f, 0x97e3e044), TOBN(0x42018520, 0x11d09fc9), + TOBN(0x56a65f17, 0xd18e6e23), TOBN(0x2ea61e2a, 0x352b683c), + TOBN(0x27d291bc, 0x575eaa94), TOBN(0x9e7bc721, 0xb8ff522d), + TOBN(0x5f7268bf, 0xa7f04d6f), TOBN(0x5868c73f, 0xaba41748), + TOBN(0x9f85c2db, 0x7be0eead), TOBN(0x511e7842, 0xff719135), + TOBN(0x5a06b1e9, 0xc5ea90d7), TOBN(0x0c19e283, 0x26fab631), + TOBN(0x8af8f0cf, 0xe9206c55), TOBN(0x89389cb4, 0x3553c06a), + TOBN(0x39dbed97, 0xf65f8004), TOBN(0x0621b037, 0xc508991d), + TOBN(0x1c52e635, 0x96e78cc4), TOBN(0x5385c8b2, 0x0c06b4a8), + TOBN(0xd84ddfdb, 0xb0e87d03), TOBN(0xc49dfb66, 0x934bafad), + TOBN(0x7071e170, 0x59f70772), TOBN(0x3a073a84, 0x3a1db56b), + TOBN(0x03494903, 0x3b8af190), TOBN(0x7d882de3, 0xd32920f0), + TOBN(0x91633f0a, 0xb2cf8940), TOBN(0x72b0b178, 0x6f948f51), + TOBN(0x2d28dc30, 0x782653c8), TOBN(0x88829849, 0xdb903a05), + TOBN(0xb8095d0c, 0x6a19d2bb), TOBN(0x4b9e7f0c, 0x86f782cb), + TOBN(0x7af73988, 0x2d907064), TOBN(0xd12be0fe, 0x8b32643c), + TOBN(0x358ed23d, 0x0e165dc3), TOBN(0x3d47ce62, 0x4e2378ce), + TOBN(0x7e2bb0b9, 0xfeb8a087), TOBN(0x3246e8ae, 0xe29e10b9), + TOBN(0x459f4ec7, 0x03ce2b4d), TOBN(0xe9b4ca1b, 0xbbc077cf), + TOBN(0x2613b4f2, 0x0e9940c1), TOBN(0xfc598bb9, 0x047d1eb1), + TOBN(0x9744c62b, 0x45036099), TOBN(0xa9dee742, 0x167c65d8), + TOBN(0x0c511525, 0xdabe1943), TOBN(0xda110554, 0x93c6c624), + TOBN(0xae00a52c, 0x651a3be2), TOBN(0xcda5111d, 0x884449a6), + TOBN(0x063c06f4, 0xff33bed1), TOBN(0x73baaf9a, 0x0d3d76b4), + TOBN(0x52fb0c9d, 0x7fc63668), TOBN(0x6886c9dd, 0x0c039cde), + TOBN(0x602bd599, 0x55b22351), TOBN(0xb00cab02, 0x360c7c13), + TOBN(0x8cb616bc, 0x81b69442), TOBN(0x41486700, 0xb55c3cee), + TOBN(0x71093281, 0xf49ba278), TOBN(0xad956d9c, 0x64a50710), + TOBN(0x9561f28b, 0x638a7e81), TOBN(0x54155cdf, 0x5980ddc3), + TOBN(0xb2db4a96, 0xd26f247a), TOBN(0x9d774e4e, 0x4787d100), + TOBN(0x1a9e6e2e, 0x078637d2), TOBN(0x1c363e2d, 0x5e0ae06a), + TOBN(0x7493483e, 0xe9cfa354), TOBN(0x76843cb3, 0x7f74b98d), + TOBN(0xbaca6591, 0xd4b66947), TOBN(0xb452ce98, 0x04460a8c), + TOBN(0x6830d246, 0x43768f55), TOBN(0xf4197ed8, 0x7dff12df), + TOBN(0x6521b472, 0x400dd0f7), TOBN(0x59f5ca8f, 0x4b1e7093), + TOBN(0x6feff11b, 0x080338ae), TOBN(0x0ada31f6, 0xa29ca3c6), + TOBN(0x24794eb6, 0x94a2c215), TOBN(0xd83a43ab, 0x05a57ab4), + TOBN(0x264a543a, 0x2a6f89fe), TOBN(0x2c2a3868, 0xdd5ec7c2), + TOBN(0xd3373940, 0x8439d9b2), TOBN(0x715ea672, 0x0acd1f11), + TOBN(0x42c1d235, 0xe7e6cc19), TOBN(0x81ce6e96, 0xb990585c), + TOBN(0x04e5dfe0, 0xd809c7bd), TOBN(0xd7b2580c, 0x8f1050ab), + TOBN(0x6d91ad78, 0xd8a4176f), TOBN(0x0af556ee, 0x4e2e897c), + TOBN(0x162a8b73, 0x921de0ac), TOBN(0x52ac9c22, 0x7ea78400), + TOBN(0xee2a4eea, 0xefce2174), TOBN(0xbe61844e, 0x6d637f79), + TOBN(0x0491f1bc, 0x789a283b), TOBN(0x72d3ac3d, 0x880836f4), + TOBN(0xaa1c5ea3, 0x88e5402d), TOBN(0x1b192421, 0xd5cc473d), + TOBN(0x5c0b9998, 0x9dc84cac), TOBN(0xb0a8482d, 0x9c6e75b8), + TOBN(0x639961d0, 0x3a191ce2), TOBN(0xda3bc865, 0x6d837930), + TOBN(0xca990653, 0x056e6f8f), TOBN(0x84861c41, 0x64d133a7), + TOBN(0x8b403276, 0x746abe40), TOBN(0xb7b4d51a, 0xebf8e303), + TOBN(0x05b43211, 0x220a255d), TOBN(0xc997152c, 0x02419e6e), + TOBN(0x76ff47b6, 0x630c2fea), TOBN(0x50518677, 0x281fdade), + TOBN(0x3283b8ba, 0xcf902b0b), TOBN(0x8d4b4eb5, 0x37db303b), + TOBN(0xcc89f42d, 0x755011bc), TOBN(0xb43d74bb, 0xdd09d19b), + TOBN(0x65746bc9, 0x8adba350), TOBN(0x364eaf8c, 0xb51c1927), + TOBN(0x13c76596, 0x10ad72ec), TOBN(0x30045121, 0xf8d40c20), + TOBN(0x6d2d99b7, 0xea7b979b), TOBN(0xcd78cd74, 0xe6fb3bcd), + TOBN(0x11e45a9e, 0x86cffbfe), TOBN(0x78a61cf4, 0x637024f6), + TOBN(0xd06bc872, 0x3d502295), TOBN(0xf1376854, 0x458cb288), + TOBN(0xb9db26a1, 0x342f8586), TOBN(0xf33effcf, 0x4beee09e), + TOBN(0xd7e0c4cd, 0xb30cfb3a), TOBN(0x6d09b8c1, 0x6c9db4c8), + TOBN(0x40ba1a42, 0x07c8d9df), TOBN(0x6fd495f7, 0x1c52c66d), + TOBN(0xfb0e169f, 0x275264da), TOBN(0x80c2b746, 0xe57d8362), + TOBN(0xedd987f7, 0x49ad7222), TOBN(0xfdc229af, 0x4398ec7b)}, + {TOBN(0xb0d1ed84, 0x52666a58), TOBN(0x4bcb6e00, 0xe6a9c3c2), + TOBN(0x3c57411c, 0x26906408), TOBN(0xcfc20755, 0x13556400), + TOBN(0xa08b1c50, 0x5294dba3), TOBN(0xa30ba286, 0x8b7dd31e), + TOBN(0xd70ba90e, 0x991eca74), TOBN(0x094e142c, 0xe762c2b9), + TOBN(0xb81d783e, 0x979f3925), TOBN(0x1efd130a, 0xaf4c89a7), + TOBN(0x525c2144, 0xfd1bf7fa), TOBN(0x4b296904, 0x1b265a9e), + TOBN(0xed8e9634, 0xb9db65b6), TOBN(0x35c82e32, 0x03599d8a), + TOBN(0xdaa7a54f, 0x403563f3), TOBN(0x9df088ad, 0x022c38ab), + TOBN(0xe5cfb066, 0xbb3fd30a), TOBN(0x429169da, 0xeff0354e), + TOBN(0x809cf852, 0x3524e36c), TOBN(0x136f4fb3, 0x0155be1d), + TOBN(0x4826af01, 0x1fbba712), TOBN(0x6ef0f0b4, 0x506ba1a1), + TOBN(0xd9928b31, 0x77aea73e), TOBN(0xe2bf6af2, 0x5eaa244e), + TOBN(0x8d084f12, 0x4237b64b), TOBN(0x688ebe99, 0xe3ecfd07), + TOBN(0x57b8a70c, 0xf6845dd8), TOBN(0x808fc59c, 0x5da4a325), + TOBN(0xa9032b2b, 0xa3585862), TOBN(0xb66825d5, 0xedf29386), + TOBN(0xb5a5a8db, 0x431ec29b), TOBN(0xbb143a98, 0x3a1e8dc8), + TOBN(0x35ee94ce, 0x12ae381b), TOBN(0x3a7f176c, 0x86ccda90), + TOBN(0xc63a657e, 0x4606eaca), TOBN(0x9ae5a380, 0x43cd04df), + TOBN(0x9bec8d15, 0xed251b46), TOBN(0x1f5d6d30, 0xcaca5e64), + TOBN(0x347b3b35, 0x9ff20f07), TOBN(0x4d65f034, 0xf7e4b286), + TOBN(0x9e93ba24, 0xf111661e), TOBN(0xedced484, 0xb105eb04), + TOBN(0x96dc9ba1, 0xf424b578), TOBN(0xbf8f66b7, 0xe83e9069), + TOBN(0x872d4df4, 0xd7ed8216), TOBN(0xbf07f377, 0x8e2cbecf), + TOBN(0x4281d899, 0x98e73754), TOBN(0xfec85fbb, 0x8aab8708), + TOBN(0x9a3c0dee, 0xa5ba5b0b), TOBN(0xe6a116ce, 0x42d05299), + TOBN(0xae9775fe, 0xe9b02d42), TOBN(0x72b05200, 0xa1545cb6), + TOBN(0xbc506f7d, 0x31a3b4ea), TOBN(0xe5893078, 0x8bbd9b32), + TOBN(0xc8bc5f37, 0xe4b12a97), TOBN(0x6b000c06, 0x4a73b671), + TOBN(0x13b5bf22, 0x765fa7d0), TOBN(0x59805bf0, 0x1d6a5370), + TOBN(0x67a5e29d, 0x4280db98), TOBN(0x4f53916f, 0x776b1ce3), + TOBN(0x714ff61f, 0x33ddf626), TOBN(0x4206238e, 0xa085d103), + TOBN(0x1c50d4b7, 0xe5809ee3), TOBN(0x999f450d, 0x85f8eb1d), + TOBN(0x658a6051, 0xe4c79e9b), TOBN(0x1394cb73, 0xc66a9fea), + TOBN(0x27f31ed5, 0xc6be7b23), TOBN(0xf4c88f36, 0x5aa6f8fe), + TOBN(0x0fb0721f, 0x4aaa499e), TOBN(0x68b3a7d5, 0xe3fb2a6b), + TOBN(0xa788097d, 0x3a92851d), TOBN(0x060e7f8a, 0xe96f4913), + TOBN(0x82eebe73, 0x1a3a93bc), TOBN(0x42bbf465, 0xa21adc1a), + TOBN(0xc10b6fa4, 0xef030efd), TOBN(0x247aa4c7, 0x87b097bb), + TOBN(0x8b8dc632, 0xf60c77da), TOBN(0x6ffbc26a, 0xc223523e), + TOBN(0xa4f6ff11, 0x344579cf), TOBN(0x5825653c, 0x980250f6), + TOBN(0xb2dd097e, 0xbc1aa2b9), TOBN(0x07889393, 0x37a0333a), + TOBN(0x1cf55e71, 0x37a0db38), TOBN(0x2648487f, 0x792c1613), + TOBN(0xdad01336, 0x3fcef261), TOBN(0x6239c81d, 0x0eabf129), + TOBN(0x8ee761de, 0x9d276be2), TOBN(0x406a7a34, 0x1eda6ad3), + TOBN(0x4bf367ba, 0x4a493b31), TOBN(0x54f20a52, 0x9bf7f026), + TOBN(0xb696e062, 0x9795914b), TOBN(0xcddab96d, 0x8bf236ac), + TOBN(0x4ff2c70a, 0xed25ea13), TOBN(0xfa1d09eb, 0x81cbbbe7), + TOBN(0x88fc8c87, 0x468544c5), TOBN(0x847a670d, 0x696b3317), + TOBN(0xf133421e, 0x64bcb626), TOBN(0xaea638c8, 0x26dee0b5), + TOBN(0xd6e7680b, 0xb310346c), TOBN(0xe06f4097, 0xd5d4ced3), + TOBN(0x09961452, 0x7512a30b), TOBN(0xf3d867fd, 0xe589a59a), + TOBN(0x2e73254f, 0x52d0c180), TOBN(0x9063d8a3, 0x333c74ac), + TOBN(0xeda6c595, 0xd314e7bc), TOBN(0x2ee7464b, 0x467899ed), + TOBN(0x1cef423c, 0x0a1ed5d3), TOBN(0x217e76ea, 0x69cc7613), + TOBN(0x27ccce1f, 0xe7cda917), TOBN(0x12d8016b, 0x8a893f16), + TOBN(0xbcd6de84, 0x9fc74f6b), TOBN(0xfa5817e2, 0xf3144e61), + TOBN(0x1f354164, 0x0821ee4c), TOBN(0x1583eab4, 0x0bc61992), + TOBN(0x7490caf6, 0x1d72879f), TOBN(0x998ad9f3, 0xf76ae7b2), + TOBN(0x1e181950, 0xa41157f7), TOBN(0xa9d7e1e6, 0xe8da3a7e), + TOBN(0x963784eb, 0x8426b95f), TOBN(0x0ee4ed6e, 0x542e2a10), + TOBN(0xb79d4cc5, 0xac751e7b), TOBN(0x93f96472, 0xfd4211bd), + TOBN(0x8c72d3d2, 0xc8de4fc6), TOBN(0x7b69cbf5, 0xdf44f064), + TOBN(0x3da90ca2, 0xf4bf94e1), TOBN(0x1a5325f8, 0xf12894e2), + TOBN(0x0a437f6c, 0x7917d60b), TOBN(0x9be70486, 0x96c9cb5d), + TOBN(0xb4d880bf, 0xe1dc5c05), TOBN(0xd738adda, 0xeebeeb57), + TOBN(0x6f0119d3, 0xdf0fe6a3), TOBN(0x5c686e55, 0x66eaaf5a), + TOBN(0x9cb10b50, 0xdfd0b7ec), TOBN(0xbdd0264b, 0x6a497c21), + TOBN(0xfc093514, 0x8c546c96), TOBN(0x58a947fa, 0x79dbf42a), + TOBN(0xc0b48d4e, 0x49ccd6d7), TOBN(0xff8fb02c, 0x88bd5580), + TOBN(0xc75235e9, 0x07d473b2), TOBN(0x4fab1ac5, 0xa2188af3), + TOBN(0x030fa3bc, 0x97576ec0), TOBN(0xe8c946e8, 0x0b7e7d2f), + TOBN(0x40a5c9cc, 0x70305600), TOBN(0x6d8260a9, 0xc8b013b4), + TOBN(0x0368304f, 0x70bba85c), TOBN(0xad090da1, 0xa4a0d311), + TOBN(0x7170e870, 0x2415eec1), TOBN(0xbfba35fe, 0x8461ea47), + TOBN(0x6279019a, 0xc1e91938), TOBN(0xa47638f3, 0x1afc415f), + TOBN(0x36c65cbb, 0xbcba0e0f), TOBN(0x02160efb, 0x034e2c48), + TOBN(0xe6c51073, 0x615cd9e4), TOBN(0x498ec047, 0xf1243c06), + TOBN(0x3e5a8809, 0xb17b3d8c), TOBN(0x5cd99e61, 0x0cc565f1), + TOBN(0x81e312df, 0x7851dafe), TOBN(0xf156f5ba, 0xa79061e2), + TOBN(0x80d62b71, 0x880c590e), TOBN(0xbec9746f, 0x0a39faa1), + TOBN(0x1d98a9c1, 0xc8ed1f7a), TOBN(0x09e43bb5, 0xa81d5ff2), + TOBN(0xd5f00f68, 0x0da0794a), TOBN(0x412050d9, 0x661aa836), + TOBN(0xa89f7c4e, 0x90747e40), TOBN(0x6dc05ebb, 0xb62a3686), + TOBN(0xdf4de847, 0x308e3353), TOBN(0x53868fbb, 0x9fb53bb9), + TOBN(0x2b09d2c3, 0xcfdcf7dd), TOBN(0x41a9fce3, 0x723fcab4), + TOBN(0x73d905f7, 0x07f57ca3), TOBN(0x080f9fb1, 0xac8e1555), + TOBN(0x7c088e84, 0x9ba7a531), TOBN(0x07d35586, 0xed9a147f), + TOBN(0x602846ab, 0xaf48c336), TOBN(0x7320fd32, 0x0ccf0e79), + TOBN(0xaa780798, 0xb18bd1ff), TOBN(0x52c2e300, 0xafdd2905), + TOBN(0xf27ea3d6, 0x434267cd), TOBN(0x8b96d16d, 0x15605b5f), + TOBN(0x7bb31049, 0x4b45706b), TOBN(0xe7f58b8e, 0x743d25f8), + TOBN(0xe9b5e45b, 0x87f30076), TOBN(0xd19448d6, 0x5d053d5a), + TOBN(0x1ecc8cb9, 0xd3210a04), TOBN(0x6bc7d463, 0xdafb5269), + TOBN(0x3e59b10a, 0x67c3489f), TOBN(0x1769788c, 0x65641e1b), + TOBN(0x8a53b82d, 0xbd6cb838), TOBN(0x7066d6e6, 0x236d5f22), + TOBN(0x03aa1c61, 0x6908536e), TOBN(0xc971da0d, 0x66ae9809), + TOBN(0x01b3a86b, 0xc49a2fac), TOBN(0x3b8420c0, 0x3092e77a), + TOBN(0x02057300, 0x7d6fb556), TOBN(0x6941b2a1, 0xbff40a87), + TOBN(0x140b6308, 0x0658ff2a), TOBN(0x87804363, 0x3424ab36), + TOBN(0x0253bd51, 0x5751e299), TOBN(0xc75bcd76, 0x449c3e3a), + TOBN(0x92eb4090, 0x7f8f875d), TOBN(0x9c9d754e, 0x56c26bbf), + TOBN(0x158cea61, 0x8110bbe7), TOBN(0x62a6b802, 0x745f91ea), + TOBN(0xa79c41aa, 0xc6e7394b), TOBN(0x445b6a83, 0xad57ef10), + TOBN(0x0c5277eb, 0x6ea6f40c), TOBN(0x319fe96b, 0x88633365), + TOBN(0x0b0fc61f, 0x385f63cb), TOBN(0x41250c84, 0x22bdd127), + TOBN(0x67d153f1, 0x09e942c2), TOBN(0x60920d08, 0xc021ad5d), + TOBN(0x229f5746, 0x724d81a5), TOBN(0xb7ffb892, 0x5bba3299), + TOBN(0x518c51a1, 0xde413032), TOBN(0x2a9bfe77, 0x3c2fd94c), + TOBN(0xcbcde239, 0x3191f4fd), TOBN(0x43093e16, 0xd3d6ada1), + TOBN(0x184579f3, 0x58769606), TOBN(0x2c94a8b3, 0xd236625c), + TOBN(0x6922b9c0, 0x5c437d8e), TOBN(0x3d4ae423, 0xd8d9f3c8), + TOBN(0xf72c31c1, 0x2e7090a2), TOBN(0x4ac3f5f3, 0xd76a55bd), + TOBN(0x342508fc, 0x6b6af991), TOBN(0x0d527100, 0x1b5cebbd), + TOBN(0xb84740d0, 0xdd440dd7), TOBN(0x748ef841, 0x780162fd), + TOBN(0xa8dbfe0e, 0xdfc6fafb), TOBN(0xeadfdf05, 0xf7300f27), + TOBN(0x7d06555f, 0xfeba4ec9), TOBN(0x12c56f83, 0x9e25fa97), + TOBN(0x77f84203, 0xd39b8c34), TOBN(0xed8b1be6, 0x3125eddb), + TOBN(0x5bbf2441, 0xf6e39dc5), TOBN(0xb00f6ee6, 0x6a5d678a), + TOBN(0xba456ecf, 0x57d0ea99), TOBN(0xdcae0f58, 0x17e06c43), + TOBN(0x01643de4, 0x0f5b4baa), TOBN(0x2c324341, 0xd161b9be), + TOBN(0x80177f55, 0xe126d468), TOBN(0xed325f1f, 0x76748e09), + TOBN(0x6116004a, 0xcfa9bdc2), TOBN(0x2d8607e6, 0x3a9fb468), + TOBN(0x0e573e27, 0x6009d660), TOBN(0x3a525d2e, 0x8d10c5a1), + TOBN(0xd26cb45c, 0x3b9009a0), TOBN(0xb6b0cdc0, 0xde9d7448), + TOBN(0x949c9976, 0xe1337c26), TOBN(0x6faadebd, 0xd73d68e5), + TOBN(0x9e158614, 0xf1b768d9), TOBN(0x22dfa557, 0x9cc4f069), + TOBN(0xccd6da17, 0xbe93c6d6), TOBN(0x24866c61, 0xa504f5b9), + TOBN(0x2121353c, 0x8d694da1), TOBN(0x1c6ca580, 0x0140b8c6), + TOBN(0xc245ad8c, 0xe964021e), TOBN(0xb83bffba, 0x032b82b3), + TOBN(0xfaa220c6, 0x47ef9898), TOBN(0x7e8d3ac6, 0x982c948a), + TOBN(0x1faa2091, 0xbc2d124a), TOBN(0xbd54c3dd, 0x05b15ff4), + TOBN(0x386bf3ab, 0xc87c6fb7), TOBN(0xfb2b0563, 0xfdeb6f66), + TOBN(0x4e77c557, 0x5b45afb4), TOBN(0xe9ded649, 0xefb8912d), + TOBN(0x7ec9bbf5, 0x42f6e557), TOBN(0x2570dfff, 0x62671f00), + TOBN(0x2b3bfb78, 0x88e084bd), TOBN(0xa024b238, 0xf37fe5b4), + TOBN(0x44e7dc04, 0x95649aee), TOBN(0x498ca255, 0x5e7ec1d8), + TOBN(0x3bc766ea, 0xaaa07e86), TOBN(0x0db6facb, 0xf3608586), + TOBN(0xbadd2549, 0xbdc259c8), TOBN(0x95af3c6e, 0x041c649f), + TOBN(0xb36a928c, 0x02e30afb), TOBN(0x9b5356ad, 0x008a88b8), + TOBN(0x4b67a5f1, 0xcf1d9e9d), TOBN(0xc6542e47, 0xa5d8d8ce), + TOBN(0x73061fe8, 0x7adfb6cc), TOBN(0xcc826fd3, 0x98678141), + TOBN(0x00e758b1, 0x3c80515a), TOBN(0x6afe3247, 0x41485083), + TOBN(0x0fcb08b9, 0xb6ae8a75), TOBN(0xb8cf388d, 0x4acf51e1), + TOBN(0x344a5560, 0x6961b9d6), TOBN(0x1a6778b8, 0x6a97fd0c), + TOBN(0xd840fdc1, 0xecc4c7e3), TOBN(0xde9fe47d, 0x16db68cc), + TOBN(0xe95f89de, 0xa3e216aa), TOBN(0x84f1a6a4, 0x9594a8be), + TOBN(0x7ddc7d72, 0x5a7b162b), TOBN(0xc5cfda19, 0xadc817a3), + TOBN(0x80a5d350, 0x78b58d46), TOBN(0x93365b13, 0x82978f19), + TOBN(0x2e44d225, 0x26a1fc90), TOBN(0x0d6d10d2, 0x4d70705d), + TOBN(0xd94b6b10, 0xd70c45f4), TOBN(0x0f201022, 0xb216c079), + TOBN(0xcec966c5, 0x658fde41), TOBN(0xa8d2bc7d, 0x7e27601d), + TOBN(0xbfcce3e1, 0xff230be7), TOBN(0x3394ff6b, 0x0033ffb5), + TOBN(0xd890c509, 0x8132c9af), TOBN(0xaac4b0eb, 0x361e7868), + TOBN(0x5194ded3, 0xe82d15aa), TOBN(0x4550bd2e, 0x23ae6b7d), + TOBN(0x3fda318e, 0xea5399d4), TOBN(0xd989bffa, 0x91638b80), + TOBN(0x5ea124d0, 0xa14aa12d), TOBN(0x1fb1b899, 0x3667b944), + TOBN(0x95ec7969, 0x44c44d6a), TOBN(0x91df144a, 0x57e86137), + TOBN(0x915fd620, 0x73adac44), TOBN(0x8f01732d, 0x59a83801), + TOBN(0xec579d25, 0x3aa0a633), TOBN(0x06de5e7c, 0xc9d6d59c), + TOBN(0xc132f958, 0xb1ef8010), TOBN(0x29476f96, 0xe65c1a02), + TOBN(0x336a77c0, 0xd34c3565), TOBN(0xef1105b2, 0x1b9f1e9e), + TOBN(0x63e6d08b, 0xf9e08002), TOBN(0x9aff2f21, 0xc613809e), + TOBN(0xb5754f85, 0x3a80e75d), TOBN(0xde71853e, 0x6bbda681), + TOBN(0x86f041df, 0x8197fd7a), TOBN(0x8b332e08, 0x127817fa), + TOBN(0x05d99be8, 0xb9c20cda), TOBN(0x89f7aad5, 0xd5cd0c98), + TOBN(0x7ef936fe, 0x5bb94183), TOBN(0x92ca0753, 0xb05cd7f2), + TOBN(0x9d65db11, 0x74a1e035), TOBN(0x02628cc8, 0x13eaea92), + TOBN(0xf2d9e242, 0x49e4fbf2), TOBN(0x94fdfd9b, 0xe384f8b7), + TOBN(0x65f56054, 0x63428c6b), TOBN(0x2f7205b2, 0x90b409a5), + TOBN(0xf778bb78, 0xff45ae11), TOBN(0xa13045be, 0xc5ee53b2), + TOBN(0xe00a14ff, 0x03ef77fe), TOBN(0x689cd59f, 0xffef8bef), + TOBN(0x3578f0ed, 0x1e9ade22), TOBN(0xe99f3ec0, 0x6268b6a8), + TOBN(0xa2057d91, 0xea1b3c3e), TOBN(0x2d1a7053, 0xb8823a4a), + TOBN(0xabbb336a, 0x2cca451e), TOBN(0xcd2466e3, 0x2218bb5d), + TOBN(0x3ac1f42f, 0xc8cb762d), TOBN(0x7e312aae, 0x7690211f), + TOBN(0xebb9bd73, 0x45d07450), TOBN(0x207c4b82, 0x46c2213f), + TOBN(0x99d425c1, 0x375913ec), TOBN(0x94e45e96, 0x67908220), + TOBN(0xc08f3087, 0xcd67dbf6), TOBN(0xa5670fbe, 0xc0887056), + TOBN(0x6717b64a, 0x66f5b8fc), TOBN(0xd5a56aea, 0x786fec28), + TOBN(0xa8c3f55f, 0xc0ff4952), TOBN(0xa77fefae, 0x457ac49b), + TOBN(0x29882d7c, 0x98379d44), TOBN(0xd000bdfb, 0x509edc8a), + TOBN(0xc6f95979, 0xe66fe464), TOBN(0x504a6115, 0xfa61bde0), + TOBN(0x56b3b871, 0xeffea31a), TOBN(0x2d3de26d, 0xf0c21a54), + TOBN(0x21dbff31, 0x834753bf), TOBN(0xe67ecf49, 0x69269d86), + TOBN(0x7a176952, 0x151fe690), TOBN(0x03515804, 0x7f2adb5f), + TOBN(0xee794b15, 0xd1b62a8d), TOBN(0xf004ceec, 0xaae454e6), + TOBN(0x0897ea7c, 0xf0386fac), TOBN(0x3b62ff12, 0xd1fca751), + TOBN(0x154181df, 0x1b7a04ec), TOBN(0x2008e04a, 0xfb5847ec), + TOBN(0xd147148e, 0x41dbd772), TOBN(0x2b419f73, 0x22942654), + TOBN(0x669f30d3, 0xe9c544f7), TOBN(0x52a2c223, 0xc8540149), + TOBN(0x5da9ee14, 0x634dfb02), TOBN(0x5f074ff0, 0xf47869f3), + TOBN(0x74ee878d, 0xa3933acc), TOBN(0xe6510651, 0x4fe35ed1), + TOBN(0xb3eb9482, 0xf1012e7a), TOBN(0x51013cc0, 0xa8a566ae), + TOBN(0xdd5e9243, 0x47c00d3b), TOBN(0x7fde089d, 0x946bb0e5), + TOBN(0x030754fe, 0xc731b4b3), TOBN(0x12a136a4, 0x99fda062), + TOBN(0x7c1064b8, 0x5a1a35bc), TOBN(0xbf1f5763, 0x446c84ef), + TOBN(0xed29a56d, 0xa16d4b34), TOBN(0x7fba9d09, 0xdca21c4f), + TOBN(0x66d7ac00, 0x6d8de486), TOBN(0x60061987, 0x73a2a5e1), + TOBN(0x8b400f86, 0x9da28ff0), TOBN(0x3133f708, 0x43c4599c), + TOBN(0x9911c9b8, 0xee28cb0d), TOBN(0xcd7e2874, 0x8e0af61d), + TOBN(0x5a85f0f2, 0x72ed91fc), TOBN(0x85214f31, 0x9cd4a373), + TOBN(0x881fe5be, 0x1925253c), TOBN(0xd8dc98e0, 0x91e8bc76), + TOBN(0x7120affe, 0x585cc3a2), TOBN(0x724952ed, 0x735bf97a), + TOBN(0x5581e7dc, 0x3eb34581), TOBN(0x5cbff4f2, 0xe52ee57d), + TOBN(0x8d320a0e, 0x87d8cc7b), TOBN(0x9beaa7f3, 0xf1d280d0), + TOBN(0x7a0b9571, 0x9beec704), TOBN(0x9126332e, 0x5b7f0057), + TOBN(0x01fbc1b4, 0x8ed3bd6d), TOBN(0x35bb2c12, 0xd945eb24), + TOBN(0x6404694e, 0x9a8ae255), TOBN(0xb6092eec, 0x8d6abfb3), + TOBN(0x4d76143f, 0xcc058865), TOBN(0x7b0a5af2, 0x6e249922), + TOBN(0x8aef9440, 0x6a50d353), TOBN(0xe11e4bcc, 0x64f0e07a), + TOBN(0x4472993a, 0xa14a90fa), TOBN(0x7706e20c, 0xba0c51d4), + TOBN(0xf403292f, 0x1532672d), TOBN(0x52573bfa, 0x21829382), + TOBN(0x6a7bb6a9, 0x3b5bdb83), TOBN(0x08da65c0, 0xa4a72318), + TOBN(0xc58d22aa, 0x63eb065f), TOBN(0x1717596c, 0x1b15d685), + TOBN(0x112df0d0, 0xb266d88b), TOBN(0xf688ae97, 0x5941945a), + TOBN(0x487386e3, 0x7c292cac), TOBN(0x42f3b50d, 0x57d6985c), + TOBN(0x6da4f998, 0x6a90fc34), TOBN(0xc8f257d3, 0x65ca8a8d), + TOBN(0xc2feabca, 0x6951f762), TOBN(0xe1bc81d0, 0x74c323ac), + TOBN(0x1bc68f67, 0x251a2a12), TOBN(0x10d86587, 0xbe8a70dc), + TOBN(0xd648af7f, 0xf0f84d2e), TOBN(0xf0aa9ebc, 0x6a43ac92), + TOBN(0x69e3be04, 0x27596893), TOBN(0xb6bb02a6, 0x45bf452b), + TOBN(0x0875c11a, 0xf4c698c8), TOBN(0x6652b5c7, 0xbece3794), + TOBN(0x7b3755fd, 0x4f5c0499), TOBN(0x6ea16558, 0xb5532b38), + TOBN(0xd1c69889, 0xa2e96ef7), TOBN(0x9c773c3a, 0x61ed8f48), + TOBN(0x2b653a40, 0x9b323abc), TOBN(0xe26605e1, 0xf0e1d791), + TOBN(0x45d41064, 0x4a87157a), TOBN(0x8f9a78b7, 0xcbbce616), + TOBN(0xcf1e44aa, 0xc407eddd), TOBN(0x81ddd1d8, 0xa35b964f), + TOBN(0x473e339e, 0xfd083999), TOBN(0x6c94bdde, 0x8e796802), + TOBN(0x5a304ada, 0x8545d185), TOBN(0x82ae44ea, 0x738bb8cb), + TOBN(0x628a35e3, 0xdf87e10e), TOBN(0xd3624f3d, 0xa15b9fe3), + TOBN(0xcc44209b, 0x14be4254), TOBN(0x7d0efcbc, 0xbdbc2ea5), + TOBN(0x1f603362, 0x04c37bbe), TOBN(0x21f363f5, 0x56a5852c), + TOBN(0xa1503d1c, 0xa8501550), TOBN(0x2251e0e1, 0xd8ab10bb), + TOBN(0xde129c96, 0x6961c51c), TOBN(0x1f7246a4, 0x81910f68), + TOBN(0x2eb744ee, 0x5f2591f2), TOBN(0x3c47d33f, 0x5e627157), + TOBN(0x4d6d62c9, 0x22f3bd68), TOBN(0x6120a64b, 0xcb8df856), + TOBN(0x3a9ac6c0, 0x7b5d07df), TOBN(0xa92b9558, 0x7ef39783), + TOBN(0xe128a134, 0xab3a9b4f), TOBN(0x41c18807, 0xb1252f05), + TOBN(0xfc7ed089, 0x80ba9b1c), TOBN(0xac8dc6de, 0xc532a9dd), + TOBN(0xbf829cef, 0x55246809), TOBN(0x101b784f, 0x5b4ee80f), + TOBN(0xc09945bb, 0xb6f11603), TOBN(0x57b09dbe, 0x41d2801e), + TOBN(0xfba5202f, 0xa97534a8), TOBN(0x7fd8ae5f, 0xc17b9614), + TOBN(0xa50ba666, 0x78308435), TOBN(0x9572f77c, 0xd3868c4d), + TOBN(0x0cef7bfd, 0x2dd7aab0), TOBN(0xe7958e08, 0x2c7c79ff), + TOBN(0x81262e42, 0x25346689), TOBN(0x716da290, 0xb07c7004), + TOBN(0x35f911ea, 0xb7950ee3), TOBN(0x6fd72969, 0x261d21b5), + TOBN(0x52389803, 0x08b640d3), TOBN(0x5b0026ee, 0x887f12a1), + TOBN(0x20e21660, 0x742e9311), TOBN(0x0ef6d541, 0x5ff77ff7), + TOBN(0x969127f0, 0xf9c41135), TOBN(0xf21d60c9, 0x68a64993), + TOBN(0x656e5d0c, 0xe541875c), TOBN(0xf1e0f84e, 0xa1d3c233), + TOBN(0x9bcca359, 0x06002d60), TOBN(0xbe2da60c, 0x06191552), + TOBN(0x5da8bbae, 0x61181ec3), TOBN(0x9f04b823, 0x65806f19), + TOBN(0xf1604a7d, 0xd4b79bb8), TOBN(0xaee806fb, 0x52c878c8), + TOBN(0x34144f11, 0x8d47b8e8), TOBN(0x72edf52b, 0x949f9054), + TOBN(0xebfca84e, 0x2127015a), TOBN(0x9051d0c0, 0x9cb7cef3), + TOBN(0x86e8fe58, 0x296deec8), TOBN(0x33b28188, 0x41010d74)}, + {TOBN(0x01079383, 0x171b445f), TOBN(0x9bcf21e3, 0x8131ad4c), + TOBN(0x8cdfe205, 0xc93987e8), TOBN(0xe63f4152, 0xc92e8c8f), + TOBN(0x729462a9, 0x30add43d), TOBN(0x62ebb143, 0xc980f05a), + TOBN(0x4f3954e5, 0x3b06e968), TOBN(0xfe1d75ad, 0x242cf6b1), + TOBN(0x5f95c6c7, 0xaf8685c8), TOBN(0xd4c1c8ce, 0x2f8f01aa), + TOBN(0xc44bbe32, 0x2574692a), TOBN(0xb8003478, 0xd4a4a068), + TOBN(0x7c8fc6e5, 0x2eca3cdb), TOBN(0xea1db16b, 0xec04d399), + TOBN(0xb05bc82e, 0x8f2bc5cf), TOBN(0x763d517f, 0xf44793d2), + TOBN(0x4451c1b8, 0x08bd98d0), TOBN(0x644b1cd4, 0x6575f240), + TOBN(0x6907eb33, 0x7375d270), TOBN(0x56c8bebd, 0xfa2286bd), + TOBN(0xc713d2ac, 0xc4632b46), TOBN(0x17da427a, 0xafd60242), + TOBN(0x313065b7, 0xc95c7546), TOBN(0xf8239898, 0xbf17a3de), + TOBN(0xf3b7963f, 0x4c830320), TOBN(0x842c7aa0, 0x903203e3), + TOBN(0xaf22ca0a, 0xe7327afb), TOBN(0x38e13092, 0x967609b6), + TOBN(0x73b8fb62, 0x757558f1), TOBN(0x3cc3e831, 0xf7eca8c1), + TOBN(0xe4174474, 0xf6331627), TOBN(0xa77989ca, 0xc3c40234), + TOBN(0xe5fd17a1, 0x44a081e0), TOBN(0xd797fb7d, 0xb70e296a), + TOBN(0x2b472b30, 0x481f719c), TOBN(0x0e632a98, 0xfe6f8c52), + TOBN(0x89ccd116, 0xc5f0c284), TOBN(0xf51088af, 0x2d987c62), + TOBN(0x2a2bccda, 0x4c2de6cf), TOBN(0x810f9efe, 0xf679f0f9), + TOBN(0xb0f394b9, 0x7ffe4b3e), TOBN(0x0b691d21, 0xe5fa5d21), + TOBN(0xb0bd7747, 0x9dfbbc75), TOBN(0xd2830fda, 0xfaf78b00), + TOBN(0xf78c249c, 0x52434f57), TOBN(0x4b1f7545, 0x98096dab), + TOBN(0x73bf6f94, 0x8ff8c0b3), TOBN(0x34aef03d, 0x454e134c), + TOBN(0xf8d151f4, 0xb7ac7ec5), TOBN(0xd6ceb95a, 0xe50da7d5), + TOBN(0xa1b492b0, 0xdc3a0eb8), TOBN(0x75157b69, 0xb3dd2863), + TOBN(0xe2c4c74e, 0xc5413d62), TOBN(0xbe329ff7, 0xbc5fc4c7), + TOBN(0x835a2aea, 0x60fa9dda), TOBN(0xf117f5ad, 0x7445cb87), + TOBN(0xae8317f4, 0xb0166f7a), TOBN(0xfbd3e3f7, 0xceec74e6), + TOBN(0xfdb516ac, 0xe0874bfd), TOBN(0x3d846019, 0xc681f3a3), + TOBN(0x0b12ee5c, 0x7c1620b0), TOBN(0xba68b4dd, 0x2b63c501), + TOBN(0xac03cd32, 0x6668c51e), TOBN(0x2a6279f7, 0x4e0bcb5b), + TOBN(0x17bd69b0, 0x6ae85c10), TOBN(0x72946979, 0x1dfdd3a6), + TOBN(0xd9a03268, 0x2c078bec), TOBN(0x41c6a658, 0xbfd68a52), + TOBN(0xcdea1024, 0x0e023900), TOBN(0xbaeec121, 0xb10d144d), + TOBN(0x5a600e74, 0x058ab8dc), TOBN(0x1333af21, 0xbb89ccdd), + TOBN(0xdf25eae0, 0x3aaba1f1), TOBN(0x2cada16e, 0x3b7144cf), + TOBN(0x657ee27d, 0x71ab98bc), TOBN(0x99088b4c, 0x7a6fc96e), + TOBN(0x05d5c0a0, 0x3549dbd4), TOBN(0x42cbdf8f, 0xf158c3ac), + TOBN(0x3fb6b3b0, 0x87edd685), TOBN(0x22071cf6, 0x86f064d0), + TOBN(0xd2d6721f, 0xff2811e5), TOBN(0xdb81b703, 0xfe7fae8c), + TOBN(0x3cfb74ef, 0xd3f1f7bb), TOBN(0x0cdbcd76, 0x16cdeb5d), + TOBN(0x4f39642a, 0x566a808c), TOBN(0x02b74454, 0x340064d6), + TOBN(0xfabbadca, 0x0528fa6f), TOBN(0xe4c3074c, 0xd3fc0bb6), + TOBN(0xb32cb8b0, 0xb796d219), TOBN(0xc3e95f4f, 0x34741dd9), + TOBN(0x87212125, 0x68edf6f5), TOBN(0x7a03aee4, 0xa2b9cb8e), + TOBN(0x0cd3c376, 0xf53a89aa), TOBN(0x0d8af9b1, 0x948a28dc), + TOBN(0xcf86a3f4, 0x902ab04f), TOBN(0x8aacb62a, 0x7f42002d), + TOBN(0x106985eb, 0xf62ffd52), TOBN(0xe670b54e, 0x5797bf10), + TOBN(0x4b405209, 0xc5e30aef), TOBN(0x12c97a20, 0x4365b5e9), + TOBN(0x104646ce, 0x1fe32093), TOBN(0x13cb4ff6, 0x3907a8c9), + TOBN(0x8b9f30d1, 0xd46e726b), TOBN(0xe1985e21, 0xaba0f499), + TOBN(0xc573dea9, 0x10a230cd), TOBN(0x24f46a93, 0xcd30f947), + TOBN(0xf2623fcf, 0xabe2010a), TOBN(0x3f278cb2, 0x73f00e4f), + TOBN(0xed55c67d, 0x50b920eb), TOBN(0xf1cb9a2d, 0x8e760571), + TOBN(0x7c50d109, 0x0895b709), TOBN(0x4207cf07, 0x190d4369), + TOBN(0x3b027e81, 0xc4127fe1), TOBN(0xa9f8b9ad, 0x3ae9c566), + TOBN(0x5ab10851, 0xacbfbba5), TOBN(0xa747d648, 0x569556f5), + TOBN(0xcc172b5c, 0x2ba97bf7), TOBN(0x15e0f77d, 0xbcfa3324), + TOBN(0xa345b797, 0x7686279d), TOBN(0x5a723480, 0xe38003d3), + TOBN(0xfd8e139f, 0x8f5fcda8), TOBN(0xf3e558c4, 0xbdee5bfd), + TOBN(0xd76cbaf4, 0xe33f9f77), TOBN(0x3a4c97a4, 0x71771969), + TOBN(0xda27e84b, 0xf6dce6a7), TOBN(0xff373d96, 0x13e6c2d1), + TOBN(0xf115193c, 0xd759a6e9), TOBN(0x3f9b7025, 0x63d2262c), + TOBN(0xd9764a31, 0x317cd062), TOBN(0x30779d8e, 0x199f8332), + TOBN(0xd8074106, 0x16b11b0b), TOBN(0x7917ab9f, 0x78aeaed8), + TOBN(0xb67a9cbe, 0x28fb1d8e), TOBN(0x2e313563, 0x136eda33), + TOBN(0x010b7069, 0xa371a86c), TOBN(0x44d90fa2, 0x6744e6b7), + TOBN(0x68190867, 0xd6b3e243), TOBN(0x9fe6cd9d, 0x59048c48), + TOBN(0xb900b028, 0x95731538), TOBN(0xa012062f, 0x32cae04f), + TOBN(0x8107c8bc, 0x9399d082), TOBN(0x47e8c54a, 0x41df12e2), + TOBN(0x14ba5117, 0xb6ef3f73), TOBN(0x22260bea, 0x81362f0b), + TOBN(0x90ea261e, 0x1a18cc20), TOBN(0x2192999f, 0x2321d636), + TOBN(0xef64d314, 0xe311b6a0), TOBN(0xd7401e4c, 0x3b54a1f5), + TOBN(0x19019983, 0x6fbca2ba), TOBN(0x46ad3293, 0x8fbffc4b), + TOBN(0xa142d3f6, 0x3786bf40), TOBN(0xeb5cbc26, 0xb67039fc), + TOBN(0x9cb0ae6c, 0x252bd479), TOBN(0x05e0f88a, 0x12b5848f), + TOBN(0x78f6d2b2, 0xa5c97663), TOBN(0x6f6e149b, 0xc162225c), + TOBN(0xe602235c, 0xde601a89), TOBN(0xd17bbe98, 0xf373be1f), + TOBN(0xcaf49a5b, 0xa8471827), TOBN(0x7e1a0a85, 0x18aaa116), + TOBN(0x6c833196, 0x270580c3), TOBN(0x1e233839, 0xf1c98a14), + TOBN(0x67b2f7b4, 0xae34e0a5), TOBN(0x47ac8745, 0xd8ce7289), + TOBN(0x2b74779a, 0x100dd467), TOBN(0x274a4337, 0x4ee50d09), + TOBN(0x603dcf13, 0x83608bc9), TOBN(0xcd9da6c3, 0xc89e8388), + TOBN(0x2660199f, 0x355116ac), TOBN(0xcc38bb59, 0xb6d18eed), + TOBN(0x3075f31f, 0x2f4bc071), TOBN(0x9774457f, 0x265dc57e), + TOBN(0x06a6a9c8, 0xc6db88bb), TOBN(0x6429d07f, 0x4ec98e04), + TOBN(0x8d05e57b, 0x05ecaa8b), TOBN(0x20f140b1, 0x7872ea7b), + TOBN(0xdf8c0f09, 0xca494693), TOBN(0x48d3a020, 0xf252e909), + TOBN(0x4c5c29af, 0x57b14b12), TOBN(0x7e6fa37d, 0xbf47ad1c), + TOBN(0x66e7b506, 0x49a0c938), TOBN(0xb72c0d48, 0x6be5f41f), + TOBN(0x6a6242b8, 0xb2359412), TOBN(0xcd35c774, 0x8e859480), + TOBN(0x12536fea, 0x87baa627), TOBN(0x58c1fec1, 0xf72aa680), + TOBN(0x6c29b637, 0x601e5dc9), TOBN(0x9e3c3c1c, 0xde9e01b9), + TOBN(0xefc8127b, 0x2bcfe0b0), TOBN(0x35107102, 0x2a12f50d), + TOBN(0x6ccd6cb1, 0x4879b397), TOBN(0xf792f804, 0xf8a82f21), + TOBN(0x509d4804, 0xa9b46402), TOBN(0xedddf85d, 0xc10f0850), + TOBN(0x928410dc, 0x4b6208aa), TOBN(0xf6229c46, 0x391012dc), + TOBN(0xc5a7c41e, 0x7727b9b6), TOBN(0x289e4e4b, 0xaa444842), + TOBN(0x049ba1d9, 0xe9a947ea), TOBN(0x44f9e47f, 0x83c8debc), + TOBN(0xfa77a1fe, 0x611f8b8e), TOBN(0xfd2e416a, 0xf518f427), + TOBN(0xc5fffa70, 0x114ebac3), TOBN(0xfe57c4e9, 0x5d89697b), + TOBN(0xfdd053ac, 0xb1aaf613), TOBN(0x31df210f, 0xea585a45), + TOBN(0x318cc10e, 0x24985034), TOBN(0x1a38efd1, 0x5f1d6130), + TOBN(0xbf86f237, 0x0b1e9e21), TOBN(0xb258514d, 0x1dbe88aa), + TOBN(0x1e38a588, 0x90c1baf9), TOBN(0x2936a01e, 0xbdb9b692), + TOBN(0xd576de98, 0x6dd5b20c), TOBN(0xb586bf71, 0x70f98ecf), + TOBN(0xcccf0f12, 0xc42d2fd7), TOBN(0x8717e61c, 0xfb35bd7b), + TOBN(0x8b1e5722, 0x35e6fc06), TOBN(0x3477728f, 0x0b3e13d5), + TOBN(0x150c294d, 0xaa8a7372), TOBN(0xc0291d43, 0x3bfa528a), + TOBN(0xc6c8bc67, 0xcec5a196), TOBN(0xdeeb31e4, 0x5c2e8a7c), + TOBN(0xba93e244, 0xfb6e1c51), TOBN(0xb9f8b71b, 0x2e28e156), + TOBN(0xce65a287, 0x968a2ab9), TOBN(0xe3c5ce69, 0x46bbcb1f), + TOBN(0xf8c835b9, 0xe7ae3f30), TOBN(0x16bbee26, 0xff72b82b), + TOBN(0x665e2017, 0xfd42cd22), TOBN(0x1e139970, 0xf8b1d2a0), + TOBN(0x125cda29, 0x79204932), TOBN(0x7aee94a5, 0x49c3bee5), + TOBN(0x68c70160, 0x89821a66), TOBN(0xf7c37678, 0x8f981669), + TOBN(0xd90829fc, 0x48cc3645), TOBN(0x346af049, 0xd70addfc), + TOBN(0x2057b232, 0x370bf29c), TOBN(0xf90c73ce, 0x42e650ee), + TOBN(0xe03386ea, 0xa126ab90), TOBN(0x0e266e7e, 0x975a087b), + TOBN(0x80578eb9, 0x0fca65d9), TOBN(0x7e2989ea, 0x16af45b8), + TOBN(0x7438212d, 0xcac75a4e), TOBN(0x38c7ca39, 0x4fef36b8), + TOBN(0x8650c494, 0xd402676a), TOBN(0x26ab5a66, 0xf72c7c48), + TOBN(0x4e6cb426, 0xce3a464e), TOBN(0xf8f99896, 0x2b72f841), + TOBN(0x8c318491, 0x1a335cc8), TOBN(0x563459ba, 0x6a5913e4), + TOBN(0x1b920d61, 0xc7b32919), TOBN(0x805ab8b6, 0xa02425ad), + TOBN(0x2ac512da, 0x8d006086), TOBN(0x6ca4846a, 0xbcf5c0fd), + TOBN(0xafea51d8, 0xac2138d7), TOBN(0xcb647545, 0x344cd443), + TOBN(0x0429ee8f, 0xbd7d9040), TOBN(0xee66a2de, 0x819b9c96), + TOBN(0x54f9ec25, 0xdea7d744), TOBN(0x2ffea642, 0x671721bb), + TOBN(0x4f19dbd1, 0x114344ea), TOBN(0x04304536, 0xfd0dbc8b), + TOBN(0x014b50aa, 0x29ec7f91), TOBN(0xb5fc22fe, 0xbb06014d), + TOBN(0x60d963a9, 0x1ee682e0), TOBN(0xdf48abc0, 0xfe85c727), + TOBN(0x0cadba13, 0x2e707c2d), TOBN(0xde608d3a, 0xa645aeff), + TOBN(0x05f1c28b, 0xedafd883), TOBN(0x3c362ede, 0xbd94de1f), + TOBN(0x8dd0629d, 0x13593e41), TOBN(0x0a5e736f, 0x766d6eaf), + TOBN(0xbfa92311, 0xf68cf9d1), TOBN(0xa4f9ef87, 0xc1797556), + TOBN(0x10d75a1f, 0x5601c209), TOBN(0x651c374c, 0x09b07361), + TOBN(0x49950b58, 0x88b5cead), TOBN(0x0ef00058, 0x6fa9dbaa), + TOBN(0xf51ddc26, 0x4e15f33a), TOBN(0x1f8b5ca6, 0x2ef46140), + TOBN(0x343ac0a3, 0xee9523f0), TOBN(0xbb75eab2, 0x975ea978), + TOBN(0x1bccf332, 0x107387f4), TOBN(0x790f9259, 0x9ab0062e), + TOBN(0xf1a363ad, 0x1e4f6a5f), TOBN(0x06e08b84, 0x62519a50), + TOBN(0x60915187, 0x7265f1ee), TOBN(0x6a80ca34, 0x93ae985e), + TOBN(0x81b29768, 0xaaba4864), TOBN(0xb13cabf2, 0x8d52a7d6), + TOBN(0xb5c36348, 0x8ead03f1), TOBN(0xc932ad95, 0x81c7c1c0), + TOBN(0x5452708e, 0xcae1e27b), TOBN(0x9dac4269, 0x1b0df648), + TOBN(0x233e3f0c, 0xdfcdb8bc), TOBN(0xe6ceccdf, 0xec540174), + TOBN(0xbd0d845e, 0x95081181), TOBN(0xcc8a7920, 0x699355d5), + TOBN(0x111c0f6d, 0xc3b375a8), TOBN(0xfd95bc6b, 0xfd51e0dc), + TOBN(0x4a106a26, 0x6888523a), TOBN(0x4d142bd6, 0xcb01a06d), + TOBN(0x79bfd289, 0xadb9b397), TOBN(0x0bdbfb94, 0xe9863914), + TOBN(0x29d8a229, 0x1660f6a6), TOBN(0x7f6abcd6, 0x551c042d), + TOBN(0x13039deb, 0x0ac3ffe8), TOBN(0xa01be628, 0xec8523fb), + TOBN(0x6ea34103, 0x0ca1c328), TOBN(0xc74114bd, 0xb903928e), + TOBN(0x8aa4ff4e, 0x9e9144b0), TOBN(0x7064091f, 0x7f9a4b17), + TOBN(0xa3f4f521, 0xe447f2c4), TOBN(0x81b8da7a, 0x604291f0), + TOBN(0xd680bc46, 0x7d5926de), TOBN(0x84f21fd5, 0x34a1202f), + TOBN(0x1d1e3181, 0x4e9df3d8), TOBN(0x1ca4861a, 0x39ab8d34), + TOBN(0x809ddeec, 0x5b19aa4a), TOBN(0x59f72f7e, 0x4d329366), + TOBN(0xa2f93f41, 0x386d5087), TOBN(0x40bf739c, 0xdd67d64f), + TOBN(0xb4494205, 0x66702158), TOBN(0xc33c65be, 0x73b1e178), + TOBN(0xcdcd657c, 0x38ca6153), TOBN(0x97f4519a, 0xdc791976), + TOBN(0xcc7c7f29, 0xcd6e1f39), TOBN(0x38de9cfb, 0x7e3c3932), + TOBN(0xe448eba3, 0x7b793f85), TOBN(0xe9f8dbf9, 0xf067e914), + TOBN(0xc0390266, 0xf114ae87), TOBN(0x39ed75a7, 0xcd6a8e2a), + TOBN(0xadb14848, 0x7ffba390), TOBN(0x67f8cb8b, 0x6af9bc09), + TOBN(0x322c3848, 0x9c7476db), TOBN(0xa320fecf, 0x52a538d6), + TOBN(0xe0493002, 0xb2aced2b), TOBN(0xdfba1809, 0x616bd430), + TOBN(0x531c4644, 0xc331be70), TOBN(0xbc04d32e, 0x90d2e450), + TOBN(0x1805a0d1, 0x0f9f142d), TOBN(0x2c44a0c5, 0x47ee5a23), + TOBN(0x31875a43, 0x3989b4e3), TOBN(0x6b1949fd, 0x0c063481), + TOBN(0x2dfb9e08, 0xbe0f4492), TOBN(0x3ff0da03, 0xe9d5e517), + TOBN(0x03dbe9a1, 0xf79466a8), TOBN(0x0b87bcd0, 0x15ea9932), + TOBN(0xeb64fc83, 0xab1f58ab), TOBN(0x6d9598da, 0x817edc8a), + TOBN(0x699cff66, 0x1d3b67e5), TOBN(0x645c0f29, 0x92635853), + TOBN(0x253cdd82, 0xeabaf21c), TOBN(0x82b9602a, 0x2241659e), + TOBN(0x2cae07ec, 0x2d9f7091), TOBN(0xbe4c720c, 0x8b48cd9b), + TOBN(0x6ce5bc03, 0x6f08d6c9), TOBN(0x36e8a997, 0xaf10bf40), + TOBN(0x83422d21, 0x3e10ff12), TOBN(0x7b26d3eb, 0xbcc12494), + TOBN(0xb240d2d0, 0xc9469ad6), TOBN(0xc4a11b4d, 0x30afa05b), + TOBN(0x4b604ace, 0xdd6ba286), TOBN(0x18486600, 0x3ee2864c), + TOBN(0x5869d6ba, 0x8d9ce5be), TOBN(0x0d8f68c5, 0xff4bfb0d), + TOBN(0xb69f210b, 0x5700cf73), TOBN(0x61f6653a, 0x6d37c135), + TOBN(0xff3d432b, 0x5aff5a48), TOBN(0x0d81c4b9, 0x72ba3a69), + TOBN(0xee879ae9, 0xfa1899ef), TOBN(0xbac7e2a0, 0x2d6acafd), + TOBN(0xd6d93f6c, 0x1c664399), TOBN(0x4c288de1, 0x5bcb135d), + TOBN(0x83031dab, 0x9dab7cbf), TOBN(0xfe23feb0, 0x3abbf5f0), + TOBN(0x9f1b2466, 0xcdedca85), TOBN(0x140bb710, 0x1a09538c), + TOBN(0xac8ae851, 0x5e11115d), TOBN(0x0d63ff67, 0x6f03f59e), + TOBN(0x755e5551, 0x7d234afb), TOBN(0x61c2db4e, 0x7e208fc1), + TOBN(0xaa9859ce, 0xf28a4b5d), TOBN(0xbdd6d4fc, 0x34af030f), + TOBN(0xd1c4a26d, 0x3be01cb1), TOBN(0x9ba14ffc, 0x243aa07c), + TOBN(0xf95cd3a9, 0xb2503502), TOBN(0xe379bc06, 0x7d2a93ab), + TOBN(0x3efc18e9, 0xd4ca8d68), TOBN(0x083558ec, 0x80bb412a), + TOBN(0xd903b940, 0x9645a968), TOBN(0xa499f0b6, 0x9ba6054f), + TOBN(0x208b573c, 0xb8349abe), TOBN(0x3baab3e5, 0x30b4fc1c), + TOBN(0x87e978ba, 0xcb524990), TOBN(0x3524194e, 0xccdf0e80), + TOBN(0x62711725, 0x7d4bcc42), TOBN(0xe90a3d9b, 0xb90109ba), + TOBN(0x3b1bdd57, 0x1323e1e0), TOBN(0xb78e9bd5, 0x5eae1599), + TOBN(0x0794b746, 0x9e03d278), TOBN(0x80178605, 0xd70e6297), + TOBN(0x171792f8, 0x99c97855), TOBN(0x11b393ee, 0xf5a86b5c), + TOBN(0x48ef6582, 0xd8884f27), TOBN(0xbd44737a, 0xbf19ba5f), + TOBN(0x8698de4c, 0xa42062c6), TOBN(0x8975eb80, 0x61ce9c54), + TOBN(0xd50e57c7, 0xd7fe71f3), TOBN(0x15342190, 0xbc97ce38), + TOBN(0x51bda2de, 0x4df07b63), TOBN(0xba12aeae, 0x200eb87d), + TOBN(0xabe135d2, 0xa9b4f8f6), TOBN(0x04619d65, 0xfad6d99c), + TOBN(0x4a6683a7, 0x7994937c), TOBN(0x7a778c8b, 0x6f94f09a), + TOBN(0x8c508623, 0x20a71b89), TOBN(0x241a2aed, 0x1c229165), + TOBN(0x352be595, 0xaaf83a99), TOBN(0x9fbfee7f, 0x1562bac8), + TOBN(0xeaf658b9, 0x5c4017e3), TOBN(0x1dc7f9e0, 0x15120b86), + TOBN(0xd84f13dd, 0x4c034d6f), TOBN(0x283dd737, 0xeaea3038), + TOBN(0x197f2609, 0xcd85d6a2), TOBN(0x6ebbc345, 0xfae60177), + TOBN(0xb80f031b, 0x4e12fede), TOBN(0xde55d0c2, 0x07a2186b), + TOBN(0x1fb3e37f, 0x24dcdd5a), TOBN(0x8d602da5, 0x7ed191fb), + TOBN(0x108fb056, 0x76023e0d), TOBN(0x70178c71, 0x459c20c0), + TOBN(0xfad5a386, 0x3fe54cf0), TOBN(0xa4a3ec4f, 0x02bbb475), + TOBN(0x1aa5ec20, 0x919d94d7), TOBN(0x5d3b63b5, 0xa81e4ab3), + TOBN(0x7fa733d8, 0x5ad3d2af), TOBN(0xfbc586dd, 0xd1ac7a37), + TOBN(0x282925de, 0x40779614), TOBN(0xfe0ffffb, 0xe74a242a), + TOBN(0x3f39e67f, 0x906151e5), TOBN(0xcea27f5f, 0x55e10649), + TOBN(0xdca1d4e1, 0xc17cf7b7), TOBN(0x0c326d12, 0x2fe2362d), + TOBN(0x05f7ac33, 0x7dd35df3), TOBN(0x0c3b7639, 0xc396dbdf), + TOBN(0x0912f5ac, 0x03b7db1c), TOBN(0x9dea4b70, 0x5c9ed4a9), + TOBN(0x475e6e53, 0xaae3f639), TOBN(0xfaba0e7c, 0xfc278bac), + TOBN(0x16f9e221, 0x9490375f), TOBN(0xaebf9746, 0xa5a7ed0a), + TOBN(0x45f9af3f, 0xf41ad5d6), TOBN(0x03c4623c, 0xb2e99224), + TOBN(0x82c5bb5c, 0xb3cf56aa), TOBN(0x64311819, 0x34567ed3), + TOBN(0xec57f211, 0x8be489ac), TOBN(0x2821895d, 0xb9a1104b), + TOBN(0x610dc875, 0x6064e007), TOBN(0x8e526f3f, 0x5b20d0fe), + TOBN(0x6e71ca77, 0x5b645aee), TOBN(0x3d1dcb9f, 0x800e10ff), + TOBN(0x36b51162, 0x189cf6de), TOBN(0x2c5a3e30, 0x6bb17353), + TOBN(0xc186cd3e, 0x2a6c6fbf), TOBN(0xa74516fa, 0x4bf97906), + TOBN(0x5b4b8f4b, 0x279d6901), TOBN(0x0c4e57b4, 0x2b573743), + TOBN(0x75fdb229, 0xb6e386b6), TOBN(0xb46793fd, 0x99deac27), + TOBN(0xeeec47ea, 0xcf712629), TOBN(0xe965f3c4, 0xcbc3b2dd), + TOBN(0x8dd1fb83, 0x425c6559), TOBN(0x7fc00ee6, 0x0af06fda), + TOBN(0xe98c9225, 0x33d956df), TOBN(0x0f1ef335, 0x4fbdc8a2), + TOBN(0x2abb5145, 0xb79b8ea2), TOBN(0x40fd2945, 0xbdbff288), + TOBN(0x6a814ac4, 0xd7185db7), TOBN(0xc4329d6f, 0xc084609a), + TOBN(0xc9ba7b52, 0xed1be45d), TOBN(0x891dd20d, 0xe4cd2c74), + TOBN(0x5a4d4a7f, 0x824139b1), TOBN(0x66c17716, 0xb873c710), + TOBN(0x5e5bc141, 0x2843c4e0), TOBN(0xd5ac4817, 0xb97eb5bf), + TOBN(0xc0f8af54, 0x450c95c7), TOBN(0xc91b3fa0, 0x318406c5), + TOBN(0x360c340a, 0xab9d97f8), TOBN(0xfb57bd07, 0x90a2d611), + TOBN(0x4339ae3c, 0xa6a6f7e5), TOBN(0x9c1fcd2a, 0x2feb8a10), + TOBN(0x972bcca9, 0xc7ea7432), TOBN(0x1b0b924c, 0x308076f6), + TOBN(0x80b2814a, 0x2a5b4ca5), TOBN(0x2f78f55b, 0x61ef3b29), + TOBN(0xf838744a, 0xc18a414f), TOBN(0xc611eaae, 0x903d0a86), + TOBN(0x94dabc16, 0x2a453f55), TOBN(0xe6f2e3da, 0x14efb279), + TOBN(0x5b7a6017, 0x9320dc3c), TOBN(0x692e382f, 0x8df6b5a4), + TOBN(0x3f5e15e0, 0x2d40fa90), TOBN(0xc87883ae, 0x643dd318), + TOBN(0x511053e4, 0x53544774), TOBN(0x834d0ecc, 0x3adba2bc), + TOBN(0x4215d7f7, 0xbae371f5), TOBN(0xfcfd57bf, 0x6c8663bc), + TOBN(0xded2383d, 0xd6901b1d), TOBN(0x3b49fbb4, 0xb5587dc3), + TOBN(0xfd44a08d, 0x07625f62), TOBN(0x3ee4d65b, 0x9de9b762)}, + {TOBN(0x64e5137d, 0x0d63d1fa), TOBN(0x658fc052, 0x02a9d89f), + TOBN(0x48894874, 0x50436309), TOBN(0xe9ae30f8, 0xd598da61), + TOBN(0x2ed710d1, 0x818baf91), TOBN(0xe27e9e06, 0x8b6a0c20), + TOBN(0x1e28dcfb, 0x1c1a6b44), TOBN(0x883acb64, 0xd6ac57dc), + TOBN(0x8735728d, 0xc2c6ff70), TOBN(0x79d6122f, 0xc5dc2235), + TOBN(0x23f5d003, 0x19e277f9), TOBN(0x7ee84e25, 0xdded8cc7), + TOBN(0x91a8afb0, 0x63cd880a), TOBN(0x3f3ea7c6, 0x3574af60), + TOBN(0x0cfcdc84, 0x02de7f42), TOBN(0x62d0792f, 0xb31aa152), + TOBN(0x8e1b4e43, 0x8a5807ce), TOBN(0xad283893, 0xe4109a7e), + TOBN(0xc30cc9cb, 0xafd59dda), TOBN(0xf65f36c6, 0x3d8d8093), + TOBN(0xdf31469e, 0xa60d32b2), TOBN(0xee93df4b, 0x3e8191c8), + TOBN(0x9c1017c5, 0x355bdeb5), TOBN(0xd2623185, 0x8616aa28), + TOBN(0xb02c83f9, 0xdec31a21), TOBN(0x988c8b23, 0x6ad9d573), + TOBN(0x53e983ae, 0xa57be365), TOBN(0xe968734d, 0x646f834e), + TOBN(0x9137ea8f, 0x5da6309b), TOBN(0x10f3a624, 0xc1f1ce16), + TOBN(0x782a9ea2, 0xca440921), TOBN(0xdf94739e, 0x5b46f1b5), + TOBN(0x9f9be006, 0xcce85c9b), TOBN(0x360e70d6, 0xa4c7c2d3), + TOBN(0x2cd5beea, 0xaefa1e60), TOBN(0x64cf63c0, 0x8c3d2b6d), + TOBN(0xfb107fa3, 0xe1cf6f90), TOBN(0xb7e937c6, 0xd5e044e6), + TOBN(0x74e8ca78, 0xce34db9f), TOBN(0x4f8b36c1, 0x3e210bd0), + TOBN(0x1df165a4, 0x34a35ea8), TOBN(0x3418e0f7, 0x4d4412f6), + TOBN(0x5af1f8af, 0x518836c3), TOBN(0x42ceef4d, 0x130e1965), + TOBN(0x5560ca0b, 0x543a1957), TOBN(0xc33761e5, 0x886cb123), + TOBN(0x66624b1f, 0xfe98ed30), TOBN(0xf772f4bf, 0x1090997d), + TOBN(0xf4e540bb, 0x4885d410), TOBN(0x7287f810, 0x9ba5f8d7), + TOBN(0x22d0d865, 0xde98dfb1), TOBN(0x49ff51a1, 0xbcfbb8a3), + TOBN(0xb6b6fa53, 0x6bc3012e), TOBN(0x3d31fd72, 0x170d541d), + TOBN(0x8018724f, 0x4b0f4966), TOBN(0x79e7399f, 0x87dbde07), + TOBN(0x56f8410e, 0xf4f8b16a), TOBN(0x97241afe, 0xc47b266a), + TOBN(0x0a406b8e, 0x6d9c87c1), TOBN(0x803f3e02, 0xcd42ab1b), + TOBN(0x7f0309a8, 0x04dbec69), TOBN(0xa83b85f7, 0x3bbad05f), + TOBN(0xc6097273, 0xad8e197f), TOBN(0xc097440e, 0x5067adc1), + TOBN(0x730eafb6, 0x3524ff16), TOBN(0xd7f9b51e, 0x823fc6ce), + TOBN(0x27bd0d32, 0x443e4ac0), TOBN(0x40c59ad9, 0x4d66f217), + TOBN(0x6c33136f, 0x17c387a4), TOBN(0x5043b8d5, 0xeb86804d), + TOBN(0x74970312, 0x675a73c9), TOBN(0x838fdb31, 0xf16669b6), + TOBN(0xc507b6dd, 0x418e7ddd), TOBN(0x39888d93, 0x472f19d6), + TOBN(0x7eae26be, 0x0c27eb4d), TOBN(0x17b53ed3, 0xfbabb884), + TOBN(0xfc27021b, 0x2b01ae4f), TOBN(0x88462e87, 0xcf488682), + TOBN(0xbee096ec, 0x215e2d87), TOBN(0xeb2fea9a, 0xd242e29b), + TOBN(0x5d985b5f, 0xb821fc28), TOBN(0x89d2e197, 0xdc1e2ad2), + TOBN(0x55b566b8, 0x9030ba62), TOBN(0xe3fd41b5, 0x4f41b1c6), + TOBN(0xb738ac2e, 0xb9a96d61), TOBN(0x7f8567ca, 0x369443f4), + TOBN(0x8698622d, 0xf803a440), TOBN(0x2b586236, 0x8fe2f4dc), + TOBN(0xbbcc00c7, 0x56b95bce), TOBN(0x5ec03906, 0x616da680), + TOBN(0x79162ee6, 0x72214252), TOBN(0x43132b63, 0x86a892d2), + TOBN(0x4bdd3ff2, 0x2f3263bf), TOBN(0xd5b3733c, 0x9cd0a142), + TOBN(0x592eaa82, 0x44415ccb), TOBN(0x663e8924, 0x8d5474ea), + TOBN(0x8058a25e, 0x5236344e), TOBN(0x82e8df9d, 0xbda76ee6), + TOBN(0xdcf6efd8, 0x11cc3d22), TOBN(0x00089cda, 0x3b4ab529), + TOBN(0x91d3a071, 0xbd38a3db), TOBN(0x4ea97fc0, 0xef72b925), + TOBN(0x0c9fc15b, 0xea3edf75), TOBN(0x5a6297cd, 0xa4348ed3), + TOBN(0x0d38ab35, 0xce7c42d4), TOBN(0x9fd493ef, 0x82feab10), + TOBN(0x46056b6d, 0x82111b45), TOBN(0xda11dae1, 0x73efc5c3), + TOBN(0xdc740278, 0x5545a7fb), TOBN(0xbdb2601c, 0x40d507e6), + TOBN(0x121dfeeb, 0x7066fa58), TOBN(0x214369a8, 0x39ae8c2a), + TOBN(0x195709cb, 0x06e0956c), TOBN(0x4c9d254f, 0x010cd34b), + TOBN(0xf51e13f7, 0x0471a532), TOBN(0xe19d6791, 0x1e73054d), + TOBN(0xf702a628, 0xdb5c7be3), TOBN(0xc7141218, 0xb24dde05), + TOBN(0xdc18233c, 0xf29b2e2e), TOBN(0x3a6bd1e8, 0x85342dba), + TOBN(0x3f747fa0, 0xb311898c), TOBN(0xe2a272e4, 0xcd0eac65), + TOBN(0x4bba5851, 0xf914d0bc), TOBN(0x7a1a9660, 0xc4a43ee3), + TOBN(0xe5a367ce, 0xa1c8cde9), TOBN(0x9d958ba9, 0x7271abe3), + TOBN(0xf3ff7eb6, 0x3d1615cd), TOBN(0xa2280dce, 0xf5ae20b0), + TOBN(0x56dba5c1, 0xcf640147), TOBN(0xea5a2e3d, 0x5e83d118), + TOBN(0x04cd6b6d, 0xda24c511), TOBN(0x1c0f4671, 0xe854d214), + TOBN(0x91a6b7a9, 0x69565381), TOBN(0xdc966240, 0xdecf1f5b), + TOBN(0x1b22d21c, 0xfcf5d009), TOBN(0x2a05f641, 0x9021dbd5), + TOBN(0x8c0ed566, 0xd4312483), TOBN(0x5179a95d, 0x643e216f), + TOBN(0xcc185fec, 0x17044493), TOBN(0xb3063339, 0x54991a21), + TOBN(0xd801ecdb, 0x0081a726), TOBN(0x0149b0c6, 0x4fa89bbb), + TOBN(0xafe9065a, 0x4391b6b9), TOBN(0xedc92786, 0xd633f3a3), + TOBN(0xe408c24a, 0xae6a8e13), TOBN(0x85833fde, 0x9f3897ab), + TOBN(0x43800e7e, 0xd81a0715), TOBN(0xde08e346, 0xb44ffc5f), + TOBN(0x7094184c, 0xcdeff2e0), TOBN(0x49f9387b, 0x165eaed1), + TOBN(0x635d6129, 0x777c468a), TOBN(0x8c0dcfd1, 0x538c2dd8), + TOBN(0xd6d9d9e3, 0x7a6a308b), TOBN(0x62375830, 0x4c2767d3), + TOBN(0x874a8bc6, 0xf38cbeb6), TOBN(0xd94d3f1a, 0xccb6fd9e), + TOBN(0x92a9735b, 0xba21f248), TOBN(0x272ad0e5, 0x6cd1efb0), + TOBN(0x7437b69c, 0x05b03284), TOBN(0xe7f04702, 0x6948c225), + TOBN(0x8a56c04a, 0xcba2ecec), TOBN(0x0c181270, 0xe3a73e41), + TOBN(0x6cb34e9d, 0x03e93725), TOBN(0xf77c8713, 0x496521a9), + TOBN(0x94569183, 0xfa7f9f90), TOBN(0xf2e7aa4c, 0x8c9707ad), + TOBN(0xced2c9ba, 0x26c1c9a3), TOBN(0x9109fe96, 0x40197507), + TOBN(0x9ae868a9, 0xe9adfe1c), TOBN(0x3984403d, 0x314e39bb), + TOBN(0xb5875720, 0xf2fe378f), TOBN(0x33f901e0, 0xba44a628), + TOBN(0xea1125fe, 0x3652438c), TOBN(0xae9ec4e6, 0x9dd1f20b), + TOBN(0x1e740d9e, 0xbebf7fbd), TOBN(0x6dbd3ddc, 0x42dbe79c), + TOBN(0x62082aec, 0xedd36776), TOBN(0xf612c478, 0xe9859039), + TOBN(0xa493b201, 0x032f7065), TOBN(0xebd4d8f2, 0x4ff9b211), + TOBN(0x3f23a0aa, 0xaac4cb32), TOBN(0xea3aadb7, 0x15ed4005), + TOBN(0xacf17ea4, 0xafa27e63), TOBN(0x56125c1a, 0xc11fd66c), + TOBN(0x266344a4, 0x3794f8dc), TOBN(0xdcca923a, 0x483c5c36), + TOBN(0x2d6b6bbf, 0x3f9d10a0), TOBN(0xb320c5ca, 0x81d9bdf3), + TOBN(0x620e28ff, 0x47b50a95), TOBN(0x933e3b01, 0xcef03371), + TOBN(0xf081bf85, 0x99100153), TOBN(0x183be9a0, 0xc3a8c8d6), + TOBN(0x4e3ddc5a, 0xd6bbe24d), TOBN(0xc6c74630, 0x53843795), + TOBN(0x78193dd7, 0x65ec2d4c), TOBN(0xb8df26cc, 0xcd3c89b2), + TOBN(0x98dbe399, 0x5a483f8d), TOBN(0x72d8a957, 0x7dd3313a), + TOBN(0x65087294, 0xab0bd375), TOBN(0xfcd89248, 0x7c259d16), + TOBN(0x8a9443d7, 0x7613aa81), TOBN(0x80100800, 0x85fe6584), + TOBN(0x70fc4dbc, 0x7fb10288), TOBN(0xf58280d3, 0xe86beee8), + TOBN(0x14fdd82f, 0x7c978c38), TOBN(0xdf1204c1, 0x0de44d7b), + TOBN(0xa08a1c84, 0x4160252f), TOBN(0x591554ca, 0xc17646a5), + TOBN(0x214a37d6, 0xa05bd525), TOBN(0x48d5f09b, 0x07957b3c), + TOBN(0x0247cdcb, 0xd7109bc9), TOBN(0x40f9e4bb, 0x30599ce7), + TOBN(0xc325fa03, 0xf46ad2ec), TOBN(0x00f766cf, 0xc3e3f9ee), + TOBN(0xab556668, 0xd43a4577), TOBN(0x68d30a61, 0x3ee03b93), + TOBN(0x7ddc81ea, 0x77b46a08), TOBN(0xcf5a6477, 0xc7480699), + TOBN(0x43a8cb34, 0x6633f683), TOBN(0x1b867e6b, 0x92363c60), + TOBN(0x43921114, 0x1f60558e), TOBN(0xcdbcdd63, 0x2f41450e), + TOBN(0x7fc04601, 0xcc630e8b), TOBN(0xea7c66d5, 0x97038b43), + TOBN(0x7259b8a5, 0x04e99fd8), TOBN(0x98a8dd12, 0x4785549a), + TOBN(0x0e459a7c, 0x840552e1), TOBN(0xcdfcf4d0, 0x4bb0909e), + TOBN(0x34a86db2, 0x53758da7), TOBN(0xe643bb83, 0xeac997e1), + TOBN(0x96400bd7, 0x530c5b7e), TOBN(0x9f97af87, 0xb41c8b52), + TOBN(0x34fc8820, 0xfbeee3f9), TOBN(0x93e53490, 0x49091afd), + TOBN(0x764b9be5, 0x9a31f35c), TOBN(0x71f37864, 0x57e3d924), + TOBN(0x02fb34e0, 0x943aa75e), TOBN(0xa18c9c58, 0xab8ff6e4), + TOBN(0x080f31b1, 0x33cf0d19), TOBN(0x5c9682db, 0x083518a7), + TOBN(0x873d4ca6, 0xb709c3de), TOBN(0x64a84262, 0x3575b8f0), + TOBN(0x6275da1f, 0x020154bb), TOBN(0x97678caa, 0xd17cf1ab), + TOBN(0x8779795f, 0x951a95c3), TOBN(0xdd35b163, 0x50fccc08), + TOBN(0x32709627, 0x33d8f031), TOBN(0x3c5ab10a, 0x498dd85c), + TOBN(0xb6c185c3, 0x41dca566), TOBN(0x7de7feda, 0xd8622aa3), + TOBN(0x99e84d92, 0x901b6dfb), TOBN(0x30a02b0e, 0x7c4ad288), + TOBN(0xc7c81daa, 0x2fd3cf36), TOBN(0xd1319547, 0xdf89e59f), + TOBN(0xb2be8184, 0xcd496733), TOBN(0xd5f449eb, 0x93d3412b), + TOBN(0x7ea41b1b, 0x25fe531d), TOBN(0xf9797432, 0x6a1d5646), + TOBN(0x86067f72, 0x2bde501a), TOBN(0xf91481c0, 0x0c85e89c), + TOBN(0xca8ee465, 0xf8b05bc6), TOBN(0x1844e1cf, 0x02e83cda), + TOBN(0xca82114a, 0xb4dbe33b), TOBN(0x0f9f8769, 0x4eabfde2), + TOBN(0x4936b1c0, 0x38b27fe2), TOBN(0x63b6359b, 0xaba402df), + TOBN(0x40c0ea2f, 0x656bdbab), TOBN(0x9c992a89, 0x6580c39c), + TOBN(0x600e8f15, 0x2a60aed1), TOBN(0xeb089ca4, 0xe0bf49df), + TOBN(0x9c233d7d, 0x2d42d99a), TOBN(0x648d3f95, 0x4c6bc2fa), + TOBN(0xdcc383a8, 0xe1add3f3), TOBN(0xf42c0c6a, 0x4f64a348), + TOBN(0x2abd176f, 0x0030dbdb), TOBN(0x4de501a3, 0x7d6c215e), + TOBN(0x4a107c1f, 0x4b9a64bc), TOBN(0xa77f0ad3, 0x2496cd59), + TOBN(0xfb78ac62, 0x7688dffb), TOBN(0x7025a2ca, 0x67937d8e), + TOBN(0xfde8b2d1, 0xd1a8f4e7), TOBN(0xf5b3da47, 0x7354927c), + TOBN(0xe48606a3, 0xd9205735), TOBN(0xac477cc6, 0xe177b917), + TOBN(0xfb1f73d2, 0xa883239a), TOBN(0xe12572f6, 0xcc8b8357), + TOBN(0x9d355e9c, 0xfb1f4f86), TOBN(0x89b795f8, 0xd9f3ec6e), + TOBN(0x27be56f1, 0xb54398dc), TOBN(0x1890efd7, 0x3fedeed5), + TOBN(0x62f77f1f, 0x9c6d0140), TOBN(0x7ef0e314, 0x596f0ee4), + TOBN(0x50ca6631, 0xcc61dab3), TOBN(0x4a39801d, 0xf4866e4f), + TOBN(0x66c8d032, 0xae363b39), TOBN(0x22c591e5, 0x2ead66aa), + TOBN(0x954ba308, 0xde02a53e), TOBN(0x2a6c060f, 0xd389f357), + TOBN(0xe6cfcde8, 0xfbf40b66), TOBN(0x8e02fc56, 0xc6340ce1), + TOBN(0xe4957795, 0x73adb4ba), TOBN(0x7b86122c, 0xa7b03805), + TOBN(0x63f83512, 0x0c8e6fa6), TOBN(0x83660ea0, 0x057d7804), + TOBN(0xbad79105, 0x21ba473c), TOBN(0xb6c50bee, 0xded5389d), + TOBN(0xee2caf4d, 0xaa7c9bc0), TOBN(0xd97b8de4, 0x8c4e98a7), + TOBN(0xa9f63e70, 0xab3bbddb), TOBN(0x3898aabf, 0x2597815a), + TOBN(0x7659af89, 0xac15b3d9), TOBN(0xedf7725b, 0x703ce784), + TOBN(0x25470fab, 0xe085116b), TOBN(0x04a43375, 0x87285310), + TOBN(0x4e39187e, 0xe2bfd52f), TOBN(0x36166b44, 0x7d9ebc74), + TOBN(0x92ad433c, 0xfd4b322c), TOBN(0x726aa817, 0xba79ab51), + TOBN(0xf96eacd8, 0xc1db15eb), TOBN(0xfaf71e91, 0x0476be63), + TOBN(0xdd69a640, 0x641fad98), TOBN(0xb7995918, 0x29622559), + TOBN(0x03c6daa5, 0xde4199dc), TOBN(0x92cadc97, 0xad545eb4), + TOBN(0x1028238b, 0x256534e4), TOBN(0x73e80ce6, 0x8595409a), + TOBN(0x690d4c66, 0xd05dc59b), TOBN(0xc95f7b8f, 0x981dee80), + TOBN(0xf4337014, 0xd856ac25), TOBN(0x441bd9dd, 0xac524dca), + TOBN(0x640b3d85, 0x5f0499f5), TOBN(0x39cf84a9, 0xd5fda182), + TOBN(0x04e7b055, 0xb2aa95a0), TOBN(0x29e33f0a, 0x0ddf1860), + TOBN(0x082e74b5, 0x423f6b43), TOBN(0x217edeb9, 0x0aaa2b0f), + TOBN(0x58b83f35, 0x83cbea55), TOBN(0xc485ee4d, 0xbc185d70), + TOBN(0x833ff03b, 0x1e5f6992), TOBN(0xb5b9b9cc, 0xcf0c0dd5), + TOBN(0x7caaee8e, 0x4e9e8a50), TOBN(0x462e907b, 0x6269dafd), + TOBN(0x6ed5cee9, 0xfbe791c6), TOBN(0x68ca3259, 0xed430790), + TOBN(0x2b72bdf2, 0x13b5ba88), TOBN(0x60294c8a, 0x35ef0ac4), + TOBN(0x9c3230ed, 0x19b99b08), TOBN(0x560fff17, 0x6c2589aa), + TOBN(0x552b8487, 0xd6770374), TOBN(0xa373202d, 0x9a56f685), + TOBN(0xd3e7f907, 0x45f175d9), TOBN(0x3c2f315f, 0xd080d810), + TOBN(0x1130e9dd, 0x7b9520e8), TOBN(0xc078f9e2, 0x0af037b5), + TOBN(0x38cd2ec7, 0x1e9c104c), TOBN(0x0f684368, 0xc472fe92), + TOBN(0xd3f1b5ed, 0x6247e7ef), TOBN(0xb32d33a9, 0x396dfe21), + TOBN(0x46f59cf4, 0x4a9aa2c2), TOBN(0x69cd5168, 0xff0f7e41), + TOBN(0x3f59da0f, 0x4b3234da), TOBN(0xcf0b0235, 0xb4579ebe), + TOBN(0x6d1cbb25, 0x6d2476c7), TOBN(0x4f0837e6, 0x9dc30f08), + TOBN(0x9a4075bb, 0x906f6e98), TOBN(0x253bb434, 0xc761e7d1), + TOBN(0xde2e645f, 0x6e73af10), TOBN(0xb89a4060, 0x0c5f131c), + TOBN(0xd12840c5, 0xb8cc037f), TOBN(0x3d093a5b, 0x7405bb47), + TOBN(0x6202c253, 0x206348b8), TOBN(0xbf5d57fc, 0xc55a3ca7), + TOBN(0x89f6c90c, 0x8c3bef48), TOBN(0x23ac7623, 0x5a0a960a), + TOBN(0xdfbd3d6b, 0x552b42ab), TOBN(0x3ef22458, 0x132061f6), + TOBN(0xd74e9bda, 0xc97e6516), TOBN(0x88779360, 0xc230f49e), + TOBN(0xa6ec1de3, 0x1e74ea49), TOBN(0x581dcee5, 0x3fb645a2), + TOBN(0xbaef2391, 0x8f483f14), TOBN(0x6d2dddfc, 0xd137d13b), + TOBN(0x54cde50e, 0xd2743a42), TOBN(0x89a34fc5, 0xe4d97e67), + TOBN(0x13f1f5b3, 0x12e08ce5), TOBN(0xa80540b8, 0xa7f0b2ca), + TOBN(0x854bcf77, 0x01982805), TOBN(0xb8653ffd, 0x233bea04), + TOBN(0x8e7b8787, 0x02b0b4c9), TOBN(0x2675261f, 0x9acb170a), + TOBN(0x061a9d90, 0x930c14e5), TOBN(0xb59b30e0, 0xdef0abea), + TOBN(0x1dc19ea6, 0x0200ec7d), TOBN(0xb6f4a3f9, 0x0bce132b), + TOBN(0xb8d5de90, 0xf13e27e0), TOBN(0xbaee5ef0, 0x1fade16f), + TOBN(0x6f406aaa, 0xe4c6cf38), TOBN(0xab4cfe06, 0xd1369815), + TOBN(0x0dcffe87, 0xefd550c6), TOBN(0x9d4f59c7, 0x75ff7d39), + TOBN(0xb02553b1, 0x51deb6ad), TOBN(0x812399a4, 0xb1877749), + TOBN(0xce90f71f, 0xca6006e1), TOBN(0xc32363a6, 0xb02b6e77), + TOBN(0x02284fbe, 0xdc36c64d), TOBN(0x86c81e31, 0xa7e1ae61), + TOBN(0x2576c7e5, 0xb909d94a), TOBN(0x8b6f7d02, 0x818b2bb0), + TOBN(0xeca3ed07, 0x56faa38a), TOBN(0xa3790e6c, 0x9305bb54), + TOBN(0xd784eeda, 0x7bc73061), TOBN(0xbd56d369, 0x6dd50614), + TOBN(0xd6575949, 0x229a8aa9), TOBN(0xdcca8f47, 0x4595ec28), + TOBN(0x814305c1, 0x06ab4fe6), TOBN(0xc8c39768, 0x24f43f16), + TOBN(0xe2a45f36, 0x523f2b36), TOBN(0x995c6493, 0x920d93bb), + TOBN(0xf8afdab7, 0x90f1632b), TOBN(0x79ebbecd, 0x1c295954), + TOBN(0xc7bb3ddb, 0x79592f48), TOBN(0x67216a7b, 0x5f88e998), + TOBN(0xd91f098b, 0xbc01193e), TOBN(0xf7d928a5, 0xb1db83fc), + TOBN(0x55e38417, 0xe991f600), TOBN(0x2a91113e, 0x2981a934), + TOBN(0xcbc9d648, 0x06b13bde), TOBN(0xb011b6ac, 0x0755ff44), + TOBN(0x6f4cb518, 0x045ec613), TOBN(0x522d2d31, 0xc2f5930a), + TOBN(0x5acae1af, 0x382e65de), TOBN(0x57643067, 0x27bc966f), + TOBN(0x5e12705d, 0x1c7193f0), TOBN(0xf0f32f47, 0x3be8858e), + TOBN(0x785c3d7d, 0x96c6dfc7), TOBN(0xd75b4a20, 0xbf31795d), + TOBN(0x91acf17b, 0x342659d4), TOBN(0xe596ea34, 0x44f0378f), + TOBN(0x4515708f, 0xce52129d), TOBN(0x17387e1e, 0x79f2f585), + TOBN(0x72cfd2e9, 0x49dee168), TOBN(0x1ae05223, 0x3e2af239), + TOBN(0x009e75be, 0x1d94066a), TOBN(0x6cca31c7, 0x38abf413), + TOBN(0xb50bd61d, 0x9bc49908), TOBN(0x4a9b4a8c, 0xf5e2bc1e), + TOBN(0xeb6cc5f7, 0x946f83ac), TOBN(0x27da93fc, 0xebffab28), + TOBN(0xea314c96, 0x4821c8c5), TOBN(0x8de49ded, 0xa83c15f4), + TOBN(0x7a64cf20, 0x7af33004), TOBN(0x45f1bfeb, 0xc9627e10), + TOBN(0x878b0626, 0x54b9df60), TOBN(0x5e4fdc3c, 0xa95c0b33), + TOBN(0xe54a37ca, 0xc2035d8e), TOBN(0x9087cda9, 0x80f20b8c), + TOBN(0x36f61c23, 0x8319ade4), TOBN(0x766f287a, 0xde8cfdf8), + TOBN(0x48821948, 0x346f3705), TOBN(0x49a7b853, 0x16e4f4a2), + TOBN(0xb9b3f8a7, 0x5cedadfd), TOBN(0x8f562815, 0x8db2a815), + TOBN(0xc0b7d554, 0x01f68f95), TOBN(0x12971e27, 0x688a208e), + TOBN(0xc9f8b696, 0xd0ff34fc), TOBN(0x20824de2, 0x1222718c), + TOBN(0x7213cf9f, 0x0c95284d), TOBN(0xe2ad741b, 0xdc158240), + TOBN(0x0ee3a6df, 0x54043ccf), TOBN(0x16ff479b, 0xd84412b3), + TOBN(0xf6c74ee0, 0xdfc98af0), TOBN(0xa78a169f, 0x52fcd2fb), + TOBN(0xd8ae8746, 0x99c930e9), TOBN(0x1d33e858, 0x49e117a5), + TOBN(0x7581fcb4, 0x6624759f), TOBN(0xde50644f, 0x5bedc01d), + TOBN(0xbeec5d00, 0xcaf3155e), TOBN(0x672d66ac, 0xbc73e75f), + TOBN(0x86b9d8c6, 0x270b01db), TOBN(0xd249ef83, 0x50f55b79), + TOBN(0x6131d6d4, 0x73978fe3), TOBN(0xcc4e4542, 0x754b00a1), + TOBN(0x4e05df05, 0x57dfcfe9), TOBN(0x94b29cdd, 0x51ef6bf0), + TOBN(0xe4530cff, 0x9bc7edf2), TOBN(0x8ac236fd, 0xd3da65f3), + TOBN(0x0faf7d5f, 0xc8eb0b48), TOBN(0x4d2de14c, 0x660eb039), + TOBN(0xc006bba7, 0x60430e54), TOBN(0x10a2d0d6, 0xda3289ab), + TOBN(0x9c037a5d, 0xd7979c59), TOBN(0x04d1f3d3, 0xa116d944), + TOBN(0x9ff22473, 0x8a0983cd), TOBN(0x28e25b38, 0xc883cabb), + TOBN(0xe968dba5, 0x47a58995), TOBN(0x2c80b505, 0x774eebdf), + TOBN(0xee763b71, 0x4a953beb), TOBN(0x502e223f, 0x1642e7f6), + TOBN(0x6fe4b641, 0x61d5e722), TOBN(0x9d37c5b0, 0xdbef5316), + TOBN(0x0115ed70, 0xf8330bc7), TOBN(0x139850e6, 0x75a72789), + TOBN(0x27d7faec, 0xffceccc2), TOBN(0x3016a860, 0x4fd9f7f6), + TOBN(0xc492ec64, 0x4cd8f64c), TOBN(0x58a2d790, 0x279d7b51), + TOBN(0x0ced1fc5, 0x1fc75256), TOBN(0x3e658aed, 0x8f433017), + TOBN(0x0b61942e, 0x05da59eb), TOBN(0xba3d60a3, 0x0ddc3722), + TOBN(0x7c311cd1, 0x742e7f87), TOBN(0x6473ffee, 0xf6b01b6e)}, + {TOBN(0x8303604f, 0x692ac542), TOBN(0xf079ffe1, 0x227b91d3), + TOBN(0x19f63e63, 0x15aaf9bd), TOBN(0xf99ee565, 0xf1f344fb), + TOBN(0x8a1d661f, 0xd6219199), TOBN(0x8c883bc6, 0xd48ce41c), + TOBN(0x1065118f, 0x3c74d904), TOBN(0x713889ee, 0x0faf8b1b), + TOBN(0x972b3f8f, 0x81a1b3be), TOBN(0x4f3ce145, 0xce2764a0), + TOBN(0xe2d0f1cc, 0x28c4f5f7), TOBN(0xdeee0c0d, 0xc7f3985b), + TOBN(0x7df4adc0, 0xd39e25c3), TOBN(0x40619820, 0xc467a080), + TOBN(0x440ebc93, 0x61cf5a58), TOBN(0x527729a6, 0x422ad600), + TOBN(0xca6c0937, 0xb1b76ba6), TOBN(0x1a2eab85, 0x4d2026dc), + TOBN(0xb1715e15, 0x19d9ae0a), TOBN(0xf1ad9199, 0xbac4a026), + TOBN(0x35b3dfb8, 0x07ea7b0e), TOBN(0xedf5496f, 0x3ed9eb89), + TOBN(0x8932e5ff, 0x2d6d08ab), TOBN(0xf314874e, 0x25bd2731), + TOBN(0xefb26a75, 0x3f73f449), TOBN(0x1d1c94f8, 0x8d44fc79), + TOBN(0x49f0fbc5, 0x3bc0dc4d), TOBN(0xb747ea0b, 0x3698a0d0), + TOBN(0x5218c3fe, 0x228d291e), TOBN(0x35b804b5, 0x43c129d6), + TOBN(0xfac859b8, 0xd1acc516), TOBN(0x6c10697d, 0x95d6e668), + TOBN(0xc38e438f, 0x0876fd4e), TOBN(0x45f0c307, 0x83d2f383), + TOBN(0x203cc2ec, 0xb10934cb), TOBN(0x6a8f2439, 0x2c9d46ee), + TOBN(0xf16b431b, 0x65ccde7b), TOBN(0x41e2cd18, 0x27e76a6f), + TOBN(0xb9c8cf8f, 0x4e3484d7), TOBN(0x64426efd, 0x8315244a), + TOBN(0x1c0a8e44, 0xfc94dea3), TOBN(0x34c8cdbf, 0xdad6a0b0), + TOBN(0x919c3840, 0x04113cef), TOBN(0xfd32fba4, 0x15490ffa), + TOBN(0x58d190f6, 0x795dcfb7), TOBN(0xfef01b03, 0x83588baf), + TOBN(0x9e6d1d63, 0xca1fc1c0), TOBN(0x53173f96, 0xf0a41ac9), + TOBN(0x2b1d402a, 0xba16f73b), TOBN(0x2fb31014, 0x8cf9b9fc), + TOBN(0x2d51e60e, 0x446ef7bf), TOBN(0xc731021b, 0xb91e1745), + TOBN(0x9d3b4724, 0x4fee99d4), TOBN(0x4bca48b6, 0xfac5c1ea), + TOBN(0x70f5f514, 0xbbea9af7), TOBN(0x751f55a5, 0x974c283a), + TOBN(0x6e30251a, 0xcb452fdb), TOBN(0x31ee6965, 0x50f30650), + TOBN(0xb0b3e508, 0x933548d9), TOBN(0xb8949a4f, 0xf4b0ef5b), + TOBN(0x208b8326, 0x3c88f3bd), TOBN(0xab147c30, 0xdb1d9989), + TOBN(0xed6515fd, 0x44d4df03), TOBN(0x17a12f75, 0xe72eb0c5), + TOBN(0x3b59796d, 0x36cf69db), TOBN(0x1219eee9, 0x56670c18), + TOBN(0xfe3341f7, 0x7a070d8e), TOBN(0x9b70130b, 0xa327f90c), + TOBN(0x36a32462, 0x0ae18e0e), TOBN(0x2021a623, 0x46c0a638), + TOBN(0x251b5817, 0xc62eb0d4), TOBN(0x87bfbcdf, 0x4c762293), + TOBN(0xf78ab505, 0xcdd61d64), TOBN(0x8c7a53fc, 0xc8c18857), + TOBN(0xa653ce6f, 0x16147515), TOBN(0x9c923aa5, 0xea7d52d5), + TOBN(0xc24709cb, 0x5c18871f), TOBN(0x7d53bec8, 0x73b3cc74), + TOBN(0x59264aff, 0xfdd1d4c4), TOBN(0x5555917e, 0x240da582), + TOBN(0xcae8bbda, 0x548f5a0e), TOBN(0x1910eaba, 0x3bbfbbe1), + TOBN(0xae579685, 0x7677afc3), TOBN(0x49ea61f1, 0x73ff0b5c), + TOBN(0x78655478, 0x4f7c3922), TOBN(0x95d337cd, 0x20c68eef), + TOBN(0x68f1e1e5, 0xdf779ab9), TOBN(0x14b491b0, 0xb5cf69a8), + TOBN(0x7a6cbbe0, 0x28e3fe89), TOBN(0xe7e1fee4, 0xc5aac0eb), + TOBN(0x7f47eda5, 0x697e5140), TOBN(0x4f450137, 0xb454921f), + TOBN(0xdb625f84, 0x95cd8185), TOBN(0x74be0ba1, 0xcdb2e583), + TOBN(0xaee4fd7c, 0xdd5e6de4), TOBN(0x4251437d, 0xe8101739), + TOBN(0x686d72a0, 0xac620366), TOBN(0x4be3fb9c, 0xb6d59344), + TOBN(0x6e8b44e7, 0xa1eb75b9), TOBN(0x84e39da3, 0x91a5c10c), + TOBN(0x37cc1490, 0xb38f0409), TOBN(0x02951943, 0x2c2ade82), + TOBN(0x9b688783, 0x1190a2d8), TOBN(0x25627d14, 0x231182ba), + TOBN(0x6eb550aa, 0x658a6d87), TOBN(0x1405aaa7, 0xcf9c7325), + TOBN(0xd147142e, 0x5c8748c9), TOBN(0x7f637e4f, 0x53ede0e0), + TOBN(0xf8ca2776, 0x14ffad2c), TOBN(0xe58fb1bd, 0xbafb6791), + TOBN(0x17158c23, 0xbf8f93fc), TOBN(0x7f15b373, 0x0a4a4655), + TOBN(0x39d4add2, 0xd842ca72), TOBN(0xa71e4391, 0x3ed96305), + TOBN(0x5bb09cbe, 0x6700be14), TOBN(0x68d69d54, 0xd8befcf6), + TOBN(0xa45f5367, 0x37183bcf), TOBN(0x7152b7bb, 0x3370dff7), + TOBN(0xcf887baa, 0xbf12525b), TOBN(0xe7ac7bdd, 0xd6d1e3cd), + TOBN(0x25914f78, 0x81fdad90), TOBN(0xcf638f56, 0x0d2cf6ab), + TOBN(0xb90bc03f, 0xcc054de5), TOBN(0x932811a7, 0x18b06350), + TOBN(0x2f00b330, 0x9bbd11ff), TOBN(0x76108a6f, 0xb4044974), + TOBN(0x801bb9e0, 0xa851d266), TOBN(0x0dd099be, 0xbf8990c1), + TOBN(0x58c5aaaa, 0xabe32986), TOBN(0x0fe9dd2a, 0x50d59c27), + TOBN(0x84951ff4, 0x8d307305), TOBN(0x6c23f829, 0x86529b78), + TOBN(0x50bb2218, 0x0b136a79), TOBN(0x7e2174de, 0x77a20996), + TOBN(0x6f00a4b9, 0xc0bb4da6), TOBN(0x89a25a17, 0xefdde8da), + TOBN(0xf728a27e, 0xc11ee01d), TOBN(0xf900553a, 0xe5f10dfb), + TOBN(0x189a83c8, 0x02ec893c), TOBN(0x3ca5bdc1, 0x23f66d77), + TOBN(0x98781537, 0x97eada9f), TOBN(0x59c50ab3, 0x10256230), + TOBN(0x346042d9, 0x323c69b3), TOBN(0x1b715a6d, 0x2c460449), + TOBN(0xa41dd476, 0x6ae06e0b), TOBN(0xcdd7888e, 0x9d42e25f), + TOBN(0x0f395f74, 0x56b25a20), TOBN(0xeadfe0ae, 0x8700e27e), + TOBN(0xb09d52a9, 0x69950093), TOBN(0x3525d9cb, 0x327f8d40), + TOBN(0xb8235a94, 0x67df886a), TOBN(0x77e4b0dd, 0x035faec2), + TOBN(0x115eb20a, 0x517d7061), TOBN(0x77fe3433, 0x6c2df683), + TOBN(0x6870ddc7, 0xcdc6fc67), TOBN(0xb1610588, 0x0b87de83), + TOBN(0x343584ca, 0xd9c4ddbe), TOBN(0xb3164f1c, 0x3d754be2), + TOBN(0x0731ed3a, 0xc1e6c894), TOBN(0x26327dec, 0x4f6b904c), + TOBN(0x9d49c6de, 0x97b5cd32), TOBN(0x40835dae, 0xb5eceecd), + TOBN(0xc66350ed, 0xd9ded7fe), TOBN(0x8aeebb5c, 0x7a678804), + TOBN(0x51d42fb7, 0x5b8ee9ec), TOBN(0xd7a17bdd, 0x8e3ca118), + TOBN(0x40d7511a, 0x2ef4400e), TOBN(0xc48990ac, 0x875a66f4), + TOBN(0x8de07d2a, 0x2199e347), TOBN(0xbee75556, 0x2a39e051), + TOBN(0x56918786, 0x916e51dc), TOBN(0xeb191313, 0x4a2d89ec), + TOBN(0x6679610d, 0x37d341ed), TOBN(0x434fbb41, 0x56d51c2b), + TOBN(0xe54b7ee7, 0xd7492dba), TOBN(0xaa33a79a, 0x59021493), + TOBN(0x49fc5054, 0xe4bd6d3d), TOBN(0x09540f04, 0x5ab551d0), + TOBN(0x8acc9085, 0x4942d3a6), TOBN(0x231af02f, 0x2d28323b), + TOBN(0x93458cac, 0x0992c163), TOBN(0x1fef8e71, 0x888e3bb4), + TOBN(0x27578da5, 0xbe8c268c), TOBN(0xcc8be792, 0xe805ec00), + TOBN(0x29267bae, 0xc61c3855), TOBN(0xebff429d, 0x58c1fd3b), + TOBN(0x22d886c0, 0x8c0b93b8), TOBN(0xca5e00b2, 0x2ddb8953), + TOBN(0xcf330117, 0xc3fed8b7), TOBN(0xd49ac6fa, 0x819c01f6), + TOBN(0x6ddaa6bd, 0x3c0fbd54), TOBN(0x91743068, 0x8049a2cf), + TOBN(0xd67f981e, 0xaff2ef81), TOBN(0xc3654d35, 0x2818ae80), + TOBN(0x81d05044, 0x1b2aa892), TOBN(0x2db067bf, 0x3d099328), + TOBN(0xe7c79e86, 0x703dcc97), TOBN(0xe66f9b37, 0xe133e215), + TOBN(0xcdf119a6, 0xe39a7a5c), TOBN(0x47c60de3, 0x876f1b61), + TOBN(0x6e405939, 0xd860f1b2), TOBN(0x3e9a1dbc, 0xf5ed4d4a), + TOBN(0x3f23619e, 0xc9b6bcbd), TOBN(0x5ee790cf, 0x734e4497), + TOBN(0xf0a834b1, 0x5bdaf9bb), TOBN(0x02cedda7, 0x4ca295f0), + TOBN(0x4619aa2b, 0xcb8e378c), TOBN(0xe5613244, 0xcc987ea4), + TOBN(0x0bc022cc, 0x76b23a50), TOBN(0x4a2793ad, 0x0a6c21ce), + TOBN(0x38328780, 0x89cac3f5), TOBN(0x29176f1b, 0xcba26d56), + TOBN(0x06296187, 0x4f6f59eb), TOBN(0x86e9bca9, 0x8bdc658e), + TOBN(0x2ca9c4d3, 0x57e30402), TOBN(0x5438b216, 0x516a09bb), + TOBN(0x0a6a063c, 0x7672765a), TOBN(0x37a3ce64, 0x0547b9bf), + TOBN(0x42c099c8, 0x98b1a633), TOBN(0xb5ab800d, 0x05ee6961), + TOBN(0xf1963f59, 0x11a5acd6), TOBN(0xbaee6157, 0x46201063), + TOBN(0x36d9a649, 0xa596210a), TOBN(0xaed04363, 0x1ba7138c), + TOBN(0xcf817d1c, 0xa4a82b76), TOBN(0x5586960e, 0xf3806be9), + TOBN(0x7ab67c89, 0x09dc6bb5), TOBN(0x52ace7a0, 0x114fe7eb), + TOBN(0xcd987618, 0xcbbc9b70), TOBN(0x4f06fd5a, 0x604ca5e1), + TOBN(0x90af14ca, 0x6dbde133), TOBN(0x1afe4322, 0x948a3264), + TOBN(0xa70d2ca6, 0xc44b2c6c), TOBN(0xab726799, 0x0ef87dfe), + TOBN(0x310f64dc, 0x2e696377), TOBN(0x49b42e68, 0x4c8126a0), + TOBN(0x0ea444c3, 0xcea0b176), TOBN(0x53a8ddf7, 0xcb269182), + TOBN(0xf3e674eb, 0xbbba9dcb), TOBN(0x0d2878a8, 0xd8669d33), + TOBN(0x04b935d5, 0xd019b6a3), TOBN(0xbb5cf88e, 0x406f1e46), + TOBN(0xa1912d16, 0x5b57c111), TOBN(0x9803fc21, 0x19ebfd78), + TOBN(0x4f231c9e, 0xc07764a9), TOBN(0xd93286ee, 0xb75bd055), + TOBN(0x83a9457d, 0x8ee6c9de), TOBN(0x04695915, 0x6087ec90), + TOBN(0x14c6dd8a, 0x58d6cd46), TOBN(0x9cb633b5, 0x8e6634d2), + TOBN(0xc1305047, 0xf81bc328), TOBN(0x12ede0e2, 0x26a177e5), + TOBN(0x332cca62, 0x065a6f4f), TOBN(0xc3a47ecd, 0x67be487b), + TOBN(0x741eb187, 0x0f47ed1c), TOBN(0x99e66e58, 0xe7598b14), + TOBN(0x6f0544ca, 0x63d0ff12), TOBN(0xe5efc784, 0xb610a05f), + TOBN(0xf72917b1, 0x7cad7b47), TOBN(0x3ff6ea20, 0xf2cac0c0), + TOBN(0xcc23791b, 0xf21db8b7), TOBN(0x7dac70b1, 0xd7d93565), + TOBN(0x682cda1d, 0x694bdaad), TOBN(0xeb88bb8c, 0x1023516d), + TOBN(0xc4c634b4, 0xdfdbeb1b), TOBN(0x22f5ca72, 0xb4ee4dea), + TOBN(0x1045a368, 0xe6524821), TOBN(0xed9e8a3f, 0x052b18b2), + TOBN(0x9b7f2cb1, 0xb961f49a), TOBN(0x7fee2ec1, 0x7b009670), + TOBN(0x350d8754, 0x22507a6d), TOBN(0x561bd711, 0x4db55f1d), + TOBN(0x4c189ccc, 0x320bbcaf), TOBN(0x568434cf, 0xdf1de48c), + TOBN(0x6af1b00e, 0x0fa8f128), TOBN(0xf0ba9d02, 0x8907583c), + TOBN(0x735a4004, 0x32ff9f60), TOBN(0x3dd8e4b6, 0xc25dcf33), + TOBN(0xf2230f16, 0x42c74cef), TOBN(0xd8117623, 0x013fa8ad), + TOBN(0x36822876, 0xf51fe76e), TOBN(0x8a6811cc, 0x11d62589), + TOBN(0xc3fc7e65, 0x46225718), TOBN(0xb7df2c9f, 0xc82fdbcd), + TOBN(0x3b1d4e52, 0xdd7b205b), TOBN(0xb6959478, 0x47a2e414), + TOBN(0x05e4d793, 0xefa91148), TOBN(0xb47ed446, 0xfd2e9675), + TOBN(0x1a7098b9, 0x04c9d9bf), TOBN(0x661e2881, 0x1b793048), + TOBN(0xb1a16966, 0xb01ee461), TOBN(0xbc521308, 0x2954746f), + TOBN(0xc909a0fc, 0x2477de50), TOBN(0xd80bb41c, 0x7dbd51ef), + TOBN(0xa85be7ec, 0x53294905), TOBN(0x6d465b18, 0x83958f97), + TOBN(0x16f6f330, 0xfb6840fd), TOBN(0xfaaeb214, 0x3401e6c8), + TOBN(0xaf83d30f, 0xccb5b4f8), TOBN(0x22885739, 0x266dec4b), + TOBN(0x51b4367c, 0x7bc467df), TOBN(0x926562e3, 0xd842d27a), + TOBN(0xdfcb6614, 0x0fea14a6), TOBN(0xeb394dae, 0xf2734cd9), + TOBN(0x3eeae5d2, 0x11c0be98), TOBN(0xb1e6ed11, 0x814e8165), + TOBN(0x191086bc, 0xe52bce1c), TOBN(0x14b74cc6, 0xa75a04da), + TOBN(0x63cf1186, 0x8c060985), TOBN(0x071047de, 0x2dbd7f7c), + TOBN(0x4e433b8b, 0xce0942ca), TOBN(0xecbac447, 0xd8fec61d), + TOBN(0x8f0ed0e2, 0xebf3232f), TOBN(0xfff80f9e, 0xc52a2edd), + TOBN(0xad9ab433, 0x75b55fdb), TOBN(0x73ca7820, 0xe42e0c11), + TOBN(0x6dace0a0, 0xe6251b46), TOBN(0x89bc6b5c, 0x4c0d932d), + TOBN(0x3438cd77, 0x095da19a), TOBN(0x2f24a939, 0x8d48bdfb), + TOBN(0x99b47e46, 0x766561b7), TOBN(0x736600e6, 0x0ed0322a), + TOBN(0x06a47cb1, 0x638e1865), TOBN(0x927c1c2d, 0xcb136000), + TOBN(0x29542337, 0x0cc5df69), TOBN(0x99b37c02, 0x09d649a9), + TOBN(0xc5f0043c, 0x6aefdb27), TOBN(0x6cdd9987, 0x1be95c27), + TOBN(0x69850931, 0x390420d2), TOBN(0x299c40ac, 0x0983efa4), + TOBN(0x3a05e778, 0xaf39aead), TOBN(0x84274408, 0x43a45193), + TOBN(0x6bcd0fb9, 0x91a711a0), TOBN(0x461592c8, 0x9f52ab17), + TOBN(0xb49302b4, 0xda3c6ed6), TOBN(0xc51fddc7, 0x330d7067), + TOBN(0x94babeb6, 0xda50d531), TOBN(0x521b840d, 0xa6a7b9da), + TOBN(0x5305151e, 0x404bdc89), TOBN(0x1bcde201, 0xd0d07449), + TOBN(0xf427a78b, 0x3b76a59a), TOBN(0xf84841ce, 0x07791a1b), + TOBN(0xebd314be, 0xbf91ed1c), TOBN(0x8e61d34c, 0xbf172943), + TOBN(0x1d5dc451, 0x5541b892), TOBN(0xb186ee41, 0xfc9d9e54), + TOBN(0x9d9f345e, 0xd5bf610d), TOBN(0x3e7ba65d, 0xf6acca9f), + TOBN(0x9dda787a, 0xa8369486), TOBN(0x09f9dab7, 0x8eb5ba53), + TOBN(0x5afb2033, 0xd6481bc3), TOBN(0x76f4ce30, 0xafa62104), + TOBN(0xa8fa00cf, 0xf4f066b5), TOBN(0x89ab5143, 0x461dafc2), + TOBN(0x44339ed7, 0xa3389998), TOBN(0x2ff862f1, 0xbc214903), + TOBN(0x2c88f985, 0xb05556e3), TOBN(0xcd96058e, 0x3467081e), + TOBN(0x7d6a4176, 0xedc637ea), TOBN(0xe1743d09, 0x36a5acdc), + TOBN(0x66fd72e2, 0x7eb37726), TOBN(0xf7fa264e, 0x1481a037), + TOBN(0x9fbd3bde, 0x45f4aa79), TOBN(0xed1e0147, 0x767c3e22), + TOBN(0x7621f979, 0x82e7abe2), TOBN(0x19eedc72, 0x45f633f8), + TOBN(0xe69b155e, 0x6137bf3a), TOBN(0xa0ad13ce, 0x414ee94e), + TOBN(0x93e3d524, 0x1c0e651a), TOBN(0xab1a6e2a, 0x02ce227e), + TOBN(0xe7af1797, 0x4ab27eca), TOBN(0x245446de, 0xbd444f39), + TOBN(0x59e22a21, 0x56c07613), TOBN(0x43deafce, 0xf4275498), + TOBN(0x10834ccb, 0x67fd0946), TOBN(0xa75841e5, 0x47406edf), + TOBN(0xebd6a677, 0x7b0ac93d), TOBN(0xa6e37b0d, 0x78f5e0d7), + TOBN(0x2516c096, 0x76f5492b), TOBN(0x1e4bf888, 0x9ac05f3a), + TOBN(0xcdb42ce0, 0x4df0ba2b), TOBN(0x935d5cfd, 0x5062341b), + TOBN(0x8a303333, 0x82acac20), TOBN(0x429438c4, 0x5198b00e), + TOBN(0x1d083bc9, 0x049d33fa), TOBN(0x58b82dda, 0x946f67ff), + TOBN(0xac3e2db8, 0x67a1d6a3), TOBN(0x62e6bead, 0x1798aac8), + TOBN(0xfc85980f, 0xde46c58c), TOBN(0xa7f69379, 0x69c8d7be), + TOBN(0x23557927, 0x837b35ec), TOBN(0x06a933d8, 0xe0790c0c), + TOBN(0x827c0e9b, 0x077ff55d), TOBN(0x53977798, 0xbb26e680), + TOBN(0x59530874, 0x1d9cb54f), TOBN(0xcca3f449, 0x4aac53ef), + TOBN(0x11dc5c87, 0xa07eda0f), TOBN(0xc138bccf, 0xfd6400c8), + TOBN(0x549680d3, 0x13e5da72), TOBN(0xc93eed82, 0x4540617e), + TOBN(0xfd3db157, 0x4d0b75c0), TOBN(0x9716eb42, 0x6386075b), + TOBN(0x0639605c, 0x817b2c16), TOBN(0x09915109, 0xf1e4f201), + TOBN(0x35c9a928, 0x5cca6c3b), TOBN(0xb25f7d1a, 0x3505c900), + TOBN(0xeb9f7d20, 0x630480c4), TOBN(0xc3c7b8c6, 0x2a1a501c), + TOBN(0x3f99183c, 0x5a1f8e24), TOBN(0xfdb118fa, 0x9dd255f0), + TOBN(0xb9b18b90, 0xc27f62a6), TOBN(0xe8f732f7, 0x396ec191), + TOBN(0x524a2d91, 0x0be786ab), TOBN(0x5d32adef, 0x0ac5a0f5), + TOBN(0x9b53d4d6, 0x9725f694), TOBN(0x032a76c6, 0x0510ba89), + TOBN(0x840391a3, 0xebeb1544), TOBN(0x44b7b88c, 0x3ed73ac3), + TOBN(0xd24bae7a, 0x256cb8b3), TOBN(0x7ceb151a, 0xe394cb12), + TOBN(0xbd6b66d0, 0x5bc1e6a8), TOBN(0xec70cecb, 0x090f07bf), + TOBN(0x270644ed, 0x7d937589), TOBN(0xee9e1a3d, 0x5f1dccfe), + TOBN(0xb0d40a84, 0x745b98d2), TOBN(0xda429a21, 0x2556ed40), + TOBN(0xf676eced, 0x85148cb9), TOBN(0x5a22d40c, 0xded18936), + TOBN(0x3bc4b9e5, 0x70e8a4ce), TOBN(0xbfd1445b, 0x9eae0379), + TOBN(0xf23f2c0c, 0x1a0bd47e), TOBN(0xa9c0bb31, 0xe1845531), + TOBN(0x9ddc4d60, 0x0a4c3f6b), TOBN(0xbdfaad79, 0x2c15ef44), + TOBN(0xce55a236, 0x7f484acc), TOBN(0x08653ca7, 0x055b1f15), + TOBN(0x2efa8724, 0x538873a3), TOBN(0x09299e5d, 0xace1c7e7), + TOBN(0x07afab66, 0xade332ba), TOBN(0x9be1fdf6, 0x92dd71b7), + TOBN(0xa49b5d59, 0x5758b11c), TOBN(0x0b852893, 0xc8654f40), + TOBN(0xb63ef6f4, 0x52379447), TOBN(0xd4957d29, 0x105e690c), + TOBN(0x7d484363, 0x646559b0), TOBN(0xf4a8273c, 0x49788a8e), + TOBN(0xee406cb8, 0x34ce54a9), TOBN(0x1e1c260f, 0xf86fda9b), + TOBN(0xe150e228, 0xcf6a4a81), TOBN(0x1fa3b6a3, 0x1b488772), + TOBN(0x1e6ff110, 0xc5a9c15b), TOBN(0xc6133b91, 0x8ad6aa47), + TOBN(0x8ac5d55c, 0x9dffa978), TOBN(0xba1d1c1d, 0x5f3965f2), + TOBN(0xf969f4e0, 0x7732b52f), TOBN(0xfceecdb5, 0xa5172a07), + TOBN(0xb0120a5f, 0x10f2b8f5), TOBN(0xc83a6cdf, 0x5c4c2f63), + TOBN(0x4d47a491, 0xf8f9c213), TOBN(0xd9e1cce5, 0xd3f1bbd5), + TOBN(0x0d91bc7c, 0xaba7e372), TOBN(0xfcdc74c8, 0xdfd1a2db), + TOBN(0x05efa800, 0x374618e5), TOBN(0x11216969, 0x15a7925e), + TOBN(0xd4c89823, 0xf6021c5d), TOBN(0x880d5e84, 0xeff14423), + TOBN(0x6523bc5a, 0x6dcd1396), TOBN(0xd1acfdfc, 0x113c978b), + TOBN(0xb0c164e8, 0xbbb66840), TOBN(0xf7f4301e, 0x72b58459), + TOBN(0xc29ad4a6, 0xa638e8ec), TOBN(0xf5ab8961, 0x46b78699), + TOBN(0x9dbd7974, 0x0e954750), TOBN(0x0121de88, 0x64f9d2c6), + TOBN(0x2e597b42, 0xd985232e), TOBN(0x55b6c3c5, 0x53451777), + TOBN(0xbb53e547, 0x519cb9fb), TOBN(0xf134019f, 0x8428600d), + TOBN(0x5a473176, 0xe081791a), TOBN(0x2f3e2263, 0x35fb0c08), + TOBN(0xb28c3017, 0x73d273b0), TOBN(0xccd21076, 0x7721ef9a), + TOBN(0x054cc292, 0xb650dc39), TOBN(0x662246de, 0x6188045e), + TOBN(0x904b52fa, 0x6b83c0d1), TOBN(0xa72df267, 0x97e9cd46), + TOBN(0x886b43cd, 0x899725e4), TOBN(0x2b651688, 0xd849ff22), + TOBN(0x60479b79, 0x02f34533), TOBN(0x5e354c14, 0x0c77c148), + TOBN(0xb4bb7581, 0xa8537c78), TOBN(0x188043d7, 0xefe1495f), + TOBN(0x9ba12f42, 0x8c1d5026), TOBN(0x2e0c8a26, 0x93d4aaab), + TOBN(0xbdba7b8b, 0xaa57c450), TOBN(0x140c9ad6, 0x9bbdafef), + TOBN(0x2067aa42, 0x25ac0f18), TOBN(0xf7b1295b, 0x04d1fbf3), + TOBN(0x14829111, 0xa4b04824), TOBN(0x2ce3f192, 0x33bd5e91), + TOBN(0x9c7a1d55, 0x8f2e1b72), TOBN(0xfe932286, 0x302aa243), + TOBN(0x497ca7b4, 0xd4be9554), TOBN(0xb8e821b8, 0xe0547a6e), + TOBN(0xfb2838be, 0x67e573e0), TOBN(0x05891db9, 0x4084c44b), + TOBN(0x91311373, 0x96c1c2c5), TOBN(0x6aebfa3f, 0xd958444b), + TOBN(0xac9cdce9, 0xe56e55c1), TOBN(0x7148ced3, 0x2caa46d0), + TOBN(0x2e10c7ef, 0xb61fe8eb), TOBN(0x9fd835da, 0xff97cf4d)}, + {TOBN(0xa36da109, 0x081e9387), TOBN(0xfb9780d7, 0x8c935828), + TOBN(0xd5940332, 0xe540b015), TOBN(0xc9d7b51b, 0xe0f466fa), + TOBN(0xfaadcd41, 0xd6d9f671), TOBN(0xba6c1e28, 0xb1a2ac17), + TOBN(0x066a7833, 0xed201e5f), TOBN(0x19d99719, 0xf90f462b), + TOBN(0xf431f462, 0x060b5f61), TOBN(0xa56f46b4, 0x7bd057c2), + TOBN(0x348dca6c, 0x47e1bf65), TOBN(0x9a38783e, 0x41bcf1ff), + TOBN(0x7a5d33a9, 0xda710718), TOBN(0x5a779987, 0x2e0aeaf6), + TOBN(0xca87314d, 0x2d29d187), TOBN(0xfa0edc3e, 0xc687d733), + TOBN(0x9df33621, 0x6a31e09b), TOBN(0xde89e44d, 0xc1350e35), + TOBN(0x29214871, 0x4ca0cf52), TOBN(0xdf379672, 0x0b88a538), + TOBN(0xc92a510a, 0x2591d61b), TOBN(0x79aa87d7, 0x585b447b), + TOBN(0xf67db604, 0xe5287f77), TOBN(0x1697c8bf, 0x5efe7a80), + TOBN(0x1c894849, 0xcb198ac7), TOBN(0xa884a93d, 0x0f264665), + TOBN(0x2da964ef, 0x9b200678), TOBN(0x3c351b87, 0x009834e6), + TOBN(0xafb2ef9f, 0xe2c4b44b), TOBN(0x580f6c47, 0x3326790c), + TOBN(0xb8480521, 0x0b02264a), TOBN(0x8ba6f9e2, 0x42a194e2), + TOBN(0xfc87975f, 0x8fb54738), TOBN(0x35160788, 0x27c3ead3), + TOBN(0x834116d2, 0xb74a085a), TOBN(0x53c99a73, 0xa62fe996), + TOBN(0x87585be0, 0x5b81c51b), TOBN(0x925bafa8, 0xbe0852b7), + TOBN(0x76a4fafd, 0xa84d19a7), TOBN(0x39a45982, 0x585206d4), + TOBN(0x499b6ab6, 0x5eb03c0e), TOBN(0xf19b7954, 0x72bc3fde), + TOBN(0xa86b5b9c, 0x6e3a80d2), TOBN(0xe4377508, 0x6d42819f), + TOBN(0xc1663650, 0xbb3ee8a3), TOBN(0x75eb14fc, 0xb132075f), + TOBN(0xa8ccc906, 0x7ad834f6), TOBN(0xea6a2474, 0xe6e92ffd), + TOBN(0x9d72fd95, 0x0f8d6758), TOBN(0xcb84e101, 0x408c07dd), + TOBN(0xb9114bfd, 0xa5e23221), TOBN(0x358b5fe2, 0xe94e742c), + TOBN(0x1c0577ec, 0x95f40e75), TOBN(0xf0155451, 0x3d73f3d6), + TOBN(0x9d55cd67, 0xbd1b9b66), TOBN(0x63e86e78, 0xaf8d63c7), + TOBN(0x39d934ab, 0xd3c095f1), TOBN(0x04b261be, 0xe4b76d71), + TOBN(0x1d2e6970, 0xe73e6984), TOBN(0x879fb23b, 0x5e5fcb11), + TOBN(0x11506c72, 0xdfd75490), TOBN(0x3a97d085, 0x61bcf1c1), + TOBN(0x43201d82, 0xbf5e7007), TOBN(0x7f0ac52f, 0x798232a7), + TOBN(0x2715cbc4, 0x6eb564d4), TOBN(0x8d6c752c, 0x9e570e29), + TOBN(0xf80247c8, 0x9ef5fd5d), TOBN(0xc3c66b46, 0xd53eb514), + TOBN(0x9666b401, 0x0f87de56), TOBN(0xce62c06f, 0xc6c603b5), + TOBN(0xae7b4c60, 0x7e4fc942), TOBN(0x38ac0b77, 0x663a9c19), + TOBN(0xcb4d20ee, 0x4b049136), TOBN(0x8b63bf12, 0x356a4613), + TOBN(0x1221aef6, 0x70e08128), TOBN(0xe62d8c51, 0x4acb6b16), + TOBN(0x71f64a67, 0x379e7896), TOBN(0xb25237a2, 0xcafd7fa5), + TOBN(0xf077bd98, 0x3841ba6a), TOBN(0xc4ac0244, 0x3cd16e7e), + TOBN(0x548ba869, 0x21fea4ca), TOBN(0xd36d0817, 0xf3dfdac1), + TOBN(0x09d8d71f, 0xf4685faf), TOBN(0x8eff66be, 0xc52c459a), + TOBN(0x182faee7, 0x0b57235e), TOBN(0xee3c39b1, 0x0106712b), + TOBN(0x5107331f, 0xc0fcdcb0), TOBN(0x669fb9dc, 0xa51054ba), + TOBN(0xb25101fb, 0x319d7682), TOBN(0xb0293129, 0x0a982fee), + TOBN(0x51c1c9b9, 0x0261b344), TOBN(0x0e008c5b, 0xbfd371fa), + TOBN(0xd866dd1c, 0x0278ca33), TOBN(0x666f76a6, 0xe5aa53b1), + TOBN(0xe5cfb779, 0x6013a2cf), TOBN(0x1d3a1aad, 0xa3521836), + TOBN(0xcedd2531, 0x73faa485), TOBN(0xc8ee6c4f, 0xc0a76878), + TOBN(0xddbccfc9, 0x2a11667d), TOBN(0x1a418ea9, 0x1c2f695a), + TOBN(0xdb11bd92, 0x51f73971), TOBN(0x3e4b3c82, 0xda2ed89f), + TOBN(0x9a44f3f4, 0xe73e0319), TOBN(0xd1e3de0f, 0x303431af), + TOBN(0x3c5604ff, 0x50f75f9c), TOBN(0x1d8eddf3, 0x7e752b22), + TOBN(0x0ef074dd, 0x3c9a1118), TOBN(0xd0ffc172, 0xccb86d7b), + TOBN(0xabd1ece3, 0x037d90f2), TOBN(0xe3f307d6, 0x6055856c), + TOBN(0x422f9328, 0x7e4c6daf), TOBN(0x902aac66, 0x334879a0), + TOBN(0xb6a1e7bf, 0x94cdfade), TOBN(0x6c97e1ed, 0x7fc6d634), + TOBN(0x662ad24d, 0xa2fb63f8), TOBN(0xf81be1b9, 0xa5928405), + TOBN(0x86d765e4, 0xd14b4206), TOBN(0xbecc2e0e, 0x8fa0db65), + TOBN(0xa28838e0, 0xb17fc76c), TOBN(0xe49a602a, 0xe37cf24e), + TOBN(0x76b4131a, 0x567193ec), TOBN(0xaf3c305a, 0xe5f6e70b), + TOBN(0x9587bd39, 0x031eebdd), TOBN(0x5709def8, 0x71bbe831), + TOBN(0x57059983, 0x0eb2b669), TOBN(0x4d80ce1b, 0x875b7029), + TOBN(0x838a7da8, 0x0364ac16), TOBN(0x2f431d23, 0xbe1c83ab), + TOBN(0xe56812a6, 0xf9294dd3), TOBN(0xb448d01f, 0x9b4b0d77), + TOBN(0xf3ae6061, 0x04e8305c), TOBN(0x2bead645, 0x94d8c63e), + TOBN(0x0a85434d, 0x84fd8b07), TOBN(0x537b983f, 0xf7a9dee5), + TOBN(0xedcc5f18, 0xef55bd85), TOBN(0x2041af62, 0x21c6cf8b), + TOBN(0x8e52874c, 0xb940c71e), TOBN(0x211935a9, 0xdb5f4b3a), + TOBN(0x94350492, 0x301b1dc3), TOBN(0x33d2646d, 0x29958620), + TOBN(0x16b0d64b, 0xef911404), TOBN(0x9d1f25ea, 0x9a3c5ef4), + TOBN(0x20f200eb, 0x4a352c78), TOBN(0x43929f2c, 0x4bd0b428), + TOBN(0xa5656667, 0xc7196e29), TOBN(0x7992c2f0, 0x9391be48), + TOBN(0xaaa97cbd, 0x9ee0cd6e), TOBN(0x51b0310c, 0x3dc8c9bf), + TOBN(0x237f8acf, 0xdd9f22cb), TOBN(0xbb1d81a1, 0xb585d584), + TOBN(0x8d5d85f5, 0x8c416388), TOBN(0x0d6e5a5a, 0x42fe474f), + TOBN(0xe7812766, 0x38235d4e), TOBN(0x1c62bd67, 0x496e3298), + TOBN(0x8378660c, 0x3f175bc8), TOBN(0x4d04e189, 0x17afdd4d), + TOBN(0x32a81601, 0x85a8068c), TOBN(0xdb58e4e1, 0x92b29a85), + TOBN(0xe8a65b86, 0xc70d8a3b), TOBN(0x5f0e6f4e, 0x98a0403b), + TOBN(0x08129684, 0x69ed2370), TOBN(0x34dc30bd, 0x0871ee26), + TOBN(0x3a5ce948, 0x7c9c5b05), TOBN(0x7d487b80, 0x43a90c87), + TOBN(0x4089ba37, 0xdd0e7179), TOBN(0x45f80191, 0xb4041811), + TOBN(0x1c3e1058, 0x98747ba5), TOBN(0x98c4e13a, 0x6e1ae592), + TOBN(0xd44636e6, 0xe82c9f9e), TOBN(0x711db87c, 0xc33a1043), + TOBN(0x6f431263, 0xaa8aec05), TOBN(0x43ff120d, 0x2744a4aa), + TOBN(0xd3bd892f, 0xae77779b), TOBN(0xf0fe0cc9, 0x8cdc9f82), + TOBN(0xca5f7fe6, 0xf1c5b1bc), TOBN(0xcc63a682, 0x44929a72), + TOBN(0xc7eaba0c, 0x09dbe19a), TOBN(0x2f3585ad, 0x6b5c73c2), + TOBN(0x8ab8924b, 0x0ae50c30), TOBN(0x17fcd27a, 0x638b30ba), + TOBN(0xaf414d34, 0x10b3d5a5), TOBN(0x09c107d2, 0x2a9accf1), + TOBN(0x15dac49f, 0x946a6242), TOBN(0xaec3df2a, 0xd707d642), + TOBN(0x2c2492b7, 0x3f894ae0), TOBN(0xf59df3e5, 0xb75f18ce), + TOBN(0x7cb740d2, 0x8f53cad0), TOBN(0x3eb585fb, 0xc4f01294), + TOBN(0x17da0c86, 0x32c7f717), TOBN(0xeb8c795b, 0xaf943f4c), + TOBN(0x4ee23fb5, 0xf67c51d2), TOBN(0xef187575, 0x68889949), + TOBN(0xa6b4bdb2, 0x0389168b), TOBN(0xc4ecd258, 0xea577d03), + TOBN(0x3a63782b, 0x55743082), TOBN(0x6f678f4c, 0xc72f08cd), + TOBN(0x553511cf, 0x65e58dd8), TOBN(0xd53b4e3e, 0xd402c0cd), + TOBN(0x37de3e29, 0xa037c14c), TOBN(0x86b6c516, 0xc05712aa), + TOBN(0x2834da3e, 0xb38dff6f), TOBN(0xbe012c52, 0xea636be8), + TOBN(0x292d238c, 0x61dd37f8), TOBN(0x0e54523f, 0x8f8142db), + TOBN(0xe31eb436, 0x036a05d8), TOBN(0x83e3cdff, 0x1e93c0ff), + TOBN(0x3fd2fe0f, 0x50821ddf), TOBN(0xc8e19b0d, 0xff9eb33b), + TOBN(0xc8cc943f, 0xb569a5fe), TOBN(0xad0090d4, 0xd4342d75), + TOBN(0x82090b4b, 0xcaeca000), TOBN(0xca39687f, 0x1bd410eb), + TOBN(0xe7bb0df7, 0x65959d77), TOBN(0x39d78218, 0x9c964999), + TOBN(0xd87f62e8, 0xb2415451), TOBN(0xe5efb774, 0xbed76108), + TOBN(0x3ea011a4, 0xe822f0d0), TOBN(0xbc647ad1, 0x5a8704f8), + TOBN(0xbb315b35, 0x50c6820f), TOBN(0x863dec3d, 0xb7e76bec), + TOBN(0x01ff5d3a, 0xf017bfc7), TOBN(0x20054439, 0x976b8229), + TOBN(0x067fca37, 0x0bbd0d3b), TOBN(0xf63dde64, 0x7f5e3d0f), + TOBN(0x22dbefb3, 0x2a4c94e9), TOBN(0xafbff0fe, 0x96f8278a), + TOBN(0x80aea0b1, 0x3503793d), TOBN(0xb2238029, 0x5f06cd29), + TOBN(0x65703e57, 0x8ec3feca), TOBN(0x06c38314, 0x393e7053), + TOBN(0xa0b751eb, 0x7c6734c4), TOBN(0xd2e8a435, 0xc59f0f1e), + TOBN(0x147d9052, 0x5e9ca895), TOBN(0x2f4dd31e, 0x972072df), + TOBN(0xa16fda8e, 0xe6c6755c), TOBN(0xc66826ff, 0xcf196558), + TOBN(0x1f1a76a3, 0x0cf43895), TOBN(0xa9d604e0, 0x83c3097b), + TOBN(0xe1908309, 0x66390e0e), TOBN(0xa50bf753, 0xb3c85eff), + TOBN(0x0696bdde, 0xf6a70251), TOBN(0x548b801b, 0x3c6ab16a), + TOBN(0x37fcf704, 0xa4d08762), TOBN(0x090b3def, 0xdff76c4e), + TOBN(0x87e8cb89, 0x69cb9158), TOBN(0x44a90744, 0x995ece43), + TOBN(0xf85395f4, 0x0ad9fbf5), TOBN(0x49b0f6c5, 0x4fb0c82d), + TOBN(0x75d9bc15, 0xadf7cccf), TOBN(0x81a3e5d6, 0xdfa1e1b0), + TOBN(0x8c39e444, 0x249bc17e), TOBN(0xf37dccb2, 0x8ea7fd43), + TOBN(0xda654873, 0x907fba12), TOBN(0x35daa6da, 0x4a372904), + TOBN(0x0564cfc6, 0x6283a6c5), TOBN(0xd09fa4f6, 0x4a9395bf), + TOBN(0x688e9ec9, 0xaeb19a36), TOBN(0xd913f1ce, 0xc7bfbfb4), + TOBN(0x797b9a3c, 0x61c2faa6), TOBN(0x2f979bec, 0x6a0a9c12), + TOBN(0xb5969d0f, 0x359679ec), TOBN(0xebcf523d, 0x079b0460), + TOBN(0xfd6b0008, 0x10fab870), TOBN(0x3f2edcda, 0x9373a39c), + TOBN(0x0d64f9a7, 0x6f568431), TOBN(0xf848c27c, 0x02f8898c), + TOBN(0xf418ade1, 0x260b5bd5), TOBN(0xc1f3e323, 0x6973dee8), + TOBN(0x46e9319c, 0x26c185dd), TOBN(0x6d85b7d8, 0x546f0ac4), + TOBN(0x427965f2, 0x247f9d57), TOBN(0xb519b636, 0xb0035f48), + TOBN(0x6b6163a9, 0xab87d59c), TOBN(0xff9f58c3, 0x39caaa11), + TOBN(0x4ac39cde, 0x3177387b), TOBN(0x5f6557c2, 0x873e77f9), + TOBN(0x67504006, 0x36a83041), TOBN(0x9b1c96ca, 0x75ef196c), + TOBN(0xf34283de, 0xb08c7940), TOBN(0x7ea09644, 0x1128c316), + TOBN(0xb510b3b5, 0x6aa39dff), TOBN(0x59b43da2, 0x9f8e4d8c), + TOBN(0xa8ce31fd, 0x9e4c4b9f), TOBN(0x0e20be26, 0xc1303c01), + TOBN(0x18187182, 0xe8ee47c9), TOBN(0xd9687cdb, 0x7db98101), + TOBN(0x7a520e4d, 0xa1e14ff6), TOBN(0x429808ba, 0x8836d572), + TOBN(0xa37ca60d, 0x4944b663), TOBN(0xf901f7a9, 0xa3f91ae5), + TOBN(0xe4e3e76e, 0x9e36e3b1), TOBN(0x9aa219cf, 0x29d93250), + TOBN(0x347fe275, 0x056a2512), TOBN(0xa4d643d9, 0xde65d95c), + TOBN(0x9669d396, 0x699fc3ed), TOBN(0xb598dee2, 0xcf8c6bbe), + TOBN(0x682ac1e5, 0xdda9e5c6), TOBN(0x4e0d3c72, 0xcaa9fc95), + TOBN(0x17faaade, 0x772bea44), TOBN(0x5ef8428c, 0xab0009c8), + TOBN(0xcc4ce47a, 0x460ff016), TOBN(0xda6d12bf, 0x725281cb), + TOBN(0x44c67848, 0x0223aad2), TOBN(0x6e342afa, 0x36256e28), + TOBN(0x1400bb0b, 0x93a37c04), TOBN(0x62b1bc9b, 0xdd10bd96), + TOBN(0x7251adeb, 0x0dac46b7), TOBN(0x7d33b92e, 0x7be4ef51), + TOBN(0x28b2a94b, 0xe61fa29a), TOBN(0x4b2be13f, 0x06422233), + TOBN(0x36d6d062, 0x330d8d37), TOBN(0x5ef80e1e, 0xb28ca005), + TOBN(0x174d4699, 0x6d16768e), TOBN(0x9fc4ff6a, 0x628bf217), + TOBN(0x77705a94, 0x154e490d), TOBN(0x9d96dd28, 0x8d2d997a), + TOBN(0x77e2d9d8, 0xce5d72c4), TOBN(0x9d06c5a4, 0xc11c714f), + TOBN(0x02aa5136, 0x79e4a03e), TOBN(0x1386b3c2, 0x030ff28b), + TOBN(0xfe82e8a6, 0xfb283f61), TOBN(0x7df203e5, 0xf3abc3fb), + TOBN(0xeec7c351, 0x3a4d3622), TOBN(0xf7d17dbf, 0xdf762761), + TOBN(0xc3956e44, 0x522055f0), TOBN(0xde3012db, 0x8fa748db), + TOBN(0xca9fcb63, 0xbf1dcc14), TOBN(0xa56d9dcf, 0xbe4e2f3a), + TOBN(0xb86186b6, 0x8bcec9c2), TOBN(0x7cf24df9, 0x680b9f06), + TOBN(0xc46b45ea, 0xc0d29281), TOBN(0xfff42bc5, 0x07b10e12), + TOBN(0x12263c40, 0x4d289427), TOBN(0x3d5f1899, 0xb4848ec4), + TOBN(0x11f97010, 0xd040800c), TOBN(0xb4c5f529, 0x300feb20), + TOBN(0xcc543f8f, 0xde94fdcb), TOBN(0xe96af739, 0xc7c2f05e), + TOBN(0xaa5e0036, 0x882692e1), TOBN(0x09c75b68, 0x950d4ae9), + TOBN(0x62f63df2, 0xb5932a7a), TOBN(0x2658252e, 0xde0979ad), + TOBN(0x2a19343f, 0xb5e69631), TOBN(0x718c7501, 0x525b666b), + TOBN(0x26a42d69, 0xea40dc3a), TOBN(0xdc84ad22, 0xaecc018f), + TOBN(0x25c36c7b, 0x3270f04a), TOBN(0x46ba6d47, 0x50fa72ed), + TOBN(0x6c37d1c5, 0x93e58a8e), TOBN(0xa2394731, 0x120c088c), + TOBN(0xc3be4263, 0xcb6e86da), TOBN(0x2c417d36, 0x7126d038), + TOBN(0x5b70f9c5, 0x8b6f8efa), TOBN(0x671a2faa, 0x37718536), + TOBN(0xd3ced3c6, 0xb539c92b), TOBN(0xe56f1bd9, 0xa31203c2), + TOBN(0x8b096ec4, 0x9ff3c8eb), TOBN(0x2deae432, 0x43491cea), + TOBN(0x2465c6eb, 0x17943794), TOBN(0x5d267e66, 0x20586843), + TOBN(0x9d3d116d, 0xb07159d0), TOBN(0xae07a67f, 0xc1896210), + TOBN(0x8fc84d87, 0xbb961579), TOBN(0x30009e49, 0x1c1f8dd6), + TOBN(0x8a8caf22, 0xe3132819), TOBN(0xcffa197c, 0xf23ab4ff), + TOBN(0x58103a44, 0x205dd687), TOBN(0x57b796c3, 0x0ded67a2), + TOBN(0x0b9c3a6c, 0xa1779ad7), TOBN(0xa33cfe2e, 0x357c09c5), + TOBN(0x2ea29315, 0x3db4a57e), TOBN(0x91959695, 0x8ebeb52e), + TOBN(0x118db9a6, 0xe546c879), TOBN(0x8e996df4, 0x6295c8d6), + TOBN(0xdd990484, 0x55ec806b), TOBN(0x24f291ca, 0x165c1035), + TOBN(0xcca523bb, 0x440e2229), TOBN(0x324673a2, 0x73ef4d04), + TOBN(0xaf3adf34, 0x3e11ec39), TOBN(0x6136d7f1, 0xdc5968d3), + TOBN(0x7a7b2899, 0xb053a927), TOBN(0x3eaa2661, 0xae067ecd), + TOBN(0x8549b9c8, 0x02779cd9), TOBN(0x061d7940, 0xc53385ea), + TOBN(0x3e0ba883, 0xf06d18bd), TOBN(0x4ba6de53, 0xb2700843), + TOBN(0xb966b668, 0x591a9e4d), TOBN(0x93f67567, 0x7f4fa0ed), + TOBN(0x5a02711b, 0x4347237b), TOBN(0xbc041e2f, 0xe794608e), + TOBN(0x55af10f5, 0x70f73d8c), TOBN(0xd2d4d4f7, 0xbb7564f7), + TOBN(0xd7d27a89, 0xb3e93ce7), TOBN(0xf7b5a875, 0x5d3a2c1b), + TOBN(0xb29e68a0, 0x255b218a), TOBN(0xb533837e, 0x8af76754), + TOBN(0xd1b05a73, 0x579fab2e), TOBN(0xb41055a1, 0xecd74385), + TOBN(0xb2369274, 0x445e9115), TOBN(0x2972a7c4, 0xf520274e), + TOBN(0x6c08334e, 0xf678e68a), TOBN(0x4e4160f0, 0x99b057ed), + TOBN(0x3cfe11b8, 0x52ccb69a), TOBN(0x2fd1823a, 0x21c8f772), + TOBN(0xdf7f072f, 0x3298f055), TOBN(0x8c0566f9, 0xfec74a6e), + TOBN(0xe549e019, 0x5bb4d041), TOBN(0x7c3930ba, 0x9208d850), + TOBN(0xe07141fc, 0xaaa2902b), TOBN(0x539ad799, 0xe4f69ad3), + TOBN(0xa6453f94, 0x813f9ffd), TOBN(0xc58d3c48, 0x375bc2f7), + TOBN(0xb3326fad, 0x5dc64e96), TOBN(0x3aafcaa9, 0xb240e354), + TOBN(0x1d1b0903, 0xaca1e7a9), TOBN(0x4ceb9767, 0x1211b8a0), + TOBN(0xeca83e49, 0xe32a858e), TOBN(0x4c32892e, 0xae907bad), + TOBN(0xd5b42ab6, 0x2eb9b494), TOBN(0x7fde3ee2, 0x1eabae1b), + TOBN(0x13b5ab09, 0xcaf54957), TOBN(0xbfb028be, 0xe5f5d5d5), + TOBN(0x928a0650, 0x2003e2c0), TOBN(0x90793aac, 0x67476843), + TOBN(0x5e942e79, 0xc81710a0), TOBN(0x557e4a36, 0x27ccadd4), + TOBN(0x72a2bc56, 0x4bcf6d0c), TOBN(0x09ee5f43, 0x26d7b80c), + TOBN(0x6b70dbe9, 0xd4292f19), TOBN(0x56f74c26, 0x63f16b18), + TOBN(0xc23db0f7, 0x35fbb42a), TOBN(0xb606bdf6, 0x6ae10040), + TOBN(0x1eb15d4d, 0x044573ac), TOBN(0x7dc3cf86, 0x556b0ba4), + TOBN(0x97af9a33, 0xc60df6f7), TOBN(0x0b1ef85c, 0xa716ce8c), + TOBN(0x2922f884, 0xc96958be), TOBN(0x7c32fa94, 0x35690963), + TOBN(0x2d7f667c, 0xeaa00061), TOBN(0xeaaf7c17, 0x3547365c), + TOBN(0x1eb4de46, 0x87032d58), TOBN(0xc54f3d83, 0x5e2c79e0), + TOBN(0x07818df4, 0x5d04ef23), TOBN(0x55faa9c8, 0x673d41b4), + TOBN(0xced64f6f, 0x89b95355), TOBN(0x4860d2ea, 0xb7415c84), + TOBN(0x5fdb9bd2, 0x050ebad3), TOBN(0xdb53e0cc, 0x6685a5bf), + TOBN(0xb830c031, 0x9feb6593), TOBN(0xdd87f310, 0x6accff17), + TOBN(0x2303ebab, 0x9f555c10), TOBN(0x94603695, 0x287e7065), + TOBN(0xf88311c3, 0x2e83358c), TOBN(0x508dd9b4, 0xeefb0178), + TOBN(0x7ca23706, 0x2dba8652), TOBN(0x62aac5a3, 0x0047abe5), + TOBN(0x9a61d2a0, 0x8b1ea7b3), TOBN(0xd495ab63, 0xae8b1485), + TOBN(0x38740f84, 0x87052f99), TOBN(0x178ebe5b, 0xb2974eea), + TOBN(0x030bbcca, 0x5b36d17f), TOBN(0xb5e4cce3, 0xaaf86eea), + TOBN(0xb51a0220, 0x68f8e9e0), TOBN(0xa4348796, 0x09eb3e75), + TOBN(0xbe592309, 0xeef1a752), TOBN(0x5d7162d7, 0x6f2aa1ed), + TOBN(0xaebfb5ed, 0x0f007dd2), TOBN(0x255e14b2, 0xc89edd22), + TOBN(0xba85e072, 0x0303b697), TOBN(0xc5d17e25, 0xf05720ff), + TOBN(0x02b58d6e, 0x5128ebb6), TOBN(0x2c80242d, 0xd754e113), + TOBN(0x919fca5f, 0xabfae1ca), TOBN(0x937afaac, 0x1a21459b), + TOBN(0x9e0ca91c, 0x1f66a4d2), TOBN(0x194cc7f3, 0x23ec1331), + TOBN(0xad25143a, 0x8aa11690), TOBN(0xbe40ad8d, 0x09b59e08), + TOBN(0x37d60d9b, 0xe750860a), TOBN(0x6c53b008, 0xc6bf434c), + TOBN(0xb572415d, 0x1356eb80), TOBN(0xb8bf9da3, 0x9578ded8), + TOBN(0x22658e36, 0x5e8fb38b), TOBN(0x9b70ce22, 0x5af8cb22), + TOBN(0x7c00018a, 0x829a8180), TOBN(0x84329f93, 0xb81ed295), + TOBN(0x7c343ea2, 0x5f3cea83), TOBN(0x38f8655f, 0x67586536), + TOBN(0xa661a0d0, 0x1d3ec517), TOBN(0x98744652, 0x512321ae), + TOBN(0x084ca591, 0xeca92598), TOBN(0xa9bb9dc9, 0x1dcb3feb), + TOBN(0x14c54355, 0x78b4c240), TOBN(0x5ed62a3b, 0x610cafdc), + TOBN(0x07512f37, 0x1b38846b), TOBN(0x571bb70a, 0xb0e38161), + TOBN(0xb556b95b, 0x2da705d2), TOBN(0x3ef8ada6, 0xb1a08f98), + TOBN(0x85302ca7, 0xddecfbe5), TOBN(0x0e530573, 0x943105cd), + TOBN(0x60554d55, 0x21a9255d), TOBN(0x63a32fa1, 0xf2f3802a), + TOBN(0x35c8c5b0, 0xcd477875), TOBN(0x97f458ea, 0x6ad42da1), + TOBN(0x832d7080, 0xeb6b242d), TOBN(0xd30bd023, 0x3b71e246), + TOBN(0x7027991b, 0xbe31139d), TOBN(0x68797e91, 0x462e4e53), + TOBN(0x423fe20a, 0x6b4e185a), TOBN(0x82f2c67e, 0x42d9b707), + TOBN(0x25c81768, 0x4cf7811b), TOBN(0xbd53005e, 0x045bb95d)}, + {TOBN(0xe5f649be, 0x9d8e68fd), TOBN(0xdb0f0533, 0x1b044320), + TOBN(0xf6fde9b3, 0xe0c33398), TOBN(0x92f4209b, 0x66c8cfae), + TOBN(0xe9d1afcc, 0x1a739d4b), TOBN(0x09aea75f, 0xa28ab8de), + TOBN(0x14375fb5, 0xeac6f1d0), TOBN(0x6420b560, 0x708f7aa5), + TOBN(0x9eae499c, 0x6254dc41), TOBN(0x7e293924, 0x7a837e7e), + TOBN(0x74aec08c, 0x090524a7), TOBN(0xf82b9219, 0x8d6f55f2), + TOBN(0x493c962e, 0x1402cec5), TOBN(0x9f17ca17, 0xfa2f30e7), + TOBN(0xbcd783e8, 0xe9b879cb), TOBN(0xea3d8c14, 0x5a6f145f), + TOBN(0xdede15e7, 0x5e0dee6e), TOBN(0x74f24872, 0xdc628aa2), + TOBN(0xd3e9c4fe, 0x7861bb93), TOBN(0x56d4822a, 0x6187b2e0), + TOBN(0xb66417cf, 0xc59826f9), TOBN(0xca260969, 0x2408169e), + TOBN(0xedf69d06, 0xc79ef885), TOBN(0x00031f8a, 0xdc7d138f), + TOBN(0x103c46e6, 0x0ebcf726), TOBN(0x4482b831, 0x6231470e), + TOBN(0x6f6dfaca, 0x487c2109), TOBN(0x2e0ace97, 0x62e666ef), + TOBN(0x3246a9d3, 0x1f8d1f42), TOBN(0x1b1e83f1, 0x574944d2), + TOBN(0x13dfa63a, 0xa57f334b), TOBN(0x0cf8daed, 0x9f025d81), + TOBN(0x30d78ea8, 0x00ee11c1), TOBN(0xeb053cd4, 0xb5e3dd75), + TOBN(0x9b65b13e, 0xd58c43c5), TOBN(0xc3ad49bd, 0xbd151663), + TOBN(0x99fd8e41, 0xb6427990), TOBN(0x12cf15bd, 0x707eae1e), + TOBN(0x29ad4f1b, 0x1aabb71e), TOBN(0x5143e74d, 0x07545d0e), + TOBN(0x30266336, 0xc88bdee1), TOBN(0x25f29306, 0x5876767c), + TOBN(0x9c078571, 0xc6731996), TOBN(0xc88690b2, 0xed552951), + TOBN(0x274f2c2d, 0x852705b4), TOBN(0xb0bf8d44, 0x4e09552d), + TOBN(0x7628beeb, 0x986575d1), TOBN(0x407be238, 0x7f864651), + TOBN(0x0e5e3049, 0xa639fc6b), TOBN(0xe75c35d9, 0x86003625), + TOBN(0x0cf35bd8, 0x5dcc1646), TOBN(0x8bcaced2, 0x6c26273a), + TOBN(0xe22ecf1d, 0xb5536742), TOBN(0x013dd897, 0x1a9e068b), + TOBN(0x17f411cb, 0x8a7909c5), TOBN(0x5757ac98, 0x861dd506), + TOBN(0x85de1f0d, 0x1e935abb), TOBN(0xdefd10b4, 0x154de37a), + TOBN(0xb8d9e392, 0x369cebb5), TOBN(0x54d5ef9b, 0x761324be), + TOBN(0x4d6341ba, 0x74f17e26), TOBN(0xc0a0e3c8, 0x78c1dde4), + TOBN(0xa6d77581, 0x87d918fd), TOBN(0x66876015, 0x02ca3a13), + TOBN(0xc7313e9c, 0xf36658f0), TOBN(0xc433ef1c, 0x71f8057e), + TOBN(0x85326246, 0x1b6a835a), TOBN(0xc8f05398, 0x7c86394c), + TOBN(0xff398cdf, 0xe983c4a1), TOBN(0xbf5e8162, 0x03b7b931), + TOBN(0x93193c46, 0xb7b9045b), TOBN(0x1e4ebf5d, 0xa4a6e46b), + TOBN(0xf9942a60, 0x43a24fe7), TOBN(0x29c1191e, 0xffb3492b), + TOBN(0x9f662449, 0x902fde05), TOBN(0xc792a7ac, 0x6713c32d), + TOBN(0x2fd88ad8, 0xb737982c), TOBN(0x7e3a0319, 0xa21e60e3), + TOBN(0x09b0de44, 0x7383591a), TOBN(0x6df141ee, 0x8310a456), + TOBN(0xaec1a039, 0xe6d6f471), TOBN(0x14b2ba0f, 0x1198d12e), + TOBN(0xebc1a160, 0x3aeee5ac), TOBN(0x401f4836, 0xe0b964ce), + TOBN(0x2ee43796, 0x4fd03f66), TOBN(0x3fdb4e49, 0xdd8f3f12), + TOBN(0x6ef267f6, 0x29380f18), TOBN(0x3e8e9670, 0x8da64d16), + TOBN(0xbc19180c, 0x207674f1), TOBN(0x112e09a7, 0x33ae8fdb), + TOBN(0x99667554, 0x6aaeb71e), TOBN(0x79432af1, 0xe101b1c7), + TOBN(0xd5eb558f, 0xde2ddec6), TOBN(0x81392d1f, 0x5357753f), + TOBN(0xa7a76b97, 0x3ae1158a), TOBN(0x416fbbff, 0x4a899991), + TOBN(0x9e65fdfd, 0x0d4a9dcf), TOBN(0x7bc29e48, 0x944ddf12), + TOBN(0xbc1a92d9, 0x3c856866), TOBN(0x273c6905, 0x6e98dfe2), + TOBN(0x69fce418, 0xcdfaa6b8), TOBN(0x606bd823, 0x5061c69f), + TOBN(0x42d495a0, 0x6af75e27), TOBN(0x8ed3d505, 0x6d873a1f), + TOBN(0xaf552841, 0x6ab25b6a), TOBN(0xc6c0ffc7, 0x2b1a4523), + TOBN(0xab18827b, 0x21c99e03), TOBN(0x060e8648, 0x9034691b), + TOBN(0x5207f90f, 0x93c7f398), TOBN(0x9f4a96cb, 0x82f8d10b), + TOBN(0xdd71cd79, 0x3ad0f9e3), TOBN(0x84f435d2, 0xfc3a54f5), + TOBN(0x4b03c55b, 0x8e33787f), TOBN(0xef42f975, 0xa6384673), + TOBN(0xff7304f7, 0x5051b9f0), TOBN(0x18aca1dc, 0x741c87c2), + TOBN(0x56f120a7, 0x2d4bfe80), TOBN(0xfd823b3d, 0x053e732c), + TOBN(0x11bccfe4, 0x7537ca16), TOBN(0xdf6c9c74, 0x1b5a996b), + TOBN(0xee7332c7, 0x904fc3fa), TOBN(0x14a23f45, 0xc7e3636a), + TOBN(0xc38659c3, 0xf091d9aa), TOBN(0x4a995e5d, 0xb12d8540), + TOBN(0x20a53bec, 0xf3a5598a), TOBN(0x56534b17, 0xb1eaa995), + TOBN(0x9ed3dca4, 0xbf04e03c), TOBN(0x716c563a, 0xd8d56268), + TOBN(0x27ba77a4, 0x1d6178e7), TOBN(0xe4c80c40, 0x68a1ff8e), + TOBN(0x75011099, 0x0a13f63d), TOBN(0x7bf33521, 0xa61d46f3), + TOBN(0x0aff218e, 0x10b365bb), TOBN(0x81021804, 0x0fd7ea75), + TOBN(0x05a3fd8a, 0xa4b3a925), TOBN(0xb829e75f, 0x9b3db4e6), + TOBN(0x6bdc75a5, 0x4d53e5fb), TOBN(0x04a5dc02, 0xd52717e3), + TOBN(0x86af502f, 0xe9a42ec2), TOBN(0x8867e8fb, 0x2630e382), + TOBN(0xbf845c6e, 0xbec9889b), TOBN(0x54f491f2, 0xcb47c98d), + TOBN(0xa3091fba, 0x790c2a12), TOBN(0xd7f6fd78, 0xc20f708b), + TOBN(0xa569ac30, 0xacde5e17), TOBN(0xd0f996d0, 0x6852b4d7), + TOBN(0xe51d4bb5, 0x4609ae54), TOBN(0x3fa37d17, 0x0daed061), + TOBN(0x62a88684, 0x34b8fb41), TOBN(0x99a2acbd, 0x9efb64f1), + TOBN(0xb75c1a5e, 0x6448e1f2), TOBN(0xfa99951a, 0x42b5a069), + TOBN(0x6d956e89, 0x2f3b26e7), TOBN(0xf4709860, 0xda875247), + TOBN(0x3ad15179, 0x2482dda3), TOBN(0xd64110e3, 0x017d82f0), + TOBN(0x14928d2c, 0xfad414e4), TOBN(0x2b155f58, 0x2ed02b24), + TOBN(0x481a141b, 0xcb821bf1), TOBN(0x12e3c770, 0x4f81f5da), + TOBN(0xe49c5de5, 0x9fff8381), TOBN(0x11053232, 0x5bbec894), + TOBN(0xa0d051cc, 0x454d88c4), TOBN(0x4f6db89c, 0x1f8e531b), + TOBN(0x34fe3fd6, 0xca563a44), TOBN(0x7f5c2215, 0x58da8ab9), + TOBN(0x8445016d, 0x9474f0a1), TOBN(0x17d34d61, 0xcb7d8a0a), + TOBN(0x8e9d3910, 0x1c474019), TOBN(0xcaff2629, 0xd52ceefb), + TOBN(0xf9cf3e32, 0xc1622c2b), TOBN(0xd4b95e3c, 0xe9071a05), + TOBN(0xfbbca61f, 0x1594438c), TOBN(0x1eb6e6a6, 0x04aadedf), + TOBN(0x853027f4, 0x68e14940), TOBN(0x221d322a, 0xdfabda9c), + TOBN(0xed8ea9f6, 0xb7cb179a), TOBN(0xdc7b764d, 0xb7934dcc), + TOBN(0xfcb13940, 0x5e09180d), TOBN(0x6629a6bf, 0xb47dc2dd), + TOBN(0xbfc55e4e, 0x9f5a915e), TOBN(0xb1db9d37, 0x6204441e), + TOBN(0xf82d68cf, 0x930c5f53), TOBN(0x17d3a142, 0xcbb605b1), + TOBN(0xdd5944ea, 0x308780f2), TOBN(0xdc8de761, 0x3845f5e4), + TOBN(0x6beaba7d, 0x7624d7a3), TOBN(0x1e709afd, 0x304df11e), + TOBN(0x95364376, 0x02170456), TOBN(0xbf204b3a, 0xc8f94b64), + TOBN(0x4e53af7c, 0x5680ca68), TOBN(0x0526074a, 0xe0c67574), + TOBN(0x95d8cef8, 0xecd92af6), TOBN(0xe6b9fa7a, 0x6cd1745a), + TOBN(0x3d546d3d, 0xa325c3e4), TOBN(0x1f57691d, 0x9ae93aae), + TOBN(0xe891f3fe, 0x9d2e1a33), TOBN(0xd430093f, 0xac063d35), + TOBN(0xeda59b12, 0x5513a327), TOBN(0xdc2134f3, 0x5536f18f), + TOBN(0xaa51fe2c, 0x5c210286), TOBN(0x3f68aaee, 0x1cab658c), + TOBN(0x5a23a00b, 0xf9357292), TOBN(0x9a626f39, 0x7efdabed), + TOBN(0xfe2b3bf3, 0x199d78e3), TOBN(0xb7a2af77, 0x71bbc345), + TOBN(0x3d19827a, 0x1e59802c), TOBN(0x823bbc15, 0xb487a51c), + TOBN(0x856139f2, 0x99d0a422), TOBN(0x9ac3df65, 0xf456c6fb), + TOBN(0xaddf65c6, 0x701f8bd6), TOBN(0x149f321e, 0x3758df87), + TOBN(0xb1ecf714, 0x721b7eba), TOBN(0xe17df098, 0x31a3312a), + TOBN(0xdb2fd6ec, 0xd5c4d581), TOBN(0xfd02996f, 0x8fcea1b3), + TOBN(0xe29fa63e, 0x7882f14f), TOBN(0xc9f6dc35, 0x07c6cadc), + TOBN(0x46f22d6f, 0xb882bed0), TOBN(0x1a45755b, 0xd118e52c), + TOBN(0x9f2c7c27, 0x7c4608cf), TOBN(0x7ccbdf32, 0x568012c2), + TOBN(0xfcb0aedd, 0x61729b0e), TOBN(0x7ca2ca9e, 0xf7d75dbf), + TOBN(0xf58fecb1, 0x6f640f62), TOBN(0xe274b92b, 0x39f51946), + TOBN(0x7f4dfc04, 0x6288af44), TOBN(0x0a91f32a, 0xeac329e5), + TOBN(0x43ad274b, 0xd6aaba31), TOBN(0x719a1640, 0x0f6884f9), + TOBN(0x685d29f6, 0xdaf91e20), TOBN(0x5ec1cc33, 0x27e49d52), + TOBN(0x38f4de96, 0x3b54a059), TOBN(0x0e0015e5, 0xefbcfdb3), + TOBN(0x177d23d9, 0x4dbb8da6), TOBN(0x98724aa2, 0x97a617ad), + TOBN(0x30f0885b, 0xfdb6558e), TOBN(0xf9f7a28a, 0xc7899a96), + TOBN(0xd2ae8ac8, 0x872dc112), TOBN(0xfa0642ca, 0x73c3c459), + TOBN(0x15296981, 0xe7dfc8d6), TOBN(0x67cd4450, 0x1fb5b94a), + TOBN(0x0ec71cf1, 0x0eddfd37), TOBN(0xc7e5eeb3, 0x9a8eddc7), + TOBN(0x02ac8e3d, 0x81d95028), TOBN(0x0088f172, 0x70b0e35d), + TOBN(0xec041fab, 0xe1881fe3), TOBN(0x62cf71b8, 0xd99e7faa), + TOBN(0x5043dea7, 0xe0f222c2), TOBN(0x309d42ac, 0x72e65142), + TOBN(0x94fe9ddd, 0x9216cd30), TOBN(0xd6539c7d, 0x0f87feec), + TOBN(0x03c5a57c, 0x432ac7d7), TOBN(0x72692cf0, 0x327fda10), + TOBN(0xec28c85f, 0x280698de), TOBN(0x2331fb46, 0x7ec283b1), + TOBN(0xd34bfa32, 0x2867e633), TOBN(0x78709a82, 0x0a9cc815), + TOBN(0xb7fe6964, 0x875e2fa5), TOBN(0x25cc064f, 0x9e98bfb5), + TOBN(0x9eb0151c, 0x493a65c5), TOBN(0x5fb5d941, 0x53182464), + TOBN(0x69e6f130, 0xf04618e2), TOBN(0xa8ecec22, 0xf89c8ab6), + TOBN(0xcd6ac88b, 0xb96209bd), TOBN(0x65fa8cdb, 0xb3e1c9e0), + TOBN(0xa47d22f5, 0x4a8d8eac), TOBN(0x83895cdf, 0x8d33f963), + TOBN(0xa8adca59, 0xb56cd3d1), TOBN(0x10c8350b, 0xdaf38232), + TOBN(0x2b161fb3, 0xa5080a9f), TOBN(0xbe7f5c64, 0x3af65b3a), + TOBN(0x2c754039, 0x97403a11), TOBN(0x94626cf7, 0x121b96af), + TOBN(0x431de7c4, 0x6a983ec2), TOBN(0x3780dd3a, 0x52cc3df7), + TOBN(0xe28a0e46, 0x2baf8e3b), TOBN(0xabe68aad, 0x51d299ae), + TOBN(0x603eb8f9, 0x647a2408), TOBN(0x14c61ed6, 0x5c750981), + TOBN(0x88b34414, 0xc53352e7), TOBN(0x5a34889c, 0x1337d46e), + TOBN(0x612c1560, 0xf95f2bc8), TOBN(0x8a3f8441, 0xd4807a3a), + TOBN(0x680d9e97, 0x5224da68), TOBN(0x60cd6e88, 0xc3eb00e9), + TOBN(0x3875a98e, 0x9a6bc375), TOBN(0xdc80f924, 0x4fd554c2), + TOBN(0x6c4b3415, 0x6ac77407), TOBN(0xa1e5ea8f, 0x25420681), + TOBN(0x541bfa14, 0x4607a458), TOBN(0x5dbc7e7a, 0x96d7fbf9), + TOBN(0x646a851b, 0x31590a47), TOBN(0x039e85ba, 0x15ee6df8), + TOBN(0xd19fa231, 0xd7b43fc0), TOBN(0x84bc8be8, 0x299a0e04), + TOBN(0x2b9d2936, 0xf20df03a), TOBN(0x24054382, 0x8608d472), + TOBN(0x76b6ba04, 0x9149202a), TOBN(0xb21c3831, 0x3670e7b7), + TOBN(0xddd93059, 0xd6fdee10), TOBN(0x9da47ad3, 0x78488e71), + TOBN(0x99cc1dfd, 0xa0fcfb25), TOBN(0x42abde10, 0x64696954), + TOBN(0x14cc15fc, 0x17eab9fe), TOBN(0xd6e863e4, 0xd3e70972), + TOBN(0x29a7765c, 0x6432112c), TOBN(0x88660001, 0x5b0774d8), + TOBN(0x3729175a, 0x2c088eae), TOBN(0x13afbcae, 0x8230b8d4), + TOBN(0x44768151, 0x915f4379), TOBN(0xf086431a, 0xd8d22812), + TOBN(0x37461955, 0xc298b974), TOBN(0x905fb5f0, 0xf8711e04), + TOBN(0x787abf3a, 0xfe969d18), TOBN(0x392167c2, 0x6f6a494e), + TOBN(0xfc7a0d2d, 0x28c511da), TOBN(0xf127c7dc, 0xb66a262d), + TOBN(0xf9c4bb95, 0xfd63fdf0), TOBN(0x90016589, 0x3913ef46), + TOBN(0x74d2a73c, 0x11aa600d), TOBN(0x2f5379bd, 0x9fb5ab52), + TOBN(0xe49e53a4, 0x7fb70068), TOBN(0x68dd39e5, 0x404aa9a7), + TOBN(0xb9b0cf57, 0x2ecaa9c3), TOBN(0xba0e103b, 0xe824826b), + TOBN(0x60c2198b, 0x4631a3c4), TOBN(0xc5ff84ab, 0xfa8966a2), + TOBN(0x2d6ebe22, 0xac95aff8), TOBN(0x1c9bb6db, 0xb5a46d09), + TOBN(0x419062da, 0x53ee4f8d), TOBN(0x7b9042d0, 0xbb97efef), + TOBN(0x0f87f080, 0x830cf6bd), TOBN(0x4861d19a, 0x6ec8a6c6), + TOBN(0xd3a0daa1, 0x202f01aa), TOBN(0xb0111674, 0xf25afbd5), + TOBN(0x6d00d6cf, 0x1afb20d9), TOBN(0x13695000, 0x40671bc5), + TOBN(0x913ab0dc, 0x2485ea9b), TOBN(0x1f2bed06, 0x9eef61ac), + TOBN(0x850c8217, 0x6d799e20), TOBN(0x93415f37, 0x3271c2de), + TOBN(0x5afb06e9, 0x6c4f5910), TOBN(0x688a52df, 0xc4e9e421), + TOBN(0x30495ba3, 0xe2a9a6db), TOBN(0x4601303d, 0x58f9268b), + TOBN(0xbe3b0dad, 0x7eb0f04f), TOBN(0x4ea47250, 0x4456936d), + TOBN(0x8caf8798, 0xd33fd3e7), TOBN(0x1ccd8a89, 0xeb433708), + TOBN(0x9effe3e8, 0x87fd50ad), TOBN(0xbe240a56, 0x6b29c4df), + TOBN(0xec4ffd98, 0xca0e7ebd), TOBN(0xf586783a, 0xe748616e), + TOBN(0xa5b00d8f, 0xc77baa99), TOBN(0x0acada29, 0xb4f34c9c), + TOBN(0x36dad67d, 0x0fe723ac), TOBN(0x1d8e53a5, 0x39c36c1e), + TOBN(0xe4dd342d, 0x1f4bea41), TOBN(0x64fd5e35, 0xebc9e4e0), + TOBN(0x96f01f90, 0x57908805), TOBN(0xb5b9ea3d, 0x5ed480dd), + TOBN(0x366c5dc2, 0x3efd2dd0), TOBN(0xed2fe305, 0x6e9dfa27), + TOBN(0x4575e892, 0x6e9197e2), TOBN(0x11719c09, 0xab502a5d), + TOBN(0x264c7bec, 0xe81f213f), TOBN(0x741b9241, 0x55f5c457), + TOBN(0x78ac7b68, 0x49a5f4f4), TOBN(0xf91d70a2, 0x9fc45b7d), + TOBN(0x39b05544, 0xb0f5f355), TOBN(0x11f06bce, 0xeef930d9), + TOBN(0xdb84d25d, 0x038d05e1), TOBN(0x04838ee5, 0xbacc1d51), + TOBN(0x9da3ce86, 0x9e8ee00b), TOBN(0xc3412057, 0xc36eda1f), + TOBN(0xae80b913, 0x64d9c2f4), TOBN(0x7468bac3, 0xa010a8ff), + TOBN(0xdfd20037, 0x37359d41), TOBN(0x1a0f5ab8, 0x15efeacc), + TOBN(0x7c25ad2f, 0x659d0ce0), TOBN(0x4011bcbb, 0x6785cff1), + TOBN(0x128b9912, 0x7e2192c7), TOBN(0xa549d8e1, 0x13ccb0e8), + TOBN(0x805588d8, 0xc85438b1), TOBN(0x5680332d, 0xbc25cb27), + TOBN(0xdcd1bc96, 0x1a4bfdf4), TOBN(0x779ff428, 0x706f6566), + TOBN(0x8bbee998, 0xf059987a), TOBN(0xf6ce8cf2, 0xcc686de7), + TOBN(0xf8ad3c4a, 0x953cfdb2), TOBN(0xd1d426d9, 0x2205da36), + TOBN(0xb3c0f13f, 0xc781a241), TOBN(0x3e89360e, 0xd75362a8), + TOBN(0xccd05863, 0xc8a91184), TOBN(0x9bd0c9b7, 0xefa8a7f4), + TOBN(0x97ee4d53, 0x8a912a4b), TOBN(0xde5e15f8, 0xbcf518fd), + TOBN(0x6a055bf8, 0xc467e1e0), TOBN(0x10be4b4b, 0x1587e256), + TOBN(0xd90c14f2, 0x668621c9), TOBN(0xd5518f51, 0xab9c92c1), + TOBN(0x8e6a0100, 0xd6d47b3c), TOBN(0xcbe980dd, 0x66716175), + TOBN(0x500d3f10, 0xddd83683), TOBN(0x3b6cb35d, 0x99cac73c), + TOBN(0x53730c8b, 0x6083d550), TOBN(0xcf159767, 0xdf0a1987), + TOBN(0x84bfcf53, 0x43ad73b3), TOBN(0x1b528c20, 0x4f035a94), + TOBN(0x4294edf7, 0x33eeac69), TOBN(0xb6283e83, 0x817f3240), + TOBN(0xc3fdc959, 0x0a5f25b1), TOBN(0xefaf8aa5, 0x5844ee22), + TOBN(0xde269ba5, 0xdbdde4de), TOBN(0xe3347160, 0xc56133bf), + TOBN(0xc1184219, 0x8d9ea9f8), TOBN(0x090de5db, 0xf3fc1ab5), + TOBN(0x404c37b1, 0x0bf22cda), TOBN(0x7de20ec8, 0xf5618894), + TOBN(0x754c588e, 0xecdaecab), TOBN(0x6ca4b0ed, 0x88342743), + TOBN(0x76f08bdd, 0xf4a938ec), TOBN(0xd182de89, 0x91493ccb), + TOBN(0xd652c53e, 0xc8a4186a), TOBN(0xb3e878db, 0x946d8e33), + TOBN(0x088453c0, 0x5f37663c), TOBN(0x5cd9daaa, 0xb407748b), + TOBN(0xa1f5197f, 0x586d5e72), TOBN(0x47500be8, 0xc443ca59), + TOBN(0x78ef35b2, 0xe2652424), TOBN(0x09c5d26f, 0x6dd7767d), + TOBN(0x7175a79a, 0xa74d3f7b), TOBN(0x0428fd8d, 0xcf5ea459), + TOBN(0x511cb97c, 0xa5d1746d), TOBN(0x36363939, 0xe71d1278), + TOBN(0xcf2df955, 0x10350bf4), TOBN(0xb3817439, 0x60aae782), + TOBN(0xa748c0e4, 0x3e688809), TOBN(0x98021fbf, 0xd7a5a006), + TOBN(0x9076a70c, 0x0e367a98), TOBN(0xbea1bc15, 0x0f62b7c2), + TOBN(0x2645a68c, 0x30fe0343), TOBN(0xacaffa78, 0x699dc14f), + TOBN(0xf4469964, 0x457bf9c4), TOBN(0x0db6407b, 0x0d2ead83), + TOBN(0x68d56cad, 0xb2c6f3eb), TOBN(0x3b512e73, 0xf376356c), + TOBN(0xe43b0e1f, 0xfce10408), TOBN(0x89ddc003, 0x5a5e257d), + TOBN(0xb0ae0d12, 0x0362e5b3), TOBN(0x07f983c7, 0xb0519161), + TOBN(0xc2e94d15, 0x5d5231e7), TOBN(0xcff22aed, 0x0b4f9513), + TOBN(0xb02588dd, 0x6ad0b0b5), TOBN(0xb967d1ac, 0x11d0dcd5), + TOBN(0x8dac6bc6, 0xcf777b6c), TOBN(0x0062bdbd, 0x4c6d1959), + TOBN(0x53da71b5, 0x0ef5cc85), TOBN(0x07012c7d, 0x4006f14f), + TOBN(0x4617f962, 0xac47800d), TOBN(0x53365f2b, 0xc102ed75), + TOBN(0xb422efcb, 0x4ab8c9d3), TOBN(0x195cb26b, 0x34af31c9), + TOBN(0x3a926e29, 0x05f2c4ce), TOBN(0xbd2bdecb, 0x9856966c), + TOBN(0x5d16ab3a, 0x85527015), TOBN(0x9f81609e, 0x4486c231), + TOBN(0xd8b96b2c, 0xda350002), TOBN(0xbd054690, 0xfa1b7d36), + TOBN(0xdc90ebf5, 0xe71d79bc), TOBN(0xf241b6f9, 0x08964e4e), + TOBN(0x7c838643, 0x2fe3cd4c), TOBN(0xe0f33acb, 0xb4bc633c), + TOBN(0xb4a9ecec, 0x3d139f1f), TOBN(0x05ce69cd, 0xdc4a1f49), + TOBN(0xa19d1b16, 0xf5f98aaf), TOBN(0x45bb71d6, 0x6f23e0ef), + TOBN(0x33789fcd, 0x46cdfdd3), TOBN(0x9b8e2978, 0xcee040ca), + TOBN(0x9c69b246, 0xae0a6828), TOBN(0xba533d24, 0x7078d5aa), + TOBN(0x7a2e42c0, 0x7bb4fbdb), TOBN(0xcfb4879a, 0x7035385c), + TOBN(0x8c3dd30b, 0x3281705b), TOBN(0x7e361c6c, 0x404fe081), + TOBN(0x7b21649c, 0x3f604edf), TOBN(0x5dbf6a3f, 0xe52ffe47), + TOBN(0xc41b7c23, 0x4b54d9bf), TOBN(0x1374e681, 0x3511c3d9), + TOBN(0x1863bf16, 0xc1b2b758), TOBN(0x90e78507, 0x1e9e6a96), + TOBN(0xab4bf98d, 0x5d86f174), TOBN(0xd74e0bd3, 0x85e96fe4), + TOBN(0x8afde39f, 0xcac5d344), TOBN(0x90946dbc, 0xbd91b847), + TOBN(0xf5b42358, 0xfe1a838c), TOBN(0x05aae6c5, 0x620ac9d8), + TOBN(0x8e193bd8, 0xa1ce5a0b), TOBN(0x8f710571, 0x4dabfd72), + TOBN(0x8d8fdd48, 0x182caaac), TOBN(0x8c4aeefa, 0x040745cf), + TOBN(0x73c6c30a, 0xf3b93e6d), TOBN(0x991241f3, 0x16f42011), + TOBN(0xa0158eea, 0xe457a477), TOBN(0xd19857db, 0xee6ddc05), + TOBN(0xb3265224, 0x18c41671), TOBN(0x3ffdfc7e, 0x3c2c0d58), + TOBN(0x3a3a5254, 0x26ee7cda), TOBN(0x341b0869, 0xdf02c3a8), + TOBN(0xa023bf42, 0x723bbfc8), TOBN(0x3d15002a, 0x14452691)}, + {TOBN(0x5ef7324c, 0x85edfa30), TOBN(0x25976554, 0x87d4f3da), + TOBN(0x352f5bc0, 0xdcb50c86), TOBN(0x8f6927b0, 0x4832a96c), + TOBN(0xd08ee1ba, 0x55f2f94c), TOBN(0x6a996f99, 0x344b45fa), + TOBN(0xe133cb8d, 0xa8aa455d), TOBN(0x5d0721ec, 0x758dc1f7), + TOBN(0x6ba7a920, 0x79e5fb67), TOBN(0xe1331feb, 0x70aa725e), + TOBN(0x5080ccf5, 0x7df5d837), TOBN(0xe4cae01d, 0x7ff72e21), + TOBN(0xd9243ee6, 0x0412a77d), TOBN(0x06ff7cac, 0xdf449025), + TOBN(0xbe75f7cd, 0x23ef5a31), TOBN(0xbc957822, 0x0ddef7a8), + TOBN(0x8cf7230c, 0xb0ce1c55), TOBN(0x5b534d05, 0x0bbfb607), + TOBN(0xee1ef113, 0x0e16363b), TOBN(0x27e0aa7a, 0xb4999e82), + TOBN(0xce1dac2d, 0x79362c41), TOBN(0x67920c90, 0x91bb6cb0), + TOBN(0x1e648d63, 0x2223df24), TOBN(0x0f7d9eef, 0xe32e8f28), + TOBN(0x6943f39a, 0xfa833834), TOBN(0x22951722, 0xa6328562), + TOBN(0x81d63dd5, 0x4170fc10), TOBN(0x9f5fa58f, 0xaecc2e6d), + TOBN(0xb66c8725, 0xe77d9a3b), TOBN(0x11235cea, 0x6384ebe0), + TOBN(0x06a8c118, 0x5845e24a), TOBN(0x0137b286, 0xebd093b1), + TOBN(0xc589e1ce, 0x44ace150), TOBN(0xe0f8d3d9, 0x4381e97c), + TOBN(0x59e99b11, 0x62c5a4b8), TOBN(0x90d262f7, 0xfd0ec9f9), + TOBN(0xfbc854c9, 0x283e13c9), TOBN(0x2d04fde7, 0xaedc7085), + TOBN(0x057d7765, 0x47dcbecb), TOBN(0x8dbdf591, 0x9a76fa5f), + TOBN(0xd0150695, 0x0de1e578), TOBN(0x2e1463e7, 0xe9f72bc6), + TOBN(0xffa68441, 0x1b39eca5), TOBN(0x673c8530, 0x7c037f2f), + TOBN(0xd0d6a600, 0x747f91da), TOBN(0xb08d43e1, 0xc9cb78e9), + TOBN(0x0fc0c644, 0x27b5cef5), TOBN(0x5c1d160a, 0xa60a2fd6), + TOBN(0xf98cae53, 0x28c8e13b), TOBN(0x375f10c4, 0xb2eddcd1), + TOBN(0xd4eb8b7f, 0x5cce06ad), TOBN(0xb4669f45, 0x80a2e1ef), + TOBN(0xd593f9d0, 0x5bbd8699), TOBN(0x5528a4c9, 0xe7976d13), + TOBN(0x3923e095, 0x1c7e28d3), TOBN(0xb9293790, 0x3f6bb577), + TOBN(0xdb567d6a, 0xc42bd6d2), TOBN(0x6df86468, 0xbb1f96ae), + TOBN(0x0efe5b1a, 0x4843b28e), TOBN(0x961bbb05, 0x6379b240), + TOBN(0xb6caf5f0, 0x70a6a26b), TOBN(0x70686c0d, 0x328e6e39), + TOBN(0x80da06cf, 0x895fc8d3), TOBN(0x804d8810, 0xb363fdc9), + TOBN(0xbe22877b, 0x207f1670), TOBN(0x9b0dd188, 0x4e615291), + TOBN(0x625ae8dc, 0x97a3c2bf), TOBN(0x08584ef7, 0x439b86e8), + TOBN(0xde7190a5, 0xdcd898ff), TOBN(0x26286c40, 0x2058ee3d), + TOBN(0x3db0b217, 0x5f87b1c1), TOBN(0xcc334771, 0x102a6db5), + TOBN(0xd99de954, 0x2f770fb1), TOBN(0x97c1c620, 0x4cd7535e), + TOBN(0xd3b6c448, 0x3f09cefc), TOBN(0xd725af15, 0x5a63b4f8), + TOBN(0x0c95d24f, 0xc01e20ec), TOBN(0xdfd37494, 0x9ae7121f), + TOBN(0x7d6ddb72, 0xec77b7ec), TOBN(0xfe079d3b, 0x0353a4ae), + TOBN(0x3066e70a, 0x2e6ac8d2), TOBN(0x9c6b5a43, 0x106e5c05), + TOBN(0x52d3c6f5, 0xede59b8c), TOBN(0x30d6a5c3, 0xfccec9ae), + TOBN(0xedec7c22, 0x4fc0a9ef), TOBN(0x190ff083, 0x95c16ced), + TOBN(0xbe12ec8f, 0x94de0fde), TOBN(0x0d131ab8, 0x852d3433), + TOBN(0x42ace07e, 0x85701291), TOBN(0x94793ed9, 0x194061a8), + TOBN(0x30e83ed6, 0xd7f4a485), TOBN(0x9eec7269, 0xf9eeff4d), + TOBN(0x90acba59, 0x0c9d8005), TOBN(0x5feca458, 0x1e79b9d1), + TOBN(0x8fbe5427, 0x1d506a1e), TOBN(0xa32b2c8e, 0x2439cfa7), + TOBN(0x1671c173, 0x73dd0b4e), TOBN(0x37a28214, 0x44a054c6), + TOBN(0x81760a1b, 0x4e8b53f1), TOBN(0xa6c04224, 0xf9f93b9e), + TOBN(0x18784b34, 0xcf671e3c), TOBN(0x81bbecd2, 0xcda9b994), + TOBN(0x38831979, 0xb2ab3848), TOBN(0xef54feb7, 0xf2e03c2d), + TOBN(0xcf197ca7, 0xfb8088fa), TOBN(0x01427247, 0x4ddc96c5), + TOBN(0xa2d2550a, 0x30777176), TOBN(0x53469898, 0x4d0cf71d), + TOBN(0x6ce937b8, 0x3a2aaac6), TOBN(0xe9f91dc3, 0x5af38d9b), + TOBN(0x2598ad83, 0xc8bf2899), TOBN(0x8e706ac9, 0xb5536c16), + TOBN(0x40dc7495, 0xf688dc98), TOBN(0x26490cd7, 0x124c4afc), + TOBN(0xe651ec84, 0x1f18775c), TOBN(0x393ea6c3, 0xb4fdaf4a), + TOBN(0x1e1f3343, 0x7f338e0d), TOBN(0x39fb832b, 0x6053e7b5), + TOBN(0x46e702da, 0x619e14d5), TOBN(0x859cacd1, 0xcdeef6e0), + TOBN(0x63b99ce7, 0x4462007d), TOBN(0xb8ab48a5, 0x4cb5f5b7), + TOBN(0x9ec673d2, 0xf55edde7), TOBN(0xd1567f74, 0x8cfaefda), + TOBN(0x46381b6b, 0x0887bcec), TOBN(0x694497ce, 0xe178f3c2), + TOBN(0x5e6525e3, 0x1e6266cb), TOBN(0x5931de26, 0x697d6413), + TOBN(0x87f8df7c, 0x0e58d493), TOBN(0xb1ae5ed0, 0x58b73f12), + TOBN(0xc368f784, 0xdea0c34d), TOBN(0x9bd0a120, 0x859a91a0), + TOBN(0xb00d88b7, 0xcc863c68), TOBN(0x3a1cc11e, 0x3d1f4d65), + TOBN(0xea38e0e7, 0x0aa85593), TOBN(0x37f13e98, 0x7dc4aee8), + TOBN(0x10d38667, 0xbc947bad), TOBN(0x738e07ce, 0x2a36ee2e), + TOBN(0xc93470cd, 0xc577fcac), TOBN(0xdee1b616, 0x2782470d), + TOBN(0x36a25e67, 0x2e793d12), TOBN(0xd6aa6cae, 0xe0f186da), + TOBN(0x474d0fd9, 0x80e07af7), TOBN(0xf7cdc47d, 0xba8a5cd4), + TOBN(0x28af6d9d, 0xab15247f), TOBN(0x7c789c10, 0x493a537f), + TOBN(0x7ac9b110, 0x23a334e7), TOBN(0x0236ac09, 0x12c9c277), + TOBN(0xa7e5bd25, 0x1d7a5144), TOBN(0x098b9c2a, 0xf13ec4ec), + TOBN(0x3639daca, 0xd3f0abca), TOBN(0x642da81a, 0xa23960f9), + TOBN(0x7d2e5c05, 0x4f7269b1), TOBN(0xfcf30777, 0xe287c385), + TOBN(0x10edc84f, 0xf2a46f21), TOBN(0x35441757, 0x4f43fa36), + TOBN(0xf1327899, 0xfd703431), TOBN(0xa438d7a6, 0x16dd587a), + TOBN(0x65c34c57, 0xe9c8352d), TOBN(0xa728edab, 0x5cc5a24e), + TOBN(0xaed78abc, 0x42531689), TOBN(0x0a51a0e8, 0x010963ef), + TOBN(0x5776fa0a, 0xd717d9b3), TOBN(0xf356c239, 0x7dd3428b), + TOBN(0x29903fff, 0x8d3a3dac), TOBN(0x409597fa, 0x3d94491f), + TOBN(0x4cd7a5ff, 0xbf4a56a4), TOBN(0xe5096474, 0x8adab462), + TOBN(0xa97b5126, 0x5c3427b0), TOBN(0x6401405c, 0xd282c9bd), + TOBN(0x3629f8d7, 0x222c5c45), TOBN(0xb1c02c16, 0xe8d50aed), + TOBN(0xbea2ed75, 0xd9635bc9), TOBN(0x226790c7, 0x6e24552f), + TOBN(0x3c33f2a3, 0x65f1d066), TOBN(0x2a43463e, 0x6dfccc2e), + TOBN(0x8cc3453a, 0xdb483761), TOBN(0xe7cc6085, 0x65d5672b), + TOBN(0x277ed6cb, 0xde3efc87), TOBN(0x19f2f368, 0x69234eaf), + TOBN(0x9aaf4317, 0x5c0b800b), TOBN(0x1f1e7c89, 0x8b6da6e2), + TOBN(0x6cfb4715, 0xb94ec75e), TOBN(0xd590dd5f, 0x453118c2), + TOBN(0x14e49da1, 0x1f17a34c), TOBN(0x5420ab39, 0x235a1456), + TOBN(0xb7637241, 0x2f50363b), TOBN(0x7b15d623, 0xc3fabb6e), + TOBN(0xa0ef40b1, 0xe274e49c), TOBN(0x5cf50744, 0x96b1860a), + TOBN(0xd6583fbf, 0x66afe5a4), TOBN(0x44240510, 0xf47e3e9a), + TOBN(0x99254343, 0x11b2d595), TOBN(0xf1367499, 0xeec8df57), + TOBN(0x3cb12c61, 0x3e73dd05), TOBN(0xd248c033, 0x7dac102a), + TOBN(0xcf154f13, 0xa77739f5), TOBN(0xbf4288cb, 0x23d2af42), + TOBN(0xaa64c9b6, 0x32e4a1cf), TOBN(0xee8c07a8, 0xc8a208f3), + TOBN(0xe10d4999, 0x6fe8393f), TOBN(0x0f809a3f, 0xe91f3a32), + TOBN(0x61096d1c, 0x802f63c8), TOBN(0x289e1462, 0x57750d3d), + TOBN(0xed06167e, 0x9889feea), TOBN(0xd5c9c0e2, 0xe0993909), + TOBN(0x46fca0d8, 0x56508ac6), TOBN(0x91826047, 0x4f1b8e83), + TOBN(0x4f2c877a, 0x9a4a2751), TOBN(0x71bd0072, 0xcae6fead), + TOBN(0x38df8dcc, 0x06aa1941), TOBN(0x5a074b4c, 0x63beeaa8), + TOBN(0xd6d65934, 0xc1cec8ed), TOBN(0xa6ecb49e, 0xaabc03bd), + TOBN(0xaade91c2, 0xde8a8415), TOBN(0xcfb0efdf, 0x691136e0), + TOBN(0x11af45ee, 0x23ab3495), TOBN(0xa132df88, 0x0b77463d), + TOBN(0x8923c15c, 0x815d06f4), TOBN(0xc3ceb3f5, 0x0d61a436), + TOBN(0xaf52291d, 0xe88fb1da), TOBN(0xea057974, 0x1da12179), + TOBN(0xb0d7218c, 0xd2fef720), TOBN(0x6c0899c9, 0x8e1d8845), + TOBN(0x98157504, 0x752ddad7), TOBN(0xd60bd74f, 0xa1a68a97), + TOBN(0x7047a3a9, 0xf658fb99), TOBN(0x1f5d86d6, 0x5f8511e4), + TOBN(0xb8a4bc42, 0x4b5a6d88), TOBN(0x69eb2c33, 0x1abefa7d), + TOBN(0x95bf39e8, 0x13c9c510), TOBN(0xf571960a, 0xd48aab43), + TOBN(0x7e8cfbcf, 0x704e23c6), TOBN(0xc71b7d22, 0x28aaa65b), + TOBN(0xa041b2bd, 0x245e3c83), TOBN(0x69b98834, 0xd21854ff), + TOBN(0x89d227a3, 0x963bfeec), TOBN(0x99947aaa, 0xde7da7cb), + TOBN(0x1d9ee9db, 0xee68a9b1), TOBN(0x0a08f003, 0x698ec368), + TOBN(0xe9ea4094, 0x78ef2487), TOBN(0xc8d2d415, 0x02cfec26), + TOBN(0xc52f9a6e, 0xb7dcf328), TOBN(0x0ed489e3, 0x85b6a937), + TOBN(0x9b94986b, 0xbef3366e), TOBN(0x0de59c70, 0xedddddb8), + TOBN(0xffdb748c, 0xeadddbe2), TOBN(0x9b9784bb, 0x8266ea40), + TOBN(0x142b5502, 0x1a93507a), TOBN(0xb4cd1187, 0x8d3c06cf), + TOBN(0xdf70e76a, 0x91ec3f40), TOBN(0x484e81ad, 0x4e7553c2), + TOBN(0x830f87b5, 0x272e9d6e), TOBN(0xea1c93e5, 0xc6ff514a), + TOBN(0x67cc2adc, 0xc4192a8e), TOBN(0xc77e27e2, 0x42f4535a), + TOBN(0x9cdbab36, 0xd2b713c5), TOBN(0x86274ea0, 0xcf7b0cd3), + TOBN(0x784680f3, 0x09af826b), TOBN(0xbfcc837a, 0x0c72dea3), + TOBN(0xa8bdfe9d, 0xd6529b73), TOBN(0x708aa228, 0x63a88002), + TOBN(0x6c7a9a54, 0xc91d45b9), TOBN(0xdf1a38bb, 0xfd004f56), + TOBN(0x2e8c9a26, 0xb8bad853), TOBN(0x2d52cea3, 0x3723eae7), + TOBN(0x054d6d81, 0x56ca2830), TOBN(0xa3317d14, 0x9a8dc411), + TOBN(0xa08662fe, 0xfd4ddeda), TOBN(0xed2a153a, 0xb55d792b), + TOBN(0x7035c16a, 0xbfc6e944), TOBN(0xb6bc5834, 0x00171cf3), + TOBN(0xe27152b3, 0x83d102b6), TOBN(0xfe695a47, 0x0646b848), + TOBN(0xa5bb09d8, 0x916e6d37), TOBN(0xb4269d64, 0x0d17015e), + TOBN(0x8d8156a1, 0x0a1d2285), TOBN(0xfeef6c51, 0x46d26d72), + TOBN(0x9dac57c8, 0x4c5434a7), TOBN(0x0282e5be, 0x59d39e31), + TOBN(0xedfff181, 0x721c486d), TOBN(0x301baf10, 0xbc58824e), + TOBN(0x8136a6aa, 0x00570031), TOBN(0x55aaf78c, 0x1cddde68), + TOBN(0x26829371, 0x59c63952), TOBN(0x3a3bd274, 0x8bc25baf), + TOBN(0xecdf8657, 0xb7e52dc3), TOBN(0x2dd8c087, 0xfd78e6c8), + TOBN(0x20553274, 0xf5531461), TOBN(0x8b4a1281, 0x5d95499b), + TOBN(0xe2c8763a, 0x1a80f9d2), TOBN(0xd1dbe32b, 0x4ddec758), + TOBN(0xaf12210d, 0x30c34169), TOBN(0xba74a953, 0x78baa533), + TOBN(0x3d133c6e, 0xa438f254), TOBN(0xa431531a, 0x201bef5b), + TOBN(0x15295e22, 0xf669d7ec), TOBN(0xca374f64, 0x357fb515), + TOBN(0x8a8406ff, 0xeaa3fdb3), TOBN(0x106ae448, 0xdf3f2da8), + TOBN(0x8f9b0a90, 0x33c8e9a1), TOBN(0x234645e2, 0x71ad5885), + TOBN(0x3d083224, 0x1c0aed14), TOBN(0xf10a7d3e, 0x7a942d46), + TOBN(0x7c11deee, 0x40d5c9be), TOBN(0xb2bae7ff, 0xba84ed98), + TOBN(0x93e97139, 0xaad58ddd), TOBN(0x3d872796, 0x3f6d1fa3), + TOBN(0x483aca81, 0x8569ff13), TOBN(0x8b89a5fb, 0x9a600f72), + TOBN(0x4cbc27c3, 0xc06f2b86), TOBN(0x22130713, 0x63ad9c0b), + TOBN(0xb5358b1e, 0x48ac2840), TOBN(0x18311294, 0xecba9477), + TOBN(0xda58f990, 0xa6946b43), TOBN(0x3098baf9, 0x9ab41819), + TOBN(0x66c4c158, 0x4198da52), TOBN(0xab4fc17c, 0x146bfd1b), + TOBN(0x2f0a4c3c, 0xbf36a908), TOBN(0x2ae9e34b, 0x58cf7838), + TOBN(0xf411529e, 0x3fa11b1f), TOBN(0x21e43677, 0x974af2b4), + TOBN(0x7c20958e, 0xc230793b), TOBN(0x710ea885, 0x16e840f3), + TOBN(0xfc0b21fc, 0xc5dc67cf), TOBN(0x08d51647, 0x88405718), + TOBN(0xd955c21f, 0xcfe49eb7), TOBN(0x9722a5d5, 0x56dd4a1f), + TOBN(0xc9ef50e2, 0xc861baa5), TOBN(0xc0c21a5d, 0x9505ac3e), + TOBN(0xaf6b9a33, 0x8b7c063f), TOBN(0xc6370339, 0x2f4779c1), + TOBN(0x22df99c7, 0x638167c3), TOBN(0xfe6ffe76, 0x795db30c), + TOBN(0x2b822d33, 0xa4854989), TOBN(0xfef031dd, 0x30563aa5), + TOBN(0x16b09f82, 0xd57c667f), TOBN(0xc70312ce, 0xcc0b76f1), + TOBN(0xbf04a9e6, 0xc9118aec), TOBN(0x82fcb419, 0x3409d133), + TOBN(0x1a8ab385, 0xab45d44d), TOBN(0xfba07222, 0x617b83a3), + TOBN(0xb05f50dd, 0x58e81b52), TOBN(0x1d8db553, 0x21ce5aff), + TOBN(0x3097b8d4, 0xe344a873), TOBN(0x7d8d116d, 0xfe36d53e), + TOBN(0x6db22f58, 0x7875e750), TOBN(0x2dc5e373, 0x43e144ea), + TOBN(0xc05f32e6, 0xe799eb95), TOBN(0xe9e5f4df, 0x6899e6ec), + TOBN(0xbdc3bd68, 0x1fab23d5), TOBN(0xb72b8ab7, 0x73af60e6), + TOBN(0x8db27ae0, 0x2cecc84a), TOBN(0x600016d8, 0x7bdb871c), + TOBN(0x42a44b13, 0xd7c46f58), TOBN(0xb8919727, 0xc3a77d39), + TOBN(0xcfc6bbbd, 0xdafd6088), TOBN(0x1a740146, 0x6bd20d39), + TOBN(0x8c747abd, 0x98c41072), TOBN(0x4c91e765, 0xbdf68ea1), + TOBN(0x7c95e5ca, 0x08819a78), TOBN(0xcf48b729, 0xc9587921), + TOBN(0x091c7c5f, 0xdebbcc7d), TOBN(0x6f287404, 0xf0e05149), + TOBN(0xf83b5ac2, 0x26cd44ec), TOBN(0x88ae32a6, 0xcfea250e), + TOBN(0x6ac5047a, 0x1d06ebc5), TOBN(0xc7e550b4, 0xd434f781), + TOBN(0x61ab1cf2, 0x5c727bd2), TOBN(0x2e4badb1, 0x1cf915b0), + TOBN(0x1b4dadec, 0xf69d3920), TOBN(0xe61b1ca6, 0xf14c1dfe), + TOBN(0x90b479cc, 0xbd6bd51f), TOBN(0x8024e401, 0x8045ec30), + TOBN(0xcab29ca3, 0x25ef0e62), TOBN(0x4f2e9416, 0x49e4ebc0), + TOBN(0x45eb40ec, 0x0ccced58), TOBN(0x25cd4b9c, 0x0da44f98), + TOBN(0x43e06458, 0x871812c6), TOBN(0x99f80d55, 0x16cef651), + TOBN(0x571340c9, 0xce6dc153), TOBN(0x138d5117, 0xd8665521), + TOBN(0xacdb45bc, 0x4e07014d), TOBN(0x2f34bb38, 0x84b60b91), + TOBN(0xf44a4fd2, 0x2ae8921e), TOBN(0xb039288e, 0x892ba1e2), + TOBN(0x9da50174, 0xb1c180b2), TOBN(0x6b70ab66, 0x1693dc87), + TOBN(0x7e9babc9, 0xe7057481), TOBN(0x4581ddef, 0x9c80dc41), + TOBN(0x0c890da9, 0x51294682), TOBN(0x0b5629d3, 0x3f4736e5), + TOBN(0x2340c79e, 0xb06f5b41), TOBN(0xa42e84ce, 0x4e243469), + TOBN(0xf9a20135, 0x045a71a9), TOBN(0xefbfb415, 0xd27b6fb6), + TOBN(0x25ebea23, 0x9d33cd6f), TOBN(0x9caedb88, 0xaa6c0af8), + TOBN(0x53dc7e9a, 0xd9ce6f96), TOBN(0x3897f9fd, 0x51e0b15a), + TOBN(0xf51cb1f8, 0x8e5d788e), TOBN(0x1aec7ba8, 0xe1d490ee), + TOBN(0x265991e0, 0xcc58cb3c), TOBN(0x9f306e8c, 0x9fc3ad31), + TOBN(0x5fed006e, 0x5040a0ac), TOBN(0xca9d5043, 0xfb476f2e), + TOBN(0xa19c06e8, 0xbeea7a23), TOBN(0xd2865801, 0x0edabb63), + TOBN(0xdb92293f, 0x6967469a), TOBN(0x2894d839, 0x8d8a8ed8), + TOBN(0x87c9e406, 0xbbc77122), TOBN(0x8671c6f1, 0x2ea3a26a), + TOBN(0xe42df8d6, 0xd7de9853), TOBN(0x2e3ce346, 0xb1f2bcc7), + TOBN(0xda601dfc, 0x899d50cf), TOBN(0xbfc913de, 0xfb1b598f), + TOBN(0x81c4909f, 0xe61f7908), TOBN(0x192e304f, 0x9bbc7b29), + TOBN(0xc3ed8738, 0xc104b338), TOBN(0xedbe9e47, 0x783f5d61), + TOBN(0x0c06e9be, 0x2db30660), TOBN(0xda3e613f, 0xc0eb7d8e), + TOBN(0xd8fa3e97, 0x322e096e), TOBN(0xfebd91e8, 0xd336e247), + TOBN(0x8f13ccc4, 0xdf655a49), TOBN(0xa9e00dfc, 0x5eb20210), + TOBN(0x84631d0f, 0xc656b6ea), TOBN(0x93a058cd, 0xd8c0d947), + TOBN(0x6846904a, 0x67bd3448), TOBN(0x4a3d4e1a, 0xf394fd5c), + TOBN(0xc102c1a5, 0xdb225f52), TOBN(0xe3455bba, 0xfc4f5e9a), + TOBN(0x6b36985b, 0x4b9ad1ce), TOBN(0xa9818536, 0x5bb7f793), + TOBN(0x6c25e1d0, 0x48b1a416), TOBN(0x1381dd53, 0x3c81bee7), + TOBN(0xd2a30d61, 0x7a4a7620), TOBN(0xc8412926, 0x39b8944c), + TOBN(0x3c1c6fbe, 0x7a97c33a), TOBN(0x941e541d, 0x938664e7), + TOBN(0x417499e8, 0x4a34f239), TOBN(0x15fdb83c, 0xb90402d5), + TOBN(0xb75f46bf, 0x433aa832), TOBN(0xb61e15af, 0x63215db1), + TOBN(0xaabe59d4, 0xa127f89a), TOBN(0x5d541e0c, 0x07e816da), + TOBN(0xaaba0659, 0xa618b692), TOBN(0x55327733, 0x17266026), + TOBN(0xaf53a0fc, 0x95f57552), TOBN(0x32947650, 0x6cacb0c9), + TOBN(0x253ff58d, 0xc821be01), TOBN(0xb0309531, 0xa06f1146), + TOBN(0x59bbbdf5, 0x05c2e54d), TOBN(0x158f27ad, 0x26e8dd22), + TOBN(0xcc5b7ffb, 0x397e1e53), TOBN(0xae03f65b, 0x7fc1e50d), + TOBN(0xa9784ebd, 0x9c95f0f9), TOBN(0x5ed9deb2, 0x24640771), + TOBN(0x31244af7, 0x035561c4), TOBN(0x87332f3a, 0x7ee857de), + TOBN(0x09e16e9e, 0x2b9e0d88), TOBN(0x52d910f4, 0x56a06049), + TOBN(0x507ed477, 0xa9592f48), TOBN(0x85cb917b, 0x2365d678), + TOBN(0xf8511c93, 0x4c8998d1), TOBN(0x2186a3f1, 0x730ea58f), + TOBN(0x50189626, 0xb2029db0), TOBN(0x9137a6d9, 0x02ceb75a), + TOBN(0x2fe17f37, 0x748bc82c), TOBN(0x87c2e931, 0x80469f8c), + TOBN(0x850f71cd, 0xbf891aa2), TOBN(0x0ca1b89b, 0x75ec3d8d), + TOBN(0x516c43aa, 0x5e1cd3cd), TOBN(0x89397808, 0x9a887c28), + TOBN(0x0059c699, 0xddea1f9f), TOBN(0x7737d6fa, 0x8e6868f7), + TOBN(0x6d93746a, 0x60f1524b), TOBN(0x36985e55, 0xba052aa7), + TOBN(0x41b1d322, 0xed923ea5), TOBN(0x3429759f, 0x25852a11), + TOBN(0xbeca6ec3, 0x092e9f41), TOBN(0x3a238c66, 0x62256bbd), + TOBN(0xd82958ea, 0x70ad487d), TOBN(0x4ac8aaf9, 0x65610d93), + TOBN(0x3fa101b1, 0x5e4ccab0), TOBN(0x9bf430f2, 0x9de14bfb), + TOBN(0xa10f5cc6, 0x6531899d), TOBN(0x590005fb, 0xea8ce17d), + TOBN(0xc437912f, 0x24544cb6), TOBN(0x9987b71a, 0xd79ac2e3), + TOBN(0x13e3d9dd, 0xc058a212), TOBN(0x00075aac, 0xd2de9606), + TOBN(0x80ab508b, 0x6cac8369), TOBN(0x87842be7, 0xf54f6c89), + TOBN(0xa7ad663d, 0x6bc532a4), TOBN(0x67813de7, 0x78a91bc8), + TOBN(0x5dcb61ce, 0xc3427239), TOBN(0x5f3c7cf0, 0xc56934d9), + TOBN(0xc079e0fb, 0xe3191591), TOBN(0xe40896bd, 0xb01aada7), + TOBN(0x8d466791, 0x0492d25f), TOBN(0x8aeb30c9, 0xe7408276), + TOBN(0xe9437495, 0x9287aacc), TOBN(0x23d4708d, 0x79fe03d4), + TOBN(0x8cda9cf2, 0xd0c05199), TOBN(0x502fbc22, 0xfae78454), + TOBN(0xc0bda9df, 0xf572a182), TOBN(0x5f9b71b8, 0x6158b372), + TOBN(0xe0f33a59, 0x2b82dd07), TOBN(0x76302735, 0x9523032e), + TOBN(0x7fe1a721, 0xc4505a32), TOBN(0x7b6e3e82, 0xf796409f)}, + {TOBN(0xe3417bc0, 0x35d0b34a), TOBN(0x440b386b, 0x8327c0a7), + TOBN(0x8fb7262d, 0xac0362d1), TOBN(0x2c41114c, 0xe0cdf943), + TOBN(0x2ba5cef1, 0xad95a0b1), TOBN(0xc09b37a8, 0x67d54362), + TOBN(0x26d6cdd2, 0x01e486c9), TOBN(0x20477abf, 0x42ff9297), + TOBN(0xa004dcb3, 0x292a9287), TOBN(0xddc15cf6, 0x77b092c7), + TOBN(0x083a8464, 0x806c0605), TOBN(0x4a68df70, 0x3db997b0), + TOBN(0x9c134e45, 0x05bf7dd0), TOBN(0xa4e63d39, 0x8ccf7f8c), + TOBN(0xa6e6517f, 0x41b5f8af), TOBN(0xaa8b9342, 0xad7bc1cc), + TOBN(0x126f35b5, 0x1e706ad9), TOBN(0xb99cebb4, 0xc3a9ebdf), + TOBN(0xa75389af, 0xbf608d90), TOBN(0x76113c4f, 0xc6c89858), + TOBN(0x80de8eb0, 0x97e2b5aa), TOBN(0x7e1022cc, 0x63b91304), + TOBN(0x3bdab605, 0x6ccc066c), TOBN(0x33cbb144, 0xb2edf900), + TOBN(0xc4176471, 0x7af715d2), TOBN(0xe2f7f594, 0xd0134a96), + TOBN(0x2c1873ef, 0xa41ec956), TOBN(0xe4e7b4f6, 0x77821304), + TOBN(0xe5c8ff97, 0x88d5374a), TOBN(0x2b915e63, 0x80823d5b), + TOBN(0xea6bc755, 0xb2ee8fe2), TOBN(0x6657624c, 0xe7112651), + TOBN(0x157af101, 0xdace5aca), TOBN(0xc4fdbcf2, 0x11a6a267), + TOBN(0xdaddf340, 0xc49c8609), TOBN(0x97e49f52, 0xe9604a65), + TOBN(0x9be8e790, 0x937e2ad5), TOBN(0x846e2508, 0x326e17f1), + TOBN(0x3f38007a, 0x0bbbc0dc), TOBN(0xcf03603f, 0xb11e16d6), + TOBN(0xd6f800e0, 0x7442f1d5), TOBN(0x475607d1, 0x66e0e3ab), + TOBN(0x82807f16, 0xb7c64047), TOBN(0x8858e1e3, 0xa749883d), + TOBN(0x5859120b, 0x8231ee10), TOBN(0x1b80e7eb, 0x638a1ece), + TOBN(0xcb72525a, 0xc6aa73a4), TOBN(0xa7cdea3d, 0x844423ac), + TOBN(0x5ed0c007, 0xf8ae7c38), TOBN(0x6db07a5c, 0x3d740192), + TOBN(0xbe5e9c2a, 0x5fe36db3), TOBN(0xd5b9d57a, 0x76e95046), + TOBN(0x54ac32e7, 0x8eba20f2), TOBN(0xef11ca8f, 0x71b9a352), + TOBN(0x305e373e, 0xff98a658), TOBN(0xffe5a100, 0x823eb667), + TOBN(0x57477b11, 0xe51732d2), TOBN(0xdfd6eb28, 0x2538fc0e), + TOBN(0x5c43b0cc, 0x3b39eec5), TOBN(0x6af12778, 0xcb36cc57), + TOBN(0x70b0852d, 0x06c425ae), TOBN(0x6df92f8c, 0x5c221b9b), + TOBN(0x6c8d4f9e, 0xce826d9c), TOBN(0xf59aba7b, 0xb49359c3), + TOBN(0x5c8ed8d5, 0xda64309d), TOBN(0x61a6de56, 0x91b30704), + TOBN(0xd6b52f6a, 0x2f9b5808), TOBN(0x0eee4194, 0x98c958a7), + TOBN(0xcddd9aab, 0x771e4caa), TOBN(0x83965dfd, 0x78bc21be), + TOBN(0x02affce3, 0xb3b504f5), TOBN(0x30847a21, 0x561c8291), + TOBN(0xd2eb2cf1, 0x52bfda05), TOBN(0xe0e4c4e9, 0x6197b98c), + TOBN(0x1d35076c, 0xf8a1726f), TOBN(0x6c06085b, 0x2db11e3d), + TOBN(0x15c0c4d7, 0x4463ba14), TOBN(0x9d292f83, 0x0030238c), + TOBN(0x1311ee8b, 0x3727536d), TOBN(0xfeea86ef, 0xbeaedc1e), + TOBN(0xb9d18cd3, 0x66131e2e), TOBN(0xf31d974f, 0x80fe2682), + TOBN(0xb6e49e0f, 0xe4160289), TOBN(0x7c48ec0b, 0x08e92799), + TOBN(0x818111d8, 0xd1989aa7), TOBN(0xb34fa0aa, 0xebf926f9), + TOBN(0xdb5fe2f5, 0xa245474a), TOBN(0xf80a6ebb, 0x3c7ca756), + TOBN(0xa7f96054, 0xafa05dd8), TOBN(0x26dfcf21, 0xfcaf119e), + TOBN(0xe20ef2e3, 0x0564bb59), TOBN(0xef4dca50, 0x61cb02b8), + TOBN(0xcda7838a, 0x65d30672), TOBN(0x8b08d534, 0xfd657e86), + TOBN(0x4c5b4395, 0x46d595c8), TOBN(0x39b58725, 0x425cb836), + TOBN(0x8ea61059, 0x3de9abe3), TOBN(0x40434881, 0x9cdc03be), + TOBN(0x9b261245, 0xcfedce8c), TOBN(0x78c318b4, 0xcf5234a1), + TOBN(0x510bcf16, 0xfde24c99), TOBN(0x2a77cb75, 0xa2c2ff5d), + TOBN(0x9c895c2b, 0x27960fb4), TOBN(0xd30ce975, 0xb0eda42b), + TOBN(0xfda85393, 0x1a62cc26), TOBN(0x23c69b96, 0x50c0e052), + TOBN(0xa227df15, 0xbfc633f3), TOBN(0x2ac78848, 0x1bae7d48), + TOBN(0x487878f9, 0x187d073d), TOBN(0x6c2be919, 0x967f807d), + TOBN(0x765861d8, 0x336e6d8f), TOBN(0x88b8974c, 0xce528a43), + TOBN(0x09521177, 0xff57d051), TOBN(0x2ff38037, 0xfb6a1961), + TOBN(0xfc0aba74, 0xa3d76ad4), TOBN(0x7c764803, 0x25a7ec17), + TOBN(0x7532d75f, 0x48879bc8), TOBN(0xea7eacc0, 0x58ce6bc1), + TOBN(0xc82176b4, 0x8e896c16), TOBN(0x9a30e0b2, 0x2c750fed), + TOBN(0xc37e2c2e, 0x421d3aa4), TOBN(0xf926407c, 0xe84fa840), + TOBN(0x18abc03d, 0x1454e41c), TOBN(0x26605ecd, 0x3f7af644), + TOBN(0x242341a6, 0xd6a5eabf), TOBN(0x1edb84f4, 0x216b668e), + TOBN(0xd836edb8, 0x04010102), TOBN(0x5b337ce7, 0x945e1d8c), + TOBN(0xd2075c77, 0xc055dc14), TOBN(0x2a0ffa25, 0x81d89cdf), + TOBN(0x8ce815ea, 0x6ffdcbaf), TOBN(0xa3428878, 0xfb648867), + TOBN(0x277699cf, 0x884655fb), TOBN(0xfa5b5bd6, 0x364d3e41), + TOBN(0x01f680c6, 0x441e1cb7), TOBN(0x3fd61e66, 0xb70a7d67), + TOBN(0x666ba2dc, 0xcc78cf66), TOBN(0xb3018174, 0x6fdbff77), + TOBN(0x8d4dd0db, 0x168d4668), TOBN(0x259455d0, 0x1dab3a2a), + TOBN(0xf58564c5, 0xcde3acec), TOBN(0x77141925, 0x13adb276), + TOBN(0x527d725d, 0x8a303f65), TOBN(0x55deb6c9, 0xe6f38f7b), + TOBN(0xfd5bb657, 0xb1fa70fb), TOBN(0xfa07f50f, 0xd8073a00), + TOBN(0xf72e3aa7, 0xbca02500), TOBN(0xf68f895d, 0x9975740d), + TOBN(0x30112060, 0x5cae2a6a), TOBN(0x01bd7218, 0x02874842), + TOBN(0x3d423891, 0x7ce47bd3), TOBN(0xa66663c1, 0x789544f6), + TOBN(0x864d05d7, 0x3272d838), TOBN(0xe22924f9, 0xfa6295c5), + TOBN(0x8189593f, 0x6c2fda32), TOBN(0x330d7189, 0xb184b544), + TOBN(0x79efa62c, 0xbde1f714), TOBN(0x35771c94, 0xe5cb1a63), + TOBN(0x2f4826b8, 0x641c8332), TOBN(0x00a894fb, 0xc8cee854), + TOBN(0xb4b9a39b, 0x36194d40), TOBN(0xe857a7c5, 0x77612601), + TOBN(0xf4209dd2, 0x4ecf2f58), TOBN(0x82b9e66d, 0x5a033487), + TOBN(0xc1e36934, 0xe4e8b9dd), TOBN(0xd2372c9d, 0xa42377d7), + TOBN(0x51dc94c7, 0x0e3ae43b), TOBN(0x4c57761e, 0x04474f6f), + TOBN(0xdcdacd0a, 0x1058a318), TOBN(0x369cf3f5, 0x78053a9a), + TOBN(0xc6c3de50, 0x31c68de2), TOBN(0x4653a576, 0x3c4b6d9f), + TOBN(0x1688dd5a, 0xaa4e5c97), TOBN(0x5be80aa1, 0xb7ab3c74), + TOBN(0x70cefe7c, 0xbc65c283), TOBN(0x57f95f13, 0x06867091), + TOBN(0xa39114e2, 0x4415503b), TOBN(0xc08ff7c6, 0x4cbb17e9), + TOBN(0x1eff674d, 0xd7dec966), TOBN(0x6d4690af, 0x53376f63), + TOBN(0xff6fe32e, 0xea74237b), TOBN(0xc436d17e, 0xcd57508e), + TOBN(0x15aa28e1, 0xedcc40fe), TOBN(0x0d769c04, 0x581bbb44), + TOBN(0xc240b6de, 0x34eaacda), TOBN(0xd9e116e8, 0x2ba0f1de), + TOBN(0xcbe45ec7, 0x79438e55), TOBN(0x91787c9d, 0x96f752d7), + TOBN(0x897f532b, 0xf129ac2f), TOBN(0xd307b7c8, 0x5a36e22c), + TOBN(0x91940675, 0x749fb8f3), TOBN(0xd14f95d0, 0x157fdb28), + TOBN(0xfe51d029, 0x6ae55043), TOBN(0x8931e98f, 0x44a87de1), + TOBN(0xe57f1cc6, 0x09e4fee2), TOBN(0x0d063b67, 0x4e072d92), + TOBN(0x70a998b9, 0xed0e4316), TOBN(0xe74a736b, 0x306aca46), + TOBN(0xecf0fbf2, 0x4fda97c7), TOBN(0xa40f65cb, 0x3e178d93), + TOBN(0x16253604, 0x16df4285), TOBN(0xb0c9babb, 0xd0c56ae2), + TOBN(0x73032b19, 0xcfc5cfc3), TOBN(0xe497e5c3, 0x09752056), + TOBN(0x12096bb4, 0x164bda96), TOBN(0x1ee42419, 0xa0b74da1), + TOBN(0x8fc36243, 0x403826ba), TOBN(0x0c8f0069, 0xdc09e660), + TOBN(0x8667e981, 0xc27253c9), TOBN(0x05a6aefb, 0x92b36a45), + TOBN(0xa62c4b36, 0x9cb7bb46), TOBN(0x8394f375, 0x11f7027b), + TOBN(0x747bc79c, 0x5f109d0f), TOBN(0xcad88a76, 0x5b8cc60a), + TOBN(0x80c5a66b, 0x58f09e68), TOBN(0xe753d451, 0xf6127eac), + TOBN(0xc44b74a1, 0x5b0ec6f5), TOBN(0x47989fe4, 0x5289b2b8), + TOBN(0x745f8484, 0x58d6fc73), TOBN(0xec362a6f, 0xf61c70ab), + TOBN(0x070c98a7, 0xb3a8ad41), TOBN(0x73a20fc0, 0x7b63db51), + TOBN(0xed2c2173, 0xf44c35f4), TOBN(0x8a56149d, 0x9acc9dca), + TOBN(0x98f17881, 0x9ac6e0f4), TOBN(0x360fdeaf, 0xa413b5ed), + TOBN(0x0625b8f4, 0xa300b0fd), TOBN(0xf1f4d76a, 0x5b3222d3), + TOBN(0x9d6f5109, 0x587f76b8), TOBN(0x8b4ee08d, 0x2317fdb5), + TOBN(0x88089bb7, 0x8c68b095), TOBN(0x95570e9a, 0x5808d9b9), + TOBN(0xa395c36f, 0x35d33ae7), TOBN(0x200ea123, 0x50bb5a94), + TOBN(0x20c789bd, 0x0bafe84b), TOBN(0x243ef52d, 0x0919276a), + TOBN(0x3934c577, 0xe23ae233), TOBN(0xb93807af, 0xa460d1ec), + TOBN(0xb72a53b1, 0xf8fa76a4), TOBN(0xd8914cb0, 0xc3ca4491), + TOBN(0x2e128494, 0x3fb42622), TOBN(0x3b2700ac, 0x500907d5), + TOBN(0xf370fb09, 0x1a95ec63), TOBN(0xf8f30be2, 0x31b6dfbd), + TOBN(0xf2b2f8d2, 0x69e55f15), TOBN(0x1fead851, 0xcc1323e9), + TOBN(0xfa366010, 0xd9e5eef6), TOBN(0x64d487b0, 0xe316107e), + TOBN(0x4c076b86, 0xd23ddc82), TOBN(0x03fd344c, 0x7e0143f0), + TOBN(0xa95362ff, 0x317af2c5), TOBN(0x0add3db7, 0xe18b7a4f), + TOBN(0x9c673e3f, 0x8260e01b), TOBN(0xfbeb49e5, 0x54a1cc91), + TOBN(0x91351bf2, 0x92f2e433), TOBN(0xc755e7ec, 0x851141eb), + TOBN(0xc9a95139, 0x29607745), TOBN(0x0ca07420, 0xa26f2b28), + TOBN(0xcb2790e7, 0x4bc6f9dd), TOBN(0x345bbb58, 0xadcaffc0), + TOBN(0xc65ea38c, 0xbe0f27a2), TOBN(0x67c24d7c, 0x641fcb56), + TOBN(0x2c25f0a7, 0xa9e2c757), TOBN(0x93f5cdb0, 0x16f16c49), + TOBN(0x2ca5a9d7, 0xc5ee30a1), TOBN(0xd1593635, 0xb909b729), + TOBN(0x804ce9f3, 0xdadeff48), TOBN(0xec464751, 0xb07c30c3), + TOBN(0x89d65ff3, 0x9e49af6a), TOBN(0xf2d6238a, 0x6f3d01bc), + TOBN(0x1095561e, 0x0bced843), TOBN(0x51789e12, 0xc8a13fd8), + TOBN(0xd633f929, 0x763231df), TOBN(0x46df9f7d, 0xe7cbddef), + TOBN(0x01c889c0, 0xcb265da8), TOBN(0xfce1ad10, 0xaf4336d2), + TOBN(0x8d110df6, 0xfc6a0a7e), TOBN(0xdd431b98, 0x6da425dc), + TOBN(0xcdc4aeab, 0x1834aabe), TOBN(0x84deb124, 0x8439b7fc), + TOBN(0x8796f169, 0x3c2a5998), TOBN(0x9b9247b4, 0x7947190d), + TOBN(0x55b9d9a5, 0x11597014), TOBN(0x7e9dd70d, 0x7b1566ee), + TOBN(0x94ad78f7, 0xcbcd5e64), TOBN(0x0359ac17, 0x9bd4c032), + TOBN(0x3b11baaf, 0x7cc222ae), TOBN(0xa6a6e284, 0xba78e812), + TOBN(0x8392053f, 0x24cea1a0), TOBN(0xc97bce4a, 0x33621491), + TOBN(0x7eb1db34, 0x35399ee9), TOBN(0x473f78ef, 0xece81ad1), + TOBN(0x41d72fe0, 0xf63d3d0d), TOBN(0xe620b880, 0xafab62fc), + TOBN(0x92096bc9, 0x93158383), TOBN(0x41a21357, 0x8f896f6c), + TOBN(0x1b5ee2fa, 0xc7dcfcab), TOBN(0x650acfde, 0x9546e007), + TOBN(0xc081b749, 0xb1b02e07), TOBN(0xda9e41a0, 0xf9eca03d), + TOBN(0x013ba727, 0x175a54ab), TOBN(0xca0cd190, 0xea5d8d10), + TOBN(0x85ea52c0, 0x95fd96a9), TOBN(0x2c591b9f, 0xbc5c3940), + TOBN(0x6fb4d4e4, 0x2bad4d5f), TOBN(0xfa4c3590, 0xfef0059b), + TOBN(0x6a10218a, 0xf5122294), TOBN(0x9a78a81a, 0xa85751d1), + TOBN(0x04f20579, 0xa98e84e7), TOBN(0xfe1242c0, 0x4997e5b5), + TOBN(0xe77a273b, 0xca21e1e4), TOBN(0xfcc8b1ef, 0x9411939d), + TOBN(0xe20ea302, 0x92d0487a), TOBN(0x1442dbec, 0x294b91fe), + TOBN(0x1f7a4afe, 0xbb6b0e8f), TOBN(0x1700ef74, 0x6889c318), + TOBN(0xf5bbffc3, 0x70f1fc62), TOBN(0x3b31d4b6, 0x69c79cca), + TOBN(0xe8bc2aab, 0xa7f6340d), TOBN(0xb0b08ab4, 0xa725e10a), + TOBN(0x44f05701, 0xae340050), TOBN(0xba4b3016, 0x1cf0c569), + TOBN(0x5aa29f83, 0xfbe19a51), TOBN(0x1b9ed428, 0xb71d752e), + TOBN(0x1666e54e, 0xeb4819f5), TOBN(0x616cdfed, 0x9e18b75b), + TOBN(0x112ed5be, 0x3ee27b0b), TOBN(0xfbf28319, 0x44c7de4d), + TOBN(0xd685ec85, 0xe0e60d84), TOBN(0x68037e30, 0x1db7ee78), + TOBN(0x5b65bdcd, 0x003c4d6e), TOBN(0x33e7363a, 0x93e29a6a), + TOBN(0x995b3a61, 0x08d0756c), TOBN(0xd727f85c, 0x2faf134b), + TOBN(0xfac6edf7, 0x1d337823), TOBN(0x99b9aa50, 0x0439b8b4), + TOBN(0x722eb104, 0xe2b4e075), TOBN(0x49987295, 0x437c4926), + TOBN(0xb1e4c0e4, 0x46a9b82d), TOBN(0xd0cb3197, 0x57a006f5), + TOBN(0xf3de0f7d, 0xd7808c56), TOBN(0xb5c54d8f, 0x51f89772), + TOBN(0x500a114a, 0xadbd31aa), TOBN(0x9afaaaa6, 0x295f6cab), + TOBN(0x94705e21, 0x04cf667a), TOBN(0xfc2a811b, 0x9d3935d7), + TOBN(0x560b0280, 0x6d09267c), TOBN(0xf19ed119, 0xf780e53b), + TOBN(0xf0227c09, 0x067b6269), TOBN(0x967b8533, 0x5caef599), + TOBN(0x155b9243, 0x68efeebc), TOBN(0xcd6d34f5, 0xc497bae6), + TOBN(0x1dd8d5d3, 0x6cceb370), TOBN(0x2aeac579, 0xa78d7bf9), + TOBN(0x5d65017d, 0x70b67a62), TOBN(0x70c8e44f, 0x17c53f67), + TOBN(0xd1fc0950, 0x86a34d09), TOBN(0xe0fca256, 0xe7134907), + TOBN(0xe24fa29c, 0x80fdd315), TOBN(0x2c4acd03, 0xd87499ad), + TOBN(0xbaaf7517, 0x3b5a9ba6), TOBN(0xb9cbe1f6, 0x12e51a51), + TOBN(0xd88edae3, 0x5e154897), TOBN(0xe4309c3c, 0x77b66ca0), + TOBN(0xf5555805, 0xf67f3746), TOBN(0x85fc37ba, 0xa36401ff), + TOBN(0xdf86e2ca, 0xd9499a53), TOBN(0x6270b2a3, 0xecbc955b), + TOBN(0xafae64f5, 0x974ad33b), TOBN(0x04d85977, 0xfe7b2df1), + TOBN(0x2a3db3ff, 0x4ab03f73), TOBN(0x0b87878a, 0x8702740a), + TOBN(0x6d263f01, 0x5a061732), TOBN(0xc25430ce, 0xa32a1901), + TOBN(0xf7ebab3d, 0xdb155018), TOBN(0x3a86f693, 0x63a9b78e), + TOBN(0x349ae368, 0xda9f3804), TOBN(0x470f07fe, 0xa164349c), + TOBN(0xd52f4cc9, 0x8562baa5), TOBN(0xc74a9e86, 0x2b290df3), + TOBN(0xd3a1aa35, 0x43471a24), TOBN(0x239446be, 0xb8194511), + TOBN(0xbec2dd00, 0x81dcd44d), TOBN(0xca3d7f0f, 0xc42ac82d), + TOBN(0x1f3db085, 0xfdaf4520), TOBN(0xbb6d3e80, 0x4549daf2), + TOBN(0xf5969d8a, 0x19ad5c42), TOBN(0x7052b13d, 0xdbfd1511), + TOBN(0x11890d1b, 0x682b9060), TOBN(0xa71d3883, 0xac34452c), + TOBN(0xa438055b, 0x783805b4), TOBN(0x43241277, 0x4725b23e), + TOBN(0xf20cf96e, 0x4901bbed), TOBN(0x6419c710, 0xf432a2bb), + TOBN(0x57a0fbb9, 0xdfa9cd7d), TOBN(0x589111e4, 0x00daa249), + TOBN(0x19809a33, 0x7b60554e), TOBN(0xea5f8887, 0xede283a4), + TOBN(0x2d713802, 0x503bfd35), TOBN(0x151bb0af, 0x585d2a53), + TOBN(0x40b08f74, 0x43b30ca8), TOBN(0xe10b5bba, 0xd9934583), + TOBN(0xe8a546d6, 0xb51110ad), TOBN(0x1dd50e66, 0x28e0b6c5), + TOBN(0x292e9d54, 0xcff2b821), TOBN(0x3882555d, 0x47281760), + TOBN(0x134838f8, 0x3724d6e3), TOBN(0xf2c679e0, 0x22ddcda1), + TOBN(0x40ee8815, 0x6d2a5768), TOBN(0x7f227bd2, 0x1c1e7e2d), + TOBN(0x487ba134, 0xd04ff443), TOBN(0x76e2ff3d, 0xc614e54b), + TOBN(0x36b88d6f, 0xa3177ec7), TOBN(0xbf731d51, 0x2328fff5), + TOBN(0x758caea2, 0x49ba158e), TOBN(0x5ab8ff4c, 0x02938188), + TOBN(0x33e16056, 0x35edc56d), TOBN(0x5a69d349, 0x7e940d79), + TOBN(0x6c4fd001, 0x03866dcb), TOBN(0x20a38f57, 0x4893cdef), + TOBN(0xfbf3e790, 0xfac3a15b), TOBN(0x6ed7ea2e, 0x7a4f8e6b), + TOBN(0xa663eb4f, 0xbc3aca86), TOBN(0x22061ea5, 0x080d53f7), + TOBN(0x2480dfe6, 0xf546783f), TOBN(0xd38bc6da, 0x5a0a641e), + TOBN(0xfb093cd1, 0x2ede8965), TOBN(0x89654db4, 0xacb455cf), + TOBN(0x413cbf9a, 0x26e1adee), TOBN(0x291f3764, 0x373294d4), + TOBN(0x00797257, 0x648083fe), TOBN(0x25f504d3, 0x208cc341), + TOBN(0x635a8e5e, 0xc3a0ee43), TOBN(0x70aaebca, 0x679898ff), + TOBN(0x9ee9f547, 0x5dc63d56), TOBN(0xce987966, 0xffb34d00), + TOBN(0xf9f86b19, 0x5e26310a), TOBN(0x9e435484, 0x382a8ca8), + TOBN(0x253bcb81, 0xc2352fe4), TOBN(0xa4eac8b0, 0x4474b571), + TOBN(0xc1b97512, 0xc1ad8cf8), TOBN(0x193b4e9e, 0x99e0b697), + TOBN(0x939d2716, 0x01e85df0), TOBN(0x4fb265b3, 0xcd44eafd), + TOBN(0x321e7dcd, 0xe51e1ae2), TOBN(0x8e3a8ca6, 0xe3d8b096), + TOBN(0x8de46cb0, 0x52604998), TOBN(0x91099ad8, 0x39072aa7), + TOBN(0x2617f91c, 0x93aa96b8), TOBN(0x0fc8716b, 0x7fca2e13), + TOBN(0xa7106f5e, 0x95328723), TOBN(0xd1c9c40b, 0x262e6522), + TOBN(0xb9bafe86, 0x42b7c094), TOBN(0x1873439d, 0x1543c021), + TOBN(0xe1baa5de, 0x5cbefd5d), TOBN(0xa363fc5e, 0x521e8aff), + TOBN(0xefe6320d, 0xf862eaac), TOBN(0x14419c63, 0x22c647dc), + TOBN(0x0e06707c, 0x4e46d428), TOBN(0xcb6c834f, 0x4a178f8f), + TOBN(0x0f993a45, 0xd30f917c), TOBN(0xd4c4b049, 0x9879afee), + TOBN(0xb6142a1e, 0x70500063), TOBN(0x7c9b41c3, 0xa5d9d605), + TOBN(0xbc00fc2f, 0x2f8ba2c7), TOBN(0x0966eb2f, 0x7c67aa28), + TOBN(0x13f7b516, 0x5a786972), TOBN(0x3bfb7557, 0x8a2fbba0), + TOBN(0x131c4f23, 0x5a2b9620), TOBN(0xbff3ed27, 0x6faf46be), + TOBN(0x9b4473d1, 0x7e172323), TOBN(0x421e8878, 0x339f6246), + TOBN(0x0fa8587a, 0x25a41632), TOBN(0xc0814124, 0xa35b6c93), + TOBN(0x2b18a9f5, 0x59ebb8db), TOBN(0x264e3357, 0x76edb29c), + TOBN(0xaf245ccd, 0xc87c51e2), TOBN(0x16b3015b, 0x501e6214), + TOBN(0xbb31c560, 0x0a3882ce), TOBN(0x6961bb94, 0xfec11e04), + TOBN(0x3b825b8d, 0xeff7a3a0), TOBN(0xbec33738, 0xb1df7326), + TOBN(0x68ad747c, 0x99604a1f), TOBN(0xd154c934, 0x9a3bd499), + TOBN(0xac33506f, 0x1cc7a906), TOBN(0x73bb5392, 0x6c560e8f), + TOBN(0x6428fcbe, 0x263e3944), TOBN(0xc11828d5, 0x1c387434), + TOBN(0x3cd04be1, 0x3e4b12ff), TOBN(0xc3aad9f9, 0x2d88667c), + TOBN(0xc52ddcf8, 0x248120cf), TOBN(0x985a892e, 0x2a389532), + TOBN(0xfbb4b21b, 0x3bb85fa0), TOBN(0xf95375e0, 0x8dfc6269), + TOBN(0xfb4fb06c, 0x7ee2acea), TOBN(0x6785426e, 0x309c4d1f), + TOBN(0x659b17c8, 0xd8ceb147), TOBN(0x9b649eee, 0xb70a5554), + TOBN(0x6b7fa0b5, 0xac6bc634), TOBN(0xd99fe2c7, 0x1d6e732f), + TOBN(0x30e6e762, 0x8d3abba2), TOBN(0x18fee6e7, 0xa797b799), + TOBN(0x5c9d360d, 0xc696464d), TOBN(0xe3baeb48, 0x27bfde12), + TOBN(0x2bf5db47, 0xf23206d5), TOBN(0x2f6d3420, 0x1d260152), + TOBN(0x17b87653, 0x3f8ff89a), TOBN(0x5157c30c, 0x378fa458), + TOBN(0x7517c5c5, 0x2d4fb936), TOBN(0xef22f7ac, 0xe6518cdc), + TOBN(0xdeb483e6, 0xbf847a64), TOBN(0xf5084558, 0x92e0fa89)}, + {TOBN(0xab9659d8, 0xdf7304d4), TOBN(0xb71bcf1b, 0xff210e8e), + TOBN(0xa9a2438b, 0xd73fbd60), TOBN(0x4595cd1f, 0x5d11b4de), + TOBN(0x9c0d329a, 0x4835859d), TOBN(0x4a0f0d2d, 0x7dbb6e56), + TOBN(0xc6038e5e, 0xdf928a4e), TOBN(0xc9429621, 0x8f5ad154), + TOBN(0x91213462, 0xf23f2d92), TOBN(0x6cab71bd, 0x60b94078), + TOBN(0x6bdd0a63, 0x176cde20), TOBN(0x54c9b20c, 0xee4d54bc), + TOBN(0x3cd2d8aa, 0x9f2ac02f), TOBN(0x03f8e617, 0x206eedb0), + TOBN(0xc7f68e16, 0x93086434), TOBN(0x831469c5, 0x92dd3db9), + TOBN(0x8521df24, 0x8f981354), TOBN(0x587e23ec, 0x3588a259), + TOBN(0xcbedf281, 0xd7a0992c), TOBN(0x06930a55, 0x38961407), + TOBN(0x09320deb, 0xbe5bbe21), TOBN(0xa7ffa5b5, 0x2491817f), + TOBN(0xe6c8b4d9, 0x09065160), TOBN(0xac4f3992, 0xfff6d2a9), + TOBN(0x7aa7a158, 0x3ae9c1bd), TOBN(0xe0af6d98, 0xe37ce240), + TOBN(0xe54342d9, 0x28ab38b4), TOBN(0xe8b75007, 0x0a1c98ca), + TOBN(0xefce86af, 0xe02358f2), TOBN(0x31b8b856, 0xea921228), + TOBN(0x052a1912, 0x0a1c67fc), TOBN(0xb4069ea4, 0xe3aead59), + TOBN(0x3232d6e2, 0x7fa03cb3), TOBN(0xdb938e5b, 0x0fdd7d88), + TOBN(0x04c1d2cd, 0x2ccbfc5d), TOBN(0xd2f45c12, 0xaf3a580f), + TOBN(0x592620b5, 0x7883e614), TOBN(0x5fd27e68, 0xbe7c5f26), + TOBN(0x139e45a9, 0x1567e1e3), TOBN(0x2cc71d2d, 0x44d8aaaf), + TOBN(0x4a9090cd, 0xe36d0757), TOBN(0xf722d7b1, 0xd9a29382), + TOBN(0xfb7fb04c, 0x04b48ddf), TOBN(0x628ad2a7, 0xebe16f43), + TOBN(0xcd3fbfb5, 0x20226040), TOBN(0x6c34ecb1, 0x5104b6c4), + TOBN(0x30c0754e, 0xc903c188), TOBN(0xec336b08, 0x2d23cab0), + TOBN(0x473d62a2, 0x1e206ee5), TOBN(0xf1e27480, 0x8c49a633), + TOBN(0x87ab956c, 0xe9f6b2c3), TOBN(0x61830b48, 0x62b606ea), + TOBN(0x67cd6846, 0xe78e815f), TOBN(0xfe40139f, 0x4c02082a), + TOBN(0x52bbbfcb, 0x952ec365), TOBN(0x74c11642, 0x6b9836ab), + TOBN(0x9f51439e, 0x558df019), TOBN(0x230da4ba, 0xac712b27), + TOBN(0x518919e3, 0x55185a24), TOBN(0x4dcefcdd, 0x84b78f50), + TOBN(0xa7d90fb2, 0xa47d4c5a), TOBN(0x55ac9abf, 0xb30e009e), + TOBN(0xfd2fc359, 0x74eed273), TOBN(0xb72d824c, 0xdbea8faf), + TOBN(0xce721a74, 0x4513e2ca), TOBN(0x0b418612, 0x38240b2c), + TOBN(0x05199968, 0xd5baa450), TOBN(0xeb1757ed, 0x2b0e8c25), + TOBN(0x6ebc3e28, 0x3dfac6d5), TOBN(0xb2431e2e, 0x48a237f5), + TOBN(0x2acb5e23, 0x52f61499), TOBN(0x5558a2a7, 0xe06c936b), + TOBN(0xd213f923, 0xcbb13d1b), TOBN(0x98799f42, 0x5bfb9bfe), + TOBN(0x1ae8ddc9, 0x701144a9), TOBN(0x0b8b3bb6, 0x4c5595ee), + TOBN(0x0ea9ef2e, 0x3ecebb21), TOBN(0x17cb6c4b, 0x3671f9a7), + TOBN(0x47ef464f, 0x726f1d1f), TOBN(0x171b9484, 0x6943a276), + TOBN(0x51a4ae2d, 0x7ef0329c), TOBN(0x08509222, 0x91c4402a), + TOBN(0x64a61d35, 0xafd45bbc), TOBN(0x38f096fe, 0x3035a851), + TOBN(0xc7468b74, 0xa1dec027), TOBN(0xe8cf10e7, 0x4fc7dcba), + TOBN(0xea35ff40, 0xf4a06353), TOBN(0x0b4c0dfa, 0x8b77dd66), + TOBN(0x779b8552, 0xde7e5c19), TOBN(0xfab28609, 0xc1c0256c), + TOBN(0x64f58eee, 0xabd4743d), TOBN(0x4e8ef838, 0x7b6cc93b), + TOBN(0xee650d26, 0x4cb1bf3d), TOBN(0x4c1f9d09, 0x73dedf61), + TOBN(0xaef7c9d7, 0xbfb70ced), TOBN(0x1ec0507e, 0x1641de1e), + TOBN(0xcd7e5cc7, 0xcde45079), TOBN(0xde173c9a, 0x516ac9e4), + TOBN(0x517a8494, 0xc170315c), TOBN(0x438fd905, 0x91d8e8fb), + TOBN(0x5145c506, 0xc7d9630b), TOBN(0x6457a87b, 0xf47d4d75), + TOBN(0xd31646bf, 0x0d9a80e8), TOBN(0x453add2b, 0xcef3aabe), + TOBN(0xc9941109, 0xa607419d), TOBN(0xfaa71e62, 0xbb6bca80), + TOBN(0x34158c13, 0x07c431f3), TOBN(0x594abebc, 0x992bc47a), + TOBN(0x6dfea691, 0xeb78399f), TOBN(0x48aafb35, 0x3f42cba4), + TOBN(0xedcd65af, 0x077c04f0), TOBN(0x1a29a366, 0xe884491a), + TOBN(0x023a40e5, 0x1c21f2bf), TOBN(0xf99a513c, 0xa5057aee), + TOBN(0xa3fe7e25, 0xbcab072e), TOBN(0x8568d2e1, 0x40e32bcf), + TOBN(0x904594eb, 0xd3f69d9f), TOBN(0x181a9733, 0x07affab1), + TOBN(0xe4d68d76, 0xb6e330f4), TOBN(0x87a6dafb, 0xc75a7fc1), + TOBN(0x549db2b5, 0xef7d9289), TOBN(0x2480d4a8, 0x197f015a), + TOBN(0x61d5590b, 0xc40493b6), TOBN(0x3a55b52e, 0x6f780331), + TOBN(0x40eb8115, 0x309eadb0), TOBN(0xdea7de5a, 0x92e5c625), + TOBN(0x64d631f0, 0xcc6a3d5a), TOBN(0x9d5e9d7c, 0x93e8dd61), + TOBN(0xf297bef5, 0x206d3ffc), TOBN(0x23d5e033, 0x7d808bd4), + TOBN(0x4a4f6912, 0xd24cf5ba), TOBN(0xe4d8163b, 0x09cdaa8a), + TOBN(0x0e0de9ef, 0xd3082e8e), TOBN(0x4fe1246c, 0x0192f360), + TOBN(0x1f900150, 0x4b8eee0a), TOBN(0x5219da81, 0xf1da391b), + TOBN(0x7bf6a5c1, 0xf7ea25aa), TOBN(0xd165e6bf, 0xfbb07d5f), + TOBN(0xe3539361, 0x89e78671), TOBN(0xa3fcac89, 0x2bac4219), + TOBN(0xdfab6fd4, 0xf0baa8ab), TOBN(0x5a4adac1, 0xe2c1c2e5), + TOBN(0x6cd75e31, 0x40d85849), TOBN(0xce263fea, 0x19b39181), + TOBN(0xcb6803d3, 0x07032c72), TOBN(0x7f40d5ce, 0x790968c8), + TOBN(0xa6de86bd, 0xdce978f0), TOBN(0x25547c4f, 0x368f751c), + TOBN(0xb1e685fd, 0x65fb2a9e), TOBN(0xce69336f, 0x1eb9179c), + TOBN(0xb15d1c27, 0x12504442), TOBN(0xb7df465c, 0xb911a06b), + TOBN(0xb8d804a3, 0x315980cd), TOBN(0x693bc492, 0xfa3bebf7), + TOBN(0x3578aeee, 0x2253c504), TOBN(0x158de498, 0xcd2474a2), + TOBN(0x1331f5c7, 0xcfda8368), TOBN(0xd2d7bbb3, 0x78d7177e), + TOBN(0xdf61133a, 0xf3c1e46e), TOBN(0x5836ce7d, 0xd30e7be8), + TOBN(0x83084f19, 0x94f834cb), TOBN(0xd35653d4, 0x429ed782), + TOBN(0xa542f16f, 0x59e58243), TOBN(0xc2b52f65, 0x0470a22d), + TOBN(0xe3b6221b, 0x18f23d96), TOBN(0xcb05abac, 0x3f5252b4), + TOBN(0xca00938b, 0x87d61402), TOBN(0x2f186cdd, 0x411933e4), + TOBN(0xe042ece5, 0x9a29a5c5), TOBN(0xb19b3c07, 0x3b6c8402), + TOBN(0xc97667c7, 0x19d92684), TOBN(0xb5624622, 0xebc66372), + TOBN(0x0cb96e65, 0x3c04fa02), TOBN(0x83a7176c, 0x8eaa39aa), + TOBN(0x2033561d, 0xeaa1633f), TOBN(0x45a9d086, 0x4533df73), + TOBN(0xe0542c1d, 0x3dc090bc), TOBN(0x82c996ef, 0xaa59c167), + TOBN(0xe3f735e8, 0x0ee7fc4d), TOBN(0x7b179393, 0x7c35db79), + TOBN(0xb6419e25, 0xf8c5dbfd), TOBN(0x4d9d7a1e, 0x1f327b04), + TOBN(0x979f6f9b, 0x298dfca8), TOBN(0xc7c5dff1, 0x8de9366a), + TOBN(0x1b7a588d, 0x04c82bdd), TOBN(0x68005534, 0xf8319dfd), + TOBN(0xde8a55b5, 0xd8eb9580), TOBN(0x5ea886da, 0x8d5bca81), + TOBN(0xe8530a01, 0x252a0b4d), TOBN(0x1bffb4fe, 0x35eaa0a1), + TOBN(0x2ad828b1, 0xd8e99563), TOBN(0x7de96ef5, 0x95f9cd87), + TOBN(0x4abb2d0c, 0xd77d970c), TOBN(0x03cfb933, 0xd33ef9cb), + TOBN(0xb0547c01, 0x8b211fe9), TOBN(0x2fe64809, 0xa56ed1c6), + TOBN(0xcb7d5624, 0xc2ac98cc), TOBN(0x2a1372c0, 0x1a393e33), + TOBN(0xc8d1ec1c, 0x29660521), TOBN(0xf3d31b04, 0xb37ac3e9), + TOBN(0xa29ae9df, 0x5ece6e7c), TOBN(0x0603ac8f, 0x0facfb55), + TOBN(0xcfe85b7a, 0xdda233a5), TOBN(0xe618919f, 0xbd75f0b8), + TOBN(0xf555a3d2, 0x99bf1603), TOBN(0x1f43afc9, 0xf184255a), + TOBN(0xdcdaf341, 0x319a3e02), TOBN(0xd3b117ef, 0x03903a39), + TOBN(0xe095da13, 0x65d1d131), TOBN(0x86f16367, 0xc37ad03e), + TOBN(0x5f37389e, 0x462cd8dd), TOBN(0xc103fa04, 0xd67a60e6), + TOBN(0x57c34344, 0xf4b478f0), TOBN(0xce91edd8, 0xe117c98d), + TOBN(0x001777b0, 0x231fc12e), TOBN(0x11ae47f2, 0xb207bccb), + TOBN(0xd983cf8d, 0x20f8a242), TOBN(0x7aff5b1d, 0xf22e1ad8), + TOBN(0x68fd11d0, 0x7fc4feb3), TOBN(0x5d53ae90, 0xb0f1c3e1), + TOBN(0x50fb7905, 0xec041803), TOBN(0x85e3c977, 0x14404888), + TOBN(0x0e67faed, 0xac628d8f), TOBN(0x2e865150, 0x6668532c), + TOBN(0x15acaaa4, 0x6a67a6b0), TOBN(0xf4cdee25, 0xb25cec41), + TOBN(0x49ee565a, 0xe4c6701e), TOBN(0x2a04ca66, 0xfc7d63d8), + TOBN(0xeb105018, 0xef0543fb), TOBN(0xf709a4f5, 0xd1b0d81d), + TOBN(0x5b906ee6, 0x2915d333), TOBN(0xf4a87412, 0x96f1f0ab), + TOBN(0xb6b82fa7, 0x4d82f4c2), TOBN(0x90725a60, 0x6804efb3), + TOBN(0xbc82ec46, 0xadc3425e), TOBN(0xb7b80581, 0x2787843e), + TOBN(0xdf46d91c, 0xdd1fc74c), TOBN(0xdc1c62cb, 0xe783a6c4), + TOBN(0x59d1b9f3, 0x1a04cbba), TOBN(0xd87f6f72, 0x95e40764), + TOBN(0x02b4cfc1, 0x317f4a76), TOBN(0x8d2703eb, 0x91036bce), + TOBN(0x98206cc6, 0xa5e72a56), TOBN(0x57be9ed1, 0xcf53fb0f), + TOBN(0x09374571, 0xef0b17ac), TOBN(0x74b2655e, 0xd9181b38), + TOBN(0xc8f80ea8, 0x89935d0e), TOBN(0xc0d9e942, 0x91529936), + TOBN(0x19686041, 0x1e84e0e5), TOBN(0xa5db84d3, 0xaea34c93), + TOBN(0xf9d5bb19, 0x7073a732), TOBN(0xb8d2fe56, 0x6bcfd7c0), + TOBN(0x45775f36, 0xf3eb82fa), TOBN(0x8cb20ccc, 0xfdff8b58), + TOBN(0x1659b65f, 0x8374c110), TOBN(0xb8b4a422, 0x330c789a), + TOBN(0x75e3c3ea, 0x6fe8208b), TOBN(0xbd74b9e4, 0x286e78fe), + TOBN(0x0be2e81b, 0xd7d93a1a), TOBN(0x7ed06e27, 0xdd0a5aae), + TOBN(0x721f5a58, 0x6be8b800), TOBN(0x428299d1, 0xd846db28), + TOBN(0x95cb8e6b, 0x5be88ed3), TOBN(0xc3186b23, 0x1c034e11), + TOBN(0xa6312c9e, 0x8977d99b), TOBN(0xbe944331, 0x83f531e7), + TOBN(0x8232c0c2, 0x18d3b1d4), TOBN(0x617aae8b, 0xe1247b73), + TOBN(0x40153fc4, 0x282aec3b), TOBN(0xc6063d2f, 0xf7b8f823), + TOBN(0x68f10e58, 0x3304f94c), TOBN(0x31efae74, 0xee676346), + TOBN(0xbadb6c6d, 0x40a9b97c), TOBN(0x14702c63, 0x4f666256), + TOBN(0xdeb954f1, 0x5184b2e3), TOBN(0x5184a526, 0x94b6ca40), + TOBN(0xfff05337, 0x003c32ea), TOBN(0x5aa374dd, 0x205974c7), + TOBN(0x9a763854, 0x4b0dd71a), TOBN(0x459cd27f, 0xdeb947ec), + TOBN(0xa6e28161, 0x459c2b92), TOBN(0x2f020fa8, 0x75ee8ef5), + TOBN(0xb132ec2d, 0x30b06310), TOBN(0xc3e15899, 0xbc6a4530), + TOBN(0xdc5f53fe, 0xaa3f451a), TOBN(0x3a3c7f23, 0xc2d9acac), + TOBN(0x2ec2f892, 0x6b27e58b), TOBN(0x68466ee7, 0xd742799f), + TOBN(0x98324dd4, 0x1fa26613), TOBN(0xa2dc6dab, 0xbdc29d63), + TOBN(0xf9675faa, 0xd712d657), TOBN(0x813994be, 0x21fd8d15), + TOBN(0x5ccbb722, 0xfd4f7553), TOBN(0x5135ff8b, 0xf3a36b20), + TOBN(0x44be28af, 0x69559df5), TOBN(0x40b65bed, 0x9d41bf30), + TOBN(0xd98bf2a4, 0x3734e520), TOBN(0x5e3abbe3, 0x209bdcba), + TOBN(0x77c76553, 0xbc945b35), TOBN(0x5331c093, 0xc6ef14aa), + TOBN(0x518ffe29, 0x76b60c80), TOBN(0x2285593b, 0x7ace16f8), + TOBN(0xab1f64cc, 0xbe2b9784), TOBN(0xe8f2c0d9, 0xab2421b6), + TOBN(0x617d7174, 0xc1df065c), TOBN(0xafeeb5ab, 0x5f6578fa), + TOBN(0x16ff1329, 0x263b54a8), TOBN(0x45c55808, 0xc990dce3), + TOBN(0x42eab6c0, 0xecc8c177), TOBN(0x799ea9b5, 0x5982ecaa), + TOBN(0xf65da244, 0xb607ef8e), TOBN(0x8ab226ce, 0x32a3fc2c), + TOBN(0x745741e5, 0x7ea973dc), TOBN(0x5c00ca70, 0x20888f2e), + TOBN(0x7cdce3cf, 0x45fd9cf1), TOBN(0x8a741ef1, 0x5507f872), + TOBN(0x47c51c2f, 0x196b4cec), TOBN(0x70d08e43, 0xc97ea618), + TOBN(0x930da15c, 0x15b18a2b), TOBN(0x33b6c678, 0x2f610514), + TOBN(0xc662e4f8, 0x07ac9794), TOBN(0x1eccf050, 0xba06cb79), + TOBN(0x1ff08623, 0xe7d954e5), TOBN(0x6ef2c5fb, 0x24cf71c3), + TOBN(0xb2c063d2, 0x67978453), TOBN(0xa0cf3796, 0x1d654af8), + TOBN(0x7cb242ea, 0x7ebdaa37), TOBN(0x206e0b10, 0xb86747e0), + TOBN(0x481dae5f, 0xd5ecfefc), TOBN(0x07084fd8, 0xc2bff8fc), + TOBN(0x8040a01a, 0xea324596), TOBN(0x4c646980, 0xd4de4036), + TOBN(0x9eb8ab4e, 0xd65abfc3), TOBN(0xe01cb91f, 0x13541ec7), + TOBN(0x8f029adb, 0xfd695012), TOBN(0x9ae28483, 0x3c7569ec), + TOBN(0xa5614c9e, 0xa66d80a1), TOBN(0x680a3e44, 0x75f5f911), + TOBN(0x0c07b14d, 0xceba4fc1), TOBN(0x891c285b, 0xa13071c1), + TOBN(0xcac67ceb, 0x799ece3c), TOBN(0x29b910a9, 0x41e07e27), + TOBN(0x66bdb409, 0xf2e43123), TOBN(0x06f8b137, 0x7ac9ecbe), + TOBN(0x5981fafd, 0x38547090), TOBN(0x19ab8b9f, 0x85e3415d), + TOBN(0xfc28c194, 0xc7e31b27), TOBN(0x843be0aa, 0x6fbcbb42), + TOBN(0xf3b1ed43, 0xa6db836c), TOBN(0x2a1330e4, 0x01a45c05), + TOBN(0x4f19f3c5, 0x95c1a377), TOBN(0xa85f39d0, 0x44b5ee33), + TOBN(0x3da18e6d, 0x4ae52834), TOBN(0x5a403b39, 0x7423dcb0), + TOBN(0xbb555e0a, 0xf2374aef), TOBN(0x2ad599c4, 0x1e8ca111), + TOBN(0x1b3a2fb9, 0x014b3bf8), TOBN(0x73092684, 0xf66d5007), + TOBN(0x079f1426, 0xc4340102), TOBN(0x1827cf81, 0x8fddf4de), + TOBN(0xc83605f6, 0xf10ff927), TOBN(0xd3871451, 0x23739fc6), + TOBN(0x6d163450, 0xcac1c2cc), TOBN(0x6b521296, 0xa2ec1ac5), + TOBN(0x0606c4f9, 0x6e3cb4a5), TOBN(0xe47d3f41, 0x778abff7), + TOBN(0x425a8d5e, 0xbe8e3a45), TOBN(0x53ea9e97, 0xa6102160), + TOBN(0x477a106e, 0x39cbb688), TOBN(0x532401d2, 0xf3386d32), + TOBN(0x8e564f64, 0xb1b9b421), TOBN(0xca9b8388, 0x81dad33f), + TOBN(0xb1422b4e, 0x2093913e), TOBN(0x533d2f92, 0x69bc8112), + TOBN(0x3fa017be, 0xebe7b2c7), TOBN(0xb2767c4a, 0xcaf197c6), + TOBN(0xc925ff87, 0xaedbae9f), TOBN(0x7daf0eb9, 0x36880a54), + TOBN(0x9284ddf5, 0x9c4d0e71), TOBN(0x1581cf93, 0x316f8cf5), + TOBN(0x3eeca887, 0x3ac1f452), TOBN(0xb417fce9, 0xfb6aeffe), + TOBN(0xa5918046, 0xeefb8dc3), TOBN(0x73d318ac, 0x02209400), + TOBN(0xe800400f, 0x728693e5), TOBN(0xe87d814b, 0x339927ed), + TOBN(0x93e94d3b, 0x57ea9910), TOBN(0xff8a35b6, 0x2245fb69), + TOBN(0x043853d7, 0x7f200d34), TOBN(0x470f1e68, 0x0f653ce1), + TOBN(0x81ac05bd, 0x59a06379), TOBN(0xa14052c2, 0x03930c29), + TOBN(0x6b72fab5, 0x26bc2797), TOBN(0x13670d16, 0x99f16771), + TOBN(0x00170052, 0x1e3e48d1), TOBN(0x978fe401, 0xb7adf678), + TOBN(0x55ecfb92, 0xd41c5dd4), TOBN(0x5ff8e247, 0xc7b27da5), + TOBN(0xe7518272, 0x013fb606), TOBN(0x5768d7e5, 0x2f547a3c), + TOBN(0xbb24eaa3, 0x60017a5f), TOBN(0x6b18e6e4, 0x9c64ce9b), + TOBN(0xc225c655, 0x103dde07), TOBN(0xfc3672ae, 0x7592f7ea), + TOBN(0x9606ad77, 0xd06283a1), TOBN(0x542fc650, 0xe4d59d99), + TOBN(0xabb57c49, 0x2a40e7c2), TOBN(0xac948f13, 0xa8db9f55), + TOBN(0x6d4c9682, 0xb04465c3), TOBN(0xe3d062fa, 0x6468bd15), + TOBN(0xa51729ac, 0x5f318d7e), TOBN(0x1fc87df6, 0x9eb6fc95), + TOBN(0x63d146a8, 0x0591f652), TOBN(0xa861b8f7, 0x589621aa), + TOBN(0x59f5f15a, 0xce31348c), TOBN(0x8f663391, 0x440da6da), + TOBN(0xcfa778ac, 0xb591ffa3), TOBN(0x027ca9c5, 0x4cdfebce), + TOBN(0xbe8e05a5, 0x444ea6b3), TOBN(0x8aab4e69, 0xa78d8254), + TOBN(0x2437f04f, 0xb474d6b8), TOBN(0x6597ffd4, 0x045b3855), + TOBN(0xbb0aea4e, 0xca47ecaa), TOBN(0x568aae83, 0x85c7ebfc), + TOBN(0x0e966e64, 0xc73b2383), TOBN(0x49eb3447, 0xd17d8762), + TOBN(0xde107821, 0x8da05dab), TOBN(0x443d8baa, 0x016b7236), + TOBN(0x163b63a5, 0xea7610d6), TOBN(0xe47e4185, 0xce1ca979), + TOBN(0xae648b65, 0x80baa132), TOBN(0xebf53de2, 0x0e0d5b64), + TOBN(0x8d3bfcb4, 0xd3c8c1ca), TOBN(0x0d914ef3, 0x5d04b309), + TOBN(0x55ef6415, 0x3de7d395), TOBN(0xbde1666f, 0x26b850e8), + TOBN(0xdbe1ca6e, 0xd449ab19), TOBN(0x8902b322, 0xe89a2672), + TOBN(0xb1674b7e, 0xdacb7a53), TOBN(0x8e9faf6e, 0xf52523ff), + TOBN(0x6ba535da, 0x9a85788b), TOBN(0xd21f03ae, 0xbd0626d4), + TOBN(0x099f8c47, 0xe873dc64), TOBN(0xcda8564d, 0x018ec97e), + TOBN(0x3e8d7a5c, 0xde92c68c), TOBN(0x78e035a1, 0x73323cc4), + TOBN(0x3ef26275, 0xf880ff7c), TOBN(0xa4ee3dff, 0x273eedaa), + TOBN(0x58823507, 0xaf4e18f8), TOBN(0x967ec9b5, 0x0672f328), + TOBN(0x9ded19d9, 0x559d3186), TOBN(0x5e2ab3de, 0x6cdce39c), + TOBN(0xabad6e4d, 0x11c226df), TOBN(0xf9783f43, 0x87723014), + TOBN(0x9a49a0cf, 0x1a885719), TOBN(0xfc0c1a5a, 0x90da9dbf), + TOBN(0x8bbaec49, 0x571d92ac), TOBN(0x569e85fe, 0x4692517f), + TOBN(0x8333b014, 0xa14ea4af), TOBN(0x32f2a62f, 0x12e5c5ad), + TOBN(0x98c2ce3a, 0x06d89b85), TOBN(0xb90741aa, 0x2ff77a08), + TOBN(0x2530defc, 0x01f795a2), TOBN(0xd6e5ba0b, 0x84b3c199), + TOBN(0x7d8e8451, 0x12e4c936), TOBN(0xae419f7d, 0xbd0be17b), + TOBN(0xa583fc8c, 0x22262bc9), TOBN(0x6b842ac7, 0x91bfe2bd), + TOBN(0x33cef4e9, 0x440d6827), TOBN(0x5f69f4de, 0xef81fb14), + TOBN(0xf16cf6f6, 0x234fbb92), TOBN(0x76ae3fc3, 0xd9e7e158), + TOBN(0x4e89f6c2, 0xe9740b33), TOBN(0x677bc85d, 0x4962d6a1), + TOBN(0x6c6d8a7f, 0x68d10d15), TOBN(0x5f9a7224, 0x0257b1cd), + TOBN(0x7096b916, 0x4ad85961), TOBN(0x5f8c47f7, 0xe657ab4a), + TOBN(0xde57d7d0, 0xf7461d7e), TOBN(0x7eb6094d, 0x80ce5ee2), + TOBN(0x0b1e1dfd, 0x34190547), TOBN(0x8a394f43, 0xf05dd150), + TOBN(0x0a9eb24d, 0x97df44e6), TOBN(0x78ca06bf, 0x87675719), + TOBN(0x6f0b3462, 0x6ffeec22), TOBN(0x9d91bcea, 0x36cdd8fb), + TOBN(0xac83363c, 0xa105be47), TOBN(0x81ba76c1, 0x069710e3), + TOBN(0x3d1b24cb, 0x28c682c6), TOBN(0x27f25228, 0x8612575b), + TOBN(0xb587c779, 0xe8e66e98), TOBN(0x7b0c03e9, 0x405eb1fe), + TOBN(0xfdf0d030, 0x15b548e7), TOBN(0xa8be76e0, 0x38b36af7), + TOBN(0x4cdab04a, 0x4f310c40), TOBN(0x6287223e, 0xf47ecaec), + TOBN(0x678e6055, 0x8b399320), TOBN(0x61fe3fa6, 0xc01e4646), + TOBN(0xc482866b, 0x03261a5e), TOBN(0xdfcf45b8, 0x5c2f244a), + TOBN(0x8fab9a51, 0x2f684b43), TOBN(0xf796c654, 0xc7220a66), + TOBN(0x1d90707e, 0xf5afa58f), TOBN(0x2c421d97, 0x4fdbe0de), + TOBN(0xc4f4cda3, 0xaf2ebc2f), TOBN(0xa0af843d, 0xcb4efe24), + TOBN(0x53b857c1, 0x9ccd10b1), TOBN(0xddc9d1eb, 0x914d3e04), + TOBN(0x7bdec8bb, 0x62771deb), TOBN(0x829277aa, 0x91c5aa81), + TOBN(0x7af18dd6, 0x832391ae), TOBN(0x1740f316, 0xc71a84ca)}, + {TOBN(0x8928e99a, 0xeeaf8c49), TOBN(0xee7aa73d, 0x6e24d728), + TOBN(0x4c5007c2, 0xe72b156c), TOBN(0x5fcf57c5, 0xed408a1d), + TOBN(0x9f719e39, 0xb6057604), TOBN(0x7d343c01, 0xc2868bbf), + TOBN(0x2cca254b, 0x7e103e2d), TOBN(0xe6eb38a9, 0xf131bea2), + TOBN(0xb33e624f, 0x8be762b4), TOBN(0x2a9ee4d1, 0x058e3413), + TOBN(0x968e6369, 0x67d805fa), TOBN(0x9848949b, 0x7db8bfd7), + TOBN(0x5308d7e5, 0xd23a8417), TOBN(0x892f3b1d, 0xf3e29da5), + TOBN(0xc95c139e, 0x3dee471f), TOBN(0x8631594d, 0xd757e089), + TOBN(0xe0c82a3c, 0xde918dcc), TOBN(0x2e7b5994, 0x26fdcf4b), + TOBN(0x82c50249, 0x32cb1b2d), TOBN(0xea613a9d, 0x7657ae07), + TOBN(0xc2eb5f6c, 0xf1fdc9f7), TOBN(0xb6eae8b8, 0x879fe682), + TOBN(0x253dfee0, 0x591cbc7f), TOBN(0x000da713, 0x3e1290e6), + TOBN(0x1083e2ea, 0x1f095615), TOBN(0x0a28ad77, 0x14e68c33), + TOBN(0x6bfc0252, 0x3d8818be), TOBN(0xb585113a, 0xf35850cd), + TOBN(0x7d935f0b, 0x30df8aa1), TOBN(0xaddda07c, 0x4ab7e3ac), + TOBN(0x92c34299, 0x552f00cb), TOBN(0xc33ed1de, 0x2909df6c), + TOBN(0x22c2195d, 0x80e87766), TOBN(0x9e99e6d8, 0x9ddf4ac0), + TOBN(0x09642e4e, 0x65e74934), TOBN(0x2610ffa2, 0xff1ff241), + TOBN(0x4d1d47d4, 0x751c8159), TOBN(0x697b4985, 0xaf3a9363), + TOBN(0x0318ca46, 0x87477c33), TOBN(0xa90cb565, 0x9441eff3), + TOBN(0x58bb3848, 0x36f024cb), TOBN(0x85be1f77, 0x36016168), + TOBN(0x6c59587c, 0xdc7e07f1), TOBN(0x191be071, 0xaf1d8f02), + TOBN(0xbf169fa5, 0xcca5e55c), TOBN(0x3864ba3c, 0xf7d04eac), + TOBN(0x915e367f, 0x8d7d05db), TOBN(0xb48a876d, 0xa6549e5d), + TOBN(0xef89c656, 0x580e40a2), TOBN(0xf194ed8c, 0x728068bc), + TOBN(0x74528045, 0xa47990c9), TOBN(0xf53fc7d7, 0x5e1a4649), + TOBN(0xbec5ae9b, 0x78593e7d), TOBN(0x2cac4ee3, 0x41db65d7), + TOBN(0xa8c1eb24, 0x04a3d39b), TOBN(0x53b7d634, 0x03f8f3ef), + TOBN(0x2dc40d48, 0x3e07113c), TOBN(0x6e4a5d39, 0x7d8b63ae), + TOBN(0x5582a94b, 0x79684c2b), TOBN(0x932b33d4, 0x622da26c), + TOBN(0xf534f651, 0x0dbbf08d), TOBN(0x211d07c9, 0x64c23a52), + TOBN(0x0eeece0f, 0xee5bdc9b), TOBN(0xdf178168, 0xf7015558), + TOBN(0xd4294635, 0x0a712229), TOBN(0x93cbe448, 0x09273f8c), + TOBN(0x00b095ef, 0x8f13bc83), TOBN(0xbb741972, 0x8798978c), + TOBN(0x9d7309a2, 0x56dbe6e7), TOBN(0xe578ec56, 0x5a5d39ec), + TOBN(0x3961151b, 0x851f9a31), TOBN(0x2da7715d, 0xe5709eb4), + TOBN(0x867f3017, 0x53dfabf0), TOBN(0x728d2078, 0xb8e39259), + TOBN(0x5c75a0cd, 0x815d9958), TOBN(0xf84867a6, 0x16603be1), + TOBN(0xc865b13d, 0x70e35b1c), TOBN(0x02414468, 0x19b03e2c), + TOBN(0xe46041da, 0xac1f3121), TOBN(0x7c9017ad, 0x6f028a7c), + TOBN(0xabc96de9, 0x0a482873), TOBN(0x4265d6b1, 0xb77e54d4), + TOBN(0x68c38e79, 0xa57d88e7), TOBN(0xd461d766, 0x9ce82de3), + TOBN(0x817a9ec5, 0x64a7e489), TOBN(0xcc5675cd, 0xa0def5f2), + TOBN(0x9a00e785, 0x985d494e), TOBN(0xc626833f, 0x1b03514a), + TOBN(0xabe7905a, 0x83cdd60e), TOBN(0x50602fb5, 0xa1170184), + TOBN(0x689886cd, 0xb023642a), TOBN(0xd568d090, 0xa6e1fb00), + TOBN(0x5b1922c7, 0x0259217f), TOBN(0x93831cd9, 0xc43141e4), + TOBN(0xdfca3587, 0x0c95f86e), TOBN(0xdec2057a, 0x568ae828), + TOBN(0xc44ea599, 0xf98a759a), TOBN(0x55a0a7a2, 0xf7c23c1d), + TOBN(0xd5ffb6e6, 0x94c4f687), TOBN(0x3563cce2, 0x12848478), + TOBN(0x812b3517, 0xe7b1fbe1), TOBN(0x8a7dc979, 0x4f7338e0), + TOBN(0x211ecee9, 0x52d048db), TOBN(0x2eea4056, 0xc86ea3b8), + TOBN(0xd8cb68a7, 0xba772b34), TOBN(0xe16ed341, 0x5f4e2541), + TOBN(0x9b32f6a6, 0x0fec14db), TOBN(0xeee376f7, 0x391698be), + TOBN(0xe9a7aa17, 0x83674c02), TOBN(0x65832f97, 0x5843022a), + TOBN(0x29f3a8da, 0x5ba4990f), TOBN(0x79a59c3a, 0xfb8e3216), + TOBN(0x9cdc4d2e, 0xbd19bb16), TOBN(0xc6c7cfd0, 0xb3262d86), + TOBN(0xd4ce14d0, 0x969c0b47), TOBN(0x1fa352b7, 0x13e56128), + TOBN(0x383d55b8, 0x973db6d3), TOBN(0x71836850, 0xe8e5b7bf), + TOBN(0xc7714596, 0xe6bb571f), TOBN(0x259df31f, 0x2d5b2dd2), + TOBN(0x568f8925, 0x913cc16d), TOBN(0x18bc5b6d, 0xe1a26f5a), + TOBN(0xdfa413be, 0xf5f499ae), TOBN(0xf8835dec, 0xc3f0ae84), + TOBN(0xb6e60bd8, 0x65a40ab0), TOBN(0x65596439, 0x194b377e), + TOBN(0xbcd85625, 0x92084a69), TOBN(0x5ce433b9, 0x4f23ede0), + TOBN(0xe8e8f04f, 0x6ad65143), TOBN(0x11511827, 0xd6e14af6), + TOBN(0x3d390a10, 0x8295c0c7), TOBN(0x71e29ee4, 0x621eba16), + TOBN(0xa588fc09, 0x63717b46), TOBN(0x02be02fe, 0xe06ad4a2), + TOBN(0x931558c6, 0x04c22b22), TOBN(0xbb4d4bd6, 0x12f3c849), + TOBN(0x54a4f496, 0x20efd662), TOBN(0x92ba6d20, 0xc5952d14), + TOBN(0x2db8ea1e, 0xcc9784c2), TOBN(0x81cc10ca, 0x4b353644), + TOBN(0x40b570ad, 0x4b4d7f6c), TOBN(0x5c9f1d96, 0x84a1dcd2), + TOBN(0x01379f81, 0x3147e797), TOBN(0xe5c6097b, 0x2bd499f5), + TOBN(0x40dcafa6, 0x328e5e20), TOBN(0xf7b5244a, 0x54815550), + TOBN(0xb9a4f118, 0x47bfc978), TOBN(0x0ea0e79f, 0xd25825b1), + TOBN(0xa50f96eb, 0x646c7ecf), TOBN(0xeb811493, 0x446dea9d), + TOBN(0x2af04677, 0xdfabcf69), TOBN(0xbe3a068f, 0xc713f6e8), + TOBN(0x860d523d, 0x42e06189), TOBN(0xbf077941, 0x4e3aff13), + TOBN(0x0b616dca, 0xc1b20650), TOBN(0xe66dd6d1, 0x2131300d), + TOBN(0xd4a0fd67, 0xff99abde), TOBN(0xc9903550, 0xc7aac50d), + TOBN(0x022ecf8b, 0x7c46b2d7), TOBN(0x3333b1e8, 0x3abf92af), + TOBN(0x11cc113c, 0x6c491c14), TOBN(0x05976688, 0x80dd3f88), + TOBN(0xf5b4d9e7, 0x29d932ed), TOBN(0xe982aad8, 0xa2c38b6d), + TOBN(0x6f925347, 0x8be0dcf0), TOBN(0x700080ae, 0x65ca53f2), + TOBN(0xd8131156, 0x443ca77f), TOBN(0xe92d6942, 0xec51f984), + TOBN(0xd2a08af8, 0x85dfe9ae), TOBN(0xd825d9a5, 0x4d2a86ca), + TOBN(0x2c53988d, 0x39dff020), TOBN(0xf38b135a, 0x430cdc40), + TOBN(0x0c918ae0, 0x62a7150b), TOBN(0xf31fd8de, 0x0c340e9b), + TOBN(0xafa0e7ae, 0x4dbbf02e), TOBN(0x5847fb2a, 0x5eba6239), + TOBN(0x6b1647dc, 0xdccbac8b), TOBN(0xb642aa78, 0x06f485c8), + TOBN(0x873f3765, 0x7038ecdf), TOBN(0x2ce5e865, 0xfa49d3fe), + TOBN(0xea223788, 0xc98c4400), TOBN(0x8104a8cd, 0xf1fa5279), + TOBN(0xbcf7cc7a, 0x06becfd7), TOBN(0x49424316, 0xc8f974ae), + TOBN(0xc0da65e7, 0x84d6365d), TOBN(0xbcb7443f, 0x8f759fb8), + TOBN(0x35c712b1, 0x7ae81930), TOBN(0x80428dff, 0x4c6e08ab), + TOBN(0xf19dafef, 0xa4faf843), TOBN(0xced8538d, 0xffa9855f), + TOBN(0x20ac409c, 0xbe3ac7ce), TOBN(0x358c1fb6, 0x882da71e), + TOBN(0xafa9c0e5, 0xfd349961), TOBN(0x2b2cfa51, 0x8421c2fc), + TOBN(0x2a80db17, 0xf3a28d38), TOBN(0xa8aba539, 0x5d138e7e), + TOBN(0x52012d1d, 0x6e96eb8d), TOBN(0x65d8dea0, 0xcbaf9622), + TOBN(0x57735447, 0xb264f56c), TOBN(0xbeebef3f, 0x1b6c8da2), + TOBN(0xfc346d98, 0xce785254), TOBN(0xd50e8d72, 0xbb64a161), + TOBN(0xc03567c7, 0x49794add), TOBN(0x15a76065, 0x752c7ef6), + TOBN(0x59f3a222, 0x961f23d6), TOBN(0x378e4438, 0x73ecc0b0), + TOBN(0xc74be434, 0x5a82fde4), TOBN(0xae509af2, 0xd8b9cf34), + TOBN(0x4a61ee46, 0x577f44a1), TOBN(0xe09b748c, 0xb611deeb), + TOBN(0xc0481b2c, 0xf5f7b884), TOBN(0x35626678, 0x61acfa6b), + TOBN(0x37f4c518, 0xbf8d21e6), TOBN(0x22d96531, 0xb205a76d), + TOBN(0x37fb85e1, 0x954073c0), TOBN(0xbceafe4f, 0x65b3a567), + TOBN(0xefecdef7, 0xbe42a582), TOBN(0xd3fc6080, 0x65046be6), + TOBN(0xc9af13c8, 0x09e8dba9), TOBN(0x1e6c9847, 0x641491ff), + TOBN(0x3b574925, 0xd30c31f7), TOBN(0xb7eb72ba, 0xac2a2122), + TOBN(0x776a0dac, 0xef0859e7), TOBN(0x06fec314, 0x21900942), + TOBN(0x2464bc10, 0xf8c22049), TOBN(0x9bfbcce7, 0x875ebf69), + TOBN(0xd7a88e2a, 0x4336326b), TOBN(0xda05261c, 0x5bc2acfa), + TOBN(0xc29f5bdc, 0xeba7efc8), TOBN(0x471237ca, 0x25dbbf2e), + TOBN(0xa72773f2, 0x2975f127), TOBN(0xdc744e8e, 0x04d0b326), + TOBN(0x38a7ed16, 0xa56edb73), TOBN(0x64357e37, 0x2c007e70), + TOBN(0xa167d15b, 0x5080b400), TOBN(0x07b41164, 0x23de4be1), + TOBN(0xb2d91e32, 0x74c89883), TOBN(0x3c162821, 0x2882e7ed), + TOBN(0xad6b36ba, 0x7503e482), TOBN(0x48434e8e, 0x0ea34331), + TOBN(0x79f4f24f, 0x2c7ae0b9), TOBN(0xc46fbf81, 0x1939b44a), + TOBN(0x76fefae8, 0x56595eb1), TOBN(0x417b66ab, 0xcd5f29c7), + TOBN(0x5f2332b2, 0xc5ceec20), TOBN(0xd69661ff, 0xe1a1cae2), + TOBN(0x5ede7e52, 0x9b0286e6), TOBN(0x9d062529, 0xe276b993), + TOBN(0x324794b0, 0x7e50122b), TOBN(0xdd744f8b, 0x4af07ca5), + TOBN(0x30a12f08, 0xd63fc97b), TOBN(0x39650f1a, 0x76626d9d), + TOBN(0x101b47f7, 0x1fa38477), TOBN(0x3d815f19, 0xd4dc124f), + TOBN(0x1569ae95, 0xb26eb58a), TOBN(0xc3cde188, 0x95fb1887), + TOBN(0x54e9f37b, 0xf9539a48), TOBN(0xb0100e06, 0x7408c1a5), + TOBN(0x821d9811, 0xea580cbb), TOBN(0x8af52d35, 0x86e50c56), + TOBN(0xdfbd9d47, 0xdbbf698b), TOBN(0x2961a1ea, 0x03dc1c73), + TOBN(0x203d38f8, 0xe76a5df8), TOBN(0x08a53a68, 0x6def707a), + TOBN(0x26eefb48, 0x1bee45d4), TOBN(0xb3cee346, 0x3c688036), + TOBN(0x463c5315, 0xc42f2469), TOBN(0x19d84d2e, 0x81378162), + TOBN(0x22d7c3c5, 0x1c4d349f), TOBN(0x65965844, 0x163d59c5), + TOBN(0xcf198c56, 0xb8abceae), TOBN(0x6fb1fb1b, 0x628559d5), + TOBN(0x8bbffd06, 0x07bf8fe3), TOBN(0x46259c58, 0x3467734b), + TOBN(0xd8953cea, 0x35f7f0d3), TOBN(0x1f0bece2, 0xd65b0ff1), + TOBN(0xf7d5b4b3, 0xf3c72914), TOBN(0x29e8ea95, 0x3cb53389), + TOBN(0x4a365626, 0x836b6d46), TOBN(0xe849f910, 0xea174fde), + TOBN(0x7ec62fbb, 0xf4737f21), TOBN(0xd8dba5ab, 0x6209f5ac), + TOBN(0x24b5d7a9, 0xa5f9adbe), TOBN(0x707d28f7, 0xa61dc768), + TOBN(0x7711460b, 0xcaa999ea), TOBN(0xba7b174d, 0x1c92e4cc), + TOBN(0x3c4bab66, 0x18d4bf2d), TOBN(0xb8f0c980, 0xeb8bd279), + TOBN(0x024bea9a, 0x324b4737), TOBN(0xfba9e423, 0x32a83bca), + TOBN(0x6e635643, 0xa232dced), TOBN(0x99619367, 0x2571c8ba), + TOBN(0xe8c9f357, 0x54b7032b), TOBN(0xf936b3ba, 0x2442d54a), + TOBN(0x2263f0f0, 0x8290c65a), TOBN(0x48989780, 0xee2c7fdb), + TOBN(0xadc5d55a, 0x13d4f95e), TOBN(0x737cff85, 0xad9b8500), + TOBN(0x271c557b, 0x8a73f43d), TOBN(0xbed617a4, 0xe18bc476), + TOBN(0x66245401, 0x7dfd8ab2), TOBN(0xae7b89ae, 0x3a2870aa), + TOBN(0x1b555f53, 0x23a7e545), TOBN(0x6791e247, 0xbe057e4c), + TOBN(0x860136ad, 0x324fa34d), TOBN(0xea111447, 0x4cbeae28), + TOBN(0x023a4270, 0xbedd3299), TOBN(0x3d5c3a7f, 0xc1c35c34), + TOBN(0xb0f6db67, 0x8d0412d2), TOBN(0xd92625e2, 0xfcdc6b9a), + TOBN(0x92ae5ccc, 0x4e28a982), TOBN(0xea251c36, 0x47a3ce7e), + TOBN(0x9d658932, 0x790691bf), TOBN(0xed610589, 0x06b736ae), + TOBN(0x712c2f04, 0xc0d63b6e), TOBN(0x5cf06fd5, 0xc63d488f), + TOBN(0x97363fac, 0xd9588e41), TOBN(0x1f9bf762, 0x2b93257e), + TOBN(0xa9d1ffc4, 0x667acace), TOBN(0x1cf4a1aa, 0x0a061ecf), + TOBN(0x40e48a49, 0xdc1818d0), TOBN(0x0643ff39, 0xa3621ab0), + TOBN(0x5768640c, 0xe39ef639), TOBN(0x1fc099ea, 0x04d86854), + TOBN(0x9130b9c3, 0xeccd28fd), TOBN(0xd743cbd2, 0x7eec54ab), + TOBN(0x052b146f, 0xe5b475b6), TOBN(0x058d9a82, 0x900a7d1f), + TOBN(0x65e02292, 0x91262b72), TOBN(0x96f924f9, 0xbb0edf03), + TOBN(0x5cfa59c8, 0xfe206842), TOBN(0xf6037004, 0x5eafa720), + TOBN(0x5f30699e, 0x18d7dd96), TOBN(0x381e8782, 0xcbab2495), + TOBN(0x91669b46, 0xdd8be949), TOBN(0xb40606f5, 0x26aae8ef), + TOBN(0x2812b839, 0xfc6751a4), TOBN(0x16196214, 0xfba800ef), + TOBN(0x4398d5ca, 0x4c1a2875), TOBN(0x720c00ee, 0x653d8349), + TOBN(0xc2699eb0, 0xd820007c), TOBN(0x880ee660, 0xa39b5825), + TOBN(0x70694694, 0x471f6984), TOBN(0xf7d16ea8, 0xe3dda99a), + TOBN(0x28d675b2, 0xc0519a23), TOBN(0x9ebf94fe, 0x4f6952e3), + TOBN(0xf28bb767, 0xa2294a8a), TOBN(0x85512b4d, 0xfe0af3f5), + TOBN(0x18958ba8, 0x99b16a0d), TOBN(0x95c2430c, 0xba7548a7), + TOBN(0xb30d1b10, 0xa16be615), TOBN(0xe3ebbb97, 0x85bfb74c), + TOBN(0xa3273cfe, 0x18549fdb), TOBN(0xf6e200bf, 0x4fcdb792), + TOBN(0x54a76e18, 0x83aba56c), TOBN(0x73ec66f6, 0x89ef6aa2), + TOBN(0x8d17add7, 0xd1b9a305), TOBN(0xa959c5b9, 0xb7ae1b9d), + TOBN(0x88643522, 0x6bcc094a), TOBN(0xcc5616c4, 0xd7d429b9), + TOBN(0xa6dada01, 0xe6a33f7c), TOBN(0xc6217a07, 0x9d4e70ad), + TOBN(0xd619a818, 0x09c15b7c), TOBN(0xea06b329, 0x0e80c854), + TOBN(0x174811ce, 0xa5f5e7b9), TOBN(0x66dfc310, 0x787c65f4), + TOBN(0x4ea7bd69, 0x3316ab54), TOBN(0xc12c4acb, 0x1dcc0f70), + TOBN(0xe4308d1a, 0x1e407dd9), TOBN(0xe8a3587c, 0x91afa997), + TOBN(0xea296c12, 0xab77b7a5), TOBN(0xb5ad49e4, 0x673c0d52), + TOBN(0x40f9b2b2, 0x7006085a), TOBN(0xa88ff340, 0x87bf6ec2), + TOBN(0x978603b1, 0x4e3066a6), TOBN(0xb3f99fc2, 0xb5e486e2), + TOBN(0x07b53f5e, 0xb2e63645), TOBN(0xbe57e547, 0x84c84232), + TOBN(0xd779c216, 0x7214d5cf), TOBN(0x617969cd, 0x029a3aca), + TOBN(0xd17668cd, 0x8a7017a0), TOBN(0x77b4d19a, 0xbe9b7ee8), + TOBN(0x58fd0e93, 0x9c161776), TOBN(0xa8c4f4ef, 0xd5968a72), + TOBN(0x296071cc, 0x67b3de77), TOBN(0xae3c0b8e, 0x634f7905), + TOBN(0x67e440c2, 0x8a7100c9), TOBN(0xbb8c3c1b, 0xeb4b9b42), + TOBN(0x6d71e8ea, 0xc51b3583), TOBN(0x7591f5af, 0x9525e642), + TOBN(0xf73a2f7b, 0x13f509f3), TOBN(0x618487aa, 0x5619ac9b), + TOBN(0x3a72e5f7, 0x9d61718a), TOBN(0x00413bcc, 0x7592d28c), + TOBN(0x7d9b11d3, 0x963c35cf), TOBN(0x77623bcf, 0xb90a46ed), + TOBN(0xdeef273b, 0xdcdd2a50), TOBN(0x4a741f9b, 0x0601846e), + TOBN(0x33b89e51, 0x0ec6e929), TOBN(0xcb02319f, 0x8b7f22cd), + TOBN(0xbbe1500d, 0x084bae24), TOBN(0x2f0ae8d7, 0x343d2693), + TOBN(0xacffb5f2, 0x7cdef811), TOBN(0xaa0c030a, 0x263fb94f), + TOBN(0x6eef0d61, 0xa0f442de), TOBN(0xf92e1817, 0x27b139d3), + TOBN(0x1ae6deb7, 0x0ad8bc28), TOBN(0xa89e38dc, 0xc0514130), + TOBN(0x81eeb865, 0xd2fdca23), TOBN(0x5a15ee08, 0xcc8ef895), + TOBN(0x768fa10a, 0x01905614), TOBN(0xeff5b8ef, 0x880ee19b), + TOBN(0xf0c0cabb, 0xcb1c8a0e), TOBN(0x2e1ee9cd, 0xb8c838f9), + TOBN(0x0587d8b8, 0x8a4a14c0), TOBN(0xf6f27896, 0x2ff698e5), + TOBN(0xed38ef1c, 0x89ee6256), TOBN(0xf44ee1fe, 0x6b353b45), + TOBN(0x9115c0c7, 0x70e903b3), TOBN(0xc78ec0a1, 0x818f31df), + TOBN(0x6c003324, 0xb7dccbc6), TOBN(0xd96dd1f3, 0x163bbc25), + TOBN(0x33aa82dd, 0x5cedd805), TOBN(0x123aae4f, 0x7f7eb2f1), + TOBN(0x1723fcf5, 0xa26262cd), TOBN(0x1f7f4d5d, 0x0060ebd5), + TOBN(0xf19c5c01, 0xb2eaa3af), TOBN(0x2ccb9b14, 0x9790accf), + TOBN(0x1f9c1cad, 0x52324aa6), TOBN(0x63200526, 0x7247df54), + TOBN(0x5732fe42, 0xbac96f82), TOBN(0x52fe771f, 0x01a1c384), + TOBN(0x546ca13d, 0xb1001684), TOBN(0xb56b4eee, 0xa1709f75), + TOBN(0x266545a9, 0xd5db8672), TOBN(0xed971c90, 0x1e8f3cfb), + TOBN(0x4e7d8691, 0xe3a07b29), TOBN(0x7570d9ec, 0xe4b696b9), + TOBN(0xdc5fa067, 0x7bc7e9ae), TOBN(0x68b44caf, 0xc82c4844), + TOBN(0x519d34b3, 0xbf44da80), TOBN(0x283834f9, 0x5ab32e66), + TOBN(0x6e608797, 0x6278a000), TOBN(0x1e62960e, 0x627312f6), + TOBN(0x9b87b27b, 0xe6901c55), TOBN(0x80e78538, 0x24fdbc1f), + TOBN(0xbbbc0951, 0x2facc27d), TOBN(0x06394239, 0xac143b5a), + TOBN(0x35bb4a40, 0x376c1944), TOBN(0x7cb62694, 0x63da1511), + TOBN(0xafd29161, 0xb7148a3b), TOBN(0xa6f9d9ed, 0x4e2ea2ee), + TOBN(0x15dc2ca2, 0x880dd212), TOBN(0x903c3813, 0xa61139a9), + TOBN(0x2aa7b46d, 0x6c0f8785), TOBN(0x36ce2871, 0x901c60ff), + TOBN(0xc683b028, 0xe10d9c12), TOBN(0x7573baa2, 0x032f33d3), + TOBN(0x87a9b1f6, 0x67a31b58), TOBN(0xfd3ed11a, 0xf4ffae12), + TOBN(0x83dcaa9a, 0x0cb2748e), TOBN(0x8239f018, 0x5d6fdf16), + TOBN(0xba67b49c, 0x72753941), TOBN(0x2beec455, 0xc321cb36), + TOBN(0x88015606, 0x3f8b84ce), TOBN(0x76417083, 0x8d38c86f), + TOBN(0x054f1ca7, 0x598953dd), TOBN(0xc939e110, 0x4e8e7429), + TOBN(0x9b1ac2b3, 0x5a914f2f), TOBN(0x39e35ed3, 0xe74b8f9c), + TOBN(0xd0debdb2, 0x781b2fb0), TOBN(0x1585638f, 0x2d997ba2), + TOBN(0x9c4b646e, 0x9e2fce99), TOBN(0x68a21081, 0x1e80857f), + TOBN(0x06d54e44, 0x3643b52a), TOBN(0xde8d6d63, 0x0d8eb843), + TOBN(0x70321563, 0x42146a0a), TOBN(0x8ba826f2, 0x5eaa3622), + TOBN(0x227a58bd, 0x86138787), TOBN(0x43b6c03c, 0x10281d37), + TOBN(0x6326afbb, 0xb54dde39), TOBN(0x744e5e8a, 0xdb6f2d5f), + TOBN(0x48b2a99a, 0xcff158e1), TOBN(0xa93c8fa0, 0xef87918f), + TOBN(0x2182f956, 0xde058c5c), TOBN(0x216235d2, 0x936f9e7a), + TOBN(0xace0c0db, 0xd2e31e67), TOBN(0xc96449bf, 0xf23ac3e7), + TOBN(0x7e9a2874, 0x170693bd), TOBN(0xa28e14fd, 0xa45e6335), + TOBN(0x5757f6b3, 0x56427344), TOBN(0x822e4556, 0xacf8edf9), + TOBN(0x2b7a6ee2, 0xe6a285cd), TOBN(0x5866f211, 0xa9df3af0), + TOBN(0x40dde2dd, 0xf845b844), TOBN(0x986c3726, 0x110e5e49), + TOBN(0x73680c2a, 0xf7172277), TOBN(0x57b94f0f, 0x0cccb244), + TOBN(0xbdff7267, 0x2d438ca7), TOBN(0xbad1ce11, 0xcf4663fd), + TOBN(0x9813ed9d, 0xd8f71cae), TOBN(0xf43272a6, 0x961fdaa6), + TOBN(0xbeff0119, 0xbd6d1637), TOBN(0xfebc4f91, 0x30361978), + TOBN(0x02b37a95, 0x2f41deff), TOBN(0x0e44a59a, 0xe63b89b7), + TOBN(0x673257dc, 0x143ff951), TOBN(0x19c02205, 0xd752baf4), + TOBN(0x46c23069, 0xc4b7d692), TOBN(0x2e6392c3, 0xfd1502ac), + TOBN(0x6057b1a2, 0x1b220846), TOBN(0xe51ff946, 0x0c1b5b63)}, + {TOBN(0x6e85cb51, 0x566c5c43), TOBN(0xcff9c919, 0x3597f046), + TOBN(0x9354e90c, 0x4994d94a), TOBN(0xe0a39332, 0x2147927d), + TOBN(0x8427fac1, 0x0dc1eb2b), TOBN(0x88cfd8c2, 0x2ff319fa), + TOBN(0xe2d4e684, 0x01965274), TOBN(0xfa2e067d, 0x67aaa746), + TOBN(0xb6d92a7f, 0x3e5f9f11), TOBN(0x9afe153a, 0xd6cb3b8e), + TOBN(0x4d1a6dd7, 0xddf800bd), TOBN(0xf6c13cc0, 0xcaf17e19), + TOBN(0x15f6c58e, 0x325fc3ee), TOBN(0x71095400, 0xa31dc3b2), + TOBN(0x168e7c07, 0xafa3d3e7), TOBN(0x3f8417a1, 0x94c7ae2d), + TOBN(0xec234772, 0x813b230d), TOBN(0x634d0f5f, 0x17344427), + TOBN(0x11548ab1, 0xd77fc56a), TOBN(0x7fab1750, 0xce06af77), + TOBN(0xb62c10a7, 0x4f7c4f83), TOBN(0xa7d2edc4, 0x220a67d9), + TOBN(0x1c404170, 0x921209a0), TOBN(0x0b9815a0, 0xface59f0), + TOBN(0x2842589b, 0x319540c3), TOBN(0x18490f59, 0xa283d6f8), + TOBN(0xa2731f84, 0xdaae9fcb), TOBN(0x3db6d960, 0xc3683ba0), + TOBN(0xc85c63bb, 0x14611069), TOBN(0xb19436af, 0x0788bf05), + TOBN(0x905459df, 0x347460d2), TOBN(0x73f6e094, 0xe11a7db1), + TOBN(0xdc7f938e, 0xb6357f37), TOBN(0xc5d00f79, 0x2bd8aa62), + TOBN(0xc878dcb9, 0x2ca979fc), TOBN(0x37e83ed9, 0xeb023a99), + TOBN(0x6b23e273, 0x1560bf3d), TOBN(0x1086e459, 0x1d0fae61), + TOBN(0x78248316, 0x9a9414bd), TOBN(0x1b956bc0, 0xf0ea9ea1), + TOBN(0x7b85bb91, 0xc31b9c38), TOBN(0x0c5aa90b, 0x48ef57b5), + TOBN(0xdedeb169, 0xaf3bab6f), TOBN(0xe610ad73, 0x2d373685), + TOBN(0xf13870df, 0x02ba8e15), TOBN(0x0337edb6, 0x8ca7f771), + TOBN(0xe4acf747, 0xb62c036c), TOBN(0xd921d576, 0xb6b94e81), + TOBN(0xdbc86439, 0x2c422f7a), TOBN(0xfb635362, 0xed348898), + TOBN(0x83084668, 0xc45bfcd1), TOBN(0xc357c9e3, 0x2b315e11), + TOBN(0xb173b540, 0x5b2e5b8c), TOBN(0x7e946931, 0xe102b9a4), + TOBN(0x17c890eb, 0x7b0fb199), TOBN(0xec225a83, 0xd61b662b), + TOBN(0xf306a3c8, 0xee3c76cb), TOBN(0x3cf11623, 0xd32a1f6e), + TOBN(0xe6d5ab64, 0x6863e956), TOBN(0x3b8a4cbe, 0x5c005c26), + TOBN(0xdcd529a5, 0x9ce6bb27), TOBN(0xc4afaa52, 0x04d4b16f), + TOBN(0xb0624a26, 0x7923798d), TOBN(0x85e56df6, 0x6b307fab), + TOBN(0x0281893c, 0x2bf29698), TOBN(0x91fc19a4, 0xd7ce7603), + TOBN(0x75a5dca3, 0xad9a558f), TOBN(0x40ceb3fa, 0x4d50bf77), + TOBN(0x1baf6060, 0xbc9ba369), TOBN(0x927e1037, 0x597888c2), + TOBN(0xd936bf19, 0x86a34c07), TOBN(0xd4cf10c1, 0xc34ae980), + TOBN(0x3a3e5334, 0x859dd614), TOBN(0x9c475b5b, 0x18d0c8ee), + TOBN(0x63080d1f, 0x07cd51d5), TOBN(0xc9c0d0a6, 0xb88b4326), + TOBN(0x1ac98691, 0xc234296f), TOBN(0x2a0a83a4, 0x94887fb6), + TOBN(0x56511427, 0x0cea9cf2), TOBN(0x5230a6e8, 0xa24802f5), + TOBN(0xf7a2bf0f, 0x72e3d5c1), TOBN(0x37717446, 0x4f21439e), + TOBN(0xfedcbf25, 0x9ce30334), TOBN(0xe0030a78, 0x7ce202f9), + TOBN(0x6f2d9ebf, 0x1202e9ca), TOBN(0xe79dde6c, 0x75e6e591), + TOBN(0xf52072af, 0xf1dac4f8), TOBN(0x6c8d087e, 0xbb9b404d), + TOBN(0xad0fc73d, 0xbce913af), TOBN(0x909e587b, 0x458a07cb), + TOBN(0x1300da84, 0xd4f00c8a), TOBN(0x425cd048, 0xb54466ac), + TOBN(0xb59cb9be, 0x90e9d8bf), TOBN(0x991616db, 0x3e431b0e), + TOBN(0xd3aa117a, 0x531aecff), TOBN(0x91af92d3, 0x59f4dc3b), + TOBN(0x9b1ec292, 0xe93fda29), TOBN(0x76bb6c17, 0xe97d91bc), + TOBN(0x7509d95f, 0xaface1e6), TOBN(0x3653fe47, 0xbe855ae3), + TOBN(0x73180b28, 0x0f680e75), TOBN(0x75eefd1b, 0xeeb6c26c), + TOBN(0xa4cdf29f, 0xb66d4236), TOBN(0x2d70a997, 0x6b5821d8), + TOBN(0x7a3ee207, 0x20445c36), TOBN(0x71d1ac82, 0x59877174), + TOBN(0x0fc539f7, 0x949f73e9), TOBN(0xd05cf3d7, 0x982e3081), + TOBN(0x8758e20b, 0x7b1c7129), TOBN(0xffadcc20, 0x569e61f2), + TOBN(0xb05d3a2f, 0x59544c2d), TOBN(0xbe16f5c1, 0x9fff5e53), + TOBN(0x73cf65b8, 0xaad58135), TOBN(0x622c2119, 0x037aa5be), + TOBN(0x79373b3f, 0x646fd6a0), TOBN(0x0e029db5, 0x0d3978cf), + TOBN(0x8bdfc437, 0x94fba037), TOBN(0xaefbd687, 0x620797a6), + TOBN(0x3fa5382b, 0xbd30d38e), TOBN(0x7627cfbf, 0x585d7464), + TOBN(0xb2330fef, 0x4e4ca463), TOBN(0xbcef7287, 0x3566cc63), + TOBN(0xd161d2ca, 0xcf780900), TOBN(0x135dc539, 0x5b54827d), + TOBN(0x638f052e, 0x27bf1bc6), TOBN(0x10a224f0, 0x07dfa06c), + TOBN(0xe973586d, 0x6d3321da), TOBN(0x8b0c5738, 0x26152c8f), + TOBN(0x07ef4f2a, 0x34606074), TOBN(0x80fe7fe8, 0xa0f7047a), + TOBN(0x3d1a8152, 0xe1a0e306), TOBN(0x32cf43d8, 0x88da5222), + TOBN(0xbf89a95f, 0x5f02ffe6), TOBN(0x3d9eb9a4, 0x806ad3ea), + TOBN(0x012c17bb, 0x79c8e55e), TOBN(0xfdcd1a74, 0x99c81dac), + TOBN(0x7043178b, 0xb9556098), TOBN(0x4090a1df, 0x801c3886), + TOBN(0x759800ff, 0x9b67b912), TOBN(0x3e5c0304, 0x232620c8), + TOBN(0x4b9d3c4b, 0x70dceeca), TOBN(0xbb2d3c15, 0x181f648e), + TOBN(0xf981d837, 0x6e33345c), TOBN(0xb626289b, 0x0cf2297a), + TOBN(0x766ac659, 0x8baebdcf), TOBN(0x1a28ae09, 0x75df01e5), + TOBN(0xb71283da, 0x375876d8), TOBN(0x4865a96d, 0x607b9800), + TOBN(0x25dd1bcd, 0x237936b2), TOBN(0x332f4f4b, 0x60417494), + TOBN(0xd0923d68, 0x370a2147), TOBN(0x497f5dfb, 0xdc842203), + TOBN(0x9dc74cbd, 0x32be5e0f), TOBN(0x7475bcb7, 0x17a01375), + TOBN(0x438477c9, 0x50d872b1), TOBN(0xcec67879, 0xffe1d63d), + TOBN(0x9b006014, 0xd8578c70), TOBN(0xc9ad99a8, 0x78bb6b8b), + TOBN(0x6799008e, 0x11fb3806), TOBN(0xcfe81435, 0xcd44cab3), + TOBN(0xa2ee1582, 0x2f4fb344), TOBN(0xb8823450, 0x483fa6eb), + TOBN(0x622d323d, 0x652c7749), TOBN(0xd8474a98, 0xbeb0a15b), + TOBN(0xe43c154d, 0x5d1c00d0), TOBN(0x7fd581d9, 0x0e3e7aac), + TOBN(0x2b44c619, 0x2525ddf8), TOBN(0x67a033eb, 0xb8ae9739), + TOBN(0x113ffec1, 0x9ef2d2e4), TOBN(0x1bf6767e, 0xd5a0ea7f), + TOBN(0x57fff75e, 0x03714c0a), TOBN(0xa23c422e, 0x0a23e9ee), + TOBN(0xdd5f6b2d, 0x540f83af), TOBN(0xc2c2c27e, 0x55ea46a7), + TOBN(0xeb6b4246, 0x672a1208), TOBN(0xd13599f7, 0xae634f7a), + TOBN(0xcf914b5c, 0xd7b32c6e), TOBN(0x61a5a640, 0xeaf61814), + TOBN(0x8dc3df8b, 0x208a1bbb), TOBN(0xef627fd6, 0xb6d79aa5), + TOBN(0x44232ffc, 0xc4c86bc8), TOBN(0xe6f9231b, 0x061539fe), + TOBN(0x1d04f25a, 0x958b9533), TOBN(0x180cf934, 0x49e8c885), + TOBN(0x89689595, 0x9884aaf7), TOBN(0xb1959be3, 0x07b348a6), + TOBN(0x96250e57, 0x3c147c87), TOBN(0xae0efb3a, 0xdd0c61f8), + TOBN(0xed00745e, 0xca8c325e), TOBN(0x3c911696, 0xecff3f70), + TOBN(0x73acbc65, 0x319ad41d), TOBN(0x7b01a020, 0xf0b1c7ef), + TOBN(0xea32b293, 0x63a1483f), TOBN(0x89eabe71, 0x7a248f96), + TOBN(0x9c6231d3, 0x343157e5), TOBN(0x93a375e5, 0xdf3c546d), + TOBN(0xe76e9343, 0x6a2afe69), TOBN(0xc4f89100, 0xe166c88e), + TOBN(0x248efd0d, 0x4f872093), TOBN(0xae0eb3ea, 0x8fe0ea61), + TOBN(0xaf89790d, 0x9d79046e), TOBN(0x4d650f2d, 0x6cee0976), + TOBN(0xa3935d9a, 0x43071eca), TOBN(0x66fcd2c9, 0x283b0bfe), + TOBN(0x0e665eb5, 0x696605f1), TOBN(0xe77e5d07, 0xa54cd38d), + TOBN(0x90ee050a, 0x43d950cf), TOBN(0x86ddebda, 0xd32e69b5), + TOBN(0x6ad94a3d, 0xfddf7415), TOBN(0xf7fa1309, 0x3f6e8d5a), + TOBN(0xc4831d1d, 0xe9957f75), TOBN(0x7de28501, 0xd5817447), + TOBN(0x6f1d7078, 0x9e2aeb6b), TOBN(0xba2b9ff4, 0xf67a53c2), + TOBN(0x36963767, 0xdf9defc3), TOBN(0x479deed3, 0x0d38022c), + TOBN(0xd2edb89b, 0x3a8631e8), TOBN(0x8de855de, 0x7a213746), + TOBN(0xb2056cb7, 0xb00c5f11), TOBN(0xdeaefbd0, 0x2c9b85e4), + TOBN(0x03f39a8d, 0xd150892d), TOBN(0x37b84686, 0x218b7985), + TOBN(0x36296dd8, 0xb7375f1a), TOBN(0x472cd4b1, 0xb78e898e), + TOBN(0x15dff651, 0xe9f05de9), TOBN(0xd4045069, 0x2ce98ba9), + TOBN(0x8466a7ae, 0x9b38024c), TOBN(0xb910e700, 0xe5a6b5ef), + TOBN(0xae1c56ea, 0xb3aa8f0d), TOBN(0xbab2a507, 0x7eee74a6), + TOBN(0x0dca11e2, 0x4b4c4620), TOBN(0xfd896e2e, 0x4c47d1f4), + TOBN(0xeb45ae53, 0x308fbd93), TOBN(0x46cd5a2e, 0x02c36fda), + TOBN(0x6a3d4e90, 0xbaa48385), TOBN(0xdd55e62e, 0x9dbe9960), + TOBN(0xa1406aa0, 0x2a81ede7), TOBN(0x6860dd14, 0xf9274ea7), + TOBN(0xcfdcb0c2, 0x80414f86), TOBN(0xff410b10, 0x22f94327), + TOBN(0x5a33cc38, 0x49ad467b), TOBN(0xefb48b6c, 0x0a7335f1), + TOBN(0x14fb54a4, 0xb153a360), TOBN(0x604aa9d2, 0xb52469cc), + TOBN(0x5e9dc486, 0x754e48e9), TOBN(0x693cb455, 0x37471e8e), + TOBN(0xfb2fd7cd, 0x8d3b37b6), TOBN(0x63345e16, 0xcf09ff07), + TOBN(0x9910ba6b, 0x23a5d896), TOBN(0x1fe19e35, 0x7fe4364e), + TOBN(0x6e1da8c3, 0x9a33c677), TOBN(0x15b4488b, 0x29fd9fd0), + TOBN(0x1f439254, 0x1a1f22bf), TOBN(0x920a8a70, 0xab8163e8), + TOBN(0x3fd1b249, 0x07e5658e), TOBN(0xf2c4f79c, 0xb6ec839b), + TOBN(0x1abbc3d0, 0x4aa38d1b), TOBN(0x3b0db35c, 0xb5d9510e), + TOBN(0x1754ac78, 0x3e60dec0), TOBN(0x53272fd7, 0xea099b33), + TOBN(0x5fb0494f, 0x07a8e107), TOBN(0x4a89e137, 0x6a8191fa), + TOBN(0xa113b7f6, 0x3c4ad544), TOBN(0x88a2e909, 0x6cb9897b), + TOBN(0x17d55de3, 0xb44a3f84), TOBN(0xacb2f344, 0x17c6c690), + TOBN(0x32088168, 0x10232390), TOBN(0xf2e8a61f, 0x6c733bf7), + TOBN(0xa774aab6, 0x9c2d7652), TOBN(0xfb5307e3, 0xed95c5bc), + TOBN(0xa05c73c2, 0x4981f110), TOBN(0x1baae31c, 0xa39458c9), + TOBN(0x1def185b, 0xcbea62e7), TOBN(0xe8ac9eae, 0xeaf63059), + TOBN(0x098a8cfd, 0x9921851c), TOBN(0xd959c3f1, 0x3abe2f5b), + TOBN(0xa4f19525, 0x20e40ae5), TOBN(0x320789e3, 0x07a24aa1), + TOBN(0x259e6927, 0x7392b2bc), TOBN(0x58f6c667, 0x1918668b), + TOBN(0xce1db2bb, 0xc55d2d8b), TOBN(0x41d58bb7, 0xf4f6ca56), + TOBN(0x7650b680, 0x8f877614), TOBN(0x905e16ba, 0xf4c349ed), + TOBN(0xed415140, 0xf661acac), TOBN(0x3b8784f0, 0xcb2270af), + TOBN(0x3bc280ac, 0x8a402cba), TOBN(0xd53f7146, 0x0937921a), + TOBN(0xc03c8ee5, 0xe5681e83), TOBN(0x62126105, 0xf6ac9e4a), + TOBN(0x9503a53f, 0x936b1a38), TOBN(0x3d45e2d4, 0x782fecbd), + TOBN(0x69a5c439, 0x76e8ae98), TOBN(0xb53b2eeb, 0xbfb4b00e), + TOBN(0xf1674712, 0x72386c89), TOBN(0x30ca34a2, 0x4268bce4), + TOBN(0x7f1ed86c, 0x78341730), TOBN(0x8ef5beb8, 0xb525e248), + TOBN(0xbbc489fd, 0xb74fbf38), TOBN(0x38a92a0e, 0x91a0b382), + TOBN(0x7a77ba3f, 0x22433ccf), TOBN(0xde8362d6, 0xa29f05a9), + TOBN(0x7f6a30ea, 0x61189afc), TOBN(0x693b5505, 0x59ef114f), + TOBN(0x50266bc0, 0xcd1797a1), TOBN(0xea17b47e, 0xf4b7af2d), + TOBN(0xd6c4025c, 0x3df9483e), TOBN(0x8cbb9d9f, 0xa37b18c9), + TOBN(0x91cbfd9c, 0x4d8424cf), TOBN(0xdb7048f1, 0xab1c3506), + TOBN(0x9eaf641f, 0x028206a3), TOBN(0xf986f3f9, 0x25bdf6ce), + TOBN(0x262143b5, 0x224c08dc), TOBN(0x2bbb09b4, 0x81b50c91), + TOBN(0xc16ed709, 0xaca8c84f), TOBN(0xa6210d9d, 0xb2850ca8), + TOBN(0x6d8df67a, 0x09cb54d6), TOBN(0x91eef6e0, 0x500919a4), + TOBN(0x90f61381, 0x0f132857), TOBN(0x9acede47, 0xf8d5028b), + TOBN(0x844d1b71, 0x90b771c3), TOBN(0x563b71e4, 0xba6426be), + TOBN(0x2efa2e83, 0xbdb802ff), TOBN(0x3410cbab, 0xab5b4a41), + TOBN(0x555b2d26, 0x30da84dd), TOBN(0xd0711ae9, 0xee1cc29a), + TOBN(0xcf3e8c60, 0x2f547792), TOBN(0x03d7d5de, 0xdc678b35), + TOBN(0x071a2fa8, 0xced806b8), TOBN(0x222e6134, 0x697f1478), + TOBN(0xdc16fd5d, 0xabfcdbbf), TOBN(0x44912ebf, 0x121b53b8), + TOBN(0xac943674, 0x2496c27c), TOBN(0x8ea3176c, 0x1ffc26b0), + TOBN(0xb6e224ac, 0x13debf2c), TOBN(0x524cc235, 0xf372a832), + TOBN(0xd706e1d8, 0x9f6f1b18), TOBN(0x2552f005, 0x44cce35b), + TOBN(0x8c8326c2, 0xa88e31fc), TOBN(0xb5468b2c, 0xf9552047), + TOBN(0xce683e88, 0x3ff90f2b), TOBN(0x77947bdf, 0x2f0a5423), + TOBN(0xd0a1b28b, 0xed56e328), TOBN(0xaee35253, 0xc20134ac), + TOBN(0x7e98367d, 0x3567962f), TOBN(0x379ed61f, 0x8188bffb), + TOBN(0x73bba348, 0xfaf130a1), TOBN(0x6c1f75e1, 0x904ed734), + TOBN(0x18956642, 0x3b4a79fc), TOBN(0xf20bc83d, 0x54ef4493), + TOBN(0x836d425d, 0x9111eca1), TOBN(0xe5b5c318, 0x009a8dcf), + TOBN(0x3360b25d, 0x13221bc5), TOBN(0x707baad2, 0x6b3eeaf7), + TOBN(0xd7279ed8, 0x743a95a1), TOBN(0x7450a875, 0x969e809f), + TOBN(0x32b6bd53, 0xe5d0338f), TOBN(0x1e77f7af, 0x2b883bbc), + TOBN(0x90da12cc, 0x1063ecd0), TOBN(0xe2697b58, 0xc315be47), + TOBN(0x2771a5bd, 0xda85d534), TOBN(0x53e78c1f, 0xff980eea), + TOBN(0xadf1cf84, 0x900385e7), TOBN(0x7d3b14f6, 0xc9387b62), + TOBN(0x170e74b0, 0xcb8f2bd2), TOBN(0x2d50b486, 0x827fa993), + TOBN(0xcdbe8c9a, 0xf6f32bab), TOBN(0x55e906b0, 0xc3b93ab8), + TOBN(0x747f22fc, 0x8fe280d1), TOBN(0xcd8e0de5, 0xb2e114ab), + TOBN(0x5ab7dbeb, 0xe10b68b0), TOBN(0x9dc63a9c, 0xa480d4b2), + TOBN(0x78d4bc3b, 0x4be1495f), TOBN(0x25eb3db8, 0x9359122d), + TOBN(0x3f8ac05b, 0x0809cbdc), TOBN(0xbf4187bb, 0xd37c702f), + TOBN(0x84cea069, 0x1416a6a5), TOBN(0x8f860c79, 0x43ef881c), + TOBN(0x41311f8a, 0x38038a5d), TOBN(0xe78c2ec0, 0xfc612067), + TOBN(0x494d2e81, 0x5ad73581), TOBN(0xb4cc9e00, 0x59604097), + TOBN(0xff558aec, 0xf3612cba), TOBN(0x35beef7a, 0x9e36c39e), + TOBN(0x1845c7cf, 0xdbcf41b9), TOBN(0x5703662a, 0xaea997c0), + TOBN(0x8b925afe, 0xe402f6d8), TOBN(0xd0a1b1ae, 0x4dd72162), + TOBN(0x9f47b375, 0x03c41c4b), TOBN(0xa023829b, 0x0391d042), + TOBN(0x5f5045c3, 0x503b8b0a), TOBN(0x123c2688, 0x98c010e5), + TOBN(0x324ec0cc, 0x36ba06ee), TOBN(0xface3115, 0x3dd2cc0c), + TOBN(0xb364f3be, 0xf333e91f), TOBN(0xef8aff73, 0x28e832b0), + TOBN(0x1e9bad04, 0x2d05841b), TOBN(0x42f0e3df, 0x356a21e2), + TOBN(0xa3270bcb, 0x4add627e), TOBN(0xb09a8158, 0xd322e711), + TOBN(0x86e326a1, 0x0fee104a), TOBN(0xad7788f8, 0x3703f65d), + TOBN(0x7e765430, 0x47bc4833), TOBN(0x6cee582b, 0x2b9b893a), + TOBN(0x9cd2a167, 0xe8f55a7b), TOBN(0xefbee3c6, 0xd9e4190d), + TOBN(0x33ee7185, 0xd40c2e9d), TOBN(0x844cc9c5, 0xa380b548), + TOBN(0x323f8ecd, 0x66926e04), TOBN(0x0001e38f, 0x8110c1ba), + TOBN(0x8dbcac12, 0xfc6a7f07), TOBN(0xd65e1d58, 0x0cec0827), + TOBN(0xd2cd4141, 0xbe76ca2d), TOBN(0x7895cf5c, 0xe892f33a), + TOBN(0x956d230d, 0x367139d2), TOBN(0xa91abd3e, 0xd012c4c1), + TOBN(0x34fa4883, 0x87eb36bf), TOBN(0xc5f07102, 0x914b8fb4), + TOBN(0x90f0e579, 0xadb9c95f), TOBN(0xfe6ea8cb, 0x28888195), + TOBN(0x7b9b5065, 0xedfa9284), TOBN(0x6c510bd2, 0x2b8c8d65), + TOBN(0xd7b8ebef, 0xcbe8aafd), TOBN(0xedb3af98, 0x96b1da07), + TOBN(0x28ff779d, 0x6295d426), TOBN(0x0c4f6ac7, 0x3fa3ad7b), + TOBN(0xec44d054, 0x8b8e2604), TOBN(0x9b32a66d, 0x8b0050e1), + TOBN(0x1f943366, 0xf0476ce2), TOBN(0x7554d953, 0xa602c7b4), + TOBN(0xbe35aca6, 0x524f2809), TOBN(0xb6881229, 0xfd4edbea), + TOBN(0xe8cd0c8f, 0x508efb63), TOBN(0x9eb5b5c8, 0x6abcefc7), + TOBN(0xf5621f5f, 0xb441ab4f), TOBN(0x79e6c046, 0xb76a2b22), + TOBN(0x74a4792c, 0xe37a1f69), TOBN(0xcbd252cb, 0x03542b60), + TOBN(0x785f65d5, 0xb3c20bd3), TOBN(0x8dea6143, 0x4fabc60c), + TOBN(0x45e21446, 0xde673629), TOBN(0x57f7aa1e, 0x703c2d21), + TOBN(0xa0e99b7f, 0x98c868c7), TOBN(0x4e42f66d, 0x8b641676), + TOBN(0x602884dc, 0x91077896), TOBN(0xa0d690cf, 0xc2c9885b), + TOBN(0xfeb4da33, 0x3b9a5187), TOBN(0x5f789598, 0x153c87ee), + TOBN(0x2192dd47, 0x52b16dba), TOBN(0xdeefc0e6, 0x3524c1b1), + TOBN(0x465ea76e, 0xe4383693), TOBN(0x79401711, 0x361b8d98), + TOBN(0xa5f9ace9, 0xf21a15cb), TOBN(0x73d26163, 0xefee9aeb), + TOBN(0xcca844b3, 0xe677016c), TOBN(0x6c122b07, 0x57eaee06), + TOBN(0xb782dce7, 0x15f09690), TOBN(0x508b9b12, 0x2dfc0fc9), + TOBN(0x9015ab4b, 0x65d89fc6), TOBN(0x5e79dab7, 0xd6d5bb0f), + TOBN(0x64f021f0, 0x6c775aa2), TOBN(0xdf09d8cc, 0x37c7eca1), + TOBN(0x9a761367, 0xef2fa506), TOBN(0xed4ca476, 0x5b81eec6), + TOBN(0x262ede36, 0x10bbb8b5), TOBN(0x0737ce83, 0x0641ada3), + TOBN(0x4c94288a, 0xe9831ccc), TOBN(0x487fc1ce, 0x8065e635), + TOBN(0xb13d7ab3, 0xb8bb3659), TOBN(0xdea5df3e, 0x855e4120), + TOBN(0xb9a18573, 0x85eb0244), TOBN(0x1a1b8ea3, 0xa7cfe0a3), + TOBN(0x3b837119, 0x67b0867c), TOBN(0x8d5e0d08, 0x9d364520), + TOBN(0x52dccc1e, 0xd930f0e3), TOBN(0xefbbcec7, 0xbf20bbaf), + TOBN(0x99cffcab, 0x0263ad10), TOBN(0xd8199e6d, 0xfcd18f8a), + TOBN(0x64e2773f, 0xe9f10617), TOBN(0x0079e8e1, 0x08704848), + TOBN(0x1169989f, 0x8a342283), TOBN(0x8097799c, 0xa83012e6), + TOBN(0xece966cb, 0x8a6a9001), TOBN(0x93b3afef, 0x072ac7fc), + TOBN(0xe6893a2a, 0x2db3d5ba), TOBN(0x263dc462, 0x89bf4fdc), + TOBN(0x8852dfc9, 0xe0396673), TOBN(0x7ac70895, 0x3af362b6), + TOBN(0xbb9cce4d, 0x5c2f342b), TOBN(0xbf80907a, 0xb52d7aae), + TOBN(0x97f3d3cd, 0x2161bcd0), TOBN(0xb25b0834, 0x0962744d), + TOBN(0xc5b18ea5, 0x6c3a1dda), TOBN(0xfe4ec7eb, 0x06c92317), + TOBN(0xb787b890, 0xad1c4afe), TOBN(0xdccd9a92, 0x0ede801a), + TOBN(0x9ac6ddda, 0xdb58da1f), TOBN(0x22bbc12f, 0xb8cae6ee), + TOBN(0xc6f8bced, 0x815c4a43), TOBN(0x8105a92c, 0xf96480c7), + TOBN(0x0dc3dbf3, 0x7a859d51), TOBN(0xe3ec7ce6, 0x3041196b), + TOBN(0xd9f64b25, 0x0d1067c9), TOBN(0xf2321321, 0x3d1f8dd8), + TOBN(0x8b5c619c, 0x76497ee8), TOBN(0x5d2b0ac6, 0xc717370e), + TOBN(0x98204cb6, 0x4fcf68e1), TOBN(0x0bdec211, 0x62bc6792), + TOBN(0x6973ccef, 0xa63b1011), TOBN(0xf9e3fa97, 0xe0de1ac5), + TOBN(0x5efb693e, 0x3d0e0c8b), TOBN(0x037248e9, 0xd2d4fcb4)}, {TOBN(0x80802dc9, 0x1ec34f9e), TOBN(0xd8772d35, 0x33810603), TOBN(0x3f06d66c, 0x530cb4f3), TOBN(0x7be5ed0d, 0xc475c129), TOBN(0xcb9e3c19, 0x31e82b10), TOBN(0xc63d2857, 0xc9ff6b4c), diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.c b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.c index a9b603aeb..dbe99ed43 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.c @@ -1,24 +1,20 @@ -/* Copyright (c) 2014, Intel Corporation. +/* + * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2014, Intel Corporation. All Rights Reserved. * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -// Developers and authors: -// Shay Gueron (1, 2), and Vlad Krasnov (1) -// (1) Intel Corporation, Israel Development Center -// (2) University of Haifa -// Reference: -// S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with -// 256 Bit Primes" + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + * + * Reference: + * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with + * 256 Bit Primes" + */ #include @@ -205,13 +201,7 @@ static void ecp_nistz256_mod_inverse_mont(BN_ULONG r[P256_LIMBS], // returns one if it fits. Otherwise it returns zero. static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], const BIGNUM *in) { - if (in->top > P256_LIMBS) { - return 0; - } - - OPENSSL_memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS); - OPENSSL_memcpy(out, in->d, sizeof(BN_ULONG) * in->top); - return 1; + return bn_copy_words(out, P256_LIMBS, in); } // r = p * p_scalar @@ -446,6 +436,7 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistz256_method) { out->group_set_curve = ec_GFp_mont_group_set_curve; out->point_get_affine_coordinates = ecp_nistz256_get_affine; out->mul = ecp_nistz256_points_mul; + out->mul_public = ecp_nistz256_points_mul; out->field_mul = ec_GFp_mont_field_mul; out->field_sqr = ec_GFp_mont_field_sqr; out->field_encode = ec_GFp_mont_field_encode; diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.h b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.h index 6a0bebb75..9226124b9 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.h +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/p256-x86_64.h @@ -1,16 +1,20 @@ -/* Copyright (c) 2014, Intel Corporation. +/* + * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2014, Intel Corporation. All Rights Reserved. * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + * + * Reference: + * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with + * 256 Bit Primes" + */ #ifndef OPENSSL_HEADER_EC_P256_X86_64_H #define OPENSSL_HEADER_EC_P256_X86_64_H diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/simple.c b/Sources/BoringSSL/crypto/fipsmodule/ec/simple.c index bc395252b..90c61d5d6 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/simple.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/simple.c @@ -135,9 +135,11 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, goto err; } BN_set_negative(&group->field, 0); + // Store the field in minimal form, so it can be used with |BN_ULONG| arrays. + bn_set_minimal_width(&group->field); // group->a - if (!BN_nnmod(tmp_a, a, p, ctx)) { + if (!BN_nnmod(tmp_a, a, &group->field, ctx)) { goto err; } if (group->meth->field_encode) { @@ -149,7 +151,7 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, } // group->b - if (!BN_nnmod(&group->b, b, p, ctx)) { + if (!BN_nnmod(&group->b, b, &group->field, ctx)) { goto err; } if (group->meth->field_encode && @@ -269,9 +271,14 @@ static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out, return BN_copy(out, in) != NULL; } -int ec_GFp_simple_set_Jprojective_coordinates_GFp( - const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, - const BIGNUM *z, BN_CTX *ctx) { +int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) { + if (x == NULL || y == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + BN_CTX *new_ctx = NULL; int ret = 0; @@ -284,7 +291,7 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp( if (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) || !set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) || - !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) { + !BN_copy(&point->Z, &group->one)) { goto err; } @@ -295,19 +302,6 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp( return ret; } -int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, - EC_POINT *point, const BIGNUM *x, - const BIGNUM *y, BN_CTX *ctx) { - if (x == NULL || y == NULL) { - // unlike for projective coordinates, we do not tolerate this - OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return ec_point_set_Jprojective_coordinates_GFp(group, point, x, y, - BN_value_one(), ctx); -} - int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, @@ -401,8 +395,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, } // n5, n6 - if (!BN_mod_sub_quick(n5, n1, n3, p) || - !BN_mod_sub_quick(n6, n2, n4, p)) { + if (!bn_mod_sub_consttime(n5, n1, n3, p, ctx) || + !bn_mod_sub_consttime(n6, n2, n4, p, ctx)) { goto end; } // n5 = n1 - n3 @@ -424,8 +418,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, } // 'n7', 'n8' - if (!BN_mod_add_quick(n1, n1, n3, p) || - !BN_mod_add_quick(n2, n2, n4, p)) { + if (!bn_mod_add_consttime(n1, n1, n3, p, ctx) || + !bn_mod_add_consttime(n2, n2, n4, p, ctx)) { goto end; } // 'n7' = n1 + n3 @@ -459,14 +453,14 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, if (!field_sqr(group, n0, n6, ctx) || !field_sqr(group, n4, n5, ctx) || !field_mul(group, n3, n1, n4, ctx) || - !BN_mod_sub_quick(&r->X, n0, n3, p)) { + !bn_mod_sub_consttime(&r->X, n0, n3, p, ctx)) { goto end; } // X_r = n6^2 - n5^2 * 'n7' // 'n9' - if (!BN_mod_lshift1_quick(n0, &r->X, p) || - !BN_mod_sub_quick(n0, n3, n0, p)) { + if (!bn_mod_lshift1_consttime(n0, &r->X, p, ctx) || + !bn_mod_sub_consttime(n0, n3, n0, p, ctx)) { goto end; } // n9 = n5^2 * 'n7' - 2 * X_r @@ -477,7 +471,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, goto end; // now n5 is n5^3 } if (!field_mul(group, n1, n2, n5, ctx) || - !BN_mod_sub_quick(n0, n0, n1, p)) { + !bn_mod_sub_consttime(n0, n0, n1, p, ctx)) { goto end; } if (BN_is_odd(n0) && !BN_add(n0, n0, p)) { @@ -542,31 +536,31 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, // n1 if (BN_cmp(&a->Z, &group->one) == 0) { if (!field_sqr(group, n0, &a->X, ctx) || - !BN_mod_lshift1_quick(n1, n0, p) || - !BN_mod_add_quick(n0, n0, n1, p) || - !BN_mod_add_quick(n1, n0, &group->a, p)) { + !bn_mod_lshift1_consttime(n1, n0, p, ctx) || + !bn_mod_add_consttime(n0, n0, n1, p, ctx) || + !bn_mod_add_consttime(n1, n0, &group->a, p, ctx)) { goto err; } // n1 = 3 * X_a^2 + a_curve } else if (group->a_is_minus3) { if (!field_sqr(group, n1, &a->Z, ctx) || - !BN_mod_add_quick(n0, &a->X, n1, p) || - !BN_mod_sub_quick(n2, &a->X, n1, p) || + !bn_mod_add_consttime(n0, &a->X, n1, p, ctx) || + !bn_mod_sub_consttime(n2, &a->X, n1, p, ctx) || !field_mul(group, n1, n0, n2, ctx) || - !BN_mod_lshift1_quick(n0, n1, p) || - !BN_mod_add_quick(n1, n0, n1, p)) { + !bn_mod_lshift1_consttime(n0, n1, p, ctx) || + !bn_mod_add_consttime(n1, n0, n1, p, ctx)) { goto err; } // n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) // = 3 * X_a^2 - 3 * Z_a^4 } else { if (!field_sqr(group, n0, &a->X, ctx) || - !BN_mod_lshift1_quick(n1, n0, p) || - !BN_mod_add_quick(n0, n0, n1, p) || + !bn_mod_lshift1_consttime(n1, n0, p, ctx) || + !bn_mod_add_consttime(n0, n0, n1, p, ctx) || !field_sqr(group, n1, &a->Z, ctx) || !field_sqr(group, n1, n1, ctx) || !field_mul(group, n1, n1, &group->a, ctx) || - !BN_mod_add_quick(n1, n1, n0, p)) { + !bn_mod_add_consttime(n1, n1, n0, p, ctx)) { goto err; } // n1 = 3 * X_a^2 + a_curve * Z_a^4 @@ -580,7 +574,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, } else if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) { goto err; } - if (!BN_mod_lshift1_quick(&r->Z, n0, p)) { + if (!bn_mod_lshift1_consttime(&r->Z, n0, p, ctx)) { goto err; } // Z_r = 2 * Y_a * Z_a @@ -588,30 +582,30 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, // n2 if (!field_sqr(group, n3, &a->Y, ctx) || !field_mul(group, n2, &a->X, n3, ctx) || - !BN_mod_lshift_quick(n2, n2, 2, p)) { + !bn_mod_lshift_consttime(n2, n2, 2, p, ctx)) { goto err; } // n2 = 4 * X_a * Y_a^2 // X_r - if (!BN_mod_lshift1_quick(n0, n2, p) || + if (!bn_mod_lshift1_consttime(n0, n2, p, ctx) || !field_sqr(group, &r->X, n1, ctx) || - !BN_mod_sub_quick(&r->X, &r->X, n0, p)) { + !bn_mod_sub_consttime(&r->X, &r->X, n0, p, ctx)) { goto err; } // X_r = n1^2 - 2 * n2 // n3 if (!field_sqr(group, n0, n3, ctx) || - !BN_mod_lshift_quick(n3, n0, 3, p)) { + !bn_mod_lshift_consttime(n3, n0, 3, p, ctx)) { goto err; } // n3 = 8 * Y_a^4 // Y_r - if (!BN_mod_sub_quick(n0, n2, &r->X, p) || + if (!bn_mod_sub_consttime(n0, n2, &r->X, p, ctx) || !field_mul(group, n0, n1, n0, ctx) || - !BN_mod_sub_quick(&r->Y, n0, n3, p)) { + !bn_mod_sub_consttime(&r->Y, n0, n3, p, ctx)) { goto err; } // Y_r = n1 * (n2 - X_r) - n3 @@ -694,15 +688,15 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, // rh := (rh + a*Z^4)*X if (group->a_is_minus3) { - if (!BN_mod_lshift1_quick(tmp, Z4, p) || - !BN_mod_add_quick(tmp, tmp, Z4, p) || - !BN_mod_sub_quick(rh, rh, tmp, p) || + if (!bn_mod_lshift1_consttime(tmp, Z4, p, ctx) || + !bn_mod_add_consttime(tmp, tmp, Z4, p, ctx) || + !bn_mod_sub_consttime(rh, rh, tmp, p, ctx) || !field_mul(group, rh, rh, &point->X, ctx)) { goto err; } } else { if (!field_mul(group, tmp, Z4, &group->a, ctx) || - !BN_mod_add_quick(rh, rh, tmp, p) || + !bn_mod_add_consttime(rh, rh, tmp, p, ctx) || !field_mul(group, rh, rh, &point->X, ctx)) { goto err; } @@ -710,17 +704,17 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, // rh := rh + b*Z^6 if (!field_mul(group, tmp, &group->b, Z6, ctx) || - !BN_mod_add_quick(rh, rh, tmp, p)) { + !bn_mod_add_consttime(rh, rh, tmp, p, ctx)) { goto err; } } else { // rh := (rh + a)*X - if (!BN_mod_add_quick(rh, rh, &group->a, p) || + if (!bn_mod_add_consttime(rh, rh, &group->a, p, ctx) || !field_mul(group, rh, rh, &point->X, ctx)) { goto err; } // rh := rh + b - if (!BN_mod_add_quick(rh, rh, &group->b, p)) { + if (!bn_mod_add_consttime(rh, rh, &group->b, p, ctx)) { goto err; } } diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/util-64.c b/Sources/BoringSSL/crypto/fipsmodule/ec/util.c similarity index 98% rename from Sources/BoringSSL/crypto/fipsmodule/ec/util-64.c rename to Sources/BoringSSL/crypto/fipsmodule/ec/util.c index 0cb117b4d..7303a1515 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/util-64.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/util.c @@ -14,9 +14,6 @@ #include - -#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) - #include #include "internal.h" @@ -105,5 +102,3 @@ void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, *sign = s & 1; *digit = d; } - -#endif // 64_BIT && !WINDOWS diff --git a/Sources/BoringSSL/crypto/fipsmodule/ec/wnaf.c b/Sources/BoringSSL/crypto/fipsmodule/ec/wnaf.c index e3b6437b6..7bc0bc7bc 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ec/wnaf.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ec/wnaf.c @@ -73,8 +73,10 @@ #include #include #include +#include #include "internal.h" +#include "../bn/internal.h" #include "../../internal.h" @@ -83,58 +85,21 @@ // http://link.springer.com/chapter/10.1007%2F3-540-45537-X_13 // http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf -// Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. -// This is an array r[] of values that are either zero or odd with an -// absolute value less than 2^w satisfying -// scalar = \sum_j r[j]*2^j -// where at most one of any w+1 consecutive digits is non-zero -// with the exception that the most significant digit may be only -// w-1 zeros away from that next non-zero digit. -static int8_t *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { - int window_val; - int ok = 0; - int8_t *r = NULL; - int sign = 1; - int bit, next_bit, mask; - size_t len = 0, j; - - if (BN_is_zero(scalar)) { - r = OPENSSL_malloc(1); - if (!r) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - goto err; - } - r[0] = 0; - *ret_len = 1; - return r; - } - +int ec_compute_wNAF(const EC_GROUP *group, int8_t *out, const EC_SCALAR *scalar, + size_t bits, int w) { // 'int8_t' can represent integers with absolute values less than 2^7. - if (w <= 0 || w > 7) { + if (w <= 0 || w > 7 || bits == 0) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); - goto err; - } - bit = 1 << w; // at most 128 - next_bit = bit << 1; // at most 256 - mask = next_bit - 1; // at most 255 - - if (BN_is_negative(scalar)) { - sign = -1; + return 0; } - - len = BN_num_bits(scalar); - // The modified wNAF may be one digit longer than binary representation - // (*ret_len will be set to the actual length, i.e. at most - // BN_num_bits(scalar) + 1). - r = OPENSSL_malloc(len + 1); - if (r == NULL) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - goto err; - } - window_val = scalar->d[0] & mask; - j = 0; - // If j+w+1 >= len, window_val will not increase. - while (window_val != 0 || j + w + 1 < len) { + int bit = 1 << w; // at most 128 + int next_bit = bit << 1; // at most 256 + int mask = next_bit - 1; // at most 255 + + int window_val = scalar->words[0] & mask; + size_t j = 0; + // If j+w+1 >= bits, window_val will not increase. + while (window_val != 0 || j + w + 1 < bits) { int digit = 0; // 0 <= window_val <= 2^(w+1) @@ -146,7 +111,7 @@ static int8_t *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { digit = window_val - next_bit; // -2^w < digit < 0 #if 1 // modified wNAF - if (j + w + 1 >= len) { + if (j + w + 1 >= bits) { // special case for generating modified wNAFs: // no new bits will be added into window_val, // so using a positive digit here will decrease @@ -161,7 +126,7 @@ static int8_t *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { if (digit <= -bit || digit >= bit || !(digit & 1)) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } window_val -= digit; @@ -170,52 +135,38 @@ static int8_t *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { // for modified window NAFs, it may also be 2^w. if (window_val != 0 && window_val != next_bit && window_val != bit) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } } - r[j++] = sign * digit; + out[j++] = digit; window_val >>= 1; - window_val += bit * BN_is_bit_set(scalar, j + w); + window_val += + bit * bn_is_bit_set_words(scalar->words, group->order.width, j + w); if (window_val > next_bit) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } } - if (j > len + 1) { + // Fill the rest of the wNAF with zeros. + if (j > bits + 1) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); - goto err; - } - len = j; - ok = 1; - -err: - if (!ok) { - OPENSSL_free(r); - r = NULL; + return 0; } - if (ok) { - *ret_len = len; + for (size_t i = j; i < bits + 1; i++) { + out[i] = 0; } - return r; -} + return 1; +} // TODO: table should be optimised for the wNAF-based implementation, // sometimes smaller windows will give better performance // (thus the boundaries should be increased) static size_t window_bits_for_scalar_size(size_t b) { - if (b >= 2000) { - return 6; - } - - if (b >= 800) { - return 5; - } - if (b >= 300) { return 4; } @@ -231,244 +182,173 @@ static size_t window_bits_for_scalar_size(size_t b) { return 1; } -int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, - const EC_SCALAR *g_scalar_raw, const EC_POINT *p, - const EC_SCALAR *p_scalar_raw, BN_CTX *ctx) { - BN_CTX *new_ctx = NULL; - const EC_POINT *generator = NULL; - EC_POINT *tmp = NULL; - size_t total_num = 0; - size_t i, j; - int k; - int r_is_inverted = 0; - int r_is_at_infinity = 1; - size_t *wsize = NULL; // individual window sizes - int8_t **wNAF = NULL; // individual wNAFs - size_t *wNAF_len = NULL; - size_t max_len = 0; - size_t num_val = 0; - EC_POINT **val = NULL; // precomputation - EC_POINT **v; - EC_POINT ***val_sub = NULL; // pointers to sub-arrays of 'val' - int ret = 0; +// EC_WNAF_MAX_WINDOW_BITS is the largest value returned by +// |window_bits_for_scalar_size|. +#define EC_WNAF_MAX_WINDOW_BITS 4 + +// compute_precomp sets |out[i]| to a newly-allocated |EC_POINT| containing +// (2*i+1)*p, for i from 0 to |len|. It returns one on success and +// zero on error. +static int compute_precomp(const EC_GROUP *group, EC_POINT **out, + const EC_POINT *p, size_t len, BN_CTX *ctx) { + out[0] = EC_POINT_new(group); + if (out[0] == NULL || + !EC_POINT_copy(out[0], p)) { + return 0; + } - if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } + int ret = 0; + EC_POINT *two_p = EC_POINT_new(group); + if (two_p == NULL || + !EC_POINT_dbl(group, two_p, p, ctx)) { + goto err; } - BN_CTX_start(ctx); - - // Convert from |EC_SCALAR| to |BIGNUM|. |BIGNUM| is not constant-time, but - // neither is the rest of this function. - BIGNUM *g_scalar = NULL, *p_scalar = NULL; - if (g_scalar_raw != NULL) { - g_scalar = BN_CTX_get(ctx); - if (g_scalar == NULL || - !bn_set_words(g_scalar, g_scalar_raw->words, group->order.top)) { + + for (size_t i = 1; i < len; i++) { + out[i] = EC_POINT_new(group); + if (out[i] == NULL || + !EC_POINT_add(group, out[i], out[i - 1], two_p, ctx)) { goto err; } } - if (p_scalar_raw != NULL) { - p_scalar = BN_CTX_get(ctx); - if (p_scalar == NULL || - !bn_set_words(p_scalar, p_scalar_raw->words, group->order.top)) { - goto err; - } + + ret = 1; + +err: + EC_POINT_free(two_p); + return ret; +} + +static int lookup_precomp(const EC_GROUP *group, EC_POINT *out, + EC_POINT *const *precomp, int digit, BN_CTX *ctx) { + if (digit < 0) { + digit = -digit; + return EC_POINT_copy(out, precomp[digit >> 1]) && + EC_POINT_invert(group, out, ctx); } - // TODO: This function used to take |points| and |scalars| as arrays of - // |num| elements. The code below should be simplified to work in terms of |p| - // and |p_scalar|. - size_t num = p != NULL ? 1 : 0; - const EC_POINT **points = p != NULL ? &p : NULL; - BIGNUM **scalars = p != NULL ? &p_scalar : NULL; + return EC_POINT_copy(out, precomp[digit >> 1]); +} - total_num = num; +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const EC_SCALAR *g_scalar, + const EC_POINT *p, const EC_SCALAR *p_scalar, BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + EC_POINT *precomp_storage[2 * (1 << (EC_WNAF_MAX_WINDOW_BITS - 1))] = {NULL}; + EC_POINT **g_precomp = NULL, **p_precomp = NULL; + int8_t g_wNAF[EC_MAX_SCALAR_BYTES * 8 + 1]; + int8_t p_wNAF[EC_MAX_SCALAR_BYTES * 8 + 1]; + EC_POINT *tmp = NULL; + int ret = 0; - if (g_scalar != NULL) { - generator = EC_GROUP_get0_generator(group); - if (generator == NULL) { - OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR); + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { goto err; } - - ++total_num; // treat 'g_scalar' like 'num'-th element of 'scalars' } + size_t bits = BN_num_bits(&group->order); + size_t wsize = window_bits_for_scalar_size(bits); + size_t wNAF_len = bits + 1; + size_t precomp_len = (size_t)1 << (wsize - 1); - wsize = OPENSSL_malloc(total_num * sizeof(wsize[0])); - wNAF_len = OPENSSL_malloc(total_num * sizeof(wNAF_len[0])); - wNAF = OPENSSL_malloc(total_num * sizeof(wNAF[0])); - val_sub = OPENSSL_malloc(total_num * sizeof(val_sub[0])); - - // Ensure wNAF is initialised in case we end up going to err. - if (wNAF != NULL) { - OPENSSL_memset(wNAF, 0, total_num * sizeof(wNAF[0])); - } + OPENSSL_COMPILE_ASSERT( + OPENSSL_ARRAY_SIZE(g_wNAF) == OPENSSL_ARRAY_SIZE(p_wNAF), + g_wNAF_and_p_wNAF_are_different_sizes); - if (!wsize || !wNAF_len || !wNAF || !val_sub) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + if (wNAF_len > OPENSSL_ARRAY_SIZE(g_wNAF) || + 2 * precomp_len > OPENSSL_ARRAY_SIZE(precomp_storage)) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } - // num_val will be the total number of temporarily precomputed points - num_val = 0; - - for (i = 0; i < total_num; i++) { - size_t bits; - - bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_scalar); - wsize[i] = window_bits_for_scalar_size(bits); - num_val += (size_t)1 << (wsize[i] - 1); - wNAF[i] = - compute_wNAF((i < num ? scalars[i] : g_scalar), wsize[i], &wNAF_len[i]); - if (wNAF[i] == NULL) { + // TODO(davidben): |mul_public| is for ECDSA verification which can assume + // non-NULL inputs, but this code is also used for |mul| which cannot. It's + // not constant-time, so replace the generic |mul| and remove the NULL checks. + size_t total_precomp = 0; + if (g_scalar != NULL) { + const EC_POINT *g = EC_GROUP_get0_generator(group); + if (g == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR); goto err; } - if (wNAF_len[i] > max_len) { - max_len = wNAF_len[i]; + g_precomp = precomp_storage + total_precomp; + total_precomp += precomp_len; + if (!ec_compute_wNAF(group, g_wNAF, g_scalar, bits, wsize) || + !compute_precomp(group, g_precomp, g, precomp_len, ctx)) { + goto err; } } - // All points we precompute now go into a single array 'val'. 'val_sub[i]' is - // a pointer to the subarray for the i-th point. - val = OPENSSL_malloc(num_val * sizeof(val[0])); - if (val == NULL) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_memset(val, 0, num_val * sizeof(val[0])); - - // allocate points for precomputation - v = val; - for (i = 0; i < total_num; i++) { - val_sub[i] = v; - for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { - *v = EC_POINT_new(group); - if (*v == NULL) { - goto err; - } - v++; + if (p_scalar != NULL) { + p_precomp = precomp_storage + total_precomp; + total_precomp += precomp_len; + if (!ec_compute_wNAF(group, p_wNAF, p_scalar, bits, wsize) || + !compute_precomp(group, p_precomp, p, precomp_len, ctx)) { + goto err; } } - if (!(v == val + num_val)) { - OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); - goto err; - } - if (!(tmp = EC_POINT_new(group))) { + tmp = EC_POINT_new(group); + if (tmp == NULL || + // |window_bits_for_scalar_size| assumes we do this step. + !EC_POINTs_make_affine(group, total_precomp, precomp_storage, ctx)) { goto err; } - // prepare precomputed values: - // val_sub[i][0] := points[i] - // val_sub[i][1] := 3 * points[i] - // val_sub[i][2] := 5 * points[i] - // ... - for (i = 0; i < total_num; i++) { - if (i < num) { - if (!EC_POINT_copy(val_sub[i][0], points[i])) { - goto err; - } - } else if (!EC_POINT_copy(val_sub[i][0], generator)) { + int r_is_at_infinity = 1; + for (size_t k = wNAF_len - 1; k < wNAF_len; k--) { + if (!r_is_at_infinity && !EC_POINT_dbl(group, r, r, ctx)) { goto err; } - if (wsize[i] > 1) { - if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) { - goto err; - } - for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { - if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) { + if (g_scalar != NULL) { + if (g_wNAF[k] != 0) { + if (!lookup_precomp(group, tmp, g_precomp, g_wNAF[k], ctx)) { + goto err; + } + if (r_is_at_infinity) { + if (!EC_POINT_copy(r, tmp)) { + goto err; + } + r_is_at_infinity = 0; + } else if (!EC_POINT_add(group, r, r, tmp, ctx)) { goto err; } } } - } -#if 1 // optional; window_bits_for_scalar_size assumes we do this step - if (!EC_POINTs_make_affine(group, num_val, val, ctx)) { - goto err; - } -#endif - - r_is_at_infinity = 1; - - for (k = max_len - 1; k >= 0; k--) { - if (!r_is_at_infinity && !EC_POINT_dbl(group, r, r, ctx)) { - goto err; - } - - for (i = 0; i < total_num; i++) { - if (wNAF_len[i] > (size_t)k) { - int digit = wNAF[i][k]; - int is_neg; - - if (digit) { - is_neg = digit < 0; - - if (is_neg) { - digit = -digit; - } - - if (is_neg != r_is_inverted) { - if (!r_is_at_infinity && !EC_POINT_invert(group, r, ctx)) { - goto err; - } - r_is_inverted = !r_is_inverted; - } - - // digit > 0 - - if (r_is_at_infinity) { - if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) { - goto err; - } - r_is_at_infinity = 0; - } else { - if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) { - goto err; - } + if (p_scalar != NULL) { + if (p_wNAF[k] != 0) { + if (!lookup_precomp(group, tmp, p_precomp, p_wNAF[k], ctx)) { + goto err; + } + if (r_is_at_infinity) { + if (!EC_POINT_copy(r, tmp)) { + goto err; } + r_is_at_infinity = 0; + } else if (!EC_POINT_add(group, r, r, tmp, ctx)) { + goto err; } } } } - if (r_is_at_infinity) { - if (!EC_POINT_set_to_infinity(group, r)) { - goto err; - } - } else if (r_is_inverted && !EC_POINT_invert(group, r, ctx)) { + if (r_is_at_infinity && + !EC_POINT_set_to_infinity(group, r)) { goto err; } ret = 1; err: - if (ctx != NULL) { - BN_CTX_end(ctx); - } BN_CTX_free(new_ctx); EC_POINT_free(tmp); - OPENSSL_free(wsize); - OPENSSL_free(wNAF_len); - if (wNAF != NULL) { - for (i = 0; i < total_num; i++) { - OPENSSL_free(wNAF[i]); - } - - OPENSSL_free(wNAF); - } - if (val != NULL) { - for (i = 0; i < num_val; i++) { - EC_POINT_free(val[i]); - } - - OPENSSL_free(val); + OPENSSL_cleanse(&g_wNAF, sizeof(g_wNAF)); + OPENSSL_cleanse(&p_wNAF, sizeof(p_wNAF)); + for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(precomp_storage); i++) { + EC_POINT_free(precomp_storage[i]); } - OPENSSL_free(val_sub); return ret; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/ecdsa/ecdsa.c b/Sources/BoringSSL/crypto/fipsmodule/ecdsa/ecdsa.c index 319a934e7..1d08123ba 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/ecdsa/ecdsa.c +++ b/Sources/BoringSSL/crypto/fipsmodule/ecdsa/ecdsa.c @@ -66,10 +66,52 @@ #include "../../internal.h" +// EC_LOOSE_SCALAR is like |EC_SCALAR| but is bounded by 2^|BN_num_bits(order)| +// rather than |order|. +typedef union { + // bytes is the representation of the scalar in little-endian order. + uint8_t bytes[EC_MAX_SCALAR_BYTES]; + BN_ULONG words[EC_MAX_SCALAR_WORDS]; +} EC_LOOSE_SCALAR; + +static void scalar_add_loose(const EC_GROUP *group, EC_LOOSE_SCALAR *r, + const EC_LOOSE_SCALAR *a, const EC_SCALAR *b) { + // Add and subtract one copy of |order| if necessary. We have: + // |a| + |b| < 2^BN_num_bits(order) + order + // so this leaves |r| < 2^BN_num_bits(order). + const BIGNUM *order = &group->order; + BN_ULONG carry = bn_add_words(r->words, a->words, b->words, order->width); + EC_LOOSE_SCALAR tmp; + BN_ULONG v = + bn_sub_words(tmp.words, r->words, order->d, order->width) - carry; + bn_select_words(r->words, 0u - v, r->words /* tmp < 0 */, + tmp.words /* tmp >= 0 */, order->width); +} + +static int scalar_mod_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r, + const EC_SCALAR *a, const EC_SCALAR *b) { + const BIGNUM *order = &group->order; + return bn_mod_mul_montgomery_small(r->words, order->width, a->words, + order->width, b->words, order->width, + group->order_mont); +} + +static int scalar_mod_mul_montgomery_loose(const EC_GROUP *group, EC_SCALAR *r, + const EC_LOOSE_SCALAR *a, + const EC_SCALAR *b) { + // Although |a| is loose, |bn_mod_mul_montgomery_small| only requires the + // product not exceed R * |order|. |b| is fully reduced and |a| < + // 2^BN_num_bits(order) <= R, so this holds. + const BIGNUM *order = &group->order; + return bn_mod_mul_montgomery_small(r->words, order->width, a->words, + order->width, b->words, order->width, + group->order_mont); +} + // digest_to_scalar interprets |digest_len| bytes from |digest| as a scalar for // ECDSA. Note this value is not fully reduced modulo the order, only the // correct number of bits. -static void digest_to_scalar(const EC_GROUP *group, EC_SCALAR *out, +static void digest_to_scalar(const EC_GROUP *group, EC_LOOSE_SCALAR *out, const uint8_t *digest, size_t digest_len) { const BIGNUM *order = &group->order; size_t num_bits = BN_num_bits(order); @@ -85,11 +127,11 @@ static void digest_to_scalar(const EC_GROUP *group, EC_SCALAR *out, // If still too long truncate remaining bits with a shift if (8 * digest_len > num_bits) { size_t shift = 8 - (num_bits & 0x7); - for (int i = 0; i < order->top - 1; i++) { + for (int i = 0; i < order->width - 1; i++) { out->words[i] = (out->words[i] >> shift) | (out->words[i + 1] << (BN_BITS2 - shift)); } - out->words[order->top - 1] >>= shift; + out->words[order->width - 1] >>= shift; } } @@ -195,15 +237,12 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len, goto err; } - EC_SCALAR r, s, m, u1, u2, s_inv_mont; + EC_SCALAR r, s, u1, u2, s_inv_mont; + EC_LOOSE_SCALAR m; const BIGNUM *order = EC_GROUP_get0_order(group); if (BN_is_zero(sig->r) || - BN_is_negative(sig->r) || - BN_ucmp(sig->r, order) >= 0 || !ec_bignum_to_scalar(group, &r, sig->r) || BN_is_zero(sig->s) || - BN_is_negative(sig->s) || - BN_ucmp(sig->s, order) >= 0 || !ec_bignum_to_scalar(group, &s, sig->s)) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); goto err; @@ -212,26 +251,21 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len, // the products below. int no_inverse; if (!BN_mod_inverse_odd(X, &no_inverse, sig->s, order, ctx) || - !ec_bignum_to_scalar(group, &s_inv_mont, X) || - !bn_to_montgomery_small(s_inv_mont.words, order->top, s_inv_mont.words, - order->top, group->order_mont)) { + // TODO(davidben): Add a words version of |BN_mod_inverse_odd| and write + // into |s_inv_mont| directly. + !ec_bignum_to_scalar_unchecked(group, &s_inv_mont, X) || + !bn_to_montgomery_small(s_inv_mont.words, order->width, s_inv_mont.words, + order->width, group->order_mont)) { goto err; } - // u1 = m * s_inv_mont mod order - // u2 = r * s_inv_mont mod order + // u1 = m * s^-1 mod order + // u2 = r * s^-1 mod order // // |s_inv_mont| is in Montgomery form while |m| and |r| are not, so |u1| and - // |u2| will be taken out of Montgomery form, as desired. Note that, although - // |m| is not fully reduced, |bn_mod_mul_montgomery_small| only requires the - // product not exceed R * |order|. |s_inv_mont| is fully reduced and |m| < - // 2^BN_num_bits(order) <= R, so this holds. + // |u2| will be taken out of Montgomery form, as desired. digest_to_scalar(group, &m, digest, digest_len); - if (!bn_mod_mul_montgomery_small(u1.words, order->top, m.words, order->top, - s_inv_mont.words, order->top, - group->order_mont) || - !bn_mod_mul_montgomery_small(u2.words, order->top, r.words, order->top, - s_inv_mont.words, order->top, - group->order_mont)) { + if (!scalar_mod_mul_montgomery_loose(group, &u1, &m, &s_inv_mont) || + !scalar_mod_mul_montgomery(group, &u2, &r, &s_inv_mont)) { goto err; } @@ -240,7 +274,7 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len, OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } - if (!ec_point_mul_scalar(group, point, &u1, pub_key, &u2, ctx)) { + if (!ec_point_mul_scalar_public(group, point, &u1, pub_key, &u2, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } @@ -308,7 +342,7 @@ static int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx, SHA512_CTX sha; uint8_t additional_data[SHA512_DIGEST_LENGTH]; SHA512_Init(&sha); - SHA512_Update(&sha, priv_key->words, order->top * sizeof(BN_ULONG)); + SHA512_Update(&sha, priv_key->words, order->width * sizeof(BN_ULONG)); SHA512_Update(&sha, digest, digest_len); SHA512_Final(additional_data, &sha); if (!ec_random_nonzero_scalar(group, &k, additional_data)) { @@ -318,10 +352,10 @@ static int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx, // Compute k^-1. We leave it in the Montgomery domain as an optimization for // later operations. - if (!bn_to_montgomery_small(out_kinv_mont->words, order->top, k.words, - order->top, group->order_mont) || - !bn_mod_inverse_prime_mont_small(out_kinv_mont->words, order->top, - out_kinv_mont->words, order->top, + if (!bn_to_montgomery_small(out_kinv_mont->words, order->width, k.words, + order->width, group->order_mont) || + !bn_mod_inverse_prime_mont_small(out_kinv_mont->words, order->width, + out_kinv_mont->words, order->width, group->order_mont)) { goto err; } @@ -358,64 +392,47 @@ ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len, } const EC_GROUP *group = EC_KEY_get0_group(eckey); - const BIGNUM *priv_key_bn = EC_KEY_get0_private_key(eckey); - if (group == NULL || priv_key_bn == NULL) { + if (group == NULL || eckey->priv_key == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); return NULL; } const BIGNUM *order = EC_GROUP_get0_order(group); + const EC_SCALAR *priv_key = &eckey->priv_key->scalar; int ok = 0; ECDSA_SIG *ret = ECDSA_SIG_new(); BN_CTX *ctx = BN_CTX_new(); - EC_SCALAR kinv_mont, priv_key, r_mont, s, tmp, m; + EC_SCALAR kinv_mont, r_mont, s; + EC_LOOSE_SCALAR m, tmp; if (ret == NULL || ctx == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return NULL; } digest_to_scalar(group, &m, digest, digest_len); - if (!ec_bignum_to_scalar(group, &priv_key, priv_key_bn)) { - goto err; - } for (;;) { if (!ecdsa_sign_setup(eckey, ctx, &kinv_mont, &ret->r, digest, digest_len, - &priv_key)) { + priv_key)) { goto err; } // Compute priv_key * r (mod order). Note if only one parameter is in the - // Montgomery domain, |bn_mod_mul_montgomery_small| will compute the answer - // in the normal domain. + // Montgomery domain, |scalar_mod_mul_montgomery| will compute the answer in + // the normal domain. if (!ec_bignum_to_scalar(group, &r_mont, ret->r) || - !bn_to_montgomery_small(r_mont.words, order->top, r_mont.words, - order->top, group->order_mont) || - !bn_mod_mul_montgomery_small(s.words, order->top, priv_key.words, - order->top, r_mont.words, order->top, - group->order_mont)) { + !bn_to_montgomery_small(r_mont.words, order->width, r_mont.words, + order->width, group->order_mont) || + !scalar_mod_mul_montgomery(group, &s, priv_key, &r_mont)) { goto err; } - // Compute s += m in constant time. Reduce one copy of |order| if necessary. - // Note this does not leave |s| fully reduced. We have - // |m| < 2^BN_num_bits(order), so subtracting |order| leaves - // 0 <= |s| < 2^BN_num_bits(order). - BN_ULONG carry = bn_add_words(s.words, s.words, m.words, order->top); - BN_ULONG v = bn_sub_words(tmp.words, s.words, order->d, order->top) - carry; - v = 0u - v; - for (int i = 0; i < order->top; i++) { - s.words[i] = constant_time_select_w(v, s.words[i], tmp.words[i]); - } + // Compute tmp = m + priv_key * r. + scalar_add_loose(group, &tmp, &m, &s); // Finally, multiply s by k^-1. That was retained in Montgomery form, so the - // same technique as the previous multiplication works. Although the - // previous step did not fully reduce |s|, |bn_mod_mul_montgomery_small| - // only requires the product not exceed R * |order|. |kinv_mont| is fully - // reduced and |s| < 2^BN_num_bits(order) <= R, so this holds. - if (!bn_mod_mul_montgomery_small(s.words, order->top, s.words, order->top, - kinv_mont.words, order->top, - group->order_mont) || - !bn_set_words(ret->s, s.words, order->top)) { + // same technique as the previous multiplication works. + if (!scalar_mod_mul_montgomery_loose(group, &s, &tmp, &kinv_mont) || + !bn_set_words(ret->s, s.words, order->width)) { goto err; } if (!BN_is_zero(ret->s)) { @@ -433,7 +450,6 @@ ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len, } BN_CTX_free(ctx); OPENSSL_cleanse(&kinv_mont, sizeof(kinv_mont)); - OPENSSL_cleanse(&priv_key, sizeof(priv_key)); OPENSSL_cleanse(&r_mont, sizeof(r_mont)); OPENSSL_cleanse(&s, sizeof(s)); OPENSSL_cleanse(&tmp, sizeof(tmp)); diff --git a/Sources/BoringSSL/crypto/fipsmodule/modes/ccm.c b/Sources/BoringSSL/crypto/fipsmodule/modes/ccm.c new file mode 100644 index 000000000..784e4fa2a --- /dev/null +++ b/Sources/BoringSSL/crypto/fipsmodule/modes/ccm.c @@ -0,0 +1,256 @@ +/* ==================================================================== + * Copyright (c) 2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +#include +#include + +#include "../../internal.h" +#include "internal.h" + + +struct ccm128_state { + union { + uint64_t u[2]; + uint8_t c[16]; + } nonce, cmac; +}; + +int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const void *key, block128_f block, + ctr128_f ctr, unsigned M, unsigned L) { + if (M < 4 || M > 16 || (M & 1) != 0 || L < 2 || L > 8) { + return 0; + } + ctx->block = block; + ctx->ctr = ctr; + ctx->M = M; + ctx->L = L; + return 1; +} + +size_t CRYPTO_ccm128_max_input(const CCM128_CONTEXT *ctx) { + return ctx->L >= sizeof(size_t) ? (size_t)-1 + : (((size_t)1) << (ctx->L * 8)) - 1; +} + +static int ccm128_init_state(const CCM128_CONTEXT *ctx, + struct ccm128_state *state, const void *key, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *aad, size_t aad_len, + size_t plaintext_len) { + const block128_f block = ctx->block; + const unsigned M = ctx->M; + const unsigned L = ctx->L; + + // |L| determines the expected |nonce_len| and the limit for |plaintext_len|. + if (plaintext_len > CRYPTO_ccm128_max_input(ctx) || + nonce_len != 15 - L) { + return 0; + } + + // Assemble the first block for computing the MAC. + OPENSSL_memset(state, 0, sizeof(*state)); + state->nonce.c[0] = (uint8_t)((L - 1) | ((M - 2) / 2) << 3); + if (aad_len != 0) { + state->nonce.c[0] |= 0x40; // Set AAD Flag + } + OPENSSL_memcpy(&state->nonce.c[1], nonce, nonce_len); + for (unsigned i = 0; i < L; i++) { + state->nonce.c[15 - i] = (uint8_t)(plaintext_len >> (8 * i)); + } + + (*block)(state->nonce.c, state->cmac.c, key); + size_t blocks = 1; + + if (aad_len != 0) { + unsigned i; + // Cast to u64 to avoid the compiler complaining about invalid shifts. + uint64_t aad_len_u64 = aad_len; + if (aad_len_u64 < 0x10000 - 0x100) { + state->cmac.c[0] ^= (uint8_t)(aad_len_u64 >> 8); + state->cmac.c[1] ^= (uint8_t)aad_len_u64; + i = 2; + } else if (aad_len_u64 <= 0xffffffff) { + state->cmac.c[0] ^= 0xff; + state->cmac.c[1] ^= 0xfe; + state->cmac.c[2] ^= (uint8_t)(aad_len_u64 >> 24); + state->cmac.c[3] ^= (uint8_t)(aad_len_u64 >> 16); + state->cmac.c[4] ^= (uint8_t)(aad_len_u64 >> 8); + state->cmac.c[5] ^= (uint8_t)aad_len_u64; + i = 6; + } else { + state->cmac.c[0] ^= 0xff; + state->cmac.c[1] ^= 0xff; + state->cmac.c[2] ^= (uint8_t)(aad_len_u64 >> 56); + state->cmac.c[3] ^= (uint8_t)(aad_len_u64 >> 48); + state->cmac.c[4] ^= (uint8_t)(aad_len_u64 >> 40); + state->cmac.c[5] ^= (uint8_t)(aad_len_u64 >> 32); + state->cmac.c[6] ^= (uint8_t)(aad_len_u64 >> 24); + state->cmac.c[7] ^= (uint8_t)(aad_len_u64 >> 16); + state->cmac.c[8] ^= (uint8_t)(aad_len_u64 >> 8); + state->cmac.c[9] ^= (uint8_t)aad_len_u64; + i = 10; + } + + do { + for (; i < 16 && aad_len != 0; i++) { + state->cmac.c[i] ^= *aad; + aad++; + aad_len--; + } + (*block)(state->cmac.c, state->cmac.c, key); + blocks++; + i = 0; + } while (aad_len != 0); + } + + // Per RFC 3610, section 2.6, the total number of block cipher operations done + // must not exceed 2^61. There are two block cipher operations remaining per + // message block, plus one block at the end to encrypt the MAC. + size_t remaining_blocks = 2 * ((plaintext_len + 15) / 16) + 1; + if (plaintext_len + 15 < plaintext_len || + remaining_blocks + blocks < blocks || + (uint64_t) remaining_blocks + blocks > UINT64_C(1) << 61) { + return 0; + } + + // Assemble the first block for encrypting and decrypting. The bottom |L| + // bytes are replaced with a counter and all bit the encoding of |L| is + // cleared in the first byte. + state->nonce.c[0] &= 7; + return 1; +} + +static int ccm128_encrypt(const CCM128_CONTEXT *ctx, struct ccm128_state *state, + const void *key, uint8_t *out, const uint8_t *in, + size_t len) { + // The counter for encryption begins at one. + for (unsigned i = 0; i < ctx->L; i++) { + state->nonce.c[15 - i] = 0; + } + state->nonce.c[15] = 1; + + uint8_t partial_buf[16]; + unsigned num = 0; + if (ctx->ctr != NULL) { + CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, state->nonce.c, partial_buf, + &num, ctx->ctr); + } else { + CRYPTO_ctr128_encrypt(in, out, len, key, state->nonce.c, partial_buf, &num, + ctx->block); + } + return 1; +} + +static int ccm128_compute_mac(const CCM128_CONTEXT *ctx, + struct ccm128_state *state, const void *key, + uint8_t *out_tag, size_t tag_len, + const uint8_t *in, size_t len) { + block128_f block = ctx->block; + if (tag_len != ctx->M) { + return 0; + } + + // Incorporate |in| into the MAC. + union { + uint64_t u[2]; + uint8_t c[16]; + } tmp; + while (len >= 16) { + OPENSSL_memcpy(tmp.c, in, 16); + state->cmac.u[0] ^= tmp.u[0]; + state->cmac.u[1] ^= tmp.u[1]; + (*block)(state->cmac.c, state->cmac.c, key); + in += 16; + len -= 16; + } + if (len > 0) { + for (size_t i = 0; i < len; i++) { + state->cmac.c[i] ^= in[i]; + } + (*block)(state->cmac.c, state->cmac.c, key); + } + + // Encrypt the MAC with counter zero. + for (unsigned i = 0; i < ctx->L; i++) { + state->nonce.c[15 - i] = 0; + } + (*block)(state->nonce.c, tmp.c, key); + state->cmac.u[0] ^= tmp.u[0]; + state->cmac.u[1] ^= tmp.u[1]; + + OPENSSL_memcpy(out_tag, state->cmac.c, tag_len); + return 1; +} + +int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const void *key, + uint8_t *out, uint8_t *out_tag, size_t tag_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t len, const uint8_t *aad, + size_t aad_len) { + struct ccm128_state state; + return ccm128_init_state(ctx, &state, key, nonce, nonce_len, aad, aad_len, + len) && + ccm128_compute_mac(ctx, &state, key, out_tag, tag_len, in, len) && + ccm128_encrypt(ctx, &state, key, out, in, len); +} + +int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const void *key, + uint8_t *out, uint8_t *out_tag, size_t tag_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t len, const uint8_t *aad, + size_t aad_len) { + struct ccm128_state state; + return ccm128_init_state(ctx, &state, key, nonce, nonce_len, aad, aad_len, + len) && + ccm128_encrypt(ctx, &state, key, out, in, len) && + ccm128_compute_mac(ctx, &state, key, out_tag, tag_len, out, len); +} diff --git a/Sources/BoringSSL/crypto/fipsmodule/modes/internal.h b/Sources/BoringSSL/crypto/fipsmodule/modes/internal.h index f6ee8f45a..de6c50351 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/modes/internal.h +++ b/Sources/BoringSSL/crypto/fipsmodule/modes/internal.h @@ -66,38 +66,6 @@ extern "C" { #define STRICT_ALIGNMENT 0 #endif -#if defined(__GNUC__) && __GNUC__ >= 2 -static inline uint32_t CRYPTO_bswap4(uint32_t x) { - return __builtin_bswap32(x); -} - -static inline uint64_t CRYPTO_bswap8(uint64_t x) { - return __builtin_bswap64(x); -} -#elif defined(_MSC_VER) -OPENSSL_MSVC_PRAGMA(warning(push, 3)) -#include -OPENSSL_MSVC_PRAGMA(warning(pop)) -#pragma intrinsic(_byteswap_uint64, _byteswap_ulong) -static inline uint32_t CRYPTO_bswap4(uint32_t x) { - return _byteswap_ulong(x); -} - -static inline uint64_t CRYPTO_bswap8(uint64_t x) { - return _byteswap_uint64(x); -} -#else -static inline uint32_t CRYPTO_bswap4(uint32_t x) { - x = (x >> 16) | (x << 16); - x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8); - return x; -} - -static inline uint64_t CRYPTO_bswap8(uint64_t x) { - return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32); -} -#endif - static inline uint32_t GETU32(const void *in) { uint32_t v; OPENSSL_memcpy(&v, in, sizeof(v)); @@ -281,6 +249,42 @@ OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag, size_t len); +// CCM. + +typedef struct ccm128_context { + block128_f block; + ctr128_f ctr; + unsigned M, L; +} CCM128_CONTEXT; + +// CRYPTO_ccm128_init initialises |ctx| to use |block| (typically AES) with the +// specified |M| and |L| parameters. It returns one on success and zero if |M| +// or |L| is invalid. +int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const void *key, block128_f block, + ctr128_f ctr, unsigned M, unsigned L); + +// CRYPTO_ccm128_max_input returns the maximum input length accepted by |ctx|. +size_t CRYPTO_ccm128_max_input(const CCM128_CONTEXT *ctx); + +// CRYPTO_ccm128_encrypt encrypts |len| bytes from |in| to |out| writing the tag +// to |out_tag|. |key| must be the same key that was passed to +// |CRYPTO_ccm128_init|. It returns one on success and zero otherwise. +int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const void *key, + uint8_t *out, uint8_t *out_tag, size_t tag_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t len, const uint8_t *aad, + size_t aad_len); + +// CRYPTO_ccm128_decrypt decrypts |len| bytes from |in| to |out|, writing the +// expected tag to |out_tag|. |key| must be the same key that was passed to +// |CRYPTO_ccm128_init|. It returns one on success and zero otherwise. +int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const void *key, + uint8_t *out, uint8_t *out_tag, size_t tag_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t len, const uint8_t *aad, + size_t aad_len); + + // CBC. // cbc128_f is the type of a function that performs CBC-mode encryption. diff --git a/Sources/BoringSSL/crypto/fipsmodule/rand/ctrdrbg.c b/Sources/BoringSSL/crypto/fipsmodule/rand/ctrdrbg.c index 9f8be6667..f2fe8b34b 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/rand/ctrdrbg.c +++ b/Sources/BoringSSL/crypto/fipsmodule/rand/ctrdrbg.c @@ -74,11 +74,11 @@ static void ctr32_add(CTR_DRBG_STATE *drbg, uint32_t n) { CRYPTO_bswap4(CRYPTO_bswap4(drbg->counter.words[3]) + n); } -static int CTR_DRBG_update(CTR_DRBG_STATE *drbg, const uint8_t *data, +static int ctr_drbg_update(CTR_DRBG_STATE *drbg, const uint8_t *data, size_t data_len) { - // Section 10.2.1.2. A value of |data_len| which less than - // |CTR_DRBG_ENTROPY_LEN| is permitted and acts the same as right-padding - // with zeros. This can save a copy. + // Per section 10.2.1.2, |data_len| must be |CTR_DRBG_ENTROPY_LEN|. Here, we + // allow shorter inputs and right-pad them with zeros. This is equivalent to + // the specified algorithm but saves a copy in |CTR_DRBG_generate|. if (data_len > CTR_DRBG_ENTROPY_LEN) { return 0; } @@ -119,7 +119,7 @@ int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg, entropy = entropy_copy; } - if (!CTR_DRBG_update(drbg, entropy, CTR_DRBG_ENTROPY_LEN)) { + if (!ctr_drbg_update(drbg, entropy, CTR_DRBG_ENTROPY_LEN)) { return 0; } @@ -142,7 +142,7 @@ int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len, } if (additional_data_len != 0 && - !CTR_DRBG_update(drbg, additional_data, additional_data_len)) { + !ctr_drbg_update(drbg, additional_data, additional_data_len)) { return 0; } @@ -187,7 +187,9 @@ int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len, OPENSSL_memcpy(out, block, out_len); } - if (!CTR_DRBG_update(drbg, additional_data, additional_data_len)) { + // Right-padding |additional_data| in step 2.2 is handled implicitly by + // |ctr_drbg_update|, to save a copy. + if (!ctr_drbg_update(drbg, additional_data, additional_data_len)) { return 0; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/rsa/blinding.c b/Sources/BoringSSL/crypto/fipsmodule/rsa/blinding.c index d95605741..b05f9c90b 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/rsa/blinding.c +++ b/Sources/BoringSSL/crypto/fipsmodule/rsa/blinding.c @@ -215,46 +215,22 @@ int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont, static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, const BN_MONT_CTX *mont, BN_CTX *ctx) { - int retry_counter = 32; - - do { - if (!BN_rand_range_ex(b->A, 1, &mont->N)) { - OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); - return 0; - } - - // |BN_from_montgomery| + |BN_mod_inverse_blinded| is equivalent to, but - // more efficient than, |BN_mod_inverse_blinded| + |BN_to_montgomery|. - if (!BN_from_montgomery(b->Ai, b->A, mont, ctx)) { - OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); - return 0; - } - - int no_inverse; - if (BN_mod_inverse_blinded(b->Ai, &no_inverse, b->Ai, mont, ctx)) { - break; - } - - if (!no_inverse) { - OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); - return 0; - } - - // For reasonably-sized RSA keys, it should almost never be the case that a - // random value doesn't have an inverse. - if (retry_counter-- == 0) { - OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); - return 0; - } - ERR_clear_error(); - } while (1); - - if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) { - OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!BN_to_montgomery(b->A, b->A, mont, ctx)) { + int no_inverse; + if (!BN_rand_range_ex(b->A, 1, &mont->N) || + // Compute |b->A|^-1 in Montgomery form. Note |BN_from_montgomery| + + // |BN_mod_inverse_blinded| is equivalent to, but more efficient than, + // |BN_mod_inverse_blinded| + |BN_to_montgomery|. + // + // We do not retry if |b->A| has no inverse. Finding a non-invertible + // value of |b->A| is equivalent to factoring |mont->N|. There is + // negligible probability of stumbling on one at random. + !BN_from_montgomery(b->Ai, b->A, mont, ctx) || + !BN_mod_inverse_blinded(b->Ai, &no_inverse, b->Ai, mont, ctx) || + // TODO(davidben): |BN_mod_exp_mont| internally computes the result in + // Montgomery form. Save a pair of Montgomery reductions and a + // multiplication by returning that value directly. + !BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont) || + !BN_to_montgomery(b->A, b->A, mont, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/rsa/internal.h b/Sources/BoringSSL/crypto/fipsmodule/rsa/internal.h index 0f0c763f5..f91305801 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/rsa/internal.h +++ b/Sources/BoringSSL/crypto/fipsmodule/rsa/internal.h @@ -114,15 +114,10 @@ int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len); -// The following utility functions are exported for test purposes. - +// This constant is exported for test purposes. extern const BN_ULONG kBoringSSLRSASqrtTwo[]; extern const size_t kBoringSSLRSASqrtTwoLen; -// rsa_greater_than_pow2 returns one if |b| is greater than 2^|n| and zero -// otherwise. -int rsa_greater_than_pow2(const BIGNUM *b, int n); - #if defined(__cplusplus) } // extern C diff --git a/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa.c b/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa.c index 4a8431419..aed87a68b 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa.c +++ b/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa.c @@ -132,17 +132,21 @@ void RSA_free(RSA *rsa) { CRYPTO_free_ex_data(g_rsa_ex_data_class_bss_get(), rsa, &rsa->ex_data); - BN_clear_free(rsa->n); - BN_clear_free(rsa->e); - BN_clear_free(rsa->d); - BN_clear_free(rsa->p); - BN_clear_free(rsa->q); - BN_clear_free(rsa->dmp1); - BN_clear_free(rsa->dmq1); - BN_clear_free(rsa->iqmp); + BN_free(rsa->n); + BN_free(rsa->e); + BN_free(rsa->d); + BN_free(rsa->p); + BN_free(rsa->q); + BN_free(rsa->dmp1); + BN_free(rsa->dmq1); + BN_free(rsa->iqmp); BN_MONT_CTX_free(rsa->mont_n); BN_MONT_CTX_free(rsa->mont_p); BN_MONT_CTX_free(rsa->mont_q); + BN_free(rsa->d_fixed); + BN_free(rsa->dmp1_fixed); + BN_free(rsa->dmq1_fixed); + BN_free(rsa->inv_small_mod_large_mont); for (u = 0; u < rsa->num_blindings; u++) { BN_BLINDING_free(rsa->blindings[u]); } @@ -630,8 +634,25 @@ int RSA_verify_pss_mgf1(RSA *rsa, const uint8_t *msg, size_t msg_len, return ret; } +static int check_mod_inverse(int *out_ok, const BIGNUM *a, const BIGNUM *ainv, + const BIGNUM *m, int check_reduced, BN_CTX *ctx) { + BN_CTX_start(ctx); + BIGNUM *tmp = BN_CTX_get(ctx); + int ret = tmp != NULL && + bn_mul_consttime(tmp, a, ainv, ctx) && + bn_div_consttime(NULL, tmp, tmp, m, ctx); + if (ret) { + *out_ok = BN_is_one(tmp); + if (check_reduced && (BN_is_negative(ainv) || BN_cmp(ainv, m) >= 0)) { + *out_ok = 0; + } + } + BN_CTX_end(ctx); + return ret; +} + int RSA_check_key(const RSA *key) { - BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp_times_q; + BIGNUM n, pm1, qm1, lcm, dmp1, dmq1, iqmp_times_q; BN_CTX *ctx; int ok = 0, has_crt_values; @@ -666,26 +687,20 @@ int RSA_check_key(const RSA *key) { BN_init(&pm1); BN_init(&qm1); BN_init(&lcm); - BN_init(&gcd); - BN_init(&de); BN_init(&dmp1); BN_init(&dmq1); BN_init(&iqmp_times_q); - if (!BN_mul(&n, key->p, key->q, ctx) || + int d_ok; + if (!bn_mul_consttime(&n, key->p, key->q, ctx) || // lcm = lcm(p, q) - !BN_sub(&pm1, key->p, BN_value_one()) || - !BN_sub(&qm1, key->q, BN_value_one()) || - !BN_mul(&lcm, &pm1, &qm1, ctx) || - !BN_gcd(&gcd, &pm1, &qm1, ctx)) { - OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); - goto out; - } - - if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) || - !BN_gcd(&gcd, &pm1, &qm1, ctx) || - // de = d*e mod lcm(p, q). - !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) { + !bn_usub_consttime(&pm1, key->p, BN_value_one()) || + !bn_usub_consttime(&qm1, key->q, BN_value_one()) || + !bn_lcm_consttime(&lcm, &pm1, &qm1, ctx) || + // Other implementations use the Euler totient rather than the Carmichael + // totient, so allow unreduced |key->d|. + !check_mod_inverse(&d_ok, key->e, key->d, &lcm, + 0 /* don't require reduced */, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); goto out; } @@ -695,11 +710,16 @@ int RSA_check_key(const RSA *key) { goto out; } - if (!BN_is_one(&de)) { + if (!d_ok) { OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1); goto out; } + if (BN_is_negative(key->d) || BN_cmp(key->d, key->n) >= 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_D_OUT_OF_RANGE); + goto out; + } + has_crt_values = key->dmp1 != NULL; if (has_crt_values != (key->dmq1 != NULL) || has_crt_values != (key->iqmp != NULL)) { @@ -708,20 +728,18 @@ int RSA_check_key(const RSA *key) { } if (has_crt_values) { - if (// dmp1 = d mod (p-1) - !BN_mod(&dmp1, key->d, &pm1, ctx) || - // dmq1 = d mod (q-1) - !BN_mod(&dmq1, key->d, &qm1, ctx) || - // iqmp = q^-1 mod p - !BN_mod_mul(&iqmp_times_q, key->iqmp, key->q, key->p, ctx)) { + int dmp1_ok, dmq1_ok, iqmp_ok; + if (!check_mod_inverse(&dmp1_ok, key->e, key->dmp1, &pm1, + 1 /* check reduced */, ctx) || + !check_mod_inverse(&dmq1_ok, key->e, key->dmq1, &qm1, + 1 /* check reduced */, ctx) || + !check_mod_inverse(&iqmp_ok, key->q, key->iqmp, key->p, + 1 /* check reduced */, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); goto out; } - if (BN_cmp(&dmp1, key->dmp1) != 0 || - BN_cmp(&dmq1, key->dmq1) != 0 || - BN_cmp(key->iqmp, key->p) >= 0 || - !BN_is_one(&iqmp_times_q)) { + if (!dmp1_ok || !dmq1_ok || !iqmp_ok) { OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT); goto out; } @@ -734,8 +752,6 @@ int RSA_check_key(const RSA *key) { BN_free(&pm1); BN_free(&qm1); BN_free(&lcm); - BN_free(&gcd); - BN_free(&de); BN_free(&dmp1); BN_free(&dmq1); BN_free(&iqmp_times_q); @@ -760,8 +776,8 @@ static const BN_ULONG kSmallFactorsLimbs[] = { DEFINE_LOCAL_DATA(BIGNUM, g_small_factors) { out->d = (BN_ULONG *) kSmallFactorsLimbs; - out->top = OPENSSL_ARRAY_SIZE(kSmallFactorsLimbs); - out->dmax = out->top; + out->width = OPENSSL_ARRAY_SIZE(kSmallFactorsLimbs); + out->dmax = out->width; out->neg = 0; out->flags = BN_FLG_STATIC_DATA; } @@ -852,6 +868,8 @@ int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, return rsa_default_private_transform(rsa, out, in, len); } +int RSA_flags(const RSA *rsa) { return rsa->flags; } + int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) { return 1; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa_impl.c b/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa_impl.c index fb27320e4..49cbc15a9 100644 --- a/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa_impl.c +++ b/Sources/BoringSSL/crypto/fipsmodule/rsa/rsa_impl.c @@ -109,6 +109,133 @@ static int check_modulus_and_exponent_sizes(const RSA *rsa) { return 1; } +static int ensure_fixed_copy(BIGNUM **out, const BIGNUM *in, int width) { + if (*out != NULL) { + return 1; + } + BIGNUM *copy = BN_dup(in); + if (copy == NULL || + !bn_resize_words(copy, width)) { + BN_free(copy); + return 0; + } + *out = copy; + return 1; +} + +// freeze_private_key finishes initializing |rsa|'s private key components. +// After this function has returned, |rsa| may not be changed. This is needed +// because |RSA| is a public struct and, additionally, OpenSSL 1.1.0 opaquified +// it wrong (see https://github.com/openssl/openssl/issues/5158). +static int freeze_private_key(RSA *rsa, BN_CTX *ctx) { + CRYPTO_MUTEX_lock_read(&rsa->lock); + int frozen = rsa->private_key_frozen; + CRYPTO_MUTEX_unlock_read(&rsa->lock); + if (frozen) { + return 1; + } + + int ret = 0; + CRYPTO_MUTEX_lock_write(&rsa->lock); + if (rsa->private_key_frozen) { + ret = 1; + goto err; + } + + // Pre-compute various intermediate values, as well as copies of private + // exponents with correct widths. Note that other threads may concurrently + // read from |rsa->n|, |rsa->e|, etc., so any fixes must be in separate + // copies. We use |mont_n->N|, |mont_p->N|, and |mont_q->N| as copies of |n|, + // |p|, and |q| with the correct minimal widths. + + if (rsa->mont_n == NULL) { + rsa->mont_n = BN_MONT_CTX_new_for_modulus(rsa->n, ctx); + if (rsa->mont_n == NULL) { + goto err; + } + } + const BIGNUM *n_fixed = &rsa->mont_n->N; + + // The only public upper-bound of |rsa->d| is the bit length of |rsa->n|. The + // ASN.1 serialization of RSA private keys unfortunately leaks the byte length + // of |rsa->d|, but normalize it so we only leak it once, rather than per + // operation. + if (rsa->d != NULL && + !ensure_fixed_copy(&rsa->d_fixed, rsa->d, n_fixed->width)) { + goto err; + } + + if (rsa->p != NULL && rsa->q != NULL) { + if (rsa->mont_p == NULL) { + rsa->mont_p = BN_MONT_CTX_new_for_modulus(rsa->p, ctx); + if (rsa->mont_p == NULL) { + goto err; + } + } + const BIGNUM *p_fixed = &rsa->mont_p->N; + + if (rsa->mont_q == NULL) { + rsa->mont_q = BN_MONT_CTX_new_for_modulus(rsa->q, ctx); + if (rsa->mont_q == NULL) { + goto err; + } + } + const BIGNUM *q_fixed = &rsa->mont_q->N; + + if (rsa->dmp1 != NULL && rsa->dmq1 != NULL) { + // Key generation relies on this function to compute |iqmp|. + if (rsa->iqmp == NULL) { + BIGNUM *iqmp = BN_new(); + if (iqmp == NULL || + !bn_mod_inverse_secret_prime(iqmp, rsa->q, rsa->p, ctx, + rsa->mont_p)) { + BN_free(iqmp); + goto err; + } + rsa->iqmp = iqmp; + } + + // CRT components are only publicly bounded by their corresponding + // moduli's bit lengths. |rsa->iqmp| is unused outside of this one-time + // setup, so we do not compute a fixed-width version of it. + if (!ensure_fixed_copy(&rsa->dmp1_fixed, rsa->dmp1, p_fixed->width) || + !ensure_fixed_copy(&rsa->dmq1_fixed, rsa->dmq1, q_fixed->width)) { + goto err; + } + + // Compute |inv_small_mod_large_mont|. Note that it is always modulo the + // larger prime, independent of what is stored in |rsa->iqmp|. + if (rsa->inv_small_mod_large_mont == NULL) { + BIGNUM *inv_small_mod_large_mont = BN_new(); + int ok; + if (BN_cmp(rsa->p, rsa->q) < 0) { + ok = inv_small_mod_large_mont != NULL && + bn_mod_inverse_secret_prime(inv_small_mod_large_mont, rsa->p, + rsa->q, ctx, rsa->mont_q) && + BN_to_montgomery(inv_small_mod_large_mont, + inv_small_mod_large_mont, rsa->mont_q, ctx); + } else { + ok = inv_small_mod_large_mont != NULL && + BN_to_montgomery(inv_small_mod_large_mont, rsa->iqmp, + rsa->mont_p, ctx); + } + if (!ok) { + BN_free(inv_small_mod_large_mont); + goto err; + } + rsa->inv_small_mod_large_mont = inv_small_mod_large_mont; + } + } + } + + rsa->private_key_frozen = 1; + ret = 1; + +err: + CRYPTO_MUTEX_unlock_write(&rsa->lock); + return ret; +} + size_t rsa_default_size(const RSA *rsa) { return BN_num_bytes(rsa->n); } @@ -181,7 +308,7 @@ int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, } if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || - !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { + !BN_mod_exp_mont(result, f, rsa->e, &rsa->mont_n->N, ctx, rsa->mont_n)) { goto err; } @@ -487,7 +614,7 @@ int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, } if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || - !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { + !BN_mod_exp_mont(result, f, rsa->e, &rsa->mont_n->N, ctx, rsa->mont_n)) { goto err; } @@ -560,7 +687,7 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, goto err; } - if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { + if (!freeze_private_key(rsa, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } @@ -592,7 +719,7 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, if (!mod_exp(result, f, rsa, ctx)) { goto err; } - } else if (!BN_mod_exp_mont_consttime(result, f, rsa->d, rsa->n, ctx, + } else if (!BN_mod_exp_mont_consttime(result, f, rsa->d_fixed, rsa->n, ctx, rsa->mont_n)) { goto err; } @@ -622,6 +749,12 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, goto err; } + // The computation should have left |result| as a maximally-wide number, so + // that it and serializing does not leak information about the magnitude of + // the result. + // + // See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. + assert(result->width == rsa->mont_n->N.width); if (!BN_bn2bin_padded(out, len, result)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; @@ -641,6 +774,37 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, return ret; } +// mod_montgomery sets |r| to |I| mod |p|. |I| must already be fully reduced +// modulo |p| times |q|. It returns one on success and zero on error. +static int mod_montgomery(BIGNUM *r, const BIGNUM *I, const BIGNUM *p, + const BN_MONT_CTX *mont_p, const BIGNUM *q, + BN_CTX *ctx) { + // Reducing in constant-time with Montgomery reduction requires I <= p * R. We + // have I < p * q, so this follows if q < R. In particular, this always holds + // if p and q are the same size, which is true for any RSA keys we or anyone + // sane generates. For other keys, we fall back to |BN_mod|. + if (!bn_less_than_montgomery_R(q, mont_p)) { + return BN_mod(r, I, p, ctx); + } + + if (// Reduce mod p with Montgomery reduction. This computes I * R^-1 mod p. + !BN_from_montgomery(r, I, mont_p, ctx) || + // Multiply by R^2 and do another Montgomery reduction to compute + // I * R^-1 * R^2 * R^-1 = I mod p. + !BN_to_montgomery(r, r, mont_p, ctx)) { + return 0; + } + + // By precomputing R^3 mod p (normally |BN_MONT_CTX| only uses R^2 mod p) and + // adjusting the API for |BN_mod_exp_mont_consttime|, we could instead compute + // I * R mod p here and save a reduction per prime. But this would require + // changing the RSAZ code and may not be worth it. Note that the RSAZ code + // uses a different radix, so it uses R' = 2^1044. There we'd actually want + // R^2 * R', and would futher benefit from a precomputed R'^2. It currently + // converts |mont_p->RR| to R'^2. + return 1; +} + static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { assert(ctx != NULL); @@ -653,82 +817,67 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { assert(rsa->dmq1 != NULL); assert(rsa->iqmp != NULL); - BIGNUM *r1, *m1, *vrfy; + BIGNUM *r1, *m1; int ret = 0; BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); - vrfy = BN_CTX_get(ctx); if (r1 == NULL || - m1 == NULL || - vrfy == NULL) { - goto err; - } - - if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, rsa->p, ctx) || - !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, rsa->q, ctx)) { + m1 == NULL) { goto err; } - if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { + if (!freeze_private_key(rsa, ctx)) { goto err; } - // compute I mod q - if (!BN_mod(r1, I, rsa->q, ctx)) { - goto err; - } - - // compute r1^dmq1 mod q - if (!BN_mod_exp_mont_consttime(m1, r1, rsa->dmq1, rsa->q, ctx, rsa->mont_q)) { - goto err; - } - - // compute I mod p - if (!BN_mod(r1, I, rsa->p, ctx)) { - goto err; - } - - // compute r1^dmp1 mod p - if (!BN_mod_exp_mont_consttime(r0, r1, rsa->dmp1, rsa->p, ctx, rsa->mont_p)) { - goto err; - } - - if (!BN_sub(r0, r0, m1)) { - goto err; - } - // This will help stop the size of r0 increasing, which does - // affect the multiply if it optimised for a power of 2 size - if (BN_is_negative(r0)) { - if (!BN_add(r0, r0, rsa->p)) { - goto err; - } - } - - if (!BN_mul(r1, r0, rsa->iqmp, ctx)) { - goto err; - } - - if (!BN_mod(r0, r1, rsa->p, ctx)) { - goto err; - } - - // If p < q it is occasionally possible for the correction of - // adding 'p' if r0 is negative above to leave the result still - // negative. This can break the private key operations: the following - // second correction should *always* correct this rare occurrence. - // This will *never* happen with OpenSSL generated keys because - // they ensure p > q [steve] - if (BN_is_negative(r0)) { - if (!BN_add(r0, r0, rsa->p)) { - goto err; - } - } - if (!BN_mul(r1, r0, rsa->q, ctx)) { - goto err; - } - if (!BN_add(r0, r1, m1)) { + // Implementing RSA with CRT in constant-time is sensitive to which prime is + // larger. Canonicalize fields so that |p| is the larger prime. + const BIGNUM *dmp1 = rsa->dmp1_fixed, *dmq1 = rsa->dmq1_fixed; + const BN_MONT_CTX *mont_p = rsa->mont_p, *mont_q = rsa->mont_q; + if (BN_cmp(rsa->p, rsa->q) < 0) { + mont_p = rsa->mont_q; + mont_q = rsa->mont_p; + dmp1 = rsa->dmq1_fixed; + dmq1 = rsa->dmp1_fixed; + } + + // Use the minimal-width versions of |n|, |p|, and |q|. Either works, but if + // someone gives us non-minimal values, these will be slightly more efficient + // on the non-Montgomery operations. + const BIGNUM *n = &rsa->mont_n->N; + const BIGNUM *p = &mont_p->N; + const BIGNUM *q = &mont_q->N; + + // This is a pre-condition for |mod_montgomery|. It was already checked by the + // caller. + assert(BN_ucmp(I, n) < 0); + + if (// |m1| is the result modulo |q|. + !mod_montgomery(r1, I, q, mont_q, p, ctx) || + !BN_mod_exp_mont_consttime(m1, r1, dmq1, q, ctx, mont_q) || + // |r0| is the result modulo |p|. + !mod_montgomery(r1, I, p, mont_p, q, ctx) || + !BN_mod_exp_mont_consttime(r0, r1, dmp1, p, ctx, mont_p) || + // Compute r0 = r0 - m1 mod p. |p| is the larger prime, so |m1| is already + // fully reduced mod |p|. + !bn_mod_sub_consttime(r0, r0, m1, p, ctx) || + // r0 = r0 * iqmp mod p. We use Montgomery multiplication to compute this + // in constant time. |inv_small_mod_large_mont| is in Montgomery form and + // r0 is not, so the result is taken out of Montgomery form. + !BN_mod_mul_montgomery(r0, r0, rsa->inv_small_mod_large_mont, mont_p, + ctx) || + // r0 = r0 * q + m1 gives the final result. Reducing modulo q gives m1, so + // it is correct mod p. Reducing modulo p gives (r0-m1)*iqmp*q + m1 = r0, + // so it is correct mod q. Finally, the result is bounded by [m1, n + m1), + // and the result is at least |m1|, so this must be the unique answer in + // [0, n). + !bn_mul_consttime(r0, r0, q, ctx) || + !bn_uadd_consttime(r0, r0, m1) || + // The result should be bounded by |n|, but fixed-width operations may + // bound the width slightly higher, so fix it. + !bn_resize_words(r0, n->width)) { goto err; } @@ -775,24 +924,20 @@ const BN_ULONG kBoringSSLRSASqrtTwo[] = { }; const size_t kBoringSSLRSASqrtTwoLen = OPENSSL_ARRAY_SIZE(kBoringSSLRSASqrtTwo); -int rsa_greater_than_pow2(const BIGNUM *b, int n) { - if (BN_is_negative(b) || n == INT_MAX) { - return 0; - } - - int b_bits = BN_num_bits(b); - return b_bits > n + 1 || (b_bits == n + 1 && !BN_is_pow2(b)); -} - // generate_prime sets |out| to a prime with length |bits| such that |out|-1 is // relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to -// |p|. +// |p|. |sqrt2| must be ⌊2^(bits-1)×√2⌋ (or a slightly overestimate for large +// sizes), and |pow2_bits_100| must be 2^(bits-100). static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e, - const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb) { + const BIGNUM *p, const BIGNUM *sqrt2, + const BIGNUM *pow2_bits_100, BN_CTX *ctx, + BN_GENCB *cb) { if (bits < 128 || (bits % BN_BITS2) != 0) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } + assert(BN_is_pow2(pow2_bits_100)); + assert(BN_is_bit_set(pow2_bits_100, bits - 100)); // See FIPS 186-4 appendix B.3.3, steps 4 and 5. Note |bits| here is nlen/2. @@ -823,57 +968,45 @@ static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e, if (p != NULL) { // If |p| and |out| are too close, try again (step 5.4). - if (!BN_sub(tmp, out, p)) { + if (!bn_abs_sub_consttime(tmp, out, p, ctx)) { goto err; } - BN_set_negative(tmp, 0); - if (!rsa_greater_than_pow2(tmp, bits - 100)) { + if (BN_cmp(tmp, pow2_bits_100) <= 0) { continue; } } - // If out < 2^(bits-1)×√2, try again (steps 4.4 and 5.5). - // - // We check the most significant words, so we retry if ⌊out/2^k⌋ <= ⌊b/2^k⌋, - // where b = 2^(bits-1)×√2 and k = max(0, bits - 1536). For key sizes up to - // 3072 (bits = 1536), k = 0, so we are testing that ⌊out⌋ <= ⌊b⌋. out is an - // integer and b is not, so this is equivalent to out < b. That is, the - // comparison is exact for FIPS key sizes. + // If out < 2^(bits-1)×√2, try again (steps 4.4 and 5.5). This is equivalent + // to out <= ⌊2^(bits-1)×√2⌋, or out <= sqrt2 for FIPS key sizes. // // For larger keys, the comparison is approximate, leaning towards // retrying. That is, we reject a negligible fraction of primes that are // within the FIPS bound, but we will never accept a prime outside the - // bound, ensuring the resulting RSA key is the right size. Specifically, if - // the FIPS bound holds, we have ⌊out/2^k⌋ < out/2^k < b/2^k. This implies - // ⌊out/2^k⌋ <= ⌊b/2^k⌋. That is, the FIPS bound implies our bound and so we - // are slightly tighter. - size_t out_len = (size_t)out->top; - assert(out_len == (size_t)bits / BN_BITS2); - size_t to_check = kBoringSSLRSASqrtTwoLen; - if (to_check > out_len) { - to_check = out_len; - } - if (!bn_less_than_words( - kBoringSSLRSASqrtTwo + kBoringSSLRSASqrtTwoLen - to_check, - out->d + out_len - to_check, to_check)) { + // bound, ensuring the resulting RSA key is the right size. + if (BN_cmp(out, sqrt2) <= 0) { continue; } - // Check gcd(out-1, e) is one (steps 4.5 and 5.6). - if (!BN_sub(tmp, out, BN_value_one()) || - !BN_gcd(tmp, tmp, e, ctx)) { - goto err; - } - if (BN_is_one(tmp)) { - // Test |out| for primality (steps 4.5.1 and 5.6.1). - int is_probable_prime; - if (!BN_primality_test(&is_probable_prime, out, BN_prime_checks, ctx, 1, - cb)) { + // RSA key generation's bottleneck is discarding composites. If it fails + // trial division, do not bother computing a GCD or performing Rabin-Miller. + if (!bn_odd_number_is_obviously_composite(out)) { + // Check gcd(out-1, e) is one (steps 4.5 and 5.6). + int relatively_prime; + if (!BN_sub(tmp, out, BN_value_one()) || + !bn_is_relatively_prime(&relatively_prime, tmp, e, ctx)) { goto err; } - if (is_probable_prime) { - ret = 1; - goto err; + if (relatively_prime) { + // Test |out| for primality (steps 4.5.1 and 5.6.1). + int is_probable_prime; + if (!BN_primality_test(&is_probable_prime, out, BN_prime_checks, ctx, 0, + cb)) { + goto err; + } + if (is_probable_prime) { + ret = 1; + goto err; + } } } @@ -909,7 +1042,19 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { return 0; } + // Reject excessively large public exponents. Windows CryptoAPI and Go don't + // support values larger than 32 bits, so match their limits for generating + // keys. (|check_modulus_and_exponent_sizes| uses a slightly more conservative + // value, but we don't need to support generating such keys.) + // https://github.com/golang/go/issues/3161 + // https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx + if (BN_num_bits(e_value) > 32) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE); + return 0; + } + int ret = 0; + int prime_bits = bits / 2; BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { goto bn_err; @@ -918,8 +1063,13 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { BIGNUM *totient = BN_CTX_get(ctx); BIGNUM *pm1 = BN_CTX_get(ctx); BIGNUM *qm1 = BN_CTX_get(ctx); - BIGNUM *gcd = BN_CTX_get(ctx); - if (totient == NULL || pm1 == NULL || qm1 == NULL || gcd == NULL) { + BIGNUM *sqrt2 = BN_CTX_get(ctx); + BIGNUM *pow2_prime_bits_100 = BN_CTX_get(ctx); + BIGNUM *pow2_prime_bits = BN_CTX_get(ctx); + if (totient == NULL || pm1 == NULL || qm1 == NULL || sqrt2 == NULL || + pow2_prime_bits_100 == NULL || pow2_prime_bits == NULL || + !BN_set_bit(pow2_prime_bits_100, prime_bits - 100) || + !BN_set_bit(pow2_prime_bits, prime_bits)) { goto bn_err; } @@ -930,8 +1080,7 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { !ensure_bignum(&rsa->p) || !ensure_bignum(&rsa->q) || !ensure_bignum(&rsa->dmp1) || - !ensure_bignum(&rsa->dmq1) || - !ensure_bignum(&rsa->iqmp)) { + !ensure_bignum(&rsa->dmq1)) { goto bn_err; } @@ -939,13 +1088,36 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { goto bn_err; } - int prime_bits = bits / 2; + // Compute sqrt2 >= ⌊2^(prime_bits-1)×√2⌋. + if (!bn_set_words(sqrt2, kBoringSSLRSASqrtTwo, kBoringSSLRSASqrtTwoLen)) { + goto bn_err; + } + int sqrt2_bits = kBoringSSLRSASqrtTwoLen * BN_BITS2; + assert(sqrt2_bits == (int)BN_num_bits(sqrt2)); + if (sqrt2_bits > prime_bits) { + // For key sizes up to 3072 (prime_bits = 1536), this is exactly + // ⌊2^(prime_bits-1)×√2⌋. + if (!BN_rshift(sqrt2, sqrt2, sqrt2_bits - prime_bits)) { + goto bn_err; + } + } else if (prime_bits > sqrt2_bits) { + // For key sizes beyond 3072, this is approximate. We err towards retrying + // to ensure our key is the right size and round up. + if (!BN_add_word(sqrt2, 1) || + !BN_lshift(sqrt2, sqrt2, prime_bits - sqrt2_bits)) { + goto bn_err; + } + } + assert(prime_bits == (int)BN_num_bits(sqrt2)); + do { // Generate p and q, each of size |prime_bits|, using the steps outlined in // appendix FIPS 186-4 appendix B.3.3. - if (!generate_prime(rsa->p, prime_bits, rsa->e, NULL, ctx, cb) || + if (!generate_prime(rsa->p, prime_bits, rsa->e, NULL, sqrt2, + pow2_prime_bits_100, ctx, cb) || !BN_GENCB_call(cb, 3, 0) || - !generate_prime(rsa->q, prime_bits, rsa->e, rsa->p, ctx, cb) || + !generate_prime(rsa->q, prime_bits, rsa->e, rsa->p, sqrt2, + pow2_prime_bits_100, ctx, cb) || !BN_GENCB_call(cb, 3, 1)) { goto bn_err; } @@ -963,27 +1135,27 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { // q-1. However, we do operations with Chinese Remainder Theorem, so we only // use d (mod p-1) and d (mod q-1) as exponents. Using a minimal totient // does not affect those two values. - if (!BN_sub(pm1, rsa->p, BN_value_one()) || - !BN_sub(qm1, rsa->q, BN_value_one()) || - !BN_mul(totient, pm1, qm1, ctx) || - !BN_gcd(gcd, pm1, qm1, ctx) || - !BN_div(totient, NULL, totient, gcd, ctx) || - !BN_mod_inverse(rsa->d, rsa->e, totient, ctx)) { + int no_inverse; + if (!bn_usub_consttime(pm1, rsa->p, BN_value_one()) || + !bn_usub_consttime(qm1, rsa->q, BN_value_one()) || + !bn_lcm_consttime(totient, pm1, qm1, ctx) || + !bn_mod_inverse_consttime(rsa->d, &no_inverse, rsa->e, totient, ctx)) { goto bn_err; } - // Check that |rsa->d| > 2^|prime_bits| and try again if it fails. See - // appendix B.3.1's guidance on values for d. - } while (!rsa_greater_than_pow2(rsa->d, prime_bits)); + // Retry if |rsa->d| <= 2^|prime_bits|. See appendix B.3.1's guidance on + // values for d. + } while (BN_cmp(rsa->d, pow2_prime_bits) <= 0); if (// Calculate n. - !BN_mul(rsa->n, rsa->p, rsa->q, ctx) || + !bn_mul_consttime(rsa->n, rsa->p, rsa->q, ctx) || // Calculate d mod (p-1). - !BN_mod(rsa->dmp1, rsa->d, pm1, ctx) || + !bn_div_consttime(NULL, rsa->dmp1, rsa->d, pm1, ctx) || // Calculate d mod (q-1) - !BN_mod(rsa->dmq1, rsa->d, qm1, ctx)) { + !bn_div_consttime(NULL, rsa->dmq1, rsa->d, qm1, ctx)) { goto bn_err; } + bn_set_minimal_width(rsa->n); // Sanity-check that |rsa->n| has the specified size. This is implied by // |generate_prime|'s bounds. @@ -992,13 +1164,9 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { goto err; } - // Calculate inverse of q mod p. Note that although RSA key generation is far - // from constant-time, |bn_mod_inverse_secret_prime| uses the same modular - // exponentation logic as in RSA private key operations and, if the RSAZ-1024 - // code is enabled, will be optimized for common RSA prime sizes. - if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, rsa->p, ctx) || - !bn_mod_inverse_secret_prime(rsa->iqmp, rsa->q, rsa->p, ctx, - rsa->mont_p)) { + // Call |freeze_private_key| to compute the inverse of q mod p, by way of + // |rsa->mont_p|. + if (!freeze_private_key(rsa, ctx)) { goto bn_err; } @@ -1047,5 +1215,4 @@ DEFINE_METHOD_FUNCTION(RSA_METHOD, RSA_default_method) { // |rsa_default_*| implementation. OPENSSL_memset(out, 0, sizeof(RSA_METHOD)); out->common.is_static = 1; - out->flags = RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE; } diff --git a/Sources/BoringSSL/crypto/fipsmodule/self_check/self_check.c b/Sources/BoringSSL/crypto/fipsmodule/self_check/self_check.c new file mode 100644 index 000000000..468fd02f2 --- /dev/null +++ b/Sources/BoringSSL/crypto/fipsmodule/self_check/self_check.c @@ -0,0 +1,581 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../internal.h" +#include "../ec/internal.h" +#include "../rand/internal.h" + + +// MSVC wants to put a NUL byte at the end of non-char arrays and so cannot +// compile this. +#if !defined(_MSC_VER) + +static void hexdump(const uint8_t *in, size_t len) { + for (size_t i = 0; i < len; i++) { + printf("%02x", in[i]); + } +} + +static int check_test(const void *expected, const void *actual, + size_t expected_len, const char *name) { + if (OPENSSL_memcmp(actual, expected, expected_len) != 0) { + printf("%s failed.\nExpected: ", name); + hexdump(expected, expected_len); + printf("\nCalculated: "); + hexdump(actual, expected_len); + printf("\n"); + return 0; + } + return 1; +} + +static int set_bignum(BIGNUM **out, const uint8_t *in, size_t len) { + *out = BN_bin2bn(in, len, NULL); + return *out != NULL; +} + +static RSA *self_test_rsa_key(void) { + static const uint8_t kN[] = { + 0xd3, 0x3a, 0x62, 0x9f, 0x07, 0x77, 0xb0, 0x18, 0xf3, 0xff, 0xfe, 0xcc, + 0xc9, 0xa2, 0xc2, 0x3a, 0xa6, 0x1d, 0xd8, 0xf0, 0x26, 0x5b, 0x38, 0x90, + 0x17, 0x48, 0x15, 0xce, 0x21, 0xcd, 0xd6, 0x62, 0x99, 0xe2, 0xd7, 0xda, + 0x40, 0x80, 0x3c, 0xad, 0x18, 0xb7, 0x26, 0xe9, 0x30, 0x8a, 0x23, 0x3f, + 0x68, 0x9a, 0x9c, 0x31, 0x34, 0x91, 0x99, 0x06, 0x11, 0x36, 0xb2, 0x9e, + 0x3a, 0xd0, 0xbc, 0xb9, 0x93, 0x4e, 0xb8, 0x72, 0xa1, 0x9f, 0xb6, 0x8c, + 0xd5, 0x17, 0x1f, 0x7e, 0xaa, 0x75, 0xbb, 0xdf, 0xa1, 0x70, 0x48, 0xc4, + 0xec, 0x9a, 0x51, 0xed, 0x41, 0xc9, 0x74, 0xc0, 0x3e, 0x1e, 0x85, 0x2f, + 0xbe, 0x34, 0xc7, 0x65, 0x34, 0x8b, 0x4d, 0x55, 0x4b, 0xe1, 0x45, 0x54, + 0x0d, 0x75, 0x7e, 0x89, 0x4d, 0x0c, 0xf6, 0x33, 0xe5, 0xfc, 0xfb, 0x56, + 0x1b, 0xf2, 0x39, 0x9d, 0xe0, 0xff, 0x55, 0xcf, 0x02, 0x05, 0xb9, 0x74, + 0xd2, 0x91, 0xfc, 0x87, 0xe1, 0xbb, 0x97, 0x2a, 0xe4, 0xdd, 0x20, 0xc0, + 0x38, 0x47, 0xc0, 0x76, 0x3f, 0xa1, 0x9b, 0x5c, 0x20, 0xff, 0xff, 0xc7, + 0x49, 0x3b, 0x4c, 0xaf, 0x99, 0xa6, 0x3e, 0x82, 0x5c, 0x58, 0x27, 0xce, + 0x01, 0x03, 0xc3, 0x16, 0x35, 0x20, 0xe9, 0xf0, 0x15, 0x7a, 0x41, 0xd5, + 0x1f, 0x52, 0xea, 0xdf, 0xad, 0x4c, 0xbb, 0x0d, 0xcb, 0x04, 0x91, 0xb0, + 0x95, 0xa8, 0xce, 0x25, 0xfd, 0xd2, 0x62, 0x47, 0x77, 0xee, 0x13, 0xf1, + 0x48, 0x72, 0x9e, 0xd9, 0x2d, 0xe6, 0x5f, 0xa4, 0xc6, 0x9e, 0x5a, 0xb2, + 0xc6, 0xa2, 0xf7, 0x0a, 0x16, 0x17, 0xae, 0x6b, 0x1c, 0x30, 0x7c, 0x63, + 0x08, 0x83, 0xe7, 0x43, 0xec, 0x54, 0x5e, 0x2c, 0x08, 0x0b, 0x5e, 0x46, + 0xa7, 0x10, 0x93, 0x43, 0x53, 0x4e, 0xe3, 0x16, 0x73, 0x55, 0xce, 0xf2, + 0x94, 0xc0, 0xbe, 0xb3, + }; + static const uint8_t kE[] = {0x01, 0x00, 0x01}; // 65537 + static const uint8_t kD[] = { + 0x2f, 0x2c, 0x1e, 0xd2, 0x3d, 0x2c, 0xb1, 0x9b, 0x21, 0x02, 0xce, 0xb8, + 0x95, 0x5f, 0x4f, 0xd9, 0x21, 0x38, 0x11, 0x36, 0xb0, 0x9a, 0x36, 0xab, + 0x97, 0x47, 0x75, 0xf7, 0x2e, 0xfd, 0x75, 0x1f, 0x58, 0x16, 0x9c, 0xf6, + 0x14, 0xe9, 0x8e, 0xa3, 0x69, 0x9d, 0x9d, 0x86, 0xfe, 0x5c, 0x1b, 0x3b, + 0x11, 0xf5, 0x55, 0x64, 0x77, 0xc4, 0xfc, 0x53, 0xaa, 0x8c, 0x78, 0x9f, + 0x75, 0xab, 0x20, 0x3a, 0xa1, 0x77, 0x37, 0x22, 0x02, 0x8e, 0x54, 0x8a, + 0x67, 0x1c, 0x5e, 0xe0, 0x3e, 0xd9, 0x44, 0x37, 0xd1, 0x29, 0xee, 0x56, + 0x6c, 0x30, 0x9a, 0x93, 0x4d, 0xd9, 0xdb, 0xc5, 0x03, 0x1a, 0x75, 0xcc, + 0x0f, 0xc2, 0x61, 0xb5, 0x6c, 0x62, 0x9f, 0xc6, 0xa8, 0xc7, 0x8a, 0x60, + 0x17, 0x11, 0x62, 0x4c, 0xef, 0x74, 0x31, 0x97, 0xad, 0x89, 0x2d, 0xe8, + 0x31, 0x1d, 0x8b, 0x58, 0x82, 0xe3, 0x03, 0x1a, 0x6b, 0xdf, 0x3f, 0x3e, + 0xa4, 0x27, 0x19, 0xef, 0x46, 0x7a, 0x90, 0xdf, 0xa7, 0xe7, 0xc9, 0x66, + 0xab, 0x41, 0x1d, 0x65, 0x78, 0x1c, 0x18, 0x40, 0x5c, 0xd6, 0x87, 0xb5, + 0xea, 0x29, 0x44, 0xb3, 0xf5, 0xb3, 0xd2, 0x4f, 0xce, 0x88, 0x78, 0x49, + 0x27, 0x4e, 0x0b, 0x30, 0x85, 0xfb, 0x73, 0xfd, 0x8b, 0x32, 0x15, 0xee, + 0x1f, 0xc9, 0x0e, 0x89, 0xb9, 0x43, 0x2f, 0xe9, 0x60, 0x8d, 0xda, 0xae, + 0x2b, 0x30, 0x99, 0xee, 0x88, 0x81, 0x20, 0x7b, 0x4a, 0xc3, 0x18, 0xf2, + 0x94, 0x02, 0x79, 0x94, 0xaa, 0x65, 0xd9, 0x1b, 0x45, 0x2a, 0xac, 0x6e, + 0x30, 0x48, 0x57, 0xea, 0xbe, 0x79, 0x7d, 0xfc, 0x67, 0xaa, 0x47, 0xc0, + 0xf7, 0x52, 0xfd, 0x0b, 0x63, 0x4e, 0x3d, 0x2e, 0xcc, 0x36, 0xa0, 0xdb, + 0x92, 0x0b, 0xa9, 0x1b, 0xeb, 0xc2, 0xd5, 0x08, 0xd3, 0x85, 0x87, 0xf8, + 0x5d, 0x1a, 0xf6, 0xc1, + }; + static const uint8_t kP[] = { + 0xf7, 0x06, 0xa3, 0x98, 0x8a, 0x52, 0xf8, 0x63, 0x68, 0x27, 0x4f, 0x68, + 0x7f, 0x34, 0xec, 0x8e, 0x5d, 0xf8, 0x30, 0x92, 0xb3, 0x62, 0x4c, 0xeb, + 0xdb, 0x19, 0x6b, 0x09, 0xc5, 0xa3, 0xf0, 0xbb, 0xff, 0x0f, 0xc2, 0xd4, + 0x9b, 0xc9, 0x54, 0x4f, 0xb9, 0xf9, 0xe1, 0x4c, 0xf0, 0xe3, 0x4c, 0x90, + 0xda, 0x7a, 0x01, 0xc2, 0x9f, 0xc4, 0xc8, 0x8e, 0xb1, 0x1e, 0x93, 0x75, + 0x75, 0xc6, 0x13, 0x25, 0xc3, 0xee, 0x3b, 0xcc, 0xb8, 0x72, 0x6c, 0x49, + 0xb0, 0x09, 0xfb, 0xab, 0x44, 0xeb, 0x4d, 0x40, 0xf0, 0x61, 0x6b, 0xe5, + 0xe6, 0xfe, 0x3e, 0x0a, 0x77, 0x26, 0x39, 0x76, 0x3d, 0x4c, 0x3e, 0x9b, + 0x5b, 0xc0, 0xaf, 0xa2, 0x58, 0x76, 0xb0, 0xe9, 0xda, 0x7f, 0x0e, 0x78, + 0xc9, 0x76, 0x49, 0x5c, 0xfa, 0xb3, 0xb0, 0x15, 0x4b, 0x41, 0xc7, 0x27, + 0xa4, 0x75, 0x28, 0x5c, 0x30, 0x69, 0x50, 0x29, + }; + static const uint8_t kQ[] = { + 0xda, 0xe6, 0xd2, 0xbb, 0x44, 0xff, 0x4f, 0xdf, 0x57, 0xc1, 0x11, 0xa3, + 0x51, 0xba, 0x17, 0x89, 0x4c, 0x01, 0xc0, 0x0c, 0x97, 0x34, 0x50, 0xcf, + 0x32, 0x1e, 0xc0, 0xbd, 0x7b, 0x35, 0xb5, 0x6a, 0x26, 0xcc, 0xea, 0x4c, + 0x8e, 0x87, 0x4a, 0x67, 0x8b, 0xd3, 0xe5, 0x4f, 0x3a, 0x60, 0x48, 0x59, + 0x04, 0x93, 0x39, 0xd7, 0x7c, 0xfb, 0x19, 0x1a, 0x34, 0xd5, 0xe8, 0xaf, + 0xe7, 0x22, 0x2c, 0x0d, 0xc2, 0x91, 0x69, 0xb6, 0xe9, 0x2a, 0xe9, 0x1c, + 0x4c, 0x6e, 0x8f, 0x40, 0xf5, 0xa8, 0x3e, 0x82, 0x69, 0x69, 0xbe, 0x9f, + 0x7d, 0x5c, 0x7f, 0x92, 0x78, 0x17, 0xa3, 0x6d, 0x41, 0x2d, 0x72, 0xed, + 0x3f, 0x71, 0xfa, 0x97, 0xb4, 0x63, 0xe4, 0x4f, 0xd9, 0x46, 0x03, 0xfb, + 0x00, 0xeb, 0x30, 0x70, 0xb9, 0x51, 0xd9, 0x0a, 0xd2, 0xf8, 0x50, 0xd4, + 0xfb, 0x43, 0x84, 0xf8, 0xac, 0x58, 0xc3, 0x7b, + }; + static const uint8_t kDModPMinusOne[] = { + 0xf5, 0x50, 0x8f, 0x88, 0x7d, 0xdd, 0xb5, 0xb4, 0x2a, 0x8b, 0xd7, 0x4d, + 0x23, 0xfe, 0xaf, 0xe9, 0x16, 0x22, 0xd2, 0x41, 0xed, 0x88, 0xf2, 0x70, + 0xcb, 0x4d, 0xeb, 0xc1, 0x71, 0x97, 0xc4, 0x0b, 0x3e, 0x5a, 0x2d, 0x96, + 0xab, 0xfa, 0xfd, 0x12, 0x8b, 0xd3, 0x3e, 0x4e, 0x05, 0x6f, 0x04, 0xeb, + 0x59, 0x3c, 0x0e, 0xa1, 0x73, 0xbe, 0x9d, 0x99, 0x2f, 0x05, 0xf9, 0x54, + 0x8d, 0x98, 0x1e, 0x0d, 0xc4, 0x0c, 0xc3, 0x30, 0x23, 0xff, 0xe5, 0xd0, + 0x2b, 0xd5, 0x4e, 0x2b, 0xa0, 0xae, 0xb8, 0x32, 0x84, 0x45, 0x8b, 0x3c, + 0x6d, 0xf0, 0x10, 0x36, 0x9e, 0x6a, 0xc4, 0x67, 0xca, 0xa9, 0xfc, 0x06, + 0x96, 0xd0, 0xbc, 0xda, 0xd1, 0x55, 0x55, 0x8d, 0x77, 0x21, 0xf4, 0x82, + 0x39, 0x37, 0x91, 0xd5, 0x97, 0x56, 0x78, 0xc8, 0x3c, 0xcb, 0x5e, 0xf6, + 0xdc, 0x58, 0x48, 0xb3, 0x7c, 0x94, 0x29, 0x39, + }; + static const uint8_t kDModQMinusOne[] = { + 0x64, 0x65, 0xbd, 0x7d, 0x1a, 0x96, 0x26, 0xa1, 0xfe, 0xf3, 0x94, 0x0d, + 0x5d, 0xec, 0x85, 0xe2, 0xf8, 0xb3, 0x4c, 0xcb, 0xf9, 0x85, 0x8b, 0x12, + 0x9c, 0xa0, 0x32, 0x32, 0x35, 0x92, 0x5a, 0x94, 0x47, 0x1b, 0x70, 0xd2, + 0x90, 0x04, 0x49, 0x01, 0xd8, 0xc5, 0xe4, 0xc4, 0x43, 0xb7, 0xe9, 0x36, + 0xba, 0xbc, 0x73, 0xa8, 0xfb, 0xaf, 0x86, 0xc1, 0xd8, 0x3d, 0xcb, 0xac, + 0xf1, 0xcb, 0x60, 0x7d, 0x27, 0x21, 0xde, 0x64, 0x7f, 0xe8, 0xa8, 0x65, + 0xcc, 0x40, 0x60, 0xff, 0xa0, 0x2b, 0xfc, 0x0f, 0x80, 0x1d, 0x79, 0xca, + 0x58, 0x8a, 0xd6, 0x0f, 0xed, 0x78, 0x9a, 0x02, 0x00, 0x04, 0xc2, 0x53, + 0x41, 0xe8, 0x1a, 0xd0, 0xfd, 0x71, 0x5b, 0x43, 0xac, 0x19, 0x4a, 0xb6, + 0x12, 0xa3, 0xcb, 0xe1, 0xc7, 0x7d, 0x5c, 0x98, 0x74, 0x4e, 0x63, 0x74, + 0x6b, 0x91, 0x7a, 0x29, 0x3b, 0x92, 0xb2, 0x85, + }; + static const uint8_t kQInverseModP[] = { + 0xd0, 0xde, 0x19, 0xda, 0x1e, 0xa2, 0xd8, 0x8f, 0x1c, 0x92, 0x73, 0xb0, + 0xc9, 0x90, 0xc7, 0xf5, 0xec, 0xc5, 0x89, 0x01, 0x05, 0x78, 0x11, 0x2d, + 0x74, 0x34, 0x44, 0xad, 0xd5, 0xf7, 0xa4, 0xfe, 0x9f, 0x25, 0x4d, 0x0b, + 0x92, 0xe3, 0xb8, 0x7d, 0xd3, 0xfd, 0xa5, 0xca, 0x95, 0x60, 0xa3, 0xf9, + 0x55, 0x42, 0x14, 0xb2, 0x45, 0x51, 0x9f, 0x73, 0x88, 0x43, 0x8a, 0xd1, + 0x65, 0x9e, 0xd1, 0xf7, 0x82, 0x2a, 0x2a, 0x8d, 0x70, 0x56, 0xe3, 0xef, + 0xc9, 0x0e, 0x2a, 0x2c, 0x15, 0xaf, 0x7f, 0x97, 0x81, 0x66, 0xf3, 0xb5, + 0x00, 0xa9, 0x26, 0xcc, 0x1e, 0xc2, 0x98, 0xdd, 0xd3, 0x37, 0x06, 0x79, + 0xb3, 0x60, 0x58, 0x79, 0x99, 0x3f, 0xa3, 0x15, 0x1f, 0x31, 0xe3, 0x11, + 0x88, 0x4c, 0x35, 0x57, 0xfa, 0x79, 0xd7, 0xd8, 0x72, 0xee, 0x73, 0x95, + 0x89, 0x29, 0xc7, 0x05, 0x27, 0x68, 0x90, 0x15, + }; + + RSA *rsa = RSA_new(); + if (rsa == NULL || + !set_bignum(&rsa->n, kN, sizeof(kN)) || + !set_bignum(&rsa->e, kE, sizeof(kE)) || + !set_bignum(&rsa->d, kD, sizeof(kD)) || + !set_bignum(&rsa->p, kP, sizeof(kP)) || + !set_bignum(&rsa->q, kQ, sizeof(kQ)) || + !set_bignum(&rsa->dmp1, kDModPMinusOne, sizeof(kDModPMinusOne)) || + !set_bignum(&rsa->dmq1, kDModQMinusOne, sizeof(kDModQMinusOne)) || + !set_bignum(&rsa->iqmp, kQInverseModP, sizeof(kQInverseModP))) { + RSA_free(rsa); + return NULL; + } + + return rsa; +} + +static EC_KEY *self_test_ecdsa_key(void) { + static const uint8_t kQx[] = { + 0xc8, 0x15, 0x61, 0xec, 0xf2, 0xe5, 0x4e, 0xde, 0xfe, 0x66, 0x17, + 0xdb, 0x1c, 0x7a, 0x34, 0xa7, 0x07, 0x44, 0xdd, 0xb2, 0x61, 0xf2, + 0x69, 0xb8, 0x3d, 0xac, 0xfc, 0xd2, 0xad, 0xe5, 0xa6, 0x81, + }; + static const uint8_t kQy[] = { + 0xe0, 0xe2, 0xaf, 0xa3, 0xf9, 0xb6, 0xab, 0xe4, 0xc6, 0x98, 0xef, + 0x64, 0x95, 0xf1, 0xbe, 0x49, 0xa3, 0x19, 0x6c, 0x50, 0x56, 0xac, + 0xb3, 0x76, 0x3f, 0xe4, 0x50, 0x7e, 0xec, 0x59, 0x6e, 0x88, + }; + static const uint8_t kD[] = { + 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, + 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, + 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77, + }; + + EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + BIGNUM *qx = BN_bin2bn(kQx, sizeof(kQx), NULL); + BIGNUM *qy = BN_bin2bn(kQy, sizeof(kQy), NULL); + BIGNUM *d = BN_bin2bn(kD, sizeof(kD), NULL); + if (ec_key == NULL || qx == NULL || qy == NULL || d == NULL || + !EC_KEY_set_public_key_affine_coordinates(ec_key, qx, qy) || + !EC_KEY_set_private_key(ec_key, d)) { + EC_KEY_free(ec_key); + ec_key = NULL; + } + + BN_free(qx); + BN_free(qy); + BN_free(d); + return ec_key; +} + +int BORINGSSL_self_test(void) { + static const uint8_t kAESKey[16] = "BoringCrypto Key"; + static const uint8_t kAESIV[16] = {0}; + static const uint8_t kPlaintext[64] = + "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!"; + static const uint8_t kAESCBCCiphertext[64] = { + 0x87, 0x2d, 0x98, 0xc2, 0xcc, 0x31, 0x5b, 0x41, 0xe0, 0xfa, 0x7b, + 0x0a, 0x71, 0xc0, 0x42, 0xbf, 0x4f, 0x61, 0xd0, 0x0d, 0x58, 0x8c, + 0xf7, 0x05, 0xfb, 0x94, 0x89, 0xd3, 0xbc, 0xaa, 0x1a, 0x50, 0x45, + 0x1f, 0xc3, 0x8c, 0xb8, 0x98, 0x86, 0xa3, 0xe3, 0x6c, 0xfc, 0xad, + 0x3a, 0xb5, 0x59, 0x27, 0x7d, 0x21, 0x07, 0xca, 0x4c, 0x1d, 0x55, + 0x34, 0xdd, 0x5a, 0x2d, 0xc4, 0xb4, 0xf5, 0xa8, +#if !defined(BORINGSSL_FIPS_BREAK_AES_CBC) + 0x35 +#else + 0x00 +#endif + }; + static const uint8_t kAESGCMCiphertext[80] = { + 0x4a, 0xd8, 0xe7, 0x7d, 0x78, 0xd7, 0x7d, 0x5e, 0xb2, 0x11, 0xb6, 0xc9, + 0xa4, 0xbc, 0xb2, 0xae, 0xbe, 0x93, 0xd1, 0xb7, 0xfe, 0x65, 0xc1, 0x82, + 0x2a, 0xb6, 0x71, 0x5f, 0x1a, 0x7c, 0xe0, 0x1b, 0x2b, 0xe2, 0x53, 0xfa, + 0xa0, 0x47, 0xfa, 0xd7, 0x8f, 0xb1, 0x4a, 0xc4, 0xdc, 0x89, 0xf9, 0xb4, + 0x14, 0x4d, 0xde, 0x95, 0xea, 0x29, 0x69, 0x76, 0x81, 0xa3, 0x5c, 0x33, + 0xd8, 0x37, 0xd8, 0xfa, 0x47, 0x19, 0x46, 0x2f, 0xf1, 0x90, 0xb7, 0x61, + 0x8f, 0x6f, 0xdd, 0x31, 0x3f, 0x6a, 0x64, +#if !defined(BORINGSSL_FIPS_BREAK_AES_GCM) + 0x0d +#else + 0x00 +#endif + }; + static const DES_cblock kDESKey1 = {"BCMDESK1"}; + static const DES_cblock kDESKey2 = {"BCMDESK2"}; + static const DES_cblock kDESKey3 = {"BCMDESK3"}; + static const DES_cblock kDESIV = {"BCMDESIV"}; + static const uint8_t kDESCiphertext[64] = { + 0xa4, 0x30, 0x7a, 0x4c, 0x1f, 0x60, 0x16, 0xd7, 0x4f, 0x41, 0xe1, + 0xbb, 0x27, 0xc4, 0x27, 0x37, 0xd4, 0x7f, 0xb9, 0x10, 0xf8, 0xbc, + 0xaf, 0x93, 0x91, 0xb8, 0x88, 0x24, 0xb1, 0xf6, 0xf8, 0xbd, 0x31, + 0x96, 0x06, 0x76, 0xde, 0x32, 0xcd, 0x29, 0x29, 0xba, 0x70, 0x5f, + 0xea, 0xc0, 0xcb, 0xde, 0xc7, 0x75, 0x90, 0xe0, 0x0f, 0x5e, 0x2c, + 0x0d, 0x49, 0x20, 0xd5, 0x30, 0x83, 0xf8, 0x08, +#if !defined(BORINGSSL_FIPS_BREAK_DES) + 0x5a +#else + 0x00 +#endif + }; + static const uint8_t kPlaintextSHA1[20] = { + 0xc6, 0xf8, 0xc9, 0x63, 0x1c, 0x14, 0x23, 0x62, 0x9b, 0xbd, + 0x55, 0x82, 0xf4, 0xd6, 0x1d, 0xf2, 0xab, 0x7d, 0xc8, +#if !defined(BORINGSSL_FIPS_BREAK_SHA_1) + 0x28 +#else + 0x00 +#endif + }; + static const uint8_t kPlaintextSHA256[32] = { + 0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb, + 0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb, + 0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, +#if !defined(BORINGSSL_FIPS_BREAK_SHA_256) + 0x0f +#else + 0x00 +#endif + }; + static const uint8_t kPlaintextSHA512[64] = { + 0x08, 0x6a, 0x1c, 0x84, 0x61, 0x9d, 0x8e, 0xb3, 0xc0, 0x97, 0x4e, + 0xa1, 0x9f, 0x9c, 0xdc, 0xaf, 0x3b, 0x5c, 0x31, 0xf0, 0xf2, 0x74, + 0xc3, 0xbd, 0x6e, 0xd6, 0x1e, 0xb2, 0xbb, 0x34, 0x74, 0x72, 0x5c, + 0x51, 0x29, 0x8b, 0x87, 0x3a, 0xa3, 0xf2, 0x25, 0x23, 0xd4, 0x1c, + 0x82, 0x1b, 0xfe, 0xd3, 0xc6, 0xee, 0xb5, 0xd6, 0xaf, 0x07, 0x7b, + 0x98, 0xca, 0xa7, 0x01, 0xf3, 0x94, 0xf3, 0x68, +#if !defined(BORINGSSL_FIPS_BREAK_SHA_512) + 0x14 +#else + 0x00 +#endif + }; + static const uint8_t kRSASignature[256] = { + 0x62, 0x66, 0x4b, 0xe3, 0xb1, 0xd2, 0x83, 0xf1, 0xa8, 0x56, 0x2b, 0x33, + 0x60, 0x1e, 0xdb, 0x1e, 0x06, 0xf7, 0xa7, 0x1e, 0xa8, 0xef, 0x03, 0x4d, + 0x0c, 0xf6, 0x83, 0x75, 0x7a, 0xf0, 0x14, 0xc7, 0xe2, 0x94, 0x3a, 0xb5, + 0x67, 0x56, 0xa5, 0x48, 0x7f, 0x3a, 0xa5, 0xbf, 0xf7, 0x1d, 0x44, 0xa6, + 0x34, 0xed, 0x9b, 0xd6, 0x51, 0xaa, 0x2c, 0x4e, 0xce, 0x60, 0x5f, 0xe9, + 0x0e, 0xd5, 0xcd, 0xeb, 0x23, 0x27, 0xf8, 0xfb, 0x45, 0xe5, 0x34, 0x63, + 0x77, 0x7f, 0x2e, 0x80, 0xcf, 0x9d, 0x2e, 0xfc, 0xe2, 0x50, 0x75, 0x29, + 0x46, 0xf4, 0xaf, 0x91, 0xed, 0x36, 0xe1, 0x5e, 0xef, 0x66, 0xa1, 0xff, + 0x27, 0xfc, 0x87, 0x7e, 0x60, 0x84, 0x0f, 0x54, 0x51, 0x56, 0x0f, 0x68, + 0x99, 0xc0, 0x3f, 0xeb, 0xa5, 0xa0, 0x46, 0xb0, 0x86, 0x02, 0xb0, 0xc8, + 0xe8, 0x46, 0x13, 0x06, 0xcd, 0xb7, 0x8a, 0xd0, 0x3b, 0x46, 0xd0, 0x14, + 0x64, 0x53, 0x9b, 0x5b, 0x5e, 0x02, 0x45, 0xba, 0x6e, 0x7e, 0x0a, 0xb9, + 0x9e, 0x62, 0xb7, 0xd5, 0x7a, 0x87, 0xea, 0xd3, 0x24, 0xa5, 0xef, 0xb3, + 0xdc, 0x05, 0x9c, 0x04, 0x60, 0x4b, 0xde, 0xa8, 0x90, 0x08, 0x7b, 0x6a, + 0x5f, 0xb4, 0x3f, 0xda, 0xc5, 0x1f, 0x6e, 0xd6, 0x15, 0xde, 0x65, 0xa4, + 0x6e, 0x62, 0x9d, 0x8f, 0xa8, 0xbe, 0x86, 0xf6, 0x09, 0x90, 0x40, 0xa5, + 0xf4, 0x23, 0xc5, 0xf6, 0x38, 0x86, 0x0d, 0x1c, 0xed, 0x4a, 0x0a, 0xae, + 0xa4, 0x26, 0xc2, 0x2e, 0xd3, 0x13, 0x66, 0x61, 0xea, 0x35, 0x01, 0x0e, + 0x13, 0xda, 0x78, 0x20, 0xae, 0x59, 0x5f, 0x9b, 0xa9, 0x6c, 0xf9, 0x1b, + 0xdf, 0x76, 0x53, 0xc8, 0xa7, 0xf5, 0x63, 0x6d, 0xf3, 0xff, 0xfd, 0xaf, + 0x75, 0x4b, 0xac, 0x67, 0xb1, 0x3c, 0xbf, 0x5e, 0xde, 0x73, 0x02, 0x6d, + 0xd2, 0x0c, 0xb1, +#if !defined(BORINGSSL_FIPS_BREAK_RSA_SIG) + 0x64 +#else + 0x00 +#endif + }; + const uint8_t kDRBGEntropy[48] = + "BCM Known Answer Test DBRG Initial Entropy "; + const uint8_t kDRBGPersonalization[18] = "BCMPersonalization"; + const uint8_t kDRBGAD[16] = "BCM DRBG KAT AD "; + const uint8_t kDRBGOutput[64] = { + 0x1d, 0x63, 0xdf, 0x05, 0x51, 0x49, 0x22, 0x46, 0xcd, 0x9b, 0xc5, + 0xbb, 0xf1, 0x5d, 0x44, 0xae, 0x13, 0x78, 0xb1, 0xe4, 0x7c, 0xf1, + 0x96, 0x33, 0x3d, 0x60, 0xb6, 0x29, 0xd4, 0xbb, 0x6b, 0x44, 0xf9, + 0xef, 0xd9, 0xf4, 0xa2, 0xba, 0x48, 0xea, 0x39, 0x75, 0x59, 0x32, + 0xf7, 0x31, 0x2c, 0x98, 0x14, 0x2b, 0x49, 0xdf, 0x02, 0xb6, 0x5d, + 0x71, 0x09, 0x50, 0xdb, 0x23, 0xdb, 0xe5, 0x22, +#if !defined(BORINGSSL_FIPS_BREAK_DRBG) + 0x95 +#else + 0x00 +#endif + }; + const uint8_t kDRBGEntropy2[48] = + "BCM Known Answer Test DBRG Reseed Entropy "; + const uint8_t kDRBGReseedOutput[64] = { + 0xa4, 0x77, 0x05, 0xdb, 0x14, 0x11, 0x76, 0x71, 0x42, 0x5b, 0xd8, + 0xd7, 0xa5, 0x4f, 0x8b, 0x39, 0xf2, 0x10, 0x4a, 0x50, 0x5b, 0xa2, + 0xc8, 0xf0, 0xbb, 0x3e, 0xa1, 0xa5, 0x90, 0x7d, 0x54, 0xd9, 0xc6, + 0xb0, 0x96, 0xc0, 0x2b, 0x7e, 0x9b, 0xc9, 0xa1, 0xdd, 0x78, 0x2e, + 0xd5, 0xa8, 0x66, 0x16, 0xbd, 0x18, 0x3c, 0xf2, 0xaa, 0x7a, 0x2b, + 0x37, 0xf9, 0xab, 0x35, 0x64, 0x15, 0x01, 0x3f, 0xc4, + }; + const uint8_t kECDSASigR[32] = { + 0x67, 0x80, 0xc5, 0xfc, 0x70, 0x27, 0x5e, 0x2c, 0x70, 0x61, 0xa0, + 0xe7, 0x87, 0x7b, 0xb1, 0x74, 0xde, 0xad, 0xeb, 0x98, 0x87, 0x02, + 0x7f, 0x3f, 0xa8, 0x36, 0x54, 0x15, 0x8b, 0xa7, 0xf5, +#if !defined(BORINGSSL_FIPS_BREAK_ECDSA_SIG) + 0x0c, +#else + 0x00, +#endif + }; + const uint8_t kECDSASigS[32] = { + 0xa5, 0x93, 0xe0, 0x23, 0x91, 0xe7, 0x4b, 0x8d, 0x77, 0x25, 0xa6, + 0xba, 0x4d, 0xd9, 0x86, 0x77, 0xda, 0x7d, 0x8f, 0xef, 0xc4, 0x1a, + 0xf0, 0xcc, 0x81, 0xe5, 0xea, 0x3f, 0xc2, 0x41, 0x7f, 0xd8, + }; + + EVP_AEAD_CTX aead_ctx; + EVP_AEAD_CTX_zero(&aead_ctx); + RSA *rsa_key = NULL; + EC_KEY *ec_key = NULL; + ECDSA_SIG *sig = NULL; + int ret = 0; + + AES_KEY aes_key; + uint8_t aes_iv[16]; + uint8_t output[256]; + + // AES-CBC Encryption KAT + memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { + goto err; + } + AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv, + AES_ENCRYPT); + if (!check_test(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), + "AES-CBC Encryption KAT")) { + goto err; + } + + // AES-CBC Decryption KAT + memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { + goto err; + } + AES_cbc_encrypt(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), + &aes_key, aes_iv, AES_DECRYPT); + if (!check_test(kPlaintext, output, sizeof(kPlaintext), + "AES-CBC Decryption KAT")) { + goto err; + } + + size_t out_len; + uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; + OPENSSL_memset(nonce, 0, sizeof(nonce)); + if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey, + sizeof(kAESKey), 0, NULL)) { + goto err; + } + + // AES-GCM Encryption KAT + if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce, + EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), + kPlaintext, sizeof(kPlaintext), NULL, 0) || + !check_test(kAESGCMCiphertext, output, sizeof(kAESGCMCiphertext), + "AES-GCM Encryption KAT")) { + goto err; + } + + // AES-GCM Decryption KAT + if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce, + EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), + kAESGCMCiphertext, sizeof(kAESGCMCiphertext), NULL, + 0) || + !check_test(kPlaintext, output, sizeof(kPlaintext), + "AES-GCM Decryption KAT")) { + goto err; + } + + DES_key_schedule des1, des2, des3; + DES_cblock des_iv; + DES_set_key(&kDESKey1, &des1); + DES_set_key(&kDESKey2, &des2); + DES_set_key(&kDESKey3, &des3); + + // 3DES Encryption KAT + memcpy(&des_iv, &kDESIV, sizeof(des_iv)); + DES_ede3_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &des1, &des2, + &des3, &des_iv, DES_ENCRYPT); + if (!check_test(kDESCiphertext, output, sizeof(kDESCiphertext), + "3DES Encryption KAT")) { + goto err; + } + + // 3DES Decryption KAT + memcpy(&des_iv, &kDESIV, sizeof(des_iv)); + DES_ede3_cbc_encrypt(kDESCiphertext, output, sizeof(kDESCiphertext), &des1, + &des2, &des3, &des_iv, DES_DECRYPT); + if (!check_test(kPlaintext, output, sizeof(kPlaintext), + "3DES Decryption KAT")) { + goto err; + } + + // SHA-1 KAT + SHA1(kPlaintext, sizeof(kPlaintext), output); + if (!check_test(kPlaintextSHA1, output, sizeof(kPlaintextSHA1), + "SHA-1 KAT")) { + goto err; + } + + // SHA-256 KAT + SHA256(kPlaintext, sizeof(kPlaintext), output); + if (!check_test(kPlaintextSHA256, output, sizeof(kPlaintextSHA256), + "SHA-256 KAT")) { + goto err; + } + + // SHA-512 KAT + SHA512(kPlaintext, sizeof(kPlaintext), output); + if (!check_test(kPlaintextSHA512, output, sizeof(kPlaintextSHA512), + "SHA-512 KAT")) { + goto err; + } + + rsa_key = self_test_rsa_key(); + if (rsa_key == NULL) { + printf("RSA KeyGen failed\n"); + goto err; + } + + // RSA Sign KAT + unsigned sig_len; + + // Disable blinding for the power-on tests because it's not needed and + // triggers an entropy draw. + rsa_key->flags |= RSA_FLAG_NO_BLINDING; + + if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output, + &sig_len, rsa_key) || + !check_test(kRSASignature, output, sizeof(kRSASignature), + "RSA Sign KAT")) { + goto err; + } + + // RSA Verify KAT + if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), + kRSASignature, sizeof(kRSASignature), rsa_key)) { + printf("RSA Verify KAT failed.\n"); + goto err; + } + + ec_key = self_test_ecdsa_key(); + if (ec_key == NULL) { + printf("ECDSA KeyGen failed\n"); + goto err; + } + + // ECDSA Sign/Verify PWCT + + // The 'k' value for ECDSA is fixed to avoid an entropy draw. + ec_key->fixed_k = BN_new(); + if (ec_key->fixed_k == NULL || + !BN_set_word(ec_key->fixed_k, 42)) { + printf("Out of memory\n"); + goto err; + } + + sig = ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key); + + uint8_t ecdsa_r_bytes[sizeof(kECDSASigR)]; + uint8_t ecdsa_s_bytes[sizeof(kECDSASigS)]; + if (sig == NULL || + BN_num_bytes(sig->r) != sizeof(ecdsa_r_bytes) || + !BN_bn2bin(sig->r, ecdsa_r_bytes) || + BN_num_bytes(sig->s) != sizeof(ecdsa_s_bytes) || + !BN_bn2bin(sig->s, ecdsa_s_bytes) || + !check_test(kECDSASigR, ecdsa_r_bytes, sizeof(kECDSASigR), "ECDSA R") || + !check_test(kECDSASigS, ecdsa_s_bytes, sizeof(kECDSASigS), "ECDSA S")) { + printf("ECDSA KAT failed.\n"); + goto err; + } + + // DBRG KAT + CTR_DRBG_STATE drbg; + if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization, + sizeof(kDRBGPersonalization)) || + !CTR_DRBG_generate(&drbg, output, sizeof(kDRBGOutput), kDRBGAD, + sizeof(kDRBGAD)) || + !check_test(kDRBGOutput, output, sizeof(kDRBGOutput), + "DBRG Generate KAT") || + !CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) || + !CTR_DRBG_generate(&drbg, output, sizeof(kDRBGReseedOutput), kDRBGAD, + sizeof(kDRBGAD)) || + !check_test(kDRBGReseedOutput, output, sizeof(kDRBGReseedOutput), + "DRBG Reseed KAT")) { + goto err; + } + CTR_DRBG_clear(&drbg); + + CTR_DRBG_STATE kZeroDRBG; + memset(&kZeroDRBG, 0, sizeof(kZeroDRBG)); + if (!check_test(&kZeroDRBG, &drbg, sizeof(drbg), "DRBG Clear KAT")) { + goto err; + } + + ret = 1; + +err: + EVP_AEAD_CTX_cleanup(&aead_ctx); + RSA_free(rsa_key); + EC_KEY_free(ec_key); + ECDSA_SIG_free(sig); + + return ret; +} + +#endif // !_MSC_VER diff --git a/Sources/BoringSSL/crypto/fipsmodule/tls/internal.h b/Sources/BoringSSL/crypto/fipsmodule/tls/internal.h new file mode 100644 index 000000000..ef642a6cd --- /dev/null +++ b/Sources/BoringSSL/crypto/fipsmodule/tls/internal.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_TLS_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_TLS_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// tls1_prf calculates |out_len| bytes of the TLS PDF, using |digest|, and +// writes them to |out|. It returns one on success and zero on error. +OPENSSL_EXPORT int CRYPTO_tls1_prf(const EVP_MD *digest, + uint8_t *out, size_t out_len, + const uint8_t *secret, size_t secret_len, + const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len); + + +#if defined(__cplusplus) +} +#endif + +#endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_TLS_INTERNAL_H diff --git a/Sources/BoringSSL/crypto/fipsmodule/tls/kdf.c b/Sources/BoringSSL/crypto/fipsmodule/tls/kdf.c new file mode 100644 index 000000000..347e99875 --- /dev/null +++ b/Sources/BoringSSL/crypto/fipsmodule/tls/kdf.c @@ -0,0 +1,165 @@ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include "internal.h" +#include "../../internal.h" + + +// tls1_P_hash computes the TLS P_ function as described in RFC 5246, +// section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and +// |secret| as the secret. |label|, |seed1|, and |seed2| are concatenated to +// form the seed parameter. It returns true on success and false on failure. +static int tls1_P_hash(uint8_t *out, size_t out_len, + const EVP_MD *md, + const uint8_t *secret, size_t secret_len, + const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len) { + HMAC_CTX ctx, ctx_tmp, ctx_init; + uint8_t A1[EVP_MAX_MD_SIZE]; + unsigned A1_len; + int ret = 0; + + const size_t chunk = EVP_MD_size(md); + HMAC_CTX_init(&ctx); + HMAC_CTX_init(&ctx_tmp); + HMAC_CTX_init(&ctx_init); + + if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) || + !HMAC_CTX_copy_ex(&ctx, &ctx_init) || + !HMAC_Update(&ctx, (const uint8_t *) label, label_len) || + !HMAC_Update(&ctx, seed1, seed1_len) || + !HMAC_Update(&ctx, seed2, seed2_len) || + !HMAC_Final(&ctx, A1, &A1_len)) { + goto err; + } + + for (;;) { + unsigned len; + uint8_t hmac[EVP_MAX_MD_SIZE]; + if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) || + !HMAC_Update(&ctx, A1, A1_len) || + // Save a copy of |ctx| to compute the next A1 value below. + (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) || + !HMAC_Update(&ctx, (const uint8_t *) label, label_len) || + !HMAC_Update(&ctx, seed1, seed1_len) || + !HMAC_Update(&ctx, seed2, seed2_len) || + !HMAC_Final(&ctx, hmac, &len)) { + goto err; + } + assert(len == chunk); + + // XOR the result into |out|. + if (len > out_len) { + len = out_len; + } + for (unsigned i = 0; i < len; i++) { + out[i] ^= hmac[i]; + } + out += len; + out_len -= len; + + if (out_len == 0) { + break; + } + + // Calculate the next A1 value. + if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) { + goto err; + } + } + + ret = 1; + +err: + OPENSSL_cleanse(A1, sizeof(A1)); + HMAC_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&ctx_tmp); + HMAC_CTX_cleanup(&ctx_init); + return ret; +} + +int CRYPTO_tls1_prf(const EVP_MD *digest, + uint8_t *out, size_t out_len, + const uint8_t *secret, size_t secret_len, + const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len) { + if (out_len == 0) { + return 1; + } + + OPENSSL_memset(out, 0, out_len); + + if (digest == EVP_md5_sha1()) { + // If using the MD5/SHA1 PRF, |secret| is partitioned between MD5 and SHA-1. + size_t secret_half = secret_len - (secret_len / 2); + if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half, label, + label_len, seed1, seed1_len, seed2, seed2_len)) { + return 0; + } + + // Note that, if |secret_len| is odd, the two halves share a byte. + secret += secret_len - secret_half; + secret_len = secret_half; + digest = EVP_sha1(); + } + + return tls1_P_hash(out, out_len, digest, secret, secret_len, label, label_len, + seed1, seed1_len, seed2, seed2_len); +} diff --git a/Sources/BoringSSL/crypto/internal.h b/Sources/BoringSSL/crypto/internal.h index 76d39b742..067f3bb04 100644 --- a/Sources/BoringSSL/crypto/internal.h +++ b/Sources/BoringSSL/crypto/internal.h @@ -116,7 +116,14 @@ #include #include -#if !defined(__cplusplus) +#if defined(__GNUC__) && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 +// |alignas| and |alignof| were added in C11. GCC added support in version 4.8. +// Testing for __STDC_VERSION__/__cplusplus doesn't work because 4.7 already +// reports support for C11. +#define alignas(x) __attribute__ ((aligned (x))) +#define alignof(x) __alignof__ (x) +#elif !defined(__cplusplus) #if defined(_MSC_VER) #define alignas(x) __declspec(align(x)) #define alignof __alignof @@ -151,13 +158,34 @@ void OPENSSL_cpuid_setup(void); #endif -#if !defined(_MSC_VER) && defined(OPENSSL_64_BIT) +#if (!defined(_MSC_VER) || defined(__clang__)) && defined(OPENSSL_64_BIT) +#define BORINGSSL_HAS_UINT128 typedef __int128_t int128_t; typedef __uint128_t uint128_t; + +// clang-cl supports __uint128_t but modulus and division don't work. +// https://crbug.com/787617. +#if !defined(_MSC_VER) || !defined(__clang__) +#define BORINGSSL_CAN_DIVIDE_UINT128 +#endif #endif #define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +// Have a generic fall-through for different versions of C/C++. +#if defined(__cplusplus) && __cplusplus >= 201703L +#define OPENSSL_FALLTHROUGH [[fallthrough]] +#elif defined(__cplusplus) && __cplusplus >= 201103L && defined(__clang__) +#define OPENSSL_FALLTHROUGH [[clang::fallthrough]] +#elif defined(__cplusplus) && __cplusplus >= 201103L && defined(__GNUC__) && \ + __GNUC__ >= 7 +#define OPENSSL_FALLTHROUGH [[gnu::fallthrough]] +#elif defined(__GNUC__) && __GNUC__ >= 7 // gcc 7 +#define OPENSSL_FALLTHROUGH __attribute__ ((fallthrough)) +#else // C++11 on gcc 6, and all other cases +#define OPENSSL_FALLTHROUGH +#endif + // buffers_alias returns one if |a| and |b| alias and zero otherwise. static inline int buffers_alias(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len) { @@ -584,6 +612,41 @@ OPENSSL_EXPORT void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, void *obj, CRYPTO_EX_DATA *ad); +// Endianness conversions. + +#if defined(__GNUC__) && __GNUC__ >= 2 +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + return __builtin_bswap32(x); +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return __builtin_bswap64(x); +} +#elif defined(_MSC_VER) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#pragma intrinsic(_byteswap_uint64, _byteswap_ulong) +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + return _byteswap_ulong(x); +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return _byteswap_uint64(x); +} +#else +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + x = (x >> 16) | (x << 16); + x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8); + return x; +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32); +} +#endif + + // Language bug workarounds. // // Most C standard library functions are undefined if passed NULL, even when the diff --git a/Sources/BoringSSL/crypto/mem.c b/Sources/BoringSSL/crypto/mem.c index 67f74b794..50c6fe6d8 100644 --- a/Sources/BoringSSL/crypto/mem.c +++ b/Sources/BoringSSL/crypto/mem.c @@ -65,8 +65,6 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3)) #include OPENSSL_MSVC_PRAGMA(warning(pop)) -#else -#include #endif #include "internal.h" diff --git a/Sources/BoringSSL/crypto/obj/obj.c b/Sources/BoringSSL/crypto/obj/obj.c index 8e1e6b14c..a34d6dc03 100644 --- a/Sources/BoringSSL/crypto/obj/obj.c +++ b/Sources/BoringSSL/crypto/obj/obj.c @@ -434,36 +434,6 @@ static int strlcpy_int(char *dst, const char *src, int dst_size) { return (int)ret; } -static int parse_oid_component(CBS *cbs, uint64_t *out) { - uint64_t v = 0; - uint8_t b; - do { - if (!CBS_get_u8(cbs, &b)) { - return 0; - } - if ((v >> (64 - 7)) != 0) { - // The component is too large. - return 0; - } - if (v == 0 && b == 0x80) { - // The component must be minimally encoded. - return 0; - } - v = (v << 7) | (b & 0x7f); - - // Components end at an octet with the high bit cleared. - } while (b & 0x80); - - *out = v; - return 1; -} - -static int add_decimal(CBB *out, uint64_t v) { - char buf[DECIMAL_SIZE(uint64_t) + 1]; - BIO_snprintf(buf, sizeof(buf), "%" PRIu64, v); - return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf)); -} - int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int always_return_oid) { // Python depends on the empty OID successfully encoding as the empty @@ -485,56 +455,19 @@ int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, } } - CBB cbb; - if (!CBB_init(&cbb, 32)) { - goto err; - } - CBS cbs; CBS_init(&cbs, obj->data, obj->length); - - // The first component is 40 * value1 + value2, where value1 is 0, 1, or 2. - uint64_t v; - if (!parse_oid_component(&cbs, &v)) { - goto err; - } - - if (v >= 80) { - if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) || - !add_decimal(&cbb, v - 80)) { - goto err; - } - } else if (!add_decimal(&cbb, v / 40) || - !CBB_add_u8(&cbb, '.') || - !add_decimal(&cbb, v % 40)) { - goto err; - } - - while (CBS_len(&cbs) != 0) { - if (!parse_oid_component(&cbs, &v) || - !CBB_add_u8(&cbb, '.') || - !add_decimal(&cbb, v)) { - goto err; + char *txt = CBS_asn1_oid_to_text(&cbs); + if (txt == NULL) { + if (out_len > 0) { + out[0] = '\0'; } + return -1; } - uint8_t *txt; - size_t txt_len; - if (!CBB_add_u8(&cbb, '\0') || - !CBB_finish(&cbb, &txt, &txt_len)) { - goto err; - } - - int ret = strlcpy_int(out, (const char *)txt, out_len); + int ret = strlcpy_int(out, txt, out_len); OPENSSL_free(txt); return ret; - -err: - CBB_cleanup(&cbb); - if (out_len > 0) { - out[0] = '\0'; - } - return -1; } static uint32_t hash_nid(const ASN1_OBJECT *obj) { diff --git a/Sources/BoringSSL/crypto/thread_pthread.c b/Sources/BoringSSL/crypto/thread_pthread.c index 90b3d6051..f8bf59505 100644 --- a/Sources/BoringSSL/crypto/thread_pthread.c +++ b/Sources/BoringSSL/crypto/thread_pthread.c @@ -94,6 +94,8 @@ void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { static pthread_mutex_t g_destructors_lock = PTHREAD_MUTEX_INITIALIZER; static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS]; +// thread_local_destructor is called when a thread exits. It releases thread +// local data for that thread only. static void thread_local_destructor(void *arg) { if (arg == NULL) { return; @@ -119,16 +121,44 @@ static void thread_local_destructor(void *arg) { static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT; static pthread_key_t g_thread_local_key; -static int g_thread_local_failed = 0; +static int g_thread_local_key_created = 0; + +// OPENSSL_DANGEROUS_RELEASE_PTHREAD_KEY can be defined to cause +// |pthread_key_delete| to be called in a destructor function. This can be +// useful for programs that dlclose BoringSSL. +// +// Note that dlclose()ing BoringSSL is not supported and will leak memory: +// thread-local values will be leaked as well as anything initialised via a +// once. The |pthread_key_t| is destroyed because they run out very quickly, +// while the other leaks are slow, and this allows code that happens to use +// dlclose() despite all the problems to continue functioning. +// +// This is marked "dangerous" because it can cause multi-threaded processes to +// crash (even if they don't use dlclose): if the destructor runs while other +// threads are still executing then they may end up using an invalid key to +// access thread-local variables. +// +// This may be removed after February 2020. +#if defined(OPENSSL_DANGEROUS_RELEASE_PTHREAD_KEY) && \ + (defined(__GNUC__) || defined(__clang__)) +// thread_key_destructor is called when the library is unloaded with dlclose. +static void thread_key_destructor(void) __attribute__((destructor, unused)); +static void thread_key_destructor(void) { + if (g_thread_local_key_created) { + g_thread_local_key_created = 0; + pthread_key_delete(g_thread_local_key); + } +} +#endif static void thread_local_init(void) { - g_thread_local_failed = - pthread_key_create(&g_thread_local_key, thread_local_destructor) != 0; + g_thread_local_key_created = + pthread_key_create(&g_thread_local_key, thread_local_destructor) == 0; } void *CRYPTO_get_thread_local(thread_local_data_t index) { CRYPTO_once(&g_thread_local_init_once, thread_local_init); - if (g_thread_local_failed) { + if (!g_thread_local_key_created) { return NULL; } @@ -142,7 +172,7 @@ void *CRYPTO_get_thread_local(thread_local_data_t index) { int CRYPTO_set_thread_local(thread_local_data_t index, void *value, thread_local_destructor_t destructor) { CRYPTO_once(&g_thread_local_init_once, thread_local_init); - if (g_thread_local_failed) { + if (!g_thread_local_key_created) { destructor(value); return 0; } diff --git a/Sources/BoringSSL/crypto/x509/a_strex.c b/Sources/BoringSSL/crypto/x509/a_strex.c index d0d83564e..465ad0867 100644 --- a/Sources/BoringSSL/crypto/x509/a_strex.c +++ b/Sources/BoringSSL/crypto/x509/a_strex.c @@ -56,6 +56,7 @@ #include +#include #include #include @@ -63,6 +64,7 @@ #include #include "charmap.h" +#include "../asn1/asn1_locl.h" /* * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name @@ -105,22 +107,20 @@ typedef int char_io (void *arg, const void *buf, int len); #define HEX_SIZE(type) (sizeof(type)*2) -static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, +static int do_esc_char(uint32_t c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg) { unsigned char chflgs, chtmp; - char tmphex[HEX_SIZE(long) + 3]; + char tmphex[HEX_SIZE(uint32_t) + 3]; - if (c > 0xffffffffL) - return -1; if (c > 0xffff) { - BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c); + BIO_snprintf(tmphex, sizeof tmphex, "\\W%08" PRIX32, c); if (!io_ch(arg, tmphex, 10)) return -1; return 10; } if (c > 0xff) { - BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c); + BIO_snprintf(tmphex, sizeof tmphex, "\\U%04" PRIX32, c); if (!io_ch(arg, tmphex, 6)) return -1; return 6; @@ -180,7 +180,7 @@ static int do_buf(unsigned char *buf, int buflen, { int i, outlen, len; unsigned char orflags, *p, *q; - unsigned long c; + uint32_t c; p = buf; q = buf + buflen; outlen = 0; @@ -191,14 +191,14 @@ static int do_buf(unsigned char *buf, int buflen, orflags = 0; switch (type & BUF_TYPE_WIDTH_MASK) { case 4: - c = ((unsigned long)*p++) << 24; - c |= ((unsigned long)*p++) << 16; - c |= ((unsigned long)*p++) << 8; + c = ((uint32_t)*p++) << 24; + c |= ((uint32_t)*p++) << 16; + c |= ((uint32_t)*p++) << 8; c |= *p++; break; case 2: - c = ((unsigned long)*p++) << 8; + c = ((uint32_t)*p++) << 8; c |= *p++; break; diff --git a/Sources/BoringSSL/crypto/x509/vpm_int.h b/Sources/BoringSSL/crypto/x509/vpm_int.h index 9c55defc5..53b4a0d5e 100644 --- a/Sources/BoringSSL/crypto/x509/vpm_int.h +++ b/Sources/BoringSSL/crypto/x509/vpm_int.h @@ -67,4 +67,5 @@ struct X509_VERIFY_PARAM_ID_st { size_t emaillen; unsigned char *ip; /* If not NULL IP address to match */ size_t iplen; /* Length of IP address */ + unsigned char poison; /* Fail all verifications */ }; diff --git a/Sources/BoringSSL/crypto/x509/x509_vfy.c b/Sources/BoringSSL/crypto/x509/x509_vfy.c index aff2ee953..2b754f08e 100644 --- a/Sources/BoringSSL/crypto/x509/x509_vfy.c +++ b/Sources/BoringSSL/crypto/x509/x509_vfy.c @@ -784,6 +784,10 @@ static int check_id(X509_STORE_CTX *ctx) X509_VERIFY_PARAM *vpm = ctx->param; X509_VERIFY_PARAM_ID *id = vpm->id; X509 *x = ctx->cert; + if (id->poison) { + if (!check_id_error(ctx, X509_V_ERR_INVALID_CALL)) + return 0; + } if (id->hosts && check_hosts(x, id) <= 0) { if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) return 0; diff --git a/Sources/BoringSSL/crypto/x509/x509_vpm.c b/Sources/BoringSSL/crypto/x509/x509_vpm.c index d0f8f7947..43353c6b2 100644 --- a/Sources/BoringSSL/crypto/x509/x509_vpm.c +++ b/Sources/BoringSSL/crypto/x509/x509_vpm.c @@ -89,6 +89,11 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, { char *copy; + if (name == NULL || namelen == 0) { + // Unlike OpenSSL, we reject trying to set or add an empty name. + return 0; + } + /* * Refuse names with embedded NUL bytes. * XXX: Do we need to push an error onto the error stack? @@ -100,8 +105,6 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, string_stack_free(id->hosts); id->hosts = NULL; } - if (name == NULL || namelen == 0) - return 1; copy = BUF_strndup(name, namelen); if (copy == NULL) @@ -162,7 +165,7 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param) paramid->ip = NULL; paramid->iplen = 0; } - + paramid->poison = 0; } X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) @@ -316,6 +319,8 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, return 0; } + dest->id->poison = src->id->poison; + return 1; } @@ -334,18 +339,17 @@ static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src, size_t srclen) { void *tmp; - if (src) { - if (srclen == 0) { - tmp = BUF_strdup(src); - srclen = strlen(src); - } else - tmp = BUF_memdup(src, srclen); - if (!tmp) - return 0; - } else { - tmp = NULL; - srclen = 0; + if (src == NULL || srclen == 0) { + // Unlike OpenSSL, we do not allow an empty string to disable previously + // configured checks. + return 0; + } + + tmp = BUF_memdup(src, srclen); + if (!tmp) { + return 0; } + if (*pdest) OPENSSL_free(*pdest); *pdest = tmp; @@ -454,13 +458,21 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, size_t namelen) { - return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen); + if (!int_x509_param_set_hosts(param->id, SET_HOST, name, namelen)) { + param->id->poison = 1; + return 0; + } + return 1; } int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name, size_t namelen) { - return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen); + if (!int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen)) { + param->id->poison = 1; + return 0; + } + return 1; } void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, @@ -477,17 +489,27 @@ char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, size_t emaillen) { - return int_x509_param_set1(¶m->id->email, ¶m->id->emaillen, - email, emaillen); + if (OPENSSL_memchr(email, '\0', emaillen) != NULL || + !int_x509_param_set1(¶m->id->email, ¶m->id->emaillen, + email, emaillen)) { + param->id->poison = 1; + return 0; + } + + return 1; } int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, size_t iplen) { - if (iplen != 0 && iplen != 4 && iplen != 16) + if ((iplen != 4 && iplen != 16) || + !int_x509_param_set1((char **)¶m->id->ip, ¶m->id->iplen, + (char *)ip, iplen)) { + param->id->poison = 1; return 0; - return int_x509_param_set1((char **)¶m->id->ip, ¶m->id->iplen, - (char *)ip, iplen); + } + + return 1; } int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) @@ -512,7 +534,7 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) } static const X509_VERIFY_PARAM_ID _empty_id = - { NULL, 0U, NULL, NULL, 0, NULL, 0 }; + { NULL, 0U, NULL, NULL, 0, NULL, 0, 0 }; #define vpm_empty_id ((X509_VERIFY_PARAM_ID *)&_empty_id) diff --git a/Sources/BoringSSL/crypto/x509/x_name.c b/Sources/BoringSSL/crypto/x509/x_name.c index f132e6b6e..78241004d 100644 --- a/Sources/BoringSSL/crypto/x509/x_name.c +++ b/Sources/BoringSSL/crypto/x509/x_name.c @@ -539,3 +539,16 @@ int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) { return ne->set; } + +int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + size_t *pderlen) +{ + /* Make sure encoding is valid */ + if (i2d_X509_NAME(nm, NULL) <= 0) + return 0; + if (pder != NULL) + *pder = (unsigned char *)nm->bytes->data; + if (pderlen != NULL) + *pderlen = nm->bytes->length; + return 1; +} diff --git a/Sources/BoringSSL/err_data.c b/Sources/BoringSSL/err_data.c deleted file mode 100644 index e69de29bb..000000000 diff --git a/Sources/BoringSSL/include/openssl/aead.h b/Sources/BoringSSL/include/openssl/aead.h index 7424e29c0..1d5019710 100644 --- a/Sources/BoringSSL/include/openssl/aead.h +++ b/Sources/BoringSSL/include/openssl/aead.h @@ -117,6 +117,16 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void); // https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void); +// EVP_aead_aes_128_ccm_bluetooth is AES-128-CCM with M=4 and L=2 (4-byte tags +// and 13-byte nonces), as decribed in the Bluetooth Core Specification v5.0, +// Volume 6, Part E, Section 1. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth(void); + +// EVP_aead_aes_128_ccm_bluetooth_8 is AES-128-CCM with M=8 and L=2 (8-byte tags +// and 13-byte nonces), as used in the Bluetooth Mesh Networking Specification +// v1.0. +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth_8(void); + // EVP_has_aes_hardware returns one if we enable hardware support for fast and // constant-time AES-GCM. OPENSSL_EXPORT int EVP_has_aes_hardware(void); diff --git a/Sources/BoringSSL/include/openssl/asn1.h b/Sources/BoringSSL/include/openssl/asn1.h index 5c8bf4cde..f2e92a773 100644 --- a/Sources/BoringSSL/include/openssl/asn1.h +++ b/Sources/BoringSSL/include/openssl/asn1.h @@ -708,9 +708,6 @@ DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) DECLARE_ASN1_FUNCTIONS(ASN1_NULL) DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) -OPENSSL_EXPORT int UTF8_getc(const unsigned char *str, int len, unsigned long *val); -OPENSSL_EXPORT int UTF8_putc(unsigned char *str, int len, unsigned long value); - DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) @@ -740,6 +737,7 @@ OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a); OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len, const char *sn, const char *ln); OPENSSL_EXPORT int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +OPENSSL_EXPORT int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v); OPENSSL_EXPORT long ASN1_INTEGER_get(const ASN1_INTEGER *a); OPENSSL_EXPORT ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); OPENSSL_EXPORT BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai,BIGNUM *bn); @@ -978,5 +976,6 @@ BORINGSSL_MAKE_DELETER(ASN1_TYPE, ASN1_TYPE_free) #define ASN1_R_WRONG_PUBLIC_KEY_TYPE 189 #define ASN1_R_WRONG_TAG 190 #define ASN1_R_WRONG_TYPE 191 +#define ASN1_R_NESTED_TOO_DEEP 192 #endif diff --git a/Sources/BoringSSL/include/openssl/base.h b/Sources/BoringSSL/include/openssl/base.h index 1854a143a..6e6975485 100644 --- a/Sources/BoringSSL/include/openssl/base.h +++ b/Sources/BoringSSL/include/openssl/base.h @@ -106,6 +106,10 @@ extern "C" { #elif defined(__pnacl__) #define OPENSSL_32_BIT #define OPENSSL_PNACL +#elif defined(__wasm__) +#define OPENSSL_32_BIT +#elif defined(__asmjs__) +#define OPENSSL_32_BIT #elif defined(__myriad2__) #define OPENSSL_32_BIT #else @@ -153,7 +157,7 @@ extern "C" { // A consumer may use this symbol in the preprocessor to temporarily build // against multiple revisions of BoringSSL at the same time. It is not // recommended to do so for longer than is necessary. -#define BORINGSSL_API_VERSION 6 +#define BORINGSSL_API_VERSION 7 #if defined(BORINGSSL_SHARED_LIBRARY) @@ -225,19 +229,6 @@ extern "C" { #endif #endif -// Have a generic fall-through for different versions of C/C++. -#if defined(__cplusplus) && __cplusplus >= 201703L -#define OPENSSL_FALLTHROUGH [[fallthrough]] -#elif defined(__cplusplus) && __cplusplus >= 201103L && defined(__clang__) -#define OPENSSL_FALLTHROUGH [[clang::fallthrough]] -#elif defined(__cplusplus) && __cplusplus >= 201103L && __GNUC__ >= 7 -#define OPENSSL_FALLTHROUGH [[gnu::fallthrough]] -#elif __GNUC__ >= 7 // gcc 7 -#define OPENSSL_FALLTHROUGH __attribute__ ((fallthrough)) -#else // C++11 on gcc 6, and all other cases -#define OPENSSL_FALLTHROUGH -#endif - // CRYPTO_THREADID is a dummy value. typedef int CRYPTO_THREADID; diff --git a/Sources/BoringSSL/include/openssl/bio.h b/Sources/BoringSSL/include/openssl/bio.h index f87167ea6..5e3e2ef28 100644 --- a/Sources/BoringSSL/include/openssl/bio.h +++ b/Sources/BoringSSL/include/openssl/bio.h @@ -347,7 +347,7 @@ OPENSSL_EXPORT int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, // Memory BIOs. // // Memory BIOs can be used as a read-only source (with |BIO_new_mem_buf|) or a -// writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_get_mem_buf|). Data +// writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_mem_contents|). Data // written to a writable, memory BIO can be recalled by reading from it. // // Calling |BIO_reset| on a read-only BIO resets it to the original contents. diff --git a/Sources/BoringSSL/include/openssl/bn.h b/Sources/BoringSSL/include/openssl/bn.h index bb32c2f56..eeb25a3aa 100644 --- a/Sources/BoringSSL/include/openssl/bn.h +++ b/Sources/BoringSSL/include/openssl/bn.h @@ -237,7 +237,8 @@ OPENSSL_EXPORT BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret); // BN_bn2bin serialises the absolute value of |in| to |out| as a big-endian // integer, which must have |BN_num_bytes| of space available. It returns the -// number of bytes written. +// number of bytes written. Note this function leaks the magnitude of |in|. If +// |in| is secret, use |BN_bn2bin_padded| instead. OPENSSL_EXPORT size_t BN_bn2bin(const BIGNUM *in, uint8_t *out); // BN_le2bn sets |*ret| to the value of |len| bytes from |in|, interpreted as @@ -459,6 +460,7 @@ OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn); // BN_is_pow2 returns 1 if |a| is a power of two, and 0 otherwise. OPENSSL_EXPORT int BN_is_pow2(const BIGNUM *a); + // Bitwise operations. // BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be the @@ -492,9 +494,19 @@ OPENSSL_EXPORT int BN_clear_bit(BIGNUM *a, int n); OPENSSL_EXPORT int BN_is_bit_set(const BIGNUM *a, int n); // BN_mask_bits truncates |a| so that it is only |n| bits long. It returns one -// on success or zero if |n| is greater than the length of |a| already. +// on success or zero if |n| is negative. +// +// This differs from OpenSSL which additionally returns zero if |a|'s word +// length is less than or equal to |n|, rounded down to a number of words. Note +// word size is platform-dependent, so this behavior is also difficult to rely +// on in OpenSSL and not very useful. OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n); +// BN_count_low_zero_bits returns the number of low-order zero bits in |bn|, or +// the number of factors of two which divide it. It returns zero if |bn| is +// zero. +OPENSSL_EXPORT int BN_count_low_zero_bits(const BIGNUM *bn); + // Modulo arithmetic. @@ -694,7 +706,7 @@ enum bn_primality_result_t { // than the number-field sieve security level of |w| is used. It returns one on // success and zero on failure. If |cb| is not NULL, then it is called during // each iteration of the primality test. -int BN_enhanced_miller_rabin_primality_test( +OPENSSL_EXPORT int BN_enhanced_miller_rabin_primality_test( enum bn_primality_result_t *out_result, const BIGNUM *w, int iterations, BN_CTX *ctx, BN_GENCB *cb); @@ -767,6 +779,10 @@ OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, // value) to protect it against side-channel attacks. On failure, if the failure // was caused by |a| having no inverse mod |n| then |*out_no_inverse| will be // set to one; otherwise it will be set to zero. +// +// Note this function may incorrectly report |a| has no inverse if the random +// blinding value has no inverse. It should only be used when |n| has few +// non-invertible elements, such as an RSA modulus. int BN_mod_inverse_blinded(BIGNUM *out, int *out_no_inverse, const BIGNUM *a, const BN_MONT_CTX *mont, BN_CTX *ctx); @@ -788,8 +804,10 @@ int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a, // BN_MONT_CTX contains the precomputed values needed to work in a specific // Montgomery domain. -// BN_MONT_CTX_new returns a fresh BN_MONT_CTX or NULL on allocation failure. -OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void); +// BN_MONT_CTX_new_for_modulus returns a fresh |BN_MONT_CTX| given the modulus, +// |mod| or NULL on error. +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new_for_modulus(const BIGNUM *mod, + BN_CTX *ctx); // BN_MONT_CTX_free frees memory associated with |mont|. OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont); @@ -799,11 +817,6 @@ OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont); OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from); -// BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It -// returns one on success and zero on error. -OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, - BN_CTX *ctx); - // BN_MONT_CTX_set_locked takes |lock| and checks whether |*pmont| is NULL. If // so, it creates a new |BN_MONT_CTX| and sets the modulus for it to |mod|. It // then stores it as |*pmont|. It returns one on success and zero on error. @@ -891,21 +904,52 @@ OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p2, const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont); +// BN_MONT_CTX_new returns a fresh |BN_MONT_CTX| or NULL on allocation failure. +// Use |BN_MONT_CTX_new_for_modulus| instead. +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void); + +// BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It +// returns one on success and zero on error. Use |BN_MONT_CTX_new_for_modulus| +// instead. +OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, + BN_CTX *ctx); + // Private functions struct bignum_st { - BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks in little-endian - order. */ - int top; // Index of last used element in |d|, plus one. - int dmax; // Size of |d|, in words. - int neg; // one if the number is negative - int flags; // bitmask of BN_FLG_* values + // d is a pointer to an array of |width| |BN_BITS2|-bit chunks in + // little-endian order. This stores the absolute value of the number. + BN_ULONG *d; + // width is the number of elements of |d| which are valid. This value is not + // necessarily minimal; the most-significant words of |d| may be zero. + // |width| determines a potentially loose upper-bound on the absolute value + // of the |BIGNUM|. + // + // Functions taking |BIGNUM| inputs must compute the same answer for all + // possible widths. |bn_minimal_width|, |bn_set_minimal_width|, and other + // helpers may be used to recover the minimal width, provided it is not + // secret. If it is secret, use a different algorithm. Functions may output + // minimal or non-minimal |BIGNUM|s depending on secrecy requirements, but + // those which cause widths to unboundedly grow beyond the minimal value + // should be documented such. + // + // Note this is different from historical |BIGNUM| semantics. + int width; + // dmax is number of elements of |d| which are allocated. + int dmax; + // neg is one if the number if negative and zero otherwise. + int neg; + // flags is a bitmask of |BN_FLG_*| values + int flags; }; struct bn_mont_ctx_st { - BIGNUM RR; // used to convert to montgomery form - BIGNUM N; // The modulus + // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. + BIGNUM RR; + // N is the modulus. It is always stored in minimal form, so |N.top| + // determines R. + BIGNUM N; BN_ULONG n0[2]; // least significant words of (R*Ri-1)/N }; diff --git a/Sources/BoringSSL/include/openssl/bytestring.h b/Sources/BoringSSL/include/openssl/bytestring.h index 309c6a357..6ed1644f1 100644 --- a/Sources/BoringSSL/include/openssl/bytestring.h +++ b/Sources/BoringSSL/include/openssl/bytestring.h @@ -164,34 +164,36 @@ OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); #define CBS_ASN1_UNIVERSALSTRING 0x1cu #define CBS_ASN1_BMPSTRING 0x1eu +// CBS_ASN1_TAG_SHIFT is how much the in-memory representation shifts the class +// and constructed bits from the DER serialization. This allows representing tag +// numbers beyond 31. +// +// Consumers must use the following constants to decompose or assemble tags. +#define CBS_ASN1_TAG_SHIFT 24 + // CBS_ASN1_CONSTRUCTED may be ORed into a tag to toggle the constructed // bit. |CBS| and |CBB| APIs consider the constructed bit to be part of the // tag. -#define CBS_ASN1_CONSTRUCTED 0x20u +#define CBS_ASN1_CONSTRUCTED (0x20u << CBS_ASN1_TAG_SHIFT) -// The following values specify the constructed bit or tag class and may be ORed -// into a tag number to produce the final tag. If none is used, the tag will be -// UNIVERSAL. -// -// Note that although they currently match the DER serialization, consumers must -// use these bits rather than make assumptions about the representation. This is -// to allow for tag numbers beyond 31 in the future. -#define CBS_ASN1_APPLICATION 0x40u -#define CBS_ASN1_CONTEXT_SPECIFIC 0x80u -#define CBS_ASN1_PRIVATE 0xc0u +// The following values specify the tag class and may be ORed into a tag number +// to produce the final tag. If none is used, the tag will be UNIVERSAL. +#define CBS_ASN1_UNIVERSAL (0u << CBS_ASN1_TAG_SHIFT) +#define CBS_ASN1_APPLICATION (0x40u << CBS_ASN1_TAG_SHIFT) +#define CBS_ASN1_CONTEXT_SPECIFIC (0x80u << CBS_ASN1_TAG_SHIFT) +#define CBS_ASN1_PRIVATE (0xc0u << CBS_ASN1_TAG_SHIFT) -// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. -#define CBS_ASN1_CLASS_MASK 0xc0u +// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. This will +// give one of the four values above. +#define CBS_ASN1_CLASS_MASK (0xc0u << CBS_ASN1_TAG_SHIFT) // CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number. -#define CBS_ASN1_TAG_NUMBER_MASK 0x1fu +#define CBS_ASN1_TAG_NUMBER_MASK ((1u << (5 + CBS_ASN1_TAG_SHIFT)) - 1) // CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not // including tag and length bytes) and advances |cbs| over it. The ASN.1 // element must match |tag_value|. It returns one on success and zero // on error. -// -// Tag numbers greater than 30 are not supported (i.e. short form only). OPENSSL_EXPORT int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value); // CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the @@ -209,16 +211,12 @@ OPENSSL_EXPORT int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value); // (not including tag and length bytes), sets |*out_tag| to the tag number, and // advances |*cbs|. It returns one on success and zero on error. Either of |out| // and |out_tag| may be NULL to ignore the value. -// -// Tag numbers greater than 30 are not supported (i.e. short form only). OPENSSL_EXPORT int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag); // CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from // |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to // the tag number and |*out_header_len| to the length of the ASN.1 header. Each // of |out|, |out_tag|, and |out_header_len| may be NULL to ignore the value. -// -// Tag numbers greater than 30 are not supported (i.e. short form only). OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, size_t *out_header_len); @@ -237,11 +235,15 @@ OPENSSL_EXPORT int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, // in 64 bits. OPENSSL_EXPORT int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out); +// CBS_get_asn1_bool gets an ASN.1 BOOLEAN from |cbs| and sets |*out| to zero +// or one based on its value. It returns one on success or zero on error. +OPENSSL_EXPORT int CBS_get_asn1_bool(CBS *cbs, int *out); + // CBS_get_optional_asn1 gets an optional explicitly-tagged element from |cbs| -// tagged with |tag| and sets |*out| to its contents. If present and if -// |out_present| is not NULL, it sets |*out_present| to one, otherwise zero. It -// returns one on success, whether or not the element was present, and zero on -// decode failure. +// tagged with |tag| and sets |*out| to its contents, or ignores it if |out| is +// NULL. If present and if |out_present| is not NULL, it sets |*out_present| to +// one, otherwise zero. It returns one on success, whether or not the element +// was present, and zero on decode failure. OPENSSL_EXPORT int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag); @@ -281,6 +283,13 @@ OPENSSL_EXPORT int CBS_is_valid_asn1_bitstring(const CBS *cbs); // is indexed starting from zero. OPENSSL_EXPORT int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit); +// CBS_asn1_oid_to_text interprets |cbs| as DER-encoded ASN.1 OBJECT IDENTIFIER +// contents (not including the element framing) and returns the ASCII +// representation (e.g., "1.2.840.113554.4.1.72585") in a newly-allocated +// string, or NULL on failure. The caller must release the result with +// |OPENSSL_free|. +OPENSSL_EXPORT char *CBS_asn1_oid_to_text(const CBS *cbs); + // CRYPTO ByteBuilder. // @@ -396,9 +405,7 @@ OPENSSL_EXPORT int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); // CBB_add_asn1 sets |*out_contents| to a |CBB| into which the contents of an // ASN.1 object can be written. The |tag| argument will be used as the tag for -// the object. Passing in |tag| number 31 will return in an error since only -// single octet identifiers are supported. It returns one on success or zero -// on error. +// the object. It returns one on success or zero on error. OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag); // CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on @@ -447,6 +454,15 @@ OPENSSL_EXPORT void CBB_discard_child(CBB *cbb); // error. OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); +// CBB_add_asn1_octet_string writes an ASN.1 OCTET STRING into |cbb| with the +// given contents. It returns one on success and zero on error. +OPENSSL_EXPORT int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, + size_t data_len); + +// CBB_add_asn1_bool writes an ASN.1 BOOLEAN into |cbb| which is true iff +// |value| is non-zero. It returns one on success and zero on error. +OPENSSL_EXPORT int CBB_add_asn1_bool(CBB *cbb, int value); + // CBB_add_asn1_oid_from_text decodes |len| bytes from |text| as an ASCII OID // representation, e.g. "1.2.840.113554.4.1.72585", and writes the DER-encoded // contents to |cbb|. It returns one on success and zero on malloc failure or if @@ -454,10 +470,19 @@ OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); // the element's contents. // // This function considers OID strings with components which do not fit in a -// |uint32_t| to be invalid. +// |uint64_t| to be invalid. OPENSSL_EXPORT int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len); +// CBB_flush_asn1_set_of calls |CBB_flush| on |cbb| and then reorders the +// contents for a DER-encoded ASN.1 SET OF type. It returns one on success and +// zero on failure. DER canonicalizes SET OF contents by sorting +// lexicographically by encoding. Call this function when encoding a SET OF +// type in an order that is not already known to be canonical. +// +// Note a SET type has a slightly different ordering than a SET OF. +OPENSSL_EXPORT int CBB_flush_asn1_set_of(CBB *cbb); + #if defined(__cplusplus) } // extern C diff --git a/Sources/BoringSSL/include/openssl/crypto.h b/Sources/BoringSSL/include/openssl/crypto.h index dc87dd2d8..ccf5012c0 100644 --- a/Sources/BoringSSL/include/openssl/crypto.h +++ b/Sources/BoringSSL/include/openssl/crypto.h @@ -58,6 +58,10 @@ OPENSSL_EXPORT int CRYPTO_has_asm(void); // which case it returns one. OPENSSL_EXPORT int FIPS_mode(void); +// BORINGSSL_self_test triggers the FIPS KAT-based self tests. It returns one +// on success and zero on error. +OPENSSL_EXPORT int BORINGSSL_self_test(void); + // Deprecated functions. diff --git a/Sources/BoringSSL/include/openssl/ec.h b/Sources/BoringSSL/include/openssl/ec.h index b34605fd1..5eee36617 100644 --- a/Sources/BoringSSL/include/openssl/ec.h +++ b/Sources/BoringSSL/include/openssl/ec.h @@ -105,10 +105,13 @@ typedef enum { // curve specified by |nid|, or NULL on error. // // The supported NIDs are: -// NID_secp224r1, -// NID_X9_62_prime256v1, -// NID_secp384r1, -// NID_secp521r1 +// NID_secp224r1 (P-224), +// NID_X9_62_prime256v1 (P-256), +// NID_secp384r1 (P-384), +// NID_secp521r1 (P-521) +// +// If in doubt, use |NID_X9_62_prime256v1|, or see the curve25519.h header for +// more modern primitives. OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_by_curve_name(int nid); // EC_GROUP_free frees |group| and the data that it points to. @@ -209,6 +212,9 @@ OPENSSL_EXPORT int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, // EC_POINT_get_affine_coordinates_GFp sets |x| and |y| to the affine value of // |point| using |ctx|, if it's not NULL. It returns one on success and zero // otherwise. +// +// Either |x| or |y| may be NULL to skip computing that coordinate. This is +// slightly faster in the common case where only the x-coordinate is needed. OPENSSL_EXPORT int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, diff --git a/Sources/BoringSSL/include/openssl/ec_key.h b/Sources/BoringSSL/include/openssl/ec_key.h index 7ef1b1418..cc075e544 100644 --- a/Sources/BoringSSL/include/openssl/ec_key.h +++ b/Sources/BoringSSL/include/openssl/ec_key.h @@ -99,9 +99,6 @@ OPENSSL_EXPORT EC_KEY *EC_KEY_new_by_curve_name(int nid); // EC_KEY_free frees all the data owned by |key| and |key| itself. OPENSSL_EXPORT void EC_KEY_free(EC_KEY *key); -// EC_KEY_copy sets |dst| equal to |src| and returns |dst| or NULL on error. -OPENSSL_EXPORT EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src); - // EC_KEY_dup returns a fresh copy of |src| or NULL on error. OPENSSL_EXPORT EC_KEY *EC_KEY_dup(const EC_KEY *src); @@ -116,14 +113,16 @@ OPENSSL_EXPORT int EC_KEY_is_opaque(const EC_KEY *key); OPENSSL_EXPORT const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); // EC_KEY_set_group sets the |EC_GROUP| object that |key| will use to |group|. -// It returns one on success and zero otherwise. +// It returns one on success and zero otherwise. If |key| already has a group, +// it is an error to change to a different one. OPENSSL_EXPORT int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); // EC_KEY_get0_private_key returns a pointer to the private key inside |key|. OPENSSL_EXPORT const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); // EC_KEY_set_private_key sets the private key of |key| to |priv|. It returns -// one on success and zero otherwise. +// one on success and zero otherwise. |key| must already have had a group +// configured (see |EC_KEY_set_group| and |EC_KEY_new_by_curve_name|). OPENSSL_EXPORT int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); // EC_KEY_get0_public_key returns a pointer to the public key point inside @@ -131,7 +130,9 @@ OPENSSL_EXPORT int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); OPENSSL_EXPORT const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); // EC_KEY_set_public_key sets the public key of |key| to |pub|, by copying it. -// It returns one on success and zero otherwise. +// It returns one on success and zero otherwise. |key| must already have had a +// group configured (see |EC_KEY_set_group| and |EC_KEY_new_by_curve_name|), and +// |pub| must also belong to that group. OPENSSL_EXPORT int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); #define EC_PKEY_NO_PARAMETERS 0x001 diff --git a/Sources/BoringSSL/include/openssl/err.h b/Sources/BoringSSL/include/openssl/err.h index 9a65ffb6f..a39c09091 100644 --- a/Sources/BoringSSL/include/openssl/err.h +++ b/Sources/BoringSSL/include/openssl/err.h @@ -262,14 +262,6 @@ OPENSSL_EXPORT void ERR_print_errors_fp(FILE *file); // ERR_clear_error clears the error queue for the current thread. OPENSSL_EXPORT void ERR_clear_error(void); -// ERR_remove_thread_state clears the error queue for the current thread if -// |tid| is NULL. Otherwise it calls |assert(0)|, because it's no longer -// possible to delete the error queue for other threads. -// -// Error queues are thread-local data and are deleted automatically. You do not -// need to call this function. Use |ERR_clear_error|. -OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid); - // ERR_set_mark "marks" the most recent error for use with |ERR_pop_to_mark|. // It returns one if an error was marked and zero if there are no errors. OPENSSL_EXPORT int ERR_set_mark(void); @@ -382,6 +374,14 @@ enum { // ERR_remove_state calls |ERR_clear_error|. OPENSSL_EXPORT void ERR_remove_state(unsigned long pid); +// ERR_remove_thread_state clears the error queue for the current thread if +// |tid| is NULL. Otherwise it calls |assert(0)|, because it's no longer +// possible to delete the error queue for other threads. +// +// Use |ERR_clear_error| instead. Note error queues are deleted automatically on +// thread exit. You do not need to call this function to release memory. +OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid); + // ERR_func_error_string returns the string "OPENSSL_internal". OPENSSL_EXPORT const char *ERR_func_error_string(uint32_t packed_error); @@ -395,7 +395,7 @@ OPENSSL_EXPORT const char *ERR_func_error_string(uint32_t packed_error); // // TODO(fork): remove this function. OPENSSL_EXPORT char *ERR_error_string(uint32_t packed_error, char *buf); -#define ERR_ERROR_STRING_BUF_LEN 256 +#define ERR_ERROR_STRING_BUF_LEN 120 // ERR_GET_FUNC returns zero. BoringSSL errors do not report a function code. #define ERR_GET_FUNC(packed_error) 0 diff --git a/Sources/BoringSSL/include/openssl/evp.h b/Sources/BoringSSL/include/openssl/evp.h index f5eb20073..7816b591b 100644 --- a/Sources/BoringSSL/include/openssl/evp.h +++ b/Sources/BoringSSL/include/openssl/evp.h @@ -757,7 +757,7 @@ OPENSSL_EXPORT void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher, // RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure. // EC keys are serialized as a DER-encoded ECPrivateKey (RFC 5915) structure. // -// Use |RSA_marshal_private_key| or |EC_marshal_private_key| instead. +// Use |RSA_marshal_private_key| or |EC_KEY_marshal_private_key| instead. OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp); // i2d_PublicKey marshals a public key from |key| to a type-specific format. diff --git a/Sources/BoringSSL/include/openssl/rsa.h b/Sources/BoringSSL/include/openssl/rsa.h index 11aa8e427..a52fa5389 100644 --- a/Sources/BoringSSL/include/openssl/rsa.h +++ b/Sources/BoringSSL/include/openssl/rsa.h @@ -117,6 +117,9 @@ OPENSSL_EXPORT void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1, // // |d| may be NULL, but |n| and |e| must either be non-NULL or already // configured on |rsa|. +// +// It is an error to call this function after |rsa| has been used for a +// cryptographic operation. Construct a new |RSA| object instead. OPENSSL_EXPORT int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d); // RSA_set0_factors sets |rsa|'s prime factors to |p| and |q|, if non-NULL, and @@ -124,6 +127,9 @@ OPENSSL_EXPORT int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d); // returns one. Otherwise, it returns zero. // // Each argument must either be non-NULL or already configured on |rsa|. +// +// It is an error to call this function after |rsa| has been used for a +// cryptographic operation. Construct a new |RSA| object instead. OPENSSL_EXPORT int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q); // RSA_set0_crt_params sets |rsa|'s CRT parameters to |dmp1|, |dmq1|, and @@ -131,6 +137,9 @@ OPENSSL_EXPORT int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q); // ownership of its parameters and returns one. Otherwise, it returns zero. // // Each argument must either be non-NULL or already configured on |rsa|. +// +// It is an error to call this function after |rsa| has been used for a +// cryptographic operation. Construct a new |RSA| object instead. OPENSSL_EXPORT int RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); @@ -489,12 +498,6 @@ OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *rsa, int idx); // API, like a platform key store. #define RSA_FLAG_OPAQUE 1 -// Deprecated and ignored. -#define RSA_FLAG_CACHE_PUBLIC 2 - -// Deprecated and ignored. -#define RSA_FLAG_CACHE_PRIVATE 4 - // RSA_FLAG_NO_BLINDING disables blinding of private operations, which is a // dangerous thing to do. It is deprecated and should not be used. It will // be ignored whenever possible. @@ -506,10 +509,6 @@ OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *rsa, int idx); // RSA_FLAG_EXT_PKEY is deprecated and ignored. #define RSA_FLAG_EXT_PKEY 0x20 -// RSA_FLAG_SIGN_VER causes the |sign| and |verify| functions of |rsa_meth_st| -// to be called when set. -#define RSA_FLAG_SIGN_VER 0x40 - // RSA public exponent values. @@ -519,6 +518,12 @@ OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *rsa, int idx); // Deprecated functions. +#define RSA_METHOD_FLAG_NO_CHECK RSA_FLAG_OPAQUE + +// RSA_flags returns the flags for |rsa|. These are a bitwise OR of |RSA_FLAG_*| +// constants. +OPENSSL_EXPORT int RSA_flags(const RSA *rsa); + // RSA_blinding_on returns one. OPENSSL_EXPORT int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); @@ -631,6 +636,9 @@ typedef struct bn_blinding_st BN_BLINDING; struct rsa_st { RSA_METHOD *meth; + // Access to the following fields was historically allowed, but + // deprecated. Use |RSA_get0_*| and |RSA_set0_*| instead. Access to all other + // fields is forbidden and will cause threading errors. BIGNUM *n; BIGNUM *e; BIGNUM *d; @@ -653,6 +661,18 @@ struct rsa_st { BN_MONT_CTX *mont_p; BN_MONT_CTX *mont_q; + // The following fields are copies of |d|, |dmp1|, and |dmq1|, respectively, + // but with the correct widths to prevent side channels. These must use + // separate copies due to threading concerns caused by OpenSSL's API + // mistakes. See https://github.com/openssl/openssl/issues/5158 and + // the |freeze_private_key| implementation. + BIGNUM *d_fixed, *dmp1_fixed, *dmq1_fixed; + + // inv_small_mod_large_mont is q^-1 mod p in Montgomery form, using |mont_p|, + // if |p| >= |q|. Otherwise, it is p^-1 mod q in Montgomery form, using + // |mont_q|. + BIGNUM *inv_small_mod_large_mont; + // num_blindings contains the size of the |blindings| and |blindings_inuse| // arrays. This member and the |blindings_inuse| array are protected by // |lock|. @@ -662,6 +682,10 @@ struct rsa_st { // |blindings_inuse| from 0 to 1. BN_BLINDING **blindings; unsigned char *blindings_inuse; + + // private_key_frozen is one if the key has been used for a private key + // operation and may no longer be mutated. + unsigned private_key_frozen:1; }; @@ -727,5 +751,6 @@ BORINGSSL_MAKE_DELETER(RSA, RSA_free) #define RSA_R_VALUE_MISSING 144 #define RSA_R_WRONG_SIGNATURE_LENGTH 145 #define RSA_R_PUBLIC_KEY_VALIDATION_FAILED 146 +#define RSA_R_D_OUT_OF_RANGE 147 #endif // OPENSSL_HEADER_RSA_H diff --git a/Sources/BoringSSL/include/openssl/ssl.h b/Sources/BoringSSL/include/openssl/ssl.h index 53a8eb514..8e7d5f529 100644 --- a/Sources/BoringSSL/include/openssl/ssl.h +++ b/Sources/BoringSSL/include/openssl/ssl.h @@ -192,7 +192,9 @@ OPENSSL_EXPORT const SSL_METHOD *TLS_method(void); OPENSSL_EXPORT const SSL_METHOD *DTLS_method(void); // TLS_with_buffers_method is like |TLS_method|, but avoids all use of -// crypto/x509. +// crypto/x509. All client connections created with |TLS_with_buffers_method| +// will fail unless a certificate verifier is installed with +// |SSL_set_custom_verify| or |SSL_CTX_set_custom_verify|. OPENSSL_EXPORT const SSL_METHOD *TLS_with_buffers_method(void); // DTLS_with_buffers_method is like |DTLS_method|, but avoids all use of @@ -532,6 +534,8 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code); // See also |SSL_CTX_set_custom_verify|. #define SSL_ERROR_WANT_CERTIFICATE_VERIFY 16 +#define SSL_ERROR_HANDOFF 17 + // SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success // and zero on failure. OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu); @@ -591,12 +595,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl); #define DTLS1_VERSION 0xfeff #define DTLS1_2_VERSION 0xfefd -#define TLS1_3_DRAFT_VERSION 0x7f12 -#define TLS1_3_DRAFT21_VERSION 0x7f15 -#define TLS1_3_DRAFT22_VERSION 0x7e04 -#define TLS1_3_EXPERIMENT_VERSION 0x7e01 -#define TLS1_3_EXPERIMENT2_VERSION 0x7e02 -#define TLS1_3_EXPERIMENT3_VERSION 0x7e03 +#define TLS1_3_DRAFT23_VERSION 0x7f17 // SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to // |version|. If |version| is zero, the default minimum version is used. It @@ -2384,6 +2383,11 @@ OPENSSL_EXPORT int SSL_CTX_load_verify_locations(SSL_CTX *ctx, // either |X509_V_OK| or a |X509_V_ERR_*| value. OPENSSL_EXPORT long SSL_get_verify_result(const SSL *ssl); +// SSL_alert_from_verify_result returns the SSL alert code, such as +// |SSL_AD_CERTIFICATE_EXPIRED|, that corresponds to an |X509_V_ERR_*| value. +// The return value is always an alert, even when |result| is |X509_V_OK|. +OPENSSL_EXPORT int SSL_alert_from_verify_result(long result); + // SSL_get_ex_data_X509_STORE_CTX_idx returns the ex_data index used to look up // the |SSL| associated with an |X509_STORE_CTX| in the verify callback. OPENSSL_EXPORT int SSL_get_ex_data_X509_STORE_CTX_idx(void); @@ -2783,6 +2787,33 @@ OPENSSL_EXPORT void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))( SSL *ssl, EVP_PKEY **out_pkey); +// Token Binding. +// +// See draft-ietf-tokbind-protocol-16. + +// SSL_set_token_binding_params sets |params| as the Token Binding Key +// parameters (section 3 of draft-ietf-tokbind-protocol-16) to negotiate on the +// connection. If this function is not called, or if |len| is 0, then this +// endpoint will not attempt to negotiate Token Binding. |params| are provided +// in preference order, with the more preferred parameters at the beginning of +// the list. This function returns 1 on success and 0 on failure. +OPENSSL_EXPORT int SSL_set_token_binding_params(SSL *ssl, const uint8_t *params, + size_t len); + +// SSL_is_token_binding_negotiated returns 1 if Token Binding was negotiated +// on this connection and 0 otherwise. On a server, it is possible for this +// function to return 1 when the client's view of the connection is that Token +// Binding was not negotiated. This occurs when the server indicates a version +// of Token Binding less than the client's minimum version. +OPENSSL_EXPORT int SSL_is_token_binding_negotiated(const SSL *ssl); + +// SSL_get_negotiated_token_binding_param returns the TokenBindingKeyParameters +// enum value that was negotiated. It is only valid to call this function if +// SSL_is_token_binding_negotiated returned 1, otherwise this function returns +// an undefined value. +OPENSSL_EXPORT uint8_t SSL_get_negotiated_token_binding_param(const SSL *ssl); + + // DTLS-SRTP. // // See RFC 5764. @@ -2907,6 +2938,58 @@ OPENSSL_EXPORT const char *SSL_get_psk_identity_hint(const SSL *ssl); OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl); +// Dummy post-quantum padding. +// +// Dummy post-quantum padding invovles the client (and later server) sending +// useless, random-looking bytes in an extension in their ClientHello or +// ServerHello. These extensions are sized to simulate a post-quantum +// key-exchange and so enable measurement of the latency impact of the +// additional bandwidth. + +// SSL_set_dummy_pq_padding_size enables the sending of a dummy PQ padding +// extension and configures its size. This is only effective for a client: a +// server will echo an extension with one of equal length when we get to that +// phase of the experiment. It returns one for success and zero otherwise. +OPENSSL_EXPORT int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes); + +// SSL_dummy_pq_padding_used returns one if the server echoed a dummy PQ padding +// extension and zero otherwise. It may only be called on a client connection +// once the ServerHello has been processed, otherwise it'll return zero. +OPENSSL_EXPORT int SSL_dummy_pq_padding_used(SSL *ssl); + + +// QUIC Transport Parameters. +// +// draft-ietf-quic-tls defines a new TLS extension quic_transport_parameters +// used by QUIC for each endpoint to unilaterally declare its supported +// transport parameters. draft-ietf-quic-transport (section 7.4) defines the +// contents of that extension (a TransportParameters struct) and describes how +// to handle it and its semantic meaning. +// +// BoringSSL handles this extension as an opaque byte string. The caller is +// responsible for serializing and parsing it. + +// SSL_set_quic_transport_params configures |ssl| to send |params| (of length +// |params_len|) in the quic_transport_parameters extension in either the +// ClientHello or EncryptedExtensions handshake message. This extension will +// only be sent if the TLS version is at least 1.3, and for a server, only if +// the client sent the extension. The buffer pointed to by |params| only need be +// valid for the duration of the call to this function. This function returns 1 +// on success and 0 on failure. +OPENSSL_EXPORT int SSL_set_quic_transport_params(SSL *ssl, + const uint8_t *params, + size_t params_len); + +// SSL_get_peer_quic_transport_params provides the caller with the value of the +// quic_transport_parameters extension sent by the peer. A pointer to the buffer +// containing the TransportParameters will be put in |*out_params|, and its +// length in |*params_len|. This buffer will be valid for the lifetime of the +// |SSL|. If no params were received from the peer, |*out_params_len| will be 0. +OPENSSL_EXPORT void SSL_get_peer_quic_transport_params(const SSL *ssl, + const uint8_t **out_params, + size_t *out_params_len); + + // Early data. // // WARNING: 0-RTT support in BoringSSL is currently experimental and not fully @@ -2988,6 +3071,13 @@ OPENSSL_EXPORT int SSL_early_data_accepted(const SSL *ssl); // |SSL_ERROR_EARLY_DATA_REJECTED|. OPENSSL_EXPORT void SSL_reset_early_data_reject(SSL *ssl); +// SSL_export_early_keying_material behaves like |SSL_export_keying_material|, +// but it uses the early exporter. The operation will fail if |ssl| did not +// negotiate TLS 1.3 or 0-RTT. +OPENSSL_EXPORT int SSL_export_early_keying_material( + SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, + const uint8_t *context, size_t context_len); + // Alerts. // @@ -3219,11 +3309,6 @@ OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl); enum tls13_variant_t { tls13_default = 0, - tls13_experiment = 1, - tls13_experiment2 = 2, - tls13_experiment3 = 3, - tls13_draft21 = 4, - tls13_draft22 = 5, }; // SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the @@ -3477,6 +3562,16 @@ OPENSSL_EXPORT size_t SSL_max_seal_overhead(const SSL *ssl); // connections which resumed a session. OPENSSL_EXPORT int32_t SSL_get_ticket_age_skew(const SSL *ssl); +// SSL_CTX_set_false_start_allowed_without_alpn configures whether connections +// on |ctx| may use False Start (if |SSL_MODE_ENABLE_FALSE_START| is enabled) +// without negotiating ALPN. +OPENSSL_EXPORT void SSL_CTX_set_false_start_allowed_without_alpn(SSL_CTX *ctx, + int allowed); + +// SSL_is_draft_downgrade returns one if the TLS 1.3 anti-downgrade mechanism +// would have aborted |ssl|'s handshake and zero otherwise. +OPENSSL_EXPORT int SSL_is_draft_downgrade(const SSL *ssl); + // Deprecated functions. @@ -3505,6 +3600,7 @@ OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher); OPENSSL_EXPORT char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher); typedef void COMP_METHOD; +typedef struct ssl_comp_st SSL_COMP; // SSL_COMP_get_compression_methods returns NULL. OPENSSL_EXPORT STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); @@ -3515,6 +3611,12 @@ OPENSSL_EXPORT int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); // SSL_COMP_get_name returns NULL. OPENSSL_EXPORT const char *SSL_COMP_get_name(const COMP_METHOD *comp); +// SSL_COMP_get0_name returns the |name| member of |comp|. +OPENSSL_EXPORT const char *SSL_COMP_get0_name(const SSL_COMP *comp); + +// SSL_COMP_get_id returns the |id| member of |comp|. +OPENSSL_EXPORT int SSL_COMP_get_id(const SSL_COMP *comp); + // SSL_COMP_free_compression_methods does nothing. OPENSSL_EXPORT void SSL_COMP_free_compression_methods(void); @@ -3531,17 +3633,12 @@ OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_method(void); OPENSSL_EXPORT const SSL_METHOD *DTLSv1_method(void); OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_method(void); -// SSLv3_method returns an |SSL_METHOD| with no versions enabled. -OPENSSL_EXPORT const SSL_METHOD *SSLv3_method(void); - // These client- and server-specific methods call their corresponding generic // methods. OPENSSL_EXPORT const SSL_METHOD *TLS_server_method(void); OPENSSL_EXPORT const SSL_METHOD *TLS_client_method(void); OPENSSL_EXPORT const SSL_METHOD *SSLv23_server_method(void); OPENSSL_EXPORT const SSL_METHOD *SSLv23_client_method(void); -OPENSSL_EXPORT const SSL_METHOD *SSLv3_server_method(void); -OPENSSL_EXPORT const SSL_METHOD *SSLv3_client_method(void); OPENSSL_EXPORT const SSL_METHOD *TLSv1_server_method(void); OPENSSL_EXPORT const SSL_METHOD *TLSv1_client_method(void); OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_server_method(void); @@ -3746,8 +3843,6 @@ OPENSSL_EXPORT void SSL_set_tmp_dh_callback(SSL *ssl, #define SSL_set_timeout(session, timeout) \ SSL_SESSION_set_timeout((session), (timeout)) -typedef struct ssl_comp_st SSL_COMP; - struct ssl_comp_st { int id; const char *name; @@ -3830,6 +3925,7 @@ OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb( #define SSL_PENDING_TICKET 10 #define SSL_EARLY_DATA_REJECTED 11 #define SSL_CERTIFICATE_VERIFY 12 +#define SSL_HANDOFF 13 // SSL_want returns one of the above values to determine what the most recent // operation on |ssl| was blocked on. Use |SSL_get_error| instead. @@ -4365,6 +4461,53 @@ OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span out_prefix, Span out, Span out_suffix, Span in); + +// *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** +// +// Split handshakes. +// +// Split handshakes allows the handshake part of a TLS connection to be +// performed in a different process (or on a different machine) than the data +// exchange. This only applies to servers. +// +// In the first part of a split handshake, an |SSL| (where the |SSL_CTX| has +// been configured with |SSL_CTX_set_handoff_mode|) is used normally. Once the +// ClientHello message has been received, the handshake will stop and +// |SSL_get_error| will indicate |SSL_ERROR_HANDOFF|. At this point (and only +// at this point), |SSL_serialize_handoff| can be called to write the “handoff” +// state of the connection. +// +// Elsewhere, a fresh |SSL| can be used with |SSL_apply_handoff| to continue +// the connection. The connection from the client is fed into this |SSL| until +// the handshake completes normally. At this point (and only at this point), +// |SSL_serialize_handback| can be called to serialize the result of the +// handshake. +// +// Back at the first location, a fresh |SSL| can be used with +// |SSL_apply_handback|. Then the client's connection can be processed mostly +// as normal. +// +// Lastly, when a connection is in the handoff state, whether or not +// |SSL_serialize_handoff| is called, |SSL_decline_handoff| will move it back +// into a normal state where the connection can procede without impact. +// +// WARNING: Currently only works with TLS 1.0–1.2. +// WARNING: The serialisation formats are not yet stable: version skew may be +// fatal. +// WARNING: The handback data contains sensitive key material and must be +// protected. +// WARNING: Some calls on the final |SSL| will not work. Just as an example, +// calls like |SSL_get0_session_id_context| and |SSL_get_privatekey| won't +// work because the certificate used for handshaking isn't available. +// WARNING: |SSL_apply_handoff| may trigger “msg” callback calls. + +OPENSSL_EXPORT void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on); +OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out); +OPENSSL_EXPORT bool SSL_decline_handoff(SSL *ssl); +OPENSSL_EXPORT bool SSL_apply_handoff(SSL *ssl, Span handoff); +OPENSSL_EXPORT bool SSL_serialize_handback(const SSL *ssl, CBB *out); +OPENSSL_EXPORT bool SSL_apply_handback(SSL *ssl, Span handback); + } // namespace bssl } // extern C++ @@ -4555,6 +4698,11 @@ OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span out_prefix, #define SSL_R_NO_SUPPORTED_VERSIONS_ENABLED 280 #define SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE 281 #define SSL_R_EMPTY_HELLO_RETRY_REQUEST 282 +#define SSL_R_EARLY_DATA_NOT_IN_USE 283 +#define SSL_R_HANDSHAKE_NOT_COMPLETE 284 +#define SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI 285 +#define SSL_R_SERVER_ECHOED_INVALID_SESSION_ID 286 +#define SSL_R_PRIVATE_KEY_OPERATION_FAILED 287 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 diff --git a/Sources/BoringSSL/include/openssl/ssl3.h b/Sources/BoringSSL/include/openssl/ssl3.h index ae0be88d5..e32a6d73b 100644 --- a/Sources/BoringSSL/include/openssl/ssl3.h +++ b/Sources/BoringSSL/include/openssl/ssl3.h @@ -300,7 +300,6 @@ OPENSSL_COMPILE_ASSERT( #define SSL3_MT_SERVER_HELLO 2 #define SSL3_MT_NEW_SESSION_TICKET 4 #define SSL3_MT_END_OF_EARLY_DATA 5 -#define SSL3_MT_HELLO_RETRY_REQUEST 6 #define SSL3_MT_ENCRYPTED_EXTENSIONS 8 #define SSL3_MT_CERTIFICATE 11 #define SSL3_MT_SERVER_KEY_EXCHANGE 12 diff --git a/Sources/BoringSSL/include/openssl/stack.h b/Sources/BoringSSL/include/openssl/stack.h index 46f57a34c..625f66e43 100644 --- a/Sources/BoringSSL/include/openssl/stack.h +++ b/Sources/BoringSSL/include/openssl/stack.h @@ -344,7 +344,7 @@ struct StackTraits {}; sk_##name##_deep_copy(const STACK_OF(name) *sk, \ ptrtype(*copy_func)(ptrtype), \ void (*free_func)(ptrtype)) { \ - return (STACK_OF(name) *)sk_deep_copy((_STACK *)sk, \ + return (STACK_OF(name) *)sk_deep_copy((const _STACK *)sk, \ (void *(*)(void *))copy_func, \ (void (*)(void *))free_func); \ } diff --git a/Sources/BoringSSL/include/openssl/tls1.h b/Sources/BoringSSL/include/openssl/tls1.h index f62ee1fb5..3424f3dcc 100644 --- a/Sources/BoringSSL/include/openssl/tls1.h +++ b/Sources/BoringSSL/include/openssl/tls1.h @@ -202,19 +202,24 @@ extern "C" { // ExtensionType value from RFC7627 #define TLSEXT_TYPE_extended_master_secret 23 +// ExtensionType value from draft-ietf-tokbind-negotiation-10 +#define TLSEXT_TYPE_token_binding 24 + +// ExtensionType value from draft-ietf-quic-tls +#define TLSEXT_TYPE_quic_transport_parameters 26 + // ExtensionType value from RFC4507 #define TLSEXT_TYPE_session_ticket 35 // ExtensionType values from draft-ietf-tls-tls13-18 #define TLSEXT_TYPE_supported_groups 10 -#define TLSEXT_TYPE_key_share 40 #define TLSEXT_TYPE_pre_shared_key 41 #define TLSEXT_TYPE_early_data 42 #define TLSEXT_TYPE_supported_versions 43 #define TLSEXT_TYPE_cookie 44 #define TLSEXT_TYPE_psk_key_exchange_modes 45 -#define TLSEXT_TYPE_ticket_early_data_info 46 #define TLSEXT_TYPE_certificate_authorities 47 +#define TLSEXT_TYPE_key_share 51 // ExtensionType value from RFC5746 #define TLSEXT_TYPE_renegotiate 0xff01 @@ -228,6 +233,9 @@ extern "C" { // This is not an IANA defined extension number #define TLSEXT_TYPE_channel_id 30032 +// This is not an IANA defined extension number +#define TLSEXT_TYPE_dummy_pq_padding 54537 + // status request value from RFC 3546 #define TLSEXT_STATUSTYPE_ocsp 1 diff --git a/Sources/BoringSSL/include/openssl/x509.h b/Sources/BoringSSL/include/openssl/x509.h index 430ffc076..b336e0fcc 100644 --- a/Sources/BoringSSL/include/openssl/x509.h +++ b/Sources/BoringSSL/include/openssl/x509.h @@ -690,6 +690,9 @@ OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn); OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); OPENSSL_EXPORT int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne); +OPENSSL_EXPORT int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + size_t *pderlen); + OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t); OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s); OPENSSL_EXPORT ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t); @@ -1107,6 +1110,7 @@ extern "C++" { namespace bssl { BORINGSSL_MAKE_DELETER(NETSCAPE_SPKI, NETSCAPE_SPKI_free) +BORINGSSL_MAKE_DELETER(RSA_PSS_PARAMS, RSA_PSS_PARAMS_free) BORINGSSL_MAKE_DELETER(X509, X509_free) BORINGSSL_MAKE_DELETER(X509_ALGOR, X509_ALGOR_free) BORINGSSL_MAKE_DELETER(X509_CRL, X509_CRL_free) diff --git a/Sources/BoringSSL/include/openssl/x509v3.h b/Sources/BoringSSL/include/openssl/x509v3.h index abd52c0b1..4a1fe7bf4 100644 --- a/Sources/BoringSSL/include/openssl/x509v3.h +++ b/Sources/BoringSSL/include/openssl/x509v3.h @@ -748,6 +748,7 @@ extern "C++" { namespace bssl { +BORINGSSL_MAKE_DELETER(AUTHORITY_INFO_ACCESS, AUTHORITY_INFO_ACCESS_free) BORINGSSL_MAKE_DELETER(AUTHORITY_KEYID, AUTHORITY_KEYID_free) BORINGSSL_MAKE_DELETER(BASIC_CONSTRAINTS, BASIC_CONSTRAINTS_free) BORINGSSL_MAKE_DELETER(DIST_POINT, DIST_POINT_free) diff --git a/Sources/BoringSSL/ssl/d1_both.cc b/Sources/BoringSSL/ssl/d1_both.cc index c219f5aed..31c83c609 100644 --- a/Sources/BoringSSL/ssl/d1_both.cc +++ b/Sources/BoringSSL/ssl/d1_both.cc @@ -1,6 +1,6 @@ /* * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. */ /* ==================================================================== * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. @@ -536,6 +536,20 @@ bool dtls1_finish_message(SSL *ssl, CBB *cbb, Array *out_msg) { return true; } +// ssl_size_t_greater_than_32_bits returns whether |v| exceeds the bounds of a +// 32-bit value. The obvious thing doesn't work because, in some 32-bit build +// configurations, the compiler warns that the test is always false and breaks +// the build. +static bool ssl_size_t_greater_than_32_bits(size_t v) { +#if defined(OPENSSL_64_BIT) + return v > 0xffffffff; +#elif defined(OPENSSL_32_BIT) + return false; +#else +#error "Building for neither 32- nor 64-bits." +#endif +} + // add_outgoing adds a new handshake message or ChangeCipherSpec to the current // outgoing flight. It returns true on success and false on error. static bool add_outgoing(SSL *ssl, bool is_ccs, Array data) { @@ -550,7 +564,7 @@ static bool add_outgoing(SSL *ssl, bool is_ccs, Array data) { (1 << 8 * sizeof(ssl->d1->outgoing_messages_len)), "outgoing_messages_len is too small"); if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT || - data.size() > 0xffffffff) { + ssl_size_t_greater_than_32_bits(data.size())) { assert(false); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return false; diff --git a/Sources/BoringSSL/ssl/dtls_method.cc b/Sources/BoringSSL/ssl/dtls_method.cc index d0416adae..8d40edf84 100644 --- a/Sources/BoringSSL/ssl/dtls_method.cc +++ b/Sources/BoringSSL/ssl/dtls_method.cc @@ -1,6 +1,6 @@ /* * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. */ /* ==================================================================== * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. diff --git a/Sources/BoringSSL/ssl/handoff.cc b/Sources/BoringSSL/ssl/handoff.cc new file mode 100644 index 000000000..b19d44322 --- /dev/null +++ b/Sources/BoringSSL/ssl/handoff.cc @@ -0,0 +1,285 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include "internal.h" + + +namespace bssl { + +constexpr int kHandoffVersion = 0; +constexpr int kHandbackVersion = 0; + +bool SSL_serialize_handoff(const SSL *ssl, CBB *out) { + const SSL3_STATE *const s3 = ssl->s3; + if (!ssl->server || + s3->hs == nullptr || + s3->rwstate != SSL_HANDOFF) { + return false; + } + + CBB seq; + Span transcript = s3->hs->transcript.buffer(); + if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&seq, kHandoffVersion) || + !CBB_add_asn1_octet_string(&seq, transcript.data(), transcript.size()) || + !CBB_add_asn1_octet_string(&seq, + reinterpret_cast(s3->hs_buf->data), + s3->hs_buf->length) || + !CBB_flush(out)) { + return false; + } + + return true; +} + +bool SSL_decline_handoff(SSL *ssl) { + const SSL3_STATE *const s3 = ssl->s3; + if (!ssl->server || + s3->hs == nullptr || + s3->rwstate != SSL_HANDOFF) { + return false; + } + + ssl->handoff = false; + return true; +} + +bool SSL_apply_handoff(SSL *ssl, Span handoff) { + if (ssl->method->is_dtls) { + return false; + } + + CBS seq, handoff_cbs(handoff); + uint64_t handoff_version; + if (!CBS_get_asn1(&handoff_cbs, &seq, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&seq, &handoff_version) || + handoff_version != kHandoffVersion) { + return false; + } + + CBS transcript, hs_buf; + if (!CBS_get_asn1(&seq, &transcript, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&seq, &hs_buf, CBS_ASN1_OCTETSTRING)) { + return false; + } + + SSL_set_accept_state(ssl); + + SSL3_STATE *const s3 = ssl->s3; + s3->v2_hello_done = true; + s3->has_message = true; + + s3->hs_buf.reset(BUF_MEM_new()); + if (!s3->hs_buf || + !BUF_MEM_append(s3->hs_buf.get(), CBS_data(&hs_buf), CBS_len(&hs_buf))) { + return false; + } + + if (CBS_len(&transcript) != 0) { + s3->hs->transcript.Update(transcript); + s3->is_v2_hello = true; + ssl_do_msg_callback(ssl, 0 /* read */, 0 /* V2ClientHello */, transcript); + } + + return true; +} + +bool SSL_serialize_handback(const SSL *ssl, CBB *out) { + if (!ssl->server || + !ssl->s3->initial_handshake_complete || + ssl->method->is_dtls || + ssl->version < TLS1_VERSION) { + return false; + } + + const SSL3_STATE *const s3 = ssl->s3; + size_t hostname_len = 0; + if (s3->hostname) { + hostname_len = strlen(s3->hostname.get()); + } + + size_t iv_len = 0; + const uint8_t *read_iv = nullptr, *write_iv = nullptr; + if (ssl->version == TLS1_VERSION && + SSL_CIPHER_is_block_cipher(s3->aead_read_ctx->cipher()) && + (!s3->aead_read_ctx->GetIV(&read_iv, &iv_len) || + !s3->aead_write_ctx->GetIV(&write_iv, &iv_len))) { + return false; + } + + CBB seq; + if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&seq, kHandbackVersion) || + !CBB_add_asn1_uint64(&seq, ssl->version) || + !CBB_add_asn1_uint64(&seq, ssl->conf_max_version) || + !CBB_add_asn1_uint64(&seq, ssl->conf_min_version) || + !CBB_add_asn1_uint64(&seq, ssl->max_send_fragment) || + !CBB_add_asn1_octet_string(&seq, s3->read_sequence, + sizeof(s3->read_sequence)) || + !CBB_add_asn1_octet_string(&seq, s3->write_sequence, + sizeof(s3->write_sequence)) || + !CBB_add_asn1_octet_string(&seq, s3->server_random, + sizeof(s3->server_random)) || + !CBB_add_asn1_octet_string(&seq, s3->client_random, + sizeof(s3->client_random)) || + !CBB_add_asn1_octet_string(&seq, read_iv, iv_len) || + !CBB_add_asn1_octet_string(&seq, write_iv, iv_len) || + !CBB_add_asn1_bool(&seq, s3->session_reused) || + !CBB_add_asn1_bool(&seq, s3->send_connection_binding) || + !CBB_add_asn1_bool(&seq, s3->tlsext_channel_id_valid) || + !ssl_session_serialize(s3->established_session.get(), &seq) || + !CBB_add_asn1_octet_string(&seq, s3->next_proto_negotiated.data(), + s3->next_proto_negotiated.size()) || + !CBB_add_asn1_octet_string(&seq, s3->alpn_selected.data(), + s3->alpn_selected.size()) || + !CBB_add_asn1_octet_string( + &seq, reinterpret_cast(s3->hostname.get()), + hostname_len) || + !CBB_add_asn1_octet_string(&seq, s3->tlsext_channel_id, + sizeof(s3->tlsext_channel_id)) || + !CBB_add_asn1_uint64(&seq, ssl->options) || + !CBB_add_asn1_uint64(&seq, ssl->mode) || + !CBB_add_asn1_uint64(&seq, ssl->max_cert_list) || + !CBB_add_asn1_bool(&seq, ssl->quiet_shutdown) || + !CBB_add_asn1_bool(&seq, ssl->tlsext_channel_id_enabled) || + !CBB_add_asn1_bool(&seq, ssl->retain_only_sha256_of_client_certs) || + !CBB_flush(out)) { + return false; + } + + return true; +} + +bool SSL_apply_handback(SSL *ssl, Span handback) { + if (ssl->do_handshake != nullptr || + ssl->method->is_dtls) { + return false; + } + + SSL3_STATE *const s3 = ssl->s3; + uint64_t handback_version, version, conf_max_version, conf_min_version, + max_send_fragment, options, mode, max_cert_list; + CBS seq, read_seq, write_seq, server_rand, client_rand, read_iv, write_iv, + next_proto, alpn, hostname, channel_id; + int session_reused, send_connection_binding, channel_id_valid, + quiet_shutdown, channel_id_enabled, retain_only_sha256; + + CBS handback_cbs(handback); + if (!CBS_get_asn1(&handback_cbs, &seq, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&seq, &handback_version) || + handback_version != kHandbackVersion) { + return false; + } + + if (!CBS_get_asn1_uint64(&seq, &version) || + !CBS_get_asn1_uint64(&seq, &conf_max_version) || + !CBS_get_asn1_uint64(&seq, &conf_min_version) || + !CBS_get_asn1_uint64(&seq, &max_send_fragment) || + !CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) || + CBS_len(&read_seq) != sizeof(s3->read_sequence) || + !CBS_get_asn1(&seq, &write_seq, CBS_ASN1_OCTETSTRING) || + CBS_len(&write_seq) != sizeof(s3->write_sequence) || + !CBS_get_asn1(&seq, &server_rand, CBS_ASN1_OCTETSTRING) || + CBS_len(&server_rand) != sizeof(s3->server_random) || + !CBS_copy_bytes(&server_rand, s3->server_random, + sizeof(s3->server_random)) || + !CBS_get_asn1(&seq, &client_rand, CBS_ASN1_OCTETSTRING) || + CBS_len(&client_rand) != sizeof(s3->client_random) || + !CBS_copy_bytes(&client_rand, s3->client_random, + sizeof(s3->client_random)) || + !CBS_get_asn1(&seq, &read_iv, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&seq, &write_iv, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1_bool(&seq, &session_reused) || + !CBS_get_asn1_bool(&seq, &send_connection_binding) || + !CBS_get_asn1_bool(&seq, &channel_id_valid)) { + return false; + } + + s3->established_session = + SSL_SESSION_parse(&seq, ssl->ctx->x509_method, ssl->ctx->pool); + + if (!s3->established_session || + !CBS_get_asn1(&seq, &next_proto, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&seq, &alpn, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&seq, &hostname, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&seq, &channel_id, CBS_ASN1_OCTETSTRING) || + CBS_len(&channel_id) != sizeof(s3->tlsext_channel_id) || + !CBS_copy_bytes(&channel_id, s3->tlsext_channel_id, + sizeof(s3->tlsext_channel_id)) || + !CBS_get_asn1_uint64(&seq, &options) || + !CBS_get_asn1_uint64(&seq, &mode) || + !CBS_get_asn1_uint64(&seq, &max_cert_list) || + !CBS_get_asn1_bool(&seq, &quiet_shutdown) || + !CBS_get_asn1_bool(&seq, &channel_id_enabled) || + !CBS_get_asn1_bool(&seq, &retain_only_sha256)) { + return false; + } + + ssl->version = version; + ssl->conf_max_version = conf_max_version; + ssl->conf_min_version = conf_min_version; + ssl->max_send_fragment = max_send_fragment; + ssl->do_handshake = ssl_server_handshake; + ssl->server = true; + ssl->options = options; + ssl->mode = mode; + ssl->max_cert_list = max_cert_list; + + s3->hs.reset(); + s3->have_version = true; + s3->initial_handshake_complete = true; + s3->session_reused = session_reused; + s3->send_connection_binding = send_connection_binding; + s3->tlsext_channel_id_valid = channel_id_valid; + s3->next_proto_negotiated.CopyFrom(next_proto); + s3->alpn_selected.CopyFrom(alpn); + + const size_t hostname_len = CBS_len(&hostname); + if (hostname_len == 0) { + s3->hostname.reset(); + } else { + char *hostname_str = nullptr; + if (!CBS_strdup(&hostname, &hostname_str)) { + return false; + } + s3->hostname.reset(hostname_str); + } + + ssl->quiet_shutdown = quiet_shutdown; + ssl->tlsext_channel_id_enabled = channel_id_enabled; + ssl->retain_only_sha256_of_client_certs = retain_only_sha256; + + Array key_block; + if (!tls1_configure_aead(ssl, evp_aead_open, &key_block, + s3->established_session->cipher, read_iv) || + !tls1_configure_aead(ssl, evp_aead_seal, &key_block, + s3->established_session->cipher, write_iv)) { + return false; + } + + if (!CBS_copy_bytes(&read_seq, s3->read_sequence, + sizeof(s3->read_sequence)) || + !CBS_copy_bytes(&write_seq, s3->write_sequence, + sizeof(s3->write_sequence))) { + return false; + } + + return true; +} + +} // namespace bssl diff --git a/Sources/BoringSSL/ssl/handshake.cc b/Sources/BoringSSL/ssl/handshake.cc index 3b446a8cb..64324245d 100644 --- a/Sources/BoringSSL/ssl/handshake.cc +++ b/Sources/BoringSSL/ssl/handshake.cc @@ -116,6 +116,8 @@ #include +#include + #include "../crypto/internal.h" #include "internal.h" @@ -143,7 +145,8 @@ SSL_HANDSHAKE::SSL_HANDSHAKE(SSL *ssl_arg) next_proto_neg_seen(false), ticket_expected(false), extended_master_secret(false), - pending_private_key_op(false) { + pending_private_key_op(false), + grease_seeded(false) { } SSL_HANDSHAKE::~SSL_HANDSHAKE() { @@ -331,6 +334,11 @@ enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) { hs->new_session->verify_result = X509_V_OK; break; case ssl_verify_invalid: + // If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. + if (ssl->verify_mode == SSL_VERIFY_NONE) { + ERR_clear_error(); + ret = ssl_verify_ok; + } hs->new_session->verify_result = X509_V_ERR_APPLICATION_VERIFICATION; break; case ssl_verify_retry: @@ -351,18 +359,19 @@ enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) { return ret; } -uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index) { - // Use the client_random or server_random for entropy. This both avoids - // calling |RAND_bytes| on a single byte repeatedly and ensures the values are - // deterministic. This allows the same ClientHello be sent twice for a - // HelloRetryRequest or the same group be advertised in both supported_groups - // and key_shares. - uint16_t ret = ssl->server ? ssl->s3->server_random[index] - : ssl->s3->client_random[index]; - // The first four bytes of server_random are a timestamp prior to TLS 1.3, but - // servers have no fields to GREASE until TLS 1.3. - assert(!ssl->server || ssl_protocol_version(ssl) >= TLS1_3_VERSION); +uint16_t ssl_get_grease_value(SSL_HANDSHAKE *hs, + enum ssl_grease_index_t index) { + // Draw entropy for all GREASE values at once. This avoids calling + // |RAND_bytes| repeatedly and makes the values consistent within a + // connection. The latter is so the second ClientHello matches after + // HelloRetryRequest and so supported_groups and key_shares are consistent. + if (!hs->grease_seeded) { + RAND_bytes(hs->grease_seed, sizeof(hs->grease_seed)); + hs->grease_seeded = true; + } + // This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16. + uint16_t ret = hs->grease_seed[index]; ret = (ret & 0xf0) | 0x0a; ret |= ret << 8; return ret; @@ -551,6 +560,11 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { hs->wait = ssl_hs_ok; return -1; + case ssl_hs_handoff: + ssl->s3->rwstate = SSL_HANDOFF; + hs->wait = ssl_hs_ok; + return -1; + case ssl_hs_x509_lookup: ssl->s3->rwstate = SSL_X509_LOOKUP; hs->wait = ssl_hs_ok; diff --git a/Sources/BoringSSL/ssl/handshake_client.cc b/Sources/BoringSSL/ssl/handshake_client.cc index 583acebbe..0b352c2b5 100644 --- a/Sources/BoringSSL/ssl/handshake_client.cc +++ b/Sources/BoringSSL/ssl/handshake_client.cc @@ -223,7 +223,7 @@ static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) { // Add a fake cipher suite. See draft-davidben-tls-grease-01. if (ssl->ctx->grease_enabled && - !CBB_add_u16(&child, ssl_get_grease_value(ssl, ssl_grease_cipher))) { + !CBB_add_u16(&child, ssl_get_grease_value(hs, ssl_grease_cipher))) { return 0; } @@ -295,11 +295,6 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { return 0; } - // Renegotiations do not participate in session resumption. - int has_session_id = ssl->session != NULL && - !ssl->s3->initial_handshake_complete && - ssl->session->session_id_length > 0; - CBB child; if (!CBB_add_u16(&body, hs->client_version) || !CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) || @@ -307,19 +302,10 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { return 0; } - if (has_session_id) { - if (!CBB_add_bytes(&child, ssl->session->session_id, - ssl->session->session_id_length)) { - return 0; - } - } else { - // In TLS 1.3 experimental encodings, send a fake placeholder session ID - // when we do not otherwise have one to send. - if (hs->max_version >= TLS1_3_VERSION && - ssl_is_resumption_variant(ssl->tls13_variant) && - !CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) { - return 0; - } + // Do not send a session ID on renegotiation. + if (!ssl->s3->initial_handshake_complete && + !CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) { + return 0; } if (SSL_is_dtls(ssl)) { @@ -353,50 +339,21 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { return ssl->method->add_message(ssl, std::move(msg)); } -static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out, - const SSLMessage &msg) { - SSL *const ssl = hs->ssl; - if (msg.type != SSL3_MT_SERVER_HELLO && - msg.type != SSL3_MT_HELLO_RETRY_REQUEST) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); - return 0; +static bool parse_supported_versions(SSL_HANDSHAKE *hs, uint16_t *version, + const CBS *in) { + // If the outer version is not TLS 1.2, or there is no extensions block, use + // the outer version. + if (*version != TLS1_2_VERSION || CBS_len(in) == 0) { + return true; } - CBS server_hello = msg.body; - if (!CBS_get_u16(&server_hello, out)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return 0; - } - - // The server version may also be in the supported_versions extension if - // applicable. - if (msg.type != SSL3_MT_SERVER_HELLO || *out != TLS1_2_VERSION) { - return 1; - } - - uint8_t sid_length; - if (!CBS_skip(&server_hello, SSL3_RANDOM_SIZE) || - !CBS_get_u8(&server_hello, &sid_length) || - !CBS_skip(&server_hello, sid_length + 2 /* cipher_suite */ + - 1 /* compression_method */)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return 0; - } - - // The extensions block may not be present. - if (CBS_len(&server_hello) == 0) { - return 1; - } - - CBS extensions; - if (!CBS_get_u16_length_prefixed(&server_hello, &extensions) || - CBS_len(&server_hello) != 0) { + SSL *const ssl = hs->ssl; + CBS copy = *in, extensions; + if (!CBS_get_u16_length_prefixed(©, &extensions) || + CBS_len(©) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return 0; + return false; } bool have_supported_versions; @@ -411,17 +368,18 @@ static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out, OPENSSL_ARRAY_SIZE(ext_types), 1 /* ignore unknown */)) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); - return 0; + return false; } + // Override the outer version with the extension, if present. if (have_supported_versions && - (!CBS_get_u16(&supported_versions, out) || + (!CBS_get_u16(&supported_versions, version) || CBS_len(&supported_versions) != 0)) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return 0; + return false; } - return 1; + return true; } static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) { @@ -472,7 +430,13 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) { // Initialize a random session ID for the experimental TLS 1.3 variant // requiring a session id. - if (ssl_is_resumption_variant(ssl->tls13_variant)) { + if (ssl->session != nullptr && + !ssl->s3->initial_handshake_complete && + ssl->session->session_id_length > 0) { + hs->session_id_len = ssl->session->session_id_length; + OPENSSL_memcpy(hs->session_id, ssl->session->session_id, + hs->session_id_len); + } else if (hs->max_version >= TLS1_3_VERSION) { hs->session_id_len = sizeof(hs->session_id); if (!RAND_bytes(hs->session_id, hs->session_id_len)) { return ssl_hs_error; @@ -501,8 +465,7 @@ static enum ssl_hs_wait_t do_enter_early_data(SSL_HANDSHAKE *hs) { } ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->session->ssl_version); - if (ssl_is_draft22(ssl->session->ssl_version) && - !ssl->method->add_change_cipher_spec(ssl)) { + if (!ssl->method->add_change_cipher_spec(ssl)) { return ssl_hs_error; } @@ -576,8 +539,26 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_read_server_hello; } - uint16_t server_version; - if (!parse_server_version(hs, &server_version, msg)) { + if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { + return ssl_hs_error; + } + + CBS server_hello = msg.body, server_random, session_id; + uint16_t server_version, cipher_suite; + uint8_t compression_method; + if (!CBS_get_u16(&server_hello, &server_version) || + !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&server_hello, &session_id) || + CBS_len(&session_id) > SSL3_SESSION_ID_SIZE || + !CBS_get_u16(&server_hello, &cipher_suite) || + !CBS_get_u8(&server_hello, &compression_method)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return ssl_hs_error; + } + + // Use the supported_versions extension if applicable. + if (!parse_supported_versions(hs, &server_version, &server_hello)) { return ssl_hs_error; } @@ -618,30 +599,24 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { - return ssl_hs_error; - } - - CBS server_hello = msg.body, server_random, session_id; - uint16_t cipher_suite; - uint8_t compression_method; - if (!CBS_skip(&server_hello, 2 /* version */) || - !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&server_hello, &session_id) || - CBS_len(&session_id) > SSL3_SESSION_ID_SIZE || - !CBS_get_u16(&server_hello, &cipher_suite) || - !CBS_get_u8(&server_hello, &compression_method)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } - // Copy over the server random. OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); - // TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS - // 1.3 is finalized and we are not implementing a draft version. + // Measure, but do not enforce, the TLS 1.3 anti-downgrade feature, with a + // different value. + // + // For draft TLS 1.3 versions, it is not safe to deploy this feature. However, + // some TLS terminators are non-compliant and copy the origin server's value, + // so we wish to measure eventual compatibility impact. + if (!ssl->s3->initial_handshake_complete && + hs->max_version >= TLS1_3_VERSION && + OPENSSL_memcmp(ssl->s3->server_random + SSL3_RANDOM_SIZE - + sizeof(kDraftDowngradeRandom), + kDraftDowngradeRandom, + sizeof(kDraftDowngradeRandom)) == 0) { + ssl->s3->draft_downgrade = true; + } if (!ssl->s3->initial_handshake_complete && ssl->session != NULL && ssl->session->session_id_length != 0 && @@ -649,6 +624,18 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { ssl->session->session_id_length)) { ssl->s3->session_reused = true; } else { + // The server may also have echoed back the TLS 1.3 compatibility mode + // session ID. As we know this is not a session the server knows about, any + // server resuming it is in error. Reject the first connection + // deterministicly, rather than installing an invalid session into the + // session cache. https://crbug.com/796910 + if (hs->session_id_len != 0 && + CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SERVER_ECHOED_INVALID_SESSION_ID); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return ssl_hs_error; + } + // The session wasn't resumed. Create a fresh SSL_SESSION to // fill out. ssl_set_session(ssl, NULL); @@ -753,6 +740,13 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } + if (ssl->token_binding_negotiated && + (!hs->extended_master_secret || !ssl->s3->send_connection_binding)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); + return ssl_hs_error; + } + ssl->method->next_message(ssl); if (ssl->session != NULL) { @@ -1520,13 +1514,25 @@ static enum ssl_hs_wait_t do_send_client_finished(SSL_HANDSHAKE *hs) { static bool can_false_start(const SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - // False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. - return !SSL_is_dtls(ssl) && - SSL_version(ssl) == TLS1_2_VERSION && - (!ssl->s3->alpn_selected.empty() || - !ssl->s3->next_proto_negotiated.empty()) && - hs->new_cipher->algorithm_mkey == SSL_kECDHE && - hs->new_cipher->algorithm_mac == SSL_AEAD; + // False Start only for TLS 1.2 with an ECDHE+AEAD cipher. + if (SSL_is_dtls(ssl) || + SSL_version(ssl) != TLS1_2_VERSION || + hs->new_cipher->algorithm_mkey != SSL_kECDHE || + hs->new_cipher->algorithm_mac != SSL_AEAD) { + return false; + } + + // Additionally require ALPN or NPN by default. + // + // TODO(davidben): Can this constraint be relaxed globally now that cipher + // suite requirements have been relaxed? + if (!ssl->ctx->false_start_allowed_without_alpn && + ssl->s3->alpn_selected.empty() && + ssl->s3->next_proto_negotiated.empty()) { + return false; + } + + return true; } static enum ssl_hs_wait_t do_finish_flight(SSL_HANDSHAKE *hs) { diff --git a/Sources/BoringSSL/ssl/handshake_server.cc b/Sources/BoringSSL/ssl/handshake_server.cc index bb565e96a..fa8a24104 100644 --- a/Sources/BoringSSL/ssl/handshake_server.cc +++ b/Sources/BoringSSL/ssl/handshake_server.cc @@ -441,6 +441,10 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } + if (ssl->handoff) { + return ssl_hs_handoff; + } + SSL_CLIENT_HELLO client_hello; if (!ssl_client_hello_init(ssl, &client_hello, msg)) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); @@ -707,8 +711,16 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - // TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS - // 1.3 is finalized and we are not implementing a draft version. + // Implement the TLS 1.3 anti-downgrade feature, but with a different value. + // + // For draft TLS 1.3 versions, it is not safe to deploy this feature. However, + // some TLS terminators are non-compliant and copy the origin server's value, + // so we wish to measure eventual compatibility impact. + if (hs->max_version >= TLS1_3_VERSION) { + OPENSSL_memcpy(ssl->s3->server_random + SSL3_RANDOM_SIZE - + sizeof(kDraftDowngradeRandom), + kDraftDowngradeRandom, sizeof(kDraftDowngradeRandom)); + } const SSL_SESSION *session = hs->new_session.get(); if (ssl->session != NULL) { diff --git a/Sources/BoringSSL/ssl/internal.h b/Sources/BoringSSL/ssl/internal.h index 6c1438399..d13d5f2c9 100644 --- a/Sources/BoringSSL/ssl/internal.h +++ b/Sources/BoringSSL/ssl/internal.h @@ -342,7 +342,7 @@ class Array { }; // CBBFinishArray behaves like |CBB_finish| but stores the result in an Array. -bool CBBFinishArray(CBB *cbb, Array *out); +OPENSSL_EXPORT bool CBBFinishArray(CBB *cbb, Array *out); // Protocol versions. @@ -392,32 +392,6 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert, // call this function before the version is determined. uint16_t ssl_protocol_version(const SSL *ssl); -// ssl_is_draft21 returns whether the version corresponds to a draft21 TLS 1.3 -// variant. -bool ssl_is_draft21(uint16_t version); - -// ssl_is_draft22 returns whether the version corresponds to a draft22 TLS 1.3 -// variant. -bool ssl_is_draft22(uint16_t version); - -// ssl_is_resumption_experiment returns whether the version corresponds to a -// TLS 1.3 resumption experiment. -bool ssl_is_resumption_experiment(uint16_t version); - -// ssl_is_resumption_variant returns whether the version corresponds to a -// TLS 1.3 resumption experiment. -bool ssl_is_resumption_variant(enum tls13_variant_t variant); - -// ssl_is_resumption_client_ccs_experiment returns whether the version -// corresponds to a TLS 1.3 resumption experiment that sends a client CCS. -bool ssl_is_resumption_client_ccs_experiment(uint16_t version); - -// ssl_is_resumption_record_version_experiment returns whether the version -// corresponds to a TLS 1.3 resumption experiment that modifies the record -// version. -bool ssl_is_resumption_record_version_experiment(uint16_t version); - - // Cipher suites. } // namespace bssl @@ -1009,6 +983,7 @@ struct SSLMessage { #define SSL_MAX_HANDSHAKE_FLIGHT 7 extern const uint8_t kHelloRetryRequest[SSL3_RANDOM_SIZE]; +extern const uint8_t kDraftDowngradeRandom[8]; // ssl_max_handshake_message_len returns the maximum number of bytes permitted // in a handshake message for |ssl|. @@ -1244,10 +1219,10 @@ int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs); // tls13_export_keying_material provides an exporter interface to use the // |exporter_secret|. -int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, - const char *label, size_t label_len, - const uint8_t *context, size_t context_len, - int use_context); +int tls13_export_keying_material(SSL *ssl, Span out, + Span secret, + Span label, + Span context); // tls13_finished_mac calculates the MAC of the handshake transcript to verify // the integrity of the Finished message, and stores the result in |out| and @@ -1282,6 +1257,7 @@ enum ssl_hs_wait_t { ssl_hs_read_message, ssl_hs_flush, ssl_hs_certificate_selection_pending, + ssl_hs_handoff, ssl_hs_x509_lookup, ssl_hs_channel_id_lookup, ssl_hs_private_key_operation, @@ -1294,6 +1270,16 @@ enum ssl_hs_wait_t { ssl_hs_certificate_verify, }; +enum ssl_grease_index_t { + ssl_grease_cipher = 0, + ssl_grease_group, + ssl_grease_extension1, + ssl_grease_extension2, + ssl_grease_version, + ssl_grease_ticket_extension, + ssl_grease_last_index = ssl_grease_ticket_extension, +}; + struct SSL_HANDSHAKE { explicit SSL_HANDSHAKE(SSL *ssl); ~SSL_HANDSHAKE(); @@ -1322,11 +1308,6 @@ struct SSL_HANDSHAKE { // |SSL_OP_NO_*| and |SSL_CTX_set_max_proto_version| APIs. uint16_t max_version = 0; - // session_id is the session ID in the ClientHello, used for the experimental - // TLS 1.3 variant. - uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0}; - uint8_t session_id_len = 0; - size_t hash_len = 0; uint8_t secret[EVP_MAX_MD_SIZE] = {0}; uint8_t early_traffic_secret[EVP_MAX_MD_SIZE] = {0}; @@ -1394,6 +1375,12 @@ struct SSL_HANDSHAKE { // peer_key is the peer's ECDH key for a TLS 1.2 client. Array peer_key; + // negotiated_token_binding_version is used by a server to store the + // on-the-wire encoding of the Token Binding protocol version to advertise in + // the ServerHello/EncryptedExtensions if the Token Binding extension is to be + // sent. + uint16_t negotiated_token_binding_version; + // server_params, in a TLS 1.2 server, stores the ServerKeyExchange // parameters. It has client and server randoms prepended for signing // convenience. @@ -1505,6 +1492,9 @@ struct SSL_HANDSHAKE { // in progress. bool pending_private_key_op:1; + // grease_seeded is true if |grease_seed| has been initialized. + bool grease_seeded:1; + // client_version is the value sent or received in the ClientHello version. uint16_t client_version = 0; @@ -1515,6 +1505,20 @@ struct SSL_HANDSHAKE { // early_data_written is the amount of early data that has been written by the // record layer. uint16_t early_data_written = 0; + + // session_id is the session ID in the ClientHello, used for the experimental + // TLS 1.3 variant. + uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0}; + uint8_t session_id_len = 0; + + // grease_seed is the entropy for GREASE values. It is valid if + // |grease_seeded| is true. + uint8_t grease_seed[ssl_grease_last_index + 1] = {0}; + + // dummy_pq_padding_len, in a server, is the length of the extension that + // should be echoed in a ServerHello, or zero if no extension should be + // echoed. + uint16_t dummy_pq_padding_len = 0; }; UniquePtr ssl_handshake_new(SSL *ssl); @@ -1657,47 +1661,39 @@ int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello, // GREASE. -enum ssl_grease_index_t { - ssl_grease_cipher = 0, - ssl_grease_group, - ssl_grease_extension1, - ssl_grease_extension2, - ssl_grease_version, - ssl_grease_ticket_extension, -}; - -// ssl_get_grease_value returns a GREASE value for |ssl|. For a given +// ssl_get_grease_value returns a GREASE value for |hs|. For a given // connection, the values for each index will be deterministic. This allows the // same ClientHello be sent twice for a HelloRetryRequest or the same group be // advertised in both supported_groups and key_shares. -uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index); +uint16_t ssl_get_grease_value(SSL_HANDSHAKE *hs, enum ssl_grease_index_t index); // Signature algorithms. // tls1_parse_peer_sigalgs parses |sigalgs| as the list of peer signature -// algorithms and saves them on |hs|. It returns one on success and zero on +// algorithms and saves them on |hs|. It returns true on success and false on // error. -int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *sigalgs); +bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *sigalgs); // tls1_get_legacy_signature_algorithm sets |*out| to the signature algorithm -// that should be used with |pkey| in TLS 1.1 and earlier. It returns one on -// success and zero if |pkey| may not be used at those versions. -int tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey); +// that should be used with |pkey| in TLS 1.1 and earlier. It returns true on +// success and false if |pkey| may not be used at those versions. +bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey); // tls1_choose_signature_algorithm sets |*out| to a signature algorithm for use // with |hs|'s private key based on the peer's preferences and the algorithms -// supported. It returns one on success and zero on error. -int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out); +// supported. It returns true on success and false on error. +bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out); // tls12_add_verify_sigalgs adds the signature algorithms acceptable for the -// peer signature to |out|. It returns one on success and zero on error. -int tls12_add_verify_sigalgs(const SSL *ssl, CBB *out); +// peer signature to |out|. It returns true on success and false on error. +bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out); // tls12_check_peer_sigalg checks if |sigalg| is acceptable for the peer -// signature. It returns one on success and zero on error, setting |*out_alert| -// to an alert to send. -int tls12_check_peer_sigalg(SSL *ssl, uint8_t *out_alert, uint16_t sigalg); +// signature. It returns true on success and false on error, setting +// |*out_alert| to an alert to send. +bool tls12_check_peer_sigalg(const SSL *ssl, uint8_t *out_alert, + uint16_t sigalg); // Underdocumented functions. @@ -2165,21 +2161,29 @@ struct SSLContext { // If true, a client will request certificate timestamps. bool signed_cert_timestamps_enabled:1; - // tlsext_channel_id_enabled is one if Channel ID is enabled and zero - // otherwise. For a server, means that we'll accept Channel IDs from clients. - // For a client, means that we'll advertise support. + // tlsext_channel_id_enabled is whether Channel ID is enabled. For a server, + // means that we'll accept Channel IDs from clients. For a client, means that + // we'll advertise support. bool tlsext_channel_id_enabled:1; - // grease_enabled is one if draft-davidben-tls-grease-01 is enabled and zero - // otherwise. + // grease_enabled is whether draft-davidben-tls-grease-01 is enabled. bool grease_enabled:1; - // allow_unknown_alpn_protos is one if the client allows unsolicited ALPN + // allow_unknown_alpn_protos is whether the client allows unsolicited ALPN // protocols from the peer. bool allow_unknown_alpn_protos:1; - // ed25519_enabled is one if Ed25519 is advertised in the handshake. + // ed25519_enabled is whether Ed25519 is advertised in the handshake. bool ed25519_enabled:1; + + // false_start_allowed_without_alpn is whether False Start (if + // |SSL_MODE_ENABLE_FALSE_START| is enabled) is allowed without ALPN. + bool false_start_allowed_without_alpn:1; + + // handoff indicates that a server should stop after receiving the + // ClientHello and pause the handshake in such a way that |SSL_get_error| + // returns |SSL_HANDOFF|. + bool handoff:1; }; // An ssl_shutdown_t describes the shutdown state of one end of the connection, @@ -2293,7 +2297,12 @@ struct SSL3_STATE { // wpend_pending is true if we have a pending write outstanding. bool wpend_pending:1; - uint8_t send_alert[2] = {0}; + // early_data_accepted is true if early data was accepted by the server. + bool early_data_accepted:1; + + // draft_downgrade is whether the TLS 1.3 anti-downgrade logic would have + // fired, were it not a draft. + bool draft_downgrade:1; // hs_buf is the buffer of handshake data to process. UniquePtr hs_buf; @@ -2307,6 +2316,11 @@ struct SSL3_STATE { // been successfully written. uint32_t pending_flight_offset = 0; + // ticket_age_skew is the difference, in seconds, between the client-sent + // ticket age and the server-computed value in TLS 1.3 server connections + // which resumed a session. + int32_t ticket_age_skew = 0; + // aead_read_ctx is the current read cipher state. UniquePtr aead_read_ctx; @@ -2332,6 +2346,8 @@ struct SSL3_STATE { uint8_t previous_server_finished_len = 0; uint8_t previous_server_finished[12] = {0}; + uint8_t send_alert[2] = {0}; + // established_session is the session established by the connection. This // session is only filled upon the completion of the handshake and is // immutable. @@ -2362,10 +2378,8 @@ struct SSL3_STATE { // each are big-endian values. uint8_t tlsext_channel_id[64] = {0}; - // ticket_age_skew is the difference, in seconds, between the client-sent - // ticket age and the server-computed value in TLS 1.3 server connections - // which resumed a session. - int32_t ticket_age_skew = 0; + // Contains the QUIC transport params received by the peer. + Array peer_quic_transport_params; }; // lengths of messages @@ -2506,10 +2520,6 @@ struct SSLConnection { // further constrainted by |SSL_OP_NO_*|. uint16_t conf_min_version; - // tls13_variant is the variant of TLS 1.3 we are using for this - // configuration. - enum tls13_variant_t tls13_variant; - uint16_t max_send_fragment; // There are 2 BIO's even though they are normally both the same. This is so @@ -2538,14 +2548,18 @@ struct SSLConnection { // session info - // client cert? - // This is used to hold the server certificate used + // This is used to hold the local certificate used (i.e. the server + // certificate for a server or the client certificate for a client). CERT *cert; // initial_timeout_duration_ms is the default DTLS timeout duration in // milliseconds. It's used to initialize the timer any time it's restarted. unsigned initial_timeout_duration_ms; + // tls13_variant is the variant of TLS 1.3 we are using for this + // configuration. + enum tls13_variant_t tls13_variant; + // session is the configured session to be offered by the client. This session // is immutable. SSL_SESSION *session; @@ -2584,6 +2598,7 @@ struct SSLConnection { uint32_t options; // protocol behaviour uint32_t mode; // API behaviour uint32_t max_cert_list; + uint16_t dummy_pq_padding_len; char *tlsext_hostname; size_t supported_group_list_len; uint16_t *supported_group_list; // our list @@ -2608,6 +2623,18 @@ struct SSLConnection { uint8_t *alpn_client_proto_list; unsigned alpn_client_proto_list_len; + // Contains a list of supported Token Binding key parameters. + uint8_t *token_binding_params; + size_t token_binding_params_len; + + // The negotiated Token Binding key parameter. Only valid if + // |token_binding_negotiated| is set. + uint8_t negotiated_token_binding_param; + + // Contains the QUIC transport params that this endpoint will send. + uint8_t *quic_transport_params; + size_t quic_transport_params_len; + // renegotiate_mode controls how peer renegotiation attempts are handled. enum ssl_renegotiate_mode_t renegotiate_mode; @@ -2635,13 +2662,24 @@ struct SSLConnection { // we'll advertise support. bool tlsext_channel_id_enabled:1; + // token_binding_negotiated is set if Token Binding was negotiated. + bool token_binding_negotiated:1; + // retain_only_sha256_of_client_certs is true if we should compute the SHA256 // hash of the peer's certificate and then discard it to save memory and // session space. Only effective on the server side. bool retain_only_sha256_of_client_certs:1; - // early_data_accepted is true if early data was accepted by the server. - bool early_data_accepted:1; + // handoff indicates that a server should stop after receiving the + // ClientHello and pause the handshake in such a way that |SSL_get_error| + // returns |SSL_HANDOFF|. This is copied in |SSL_new| from the |SSL_CTX| + // element of the same name and may be cleared if the handoff is declined. + bool handoff:1; + + // did_dummy_pq_padding is only valid for a client. In that context, it is + // true iff the client observed the server echoing a dummy PQ padding + // extension. + bool did_dummy_pq_padding:1; }; // From draft-ietf-tls-tls13-18, used in determining PSK modes. @@ -2683,6 +2721,11 @@ UniquePtr SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method, CRYPTO_BUFFER_POOL *pool); +// ssl_session_serialize writes |in| to |cbb| as if it were serialising a +// session for Session-ID resumption. It returns one on success and zero on +// error. +int ssl_session_serialize(const SSL_SESSION *in, CBB *cbb); + // ssl_session_is_context_valid returns one if |session|'s session ID context // matches the one set on |ssl| and zero otherwise. int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session); @@ -2826,6 +2869,16 @@ ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed, void dtls1_next_message(SSL *ssl); int dtls1_dispatch_alert(SSL *ssl); +// tls1_configure_aead configures either the read or write direction AEAD (as +// determined by |direction|) using the keys generated by the TLS KDF. The +// |key_block_cache| argument is used to store the generated key block, if +// empty. Otherwise it's assumed that the key block is already contained within +// it. Returns one on success or zero on error. +int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction, + Array *key_block_cache, + const SSL_CIPHER *cipher, + Span iv_override); + int tls1_change_cipher_state(SSL_HANDSHAKE *hs, evp_aead_direction_t direction); int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out, Span premaster); diff --git a/Sources/BoringSSL/ssl/s3_both.cc b/Sources/BoringSSL/ssl/s3_both.cc index ede4ba7ed..9d1218cca 100644 --- a/Sources/BoringSSL/ssl/s3_both.cc +++ b/Sources/BoringSSL/ssl/s3_both.cc @@ -238,8 +238,8 @@ int ssl3_flush_flight(SSL *ssl) { return -1; } - if (ssl->s3->pending_flight->length > 0xffffffff || - ssl->s3->pending_flight->length > INT_MAX) { + static_assert(INT_MAX <= 0xffffffff, "int is larger than 32 bits"); + if (ssl->s3->pending_flight->length > INT_MAX) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } diff --git a/Sources/BoringSSL/ssl/s3_lib.cc b/Sources/BoringSSL/ssl/s3_lib.cc index b925cd72f..a3fc8d7b2 100644 --- a/Sources/BoringSSL/ssl/s3_lib.cc +++ b/Sources/BoringSSL/ssl/s3_lib.cc @@ -175,7 +175,9 @@ SSL3_STATE::SSL3_STATE() send_connection_binding(false), tlsext_channel_id_valid(false), key_update_pending(false), - wpend_pending(false) {} + wpend_pending(false), + early_data_accepted(false), + draft_downgrade(false) {} SSL3_STATE::~SSL3_STATE() {} diff --git a/Sources/BoringSSL/ssl/s3_pkt.cc b/Sources/BoringSSL/ssl/s3_pkt.cc index e6518ba8f..5eb68f6b1 100644 --- a/Sources/BoringSSL/ssl/s3_pkt.cc +++ b/Sources/BoringSSL/ssl/s3_pkt.cc @@ -304,14 +304,6 @@ ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span *out, const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl); if (type == SSL3_RT_HANDSHAKE) { - // If reading 0-RTT data, reject handshake data. 0-RTT data is terminated - // by an alert. - if (!ssl_is_draft21(ssl->version) && is_early_data_read) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); - *out_alert = SSL_AD_UNEXPECTED_MESSAGE; - return ssl_open_record_error; - } - // Post-handshake data prior to TLS 1.3 is always renegotiation, which we // never accept as a server. Otherwise |ssl3_get_message| will send // |SSL_R_EXCESSIVE_MESSAGE_SIZE|. @@ -332,16 +324,6 @@ ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span *out, return ssl_open_record_discard; } - // Handle the end_of_early_data alert. - static const uint8_t kEndOfEarlyData[2] = {SSL3_AL_WARNING, - TLS1_AD_END_OF_EARLY_DATA}; - if (!ssl_is_draft21(ssl->version) && is_early_data_read && - type == SSL3_RT_ALERT && body == kEndOfEarlyData) { - // Stop accepting early data. - ssl->s3->hs->can_early_read = false; - return ssl_open_record_discard; - } - if (type != SSL3_RT_APPLICATION_DATA) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); *out_alert = SSL_AD_UNEXPECTED_MESSAGE; diff --git a/Sources/BoringSSL/ssl/ssl_aead_ctx.cc b/Sources/BoringSSL/ssl/ssl_aead_ctx.cc index 775827c7a..247e889e5 100644 --- a/Sources/BoringSSL/ssl/ssl_aead_ctx.cc +++ b/Sources/BoringSSL/ssl/ssl_aead_ctx.cc @@ -173,10 +173,7 @@ uint16_t SSLAEADContext::RecordVersion() const { return version_; } - if (ssl_is_resumption_record_version_experiment(version_)) { - return TLS1_2_VERSION; - } - return TLS1_VERSION; + return TLS1_2_VERSION; } size_t SSLAEADContext::ExplicitNonceLen() const { diff --git a/Sources/BoringSSL/ssl/ssl_asn1.cc b/Sources/BoringSSL/ssl/ssl_asn1.cc index eb7df5b95..078ad1f48 100644 --- a/Sources/BoringSSL/ssl/ssl_asn1.cc +++ b/Sources/BoringSSL/ssl/ssl_asn1.cc @@ -197,26 +197,23 @@ static const unsigned kAuthTimeoutTag = static const unsigned kEarlyALPNTag = CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26; -static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, - size_t *out_len, int for_ticket) { +static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, CBB *cbb, + int for_ticket) { if (in == NULL || in->cipher == NULL) { return 0; } - ScopedCBB cbb; CBB session, child, child2; - if (!CBB_init(cbb.get(), 0) || - !CBB_add_asn1(cbb.get(), &session, CBS_ASN1_SEQUENCE) || + if (!CBB_add_asn1(cbb, &session, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&session, kVersion) || !CBB_add_asn1_uint64(&session, in->ssl_version) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) || - !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || // The session ID is irrelevant for a session ticket. - !CBB_add_bytes(&child, in->session_id, - for_ticket ? 0 : in->session_id_length) || - !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child, in->master_key, in->master_key_length) || + !CBB_add_asn1_octet_string(&session, in->session_id, + for_ticket ? 0 : in->session_id_length) || + !CBB_add_asn1_octet_string(&session, in->master_key, + in->master_key_length) || !CBB_add_asn1(&session, &child, kTimeTag) || !CBB_add_asn1_uint64(&child, in->time) || !CBB_add_asn1(&session, &child, kTimeoutTag) || @@ -240,8 +237,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, // Although it is OPTIONAL and usually empty, OpenSSL has // historically always encoded the sid_ctx. if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) { + !CBB_add_asn1_octet_string(&child, in->sid_ctx, in->sid_ctx_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -256,9 +252,8 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->psk_identity) { if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity, - strlen(in->psk_identity))) { + !CBB_add_asn1_octet_string(&child, (const uint8_t *)in->psk_identity, + strlen(in->psk_identity))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -274,8 +269,8 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->tlsext_tick && !for_ticket) { if (!CBB_add_asn1(&session, &child, kTicketTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) { + !CBB_add_asn1_octet_string(&child, in->tlsext_tick, + in->tlsext_ticklen)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -283,8 +278,8 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->peer_sha256_valid) { if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) { + !CBB_add_asn1_octet_string(&child, in->peer_sha256, + sizeof(in->peer_sha256))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -292,9 +287,8 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->original_handshake_hash_len > 0) { if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, in->original_handshake_hash, - in->original_handshake_hash_len)) { + !CBB_add_asn1_octet_string(&child, in->original_handshake_hash, + in->original_handshake_hash_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -302,10 +296,9 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->signed_cert_timestamp_list != nullptr) { if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, - CRYPTO_BUFFER_data(in->signed_cert_timestamp_list), - CRYPTO_BUFFER_len(in->signed_cert_timestamp_list))) { + !CBB_add_asn1_octet_string( + &child, CRYPTO_BUFFER_data(in->signed_cert_timestamp_list), + CRYPTO_BUFFER_len(in->signed_cert_timestamp_list))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -313,9 +306,9 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->ocsp_response != nullptr) { if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, CRYPTO_BUFFER_data(in->ocsp_response), - CRYPTO_BUFFER_len(in->ocsp_response))) { + !CBB_add_asn1_octet_string(&child, + CRYPTO_BUFFER_data(in->ocsp_response), + CRYPTO_BUFFER_len(in->ocsp_response))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -323,8 +316,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->extended_master_secret) { if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || - !CBB_add_u8(&child2, 0xff)) { + !CBB_add_asn1_bool(&child, true)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -367,8 +359,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (!in->is_server) { if (!CBB_add_asn1(&session, &child, kIsServerTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || - !CBB_add_u8(&child2, 0x00)) { + !CBB_add_asn1_bool(&child, false)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } @@ -397,19 +388,14 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, if (in->early_alpn) { if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) || - !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn, - in->early_alpn_len)) { + !CBB_add_asn1_octet_string(&child, (const uint8_t *)in->early_alpn, + in->early_alpn_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } } - if (!CBB_finish(cbb.get(), out_data, out_len)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - return 0; - } - return 1; + return CBB_flush(cbb); } // SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING @@ -770,6 +756,10 @@ UniquePtr SSL_SESSION_parse(CBS *cbs, return ret; } +int ssl_session_serialize(const SSL_SESSION *in, CBB *cbb) { + return SSL_SESSION_to_bytes_full(in, cbb, 0); +} + } // namespace bssl using namespace bssl; @@ -792,12 +782,26 @@ int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data, return 1; } - return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0); + ScopedCBB cbb; + if (!CBB_init(cbb.get(), 256) || + !SSL_SESSION_to_bytes_full(in, cbb.get(), 0) || + !CBB_finish(cbb.get(), out_data, out_len)) { + return 0; + } + + return 1; } int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data, size_t *out_len) { - return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1); + ScopedCBB cbb; + if (!CBB_init(cbb.get(), 256) || + !SSL_SESSION_to_bytes_full(in, cbb.get(), 1) || + !CBB_finish(cbb.get(), out_data, out_len)) { + return 0; + } + + return 1; } int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) { diff --git a/Sources/BoringSSL/ssl/ssl_cipher.cc b/Sources/BoringSSL/ssl/ssl_cipher.cc index 87dc7cd1b..32e6c2cdb 100644 --- a/Sources/BoringSSL/ssl/ssl_cipher.cc +++ b/Sources/BoringSSL/ssl/ssl_cipher.cc @@ -4,21 +4,21 @@ * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. - * + * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * + * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +33,10 @@ * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from + * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * + * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -48,7 +48,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence @@ -62,7 +62,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -109,7 +109,7 @@ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * ECC cipher suite support in OpenSSL originally developed by + * ECC cipher suite support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ /* ==================================================================== @@ -1774,4 +1774,8 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) { return 1; } const char *SSL_COMP_get_name(const COMP_METHOD *comp) { return NULL; } +const char *SSL_COMP_get0_name(const SSL_COMP *comp) { return comp->name; } + +int SSL_COMP_get_id(const SSL_COMP *comp) { return comp->id; } + void SSL_COMP_free_compression_methods(void) {} diff --git a/Sources/BoringSSL/ssl/ssl_key_share.cc b/Sources/BoringSSL/ssl/ssl_key_share.cc index a5ae57813..4d76bb233 100644 --- a/Sources/BoringSSL/ssl/ssl_key_share.cc +++ b/Sources/BoringSSL/ssl/ssl_key_share.cc @@ -97,8 +97,10 @@ class ECKeyShare : public SSLKeyShare { return false; } - if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key.data(), + if (peer_key.empty() || peer_key[0] != POINT_CONVERSION_UNCOMPRESSED || + !EC_POINT_oct2point(group.get(), peer_point.get(), peer_key.data(), peer_key.size(), bn_ctx.get())) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT); *out_alert = SSL_AD_DECODE_ERROR; return false; } diff --git a/Sources/BoringSSL/ssl/ssl_lib.cc b/Sources/BoringSSL/ssl/ssl_lib.cc index 122313fa9..ef7983119 100644 --- a/Sources/BoringSSL/ssl/ssl_lib.cc +++ b/Sources/BoringSSL/ssl/ssl_lib.cc @@ -4,21 +4,21 @@ * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. - * + * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * + * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +33,10 @@ * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from + * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * + * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -48,7 +48,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence @@ -62,7 +62,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -109,7 +109,7 @@ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * ECC cipher suite support in OpenSSL originally developed by + * ECC cipher suite support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ /* ==================================================================== @@ -465,6 +465,10 @@ void ssl_ctx_get_current_time(const SSL_CTX *ctx, #endif } +void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on) { + ctx->handoff = on; +} + } // namespace bssl using namespace bssl; @@ -577,12 +581,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) { ret->mode = SSL_MODE_NO_AUTO_CHAIN; // Lock the SSL_CTX to the specified version, for compatibility with legacy - // uses of SSL_METHOD, but we do not set the minimum version for - // |SSLv3_method|. + // uses of SSL_METHOD. if (!SSL_CTX_set_max_proto_version(ret, method->version) || - !SSL_CTX_set_min_proto_version(ret, method->version == SSL3_VERSION - ? 0 // default - : method->version)) { + !SSL_CTX_set_min_proto_version(ret, method->version)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err2; } @@ -736,6 +737,7 @@ SSL *SSL_new(SSL_CTX *ctx) { ssl->signed_cert_timestamps_enabled = ctx->signed_cert_timestamps_enabled; ssl->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled; + ssl->handoff = ctx->handoff; return ssl; @@ -771,6 +773,8 @@ void SSL_free(SSL *ssl) { SSL_CTX_free(ssl->session_ctx); OPENSSL_free(ssl->supported_group_list); OPENSSL_free(ssl->alpn_client_proto_list); + OPENSSL_free(ssl->token_binding_params); + OPENSSL_free(ssl->quic_transport_params); EVP_PKEY_free(ssl->tlsext_channel_id_private); OPENSSL_free(ssl->psk_identity_hint); sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free); @@ -1163,6 +1167,23 @@ int SSL_send_fatal_alert(SSL *ssl, uint8_t alert) { return ssl_send_alert(ssl, SSL3_AL_FATAL, alert); } +int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params, + size_t params_len) { + ssl->quic_transport_params = (uint8_t *)BUF_memdup(params, params_len); + if (!ssl->quic_transport_params) { + return 0; + } + ssl->quic_transport_params_len = params_len; + return 1; +} + +void SSL_get_peer_quic_transport_params(const SSL *ssl, + const uint8_t **out_params, + size_t *out_params_len) { + *out_params = ssl->s3->peer_quic_transport_params.data(); + *out_params_len = ssl->s3->peer_quic_transport_params.size(); +} + void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) { ctx->cert->enable_early_data = !!enabled; } @@ -1187,7 +1208,7 @@ int SSL_in_early_data(const SSL *ssl) { } int SSL_early_data_accepted(const SSL *ssl) { - return ssl->early_data_accepted; + return ssl->s3->early_data_accepted; } void SSL_reset_early_data_reject(SSL *ssl) { @@ -1250,6 +1271,9 @@ int SSL_get_error(const SSL *ssl, int ret_code) { case SSL_CERTIFICATE_SELECTION_PENDING: return SSL_ERROR_PENDING_CERTIFICATE; + case SSL_HANDOFF: + return SSL_ERROR_HANDOFF; + case SSL_READING: { BIO *bio = SSL_get_rbio(ssl); if (BIO_should_read(bio)) { @@ -2122,6 +2146,28 @@ size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) { return 64; } +int SSL_set_token_binding_params(SSL *ssl, const uint8_t *params, size_t len) { + if (len > 256) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + OPENSSL_free(ssl->token_binding_params); + ssl->token_binding_params = (uint8_t *)BUF_memdup(params, len); + if (!ssl->token_binding_params) { + return 0; + } + ssl->token_binding_params_len = len; + return 1; +} + +int SSL_is_token_binding_negotiated(const SSL *ssl) { + return ssl->token_binding_negotiated; +} + +uint8_t SSL_get_negotiated_token_binding_param(const SSL *ssl) { + return ssl->negotiated_token_binding_param; +} + size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) { if (ssl->server || ssl->s3->hs == NULL) { *out_types = NULL; @@ -2385,6 +2431,23 @@ void SSL_CTX_set_psk_server_callback( ctx->psk_server_callback = cb; } +int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes) { + if (num_bytes > 0xffff) { + return 0; + } + + ssl->dummy_pq_padding_len = num_bytes; + return 1; +} + +int SSL_dummy_pq_padding_used(SSL *ssl) { + if (ssl->server) { + return 0; + } + + return ssl->did_dummy_pq_padding; +} + void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, @@ -2567,6 +2630,12 @@ int32_t SSL_get_ticket_age_skew(const SSL *ssl) { return ssl->s3->ticket_age_skew; } +void SSL_CTX_set_false_start_allowed_without_alpn(SSL_CTX *ctx, int allowed) { + ctx->false_start_allowed_without_alpn = !!allowed; +} + +int SSL_is_draft_downgrade(const SSL *ssl) { return ssl->s3->draft_downgrade; } + int SSL_clear(SSL *ssl) { // In OpenSSL, reusing a client |SSL| with |SSL_clear| causes the previously // established session to be offered the next time around. wpa_supplicant diff --git a/Sources/BoringSSL/ssl/ssl_privkey.cc b/Sources/BoringSSL/ssl/ssl_privkey.cc index 134ad561a..33cc720a5 100644 --- a/Sources/BoringSSL/ssl/ssl_privkey.cc +++ b/Sources/BoringSSL/ssl/ssl_privkey.cc @@ -205,6 +205,9 @@ enum ssl_private_key_result_t ssl_private_key_sign( ret = ssl->cert->key_method->sign(ssl, out, out_len, max_out, sigalg, in.data(), in.size()); } + if (ret == ssl_private_key_failure) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED); + } hs->pending_private_key_op = ret == ssl_private_key_retry; return ret; } @@ -241,6 +244,9 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs, ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in.data(), in.size()); } + if (ret == ssl_private_key_failure) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED); + } hs->pending_private_key_op = ret == ssl_private_key_retry; return ret; } diff --git a/Sources/BoringSSL/ssl/ssl_stat.cc b/Sources/BoringSSL/ssl/ssl_stat.cc index 01153e94b..e1677f0aa 100644 --- a/Sources/BoringSSL/ssl/ssl_stat.cc +++ b/Sources/BoringSSL/ssl/ssl_stat.cc @@ -4,21 +4,21 @@ * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. - * + * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * + * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +33,10 @@ * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from + * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * + * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -48,7 +48,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence diff --git a/Sources/BoringSSL/ssl/ssl_versions.cc b/Sources/BoringSSL/ssl/ssl_versions.cc index 15b029433..aeb41d3d1 100644 --- a/Sources/BoringSSL/ssl/ssl_versions.cc +++ b/Sources/BoringSSL/ssl/ssl_versions.cc @@ -34,12 +34,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) { *out = version; return true; - case TLS1_3_DRAFT_VERSION: - case TLS1_3_DRAFT21_VERSION: - case TLS1_3_DRAFT22_VERSION: - case TLS1_3_EXPERIMENT_VERSION: - case TLS1_3_EXPERIMENT2_VERSION: - case TLS1_3_EXPERIMENT3_VERSION: + case TLS1_3_DRAFT23_VERSION: *out = TLS1_3_VERSION; return true; @@ -61,12 +56,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) { // decreasing preference. static const uint16_t kTLSVersions[] = { - TLS1_3_DRAFT22_VERSION, - TLS1_3_EXPERIMENT3_VERSION, - TLS1_3_EXPERIMENT2_VERSION, - TLS1_3_EXPERIMENT_VERSION, - TLS1_3_DRAFT_VERSION, - TLS1_3_DRAFT21_VERSION, + TLS1_3_DRAFT23_VERSION, TLS1_2_VERSION, TLS1_1_VERSION, TLS1_VERSION, @@ -109,12 +99,7 @@ static bool method_supports_version(const SSL_PROTOCOL_METHOD *method, static const char *ssl_version_to_string(uint16_t version) { switch (version) { - case TLS1_3_DRAFT_VERSION: - case TLS1_3_DRAFT21_VERSION: - case TLS1_3_DRAFT22_VERSION: - case TLS1_3_EXPERIMENT_VERSION: - case TLS1_3_EXPERIMENT2_VERSION: - case TLS1_3_EXPERIMENT3_VERSION: + case TLS1_3_DRAFT23_VERSION: return "TLSv1.3"; case TLS1_2_VERSION: @@ -143,12 +128,7 @@ static const char *ssl_version_to_string(uint16_t version) { static uint16_t wire_version_to_api(uint16_t version) { switch (version) { // Report TLS 1.3 draft versions as TLS 1.3 in the public API. - case TLS1_3_DRAFT_VERSION: - case TLS1_3_DRAFT21_VERSION: - case TLS1_3_DRAFT22_VERSION: - case TLS1_3_EXPERIMENT_VERSION: - case TLS1_3_EXPERIMENT2_VERSION: - case TLS1_3_EXPERIMENT3_VERSION: + case TLS1_3_DRAFT23_VERSION: return TLS1_3_VERSION; default: return version; @@ -159,16 +139,11 @@ static uint16_t wire_version_to_api(uint16_t version) { // particular, it picks an arbitrary TLS 1.3 representative. This should only be // used in context where that does not matter. static bool api_version_to_wire(uint16_t *out, uint16_t version) { - if (version == TLS1_3_DRAFT_VERSION || - version == TLS1_3_DRAFT21_VERSION || - version == TLS1_3_DRAFT22_VERSION || - version == TLS1_3_EXPERIMENT_VERSION || - version == TLS1_3_EXPERIMENT2_VERSION || - version == TLS1_3_EXPERIMENT3_VERSION) { + if (version == TLS1_3_DRAFT23_VERSION) { return false; } if (version == TLS1_3_VERSION) { - version = TLS1_3_DRAFT_VERSION; + version = TLS1_3_DRAFT23_VERSION; } // Check it is a real protocol version. @@ -319,34 +294,18 @@ bool ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) { return false; } - // TLS 1.3 variants must additionally match |tls13_variant|. + // This logic is part of the TLS 1.3 variants mechanism used in TLS 1.3 + // experimentation. Although we currently only have one variant, TLS 1.3 does + // not a final stable deployment yet, so leave the logic in place for now. if (protocol_version != TLS1_3_VERSION || - (ssl->tls13_variant == tls13_experiment && - version == TLS1_3_EXPERIMENT_VERSION) || - (ssl->tls13_variant == tls13_experiment2 && - version == TLS1_3_EXPERIMENT2_VERSION) || - (ssl->tls13_variant == tls13_experiment3 && - version == TLS1_3_EXPERIMENT3_VERSION) || - (ssl->tls13_variant == tls13_draft21 && - version == TLS1_3_DRAFT21_VERSION) || - (ssl->tls13_variant == tls13_draft22 && - version == TLS1_3_DRAFT22_VERSION) || (ssl->tls13_variant == tls13_default && - version == TLS1_3_DRAFT_VERSION)) { + version == TLS1_3_DRAFT23_VERSION)) { return true; } // The server, when not configured at |tls13_default|, should additionally - // enable all variants, except draft-21 which is implemented solely for QUIC - // interop testing and will not be deployed, and draft-22 which will be - // enabled once the draft is finalized and ready to be deployed in Chrome. - // Currently, this is to implement the draft-18 vs. experiments field trials. - // In the future, this will be to transition cleanly to a final draft-22 - // which hopefully includes the deployability fixes. - if (ssl->server && - ssl->tls13_variant != tls13_default && - version != TLS1_3_DRAFT21_VERSION && - version != TLS1_3_DRAFT22_VERSION) { + // enable all variants. + if (ssl->server && ssl->tls13_variant != tls13_default) { return true; } @@ -397,38 +356,6 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert, return false; } -bool ssl_is_draft21(uint16_t version) { - return version == TLS1_3_DRAFT21_VERSION || version == TLS1_3_DRAFT22_VERSION; -} - -bool ssl_is_draft22(uint16_t version) { - return version == TLS1_3_DRAFT22_VERSION; -} - -bool ssl_is_resumption_experiment(uint16_t version) { - return version == TLS1_3_EXPERIMENT_VERSION || - version == TLS1_3_EXPERIMENT2_VERSION || - version == TLS1_3_EXPERIMENT3_VERSION || - version == TLS1_3_DRAFT22_VERSION; -} - -bool ssl_is_resumption_variant(enum tls13_variant_t variant) { - return variant == tls13_experiment || variant == tls13_experiment2 || - variant == tls13_experiment3 || variant == tls13_draft22; -} - -bool ssl_is_resumption_client_ccs_experiment(uint16_t version) { - return version == TLS1_3_EXPERIMENT_VERSION || - version == TLS1_3_EXPERIMENT2_VERSION || - version == TLS1_3_DRAFT22_VERSION; -} - -bool ssl_is_resumption_record_version_experiment(uint16_t version) { - return version == TLS1_3_EXPERIMENT2_VERSION || - version == TLS1_3_EXPERIMENT3_VERSION || - version == TLS1_3_DRAFT22_VERSION; -} - } // namespace bssl using namespace bssl; diff --git a/Sources/BoringSSL/ssl/ssl_x509.cc b/Sources/BoringSSL/ssl/ssl_x509.cc index 2b7ba8393..cc27a6016 100644 --- a/Sources/BoringSSL/ssl/ssl_x509.cc +++ b/Sources/BoringSSL/ssl/ssl_x509.cc @@ -354,66 +354,6 @@ static void ssl_crypto_x509_session_clear(SSL_SESSION *session) { session->x509_chain_without_leaf = NULL; } -static int ssl_verify_alarm_type(long type) { - switch (type) { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - case X509_V_ERR_UNABLE_TO_GET_CRL: - case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: - return SSL_AD_UNKNOWN_CA; - - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_CRL_NOT_YET_VALID: - case X509_V_ERR_CERT_UNTRUSTED: - case X509_V_ERR_CERT_REJECTED: - case X509_V_ERR_HOSTNAME_MISMATCH: - case X509_V_ERR_EMAIL_MISMATCH: - case X509_V_ERR_IP_ADDRESS_MISMATCH: - return SSL_AD_BAD_CERTIFICATE; - - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_CRL_SIGNATURE_FAILURE: - return SSL_AD_DECRYPT_ERROR; - - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_CRL_HAS_EXPIRED: - return SSL_AD_CERTIFICATE_EXPIRED; - - case X509_V_ERR_CERT_REVOKED: - return SSL_AD_CERTIFICATE_REVOKED; - - case X509_V_ERR_UNSPECIFIED: - case X509_V_ERR_OUT_OF_MEM: - case X509_V_ERR_INVALID_CALL: - case X509_V_ERR_STORE_LOOKUP: - return SSL_AD_INTERNAL_ERROR; - - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_INVALID_CA: - return SSL_AD_UNKNOWN_CA; - - case X509_V_ERR_APPLICATION_VERIFICATION: - return SSL_AD_HANDSHAKE_FAILURE; - - case X509_V_ERR_INVALID_PURPOSE: - return SSL_AD_UNSUPPORTED_CERTIFICATE; - - default: - return SSL_AD_CERTIFICATE_UNKNOWN; - } -} - static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session, SSL *ssl, uint8_t *out_alert) { @@ -464,7 +404,7 @@ static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session, // If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) { - *out_alert = ssl_verify_alarm_type(ctx->error); + *out_alert = SSL_alert_from_verify_result(ctx->error); return 0; } @@ -1297,3 +1237,61 @@ int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store) { check_ssl_x509_method(ssl); return set_cert_store(&ssl->cert->verify_store, store, 1); } + +int SSL_alert_from_verify_result(long result) { + switch (result) { + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return SSL_AD_UNKNOWN_CA; + + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case X509_V_ERR_CERT_UNTRUSTED: + case X509_V_ERR_CERT_REJECTED: + case X509_V_ERR_HOSTNAME_MISMATCH: + case X509_V_ERR_EMAIL_MISMATCH: + case X509_V_ERR_IP_ADDRESS_MISMATCH: + return SSL_AD_BAD_CERTIFICATE; + + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + return SSL_AD_DECRYPT_ERROR; + + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_CRL_NOT_YET_VALID: + return SSL_AD_CERTIFICATE_EXPIRED; + + case X509_V_ERR_CERT_REVOKED: + return SSL_AD_CERTIFICATE_REVOKED; + + case X509_V_ERR_UNSPECIFIED: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_INVALID_CALL: + case X509_V_ERR_STORE_LOOKUP: + return SSL_AD_INTERNAL_ERROR; + + case X509_V_ERR_APPLICATION_VERIFICATION: + return SSL_AD_HANDSHAKE_FAILURE; + + case X509_V_ERR_INVALID_PURPOSE: + return SSL_AD_UNSUPPORTED_CERTIFICATE; + + default: + return SSL_AD_CERTIFICATE_UNKNOWN; + } +} diff --git a/Sources/BoringSSL/ssl/t1_enc.cc b/Sources/BoringSSL/ssl/t1_enc.cc index 2a099878f..5947627e2 100644 --- a/Sources/BoringSSL/ssl/t1_enc.cc +++ b/Sources/BoringSSL/ssl/t1_enc.cc @@ -148,102 +148,20 @@ #include #include +#include "../crypto/fipsmodule/tls/internal.h" #include "../crypto/internal.h" #include "internal.h" namespace bssl { -// tls1_P_hash computes the TLS P_ function as described in RFC 5246, -// section 5. It XORs |out.size()| bytes to |out|, using |md| as the hash and -// |secret| as the secret. |label|, |seed1|, and |seed2| are concatenated to -// form the seed parameter. It returns true on success and false on failure. -static bool tls1_P_hash(Span out, const EVP_MD *md, - Span secret, Span label, - Span seed1, Span seed2) { - ScopedHMAC_CTX ctx, ctx_tmp, ctx_init; - uint8_t A1[EVP_MAX_MD_SIZE]; - unsigned A1_len; - bool ret = false; - - size_t chunk = EVP_MD_size(md); - - if (!HMAC_Init_ex(ctx_init.get(), secret.data(), secret.size(), md, - nullptr) || - !HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) || - !HMAC_Update(ctx.get(), reinterpret_cast(label.data()), - label.size()) || - !HMAC_Update(ctx.get(), seed1.data(), seed1.size()) || - !HMAC_Update(ctx.get(), seed2.data(), seed2.size()) || - !HMAC_Final(ctx.get(), A1, &A1_len)) { - goto err; - } - - for (;;) { - unsigned len; - uint8_t hmac[EVP_MAX_MD_SIZE]; - if (!HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) || - !HMAC_Update(ctx.get(), A1, A1_len) || - // Save a copy of |ctx| to compute the next A1 value below. - (out.size() > chunk && !HMAC_CTX_copy_ex(ctx_tmp.get(), ctx.get())) || - !HMAC_Update(ctx.get(), reinterpret_cast(label.data()), - label.size()) || - !HMAC_Update(ctx.get(), seed1.data(), seed1.size()) || - !HMAC_Update(ctx.get(), seed2.data(), seed2.size()) || - !HMAC_Final(ctx.get(), hmac, &len)) { - goto err; - } - assert(len == chunk); - - // XOR the result into |out|. - if (len > out.size()) { - len = out.size(); - } - for (unsigned i = 0; i < len; i++) { - out[i] ^= hmac[i]; - } - out = out.subspan(len); - - if (out.empty()) { - break; - } - - // Calculate the next A1 value. - if (!HMAC_Final(ctx_tmp.get(), A1, &A1_len)) { - goto err; - } - } - - ret = true; - -err: - OPENSSL_cleanse(A1, sizeof(A1)); - return ret; -} - bool tls1_prf(const EVP_MD *digest, Span out, Span secret, Span label, Span seed1, Span seed2) { - if (out.empty()) { - return true; - } - - OPENSSL_memset(out.data(), 0, out.size()); - - if (digest == EVP_md5_sha1()) { - // If using the MD5/SHA1 PRF, |secret| is partitioned between MD5 and SHA-1. - size_t secret_half = secret.size() - (secret.size() / 2); - if (!tls1_P_hash(out, EVP_md5(), secret.subspan(0, secret_half), label, - seed1, seed2)) { - return false; - } - - // Note that, if |secret.size()| is odd, the two halves share a byte. - secret = secret.subspan(secret.size() - secret_half); - digest = EVP_sha1(); - } - - return tls1_P_hash(out, digest, secret, label, seed1, seed2); + return 1 == CRYPTO_tls1_prf(digest, out.data(), out.size(), secret.data(), + secret.size(), label.data(), label.size(), + seed1.data(), seed1.size(), seed2.data(), + seed2.size()); } static bool ssl3_prf(Span out, Span secret, @@ -321,42 +239,26 @@ static bool get_key_block_lengths(const SSL *ssl, size_t *out_mac_secret_len, return true; } -static bool setup_key_block(SSL_HANDSHAKE *hs) { - SSL *const ssl = hs->ssl; - if (!hs->key_block.empty()) { - return true; - } - - size_t mac_secret_len, key_len, fixed_iv_len; - Array key_block; - if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &fixed_iv_len, - hs->new_cipher) || - !key_block.Init(2 * (mac_secret_len + key_len + fixed_iv_len)) || - !SSL_generate_key_block(ssl, key_block.data(), key_block.size())) { - return false; - } - - hs->key_block = std::move(key_block); - return true; -} - -int tls1_change_cipher_state(SSL_HANDSHAKE *hs, - evp_aead_direction_t direction) { - SSL *const ssl = hs->ssl; - // Ensure the key block is set up. +int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction, + Array *key_block_cache, + const SSL_CIPHER *cipher, + Span iv_override) { size_t mac_secret_len, key_len, iv_len; - if (!setup_key_block(hs) || - !get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len, - hs->new_cipher)) { + if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len, cipher)) { return 0; } - if ((mac_secret_len + key_len + iv_len) * 2 != hs->key_block.size()) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; + // Ensure that |key_block_cache| is set up. + const size_t key_block_size = 2 * (mac_secret_len + key_len + iv_len); + if (key_block_cache->empty()) { + if (!key_block_cache->Init(key_block_size) || + !SSL_generate_key_block(ssl, key_block_cache->data(), key_block_size)) { + return 0; + } } + assert(key_block_cache->size() == key_block_size); - Span key_block = hs->key_block; + Span key_block = *key_block_cache; Span mac_secret, key, iv; if (direction == (ssl->server ? evp_aead_open : evp_aead_seal)) { // Use the client write (server read) keys. @@ -370,9 +272,15 @@ int tls1_change_cipher_state(SSL_HANDSHAKE *hs, iv = key_block.subspan(2 * mac_secret_len + 2 * key_len + iv_len, iv_len); } - UniquePtr aead_ctx = - SSLAEADContext::Create(direction, ssl->version, SSL_is_dtls(ssl), - hs->new_cipher, key, mac_secret, iv); + if (!iv_override.empty()) { + if (iv_override.size() != iv_len) { + return 0; + } + iv = iv_override; + } + + UniquePtr aead_ctx = SSLAEADContext::Create( + direction, ssl->version, SSL_is_dtls(ssl), cipher, key, mac_secret, iv); if (!aead_ctx) { return 0; } @@ -384,6 +292,12 @@ int tls1_change_cipher_state(SSL_HANDSHAKE *hs, return ssl->method->set_write_state(ssl, std::move(aead_ctx)); } +int tls1_change_cipher_state(SSL_HANDSHAKE *hs, + evp_aead_direction_t direction) { + return tls1_configure_aead(hs->ssl, direction, &hs->key_block, + hs->new_cipher, {}); +} + int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out, Span premaster) { static const char kMasterSecretLabel[] = "master secret"; @@ -458,17 +372,28 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, const uint8_t *context, size_t context_len, int use_context) { if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) { + OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_NOT_COMPLETE); return 0; } - // Exporters may not be used in the middle of a renegotiation. - if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) { + // Exporters may be used in False Start and server 0-RTT, where the handshake + // has progressed enough. Otherwise, they may not be used during a handshake. + if (SSL_in_init(ssl) && + !SSL_in_false_start(ssl) && + !(SSL_is_server(ssl) && SSL_in_early_data(ssl))) { + OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_NOT_COMPLETE); return 0; } if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { - return tls13_export_keying_material(ssl, out, out_len, label, label_len, - context, context_len, use_context); + if (!use_context) { + context = nullptr; + context_len = 0; + } + return tls13_export_keying_material( + ssl, MakeSpan(out, out_len), + MakeConstSpan(ssl->s3->exporter_secret, ssl->s3->exporter_secret_len), + MakeConstSpan(label, label_len), MakeConstSpan(context, context_len)); } size_t seed_len = 2 * SSL3_RANDOM_SIZE; @@ -501,3 +426,27 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, MakeConstSpan(session->master_key, session->master_key_length), MakeConstSpan(label, label_len), seed, {}); } + +int SSL_export_early_keying_material( + SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, + const uint8_t *context, size_t context_len) { + if (!SSL_in_early_data(ssl) && + (!ssl->s3->have_version || + ssl_protocol_version(ssl) < TLS1_3_VERSION)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION); + return 0; + } + + // The early exporter only exists if we accepted early data or offered it as + // a client. + if (!SSL_in_early_data(ssl) && !SSL_early_data_accepted(ssl)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_EARLY_DATA_NOT_IN_USE); + return 0; + } + + return tls13_export_keying_material( + ssl, MakeSpan(out, out_len), + MakeConstSpan(ssl->s3->early_exporter_secret, + ssl->s3->early_exporter_secret_len), + MakeConstSpan(label, label_len), MakeConstSpan(context, context_len)); +} diff --git a/Sources/BoringSSL/ssl/t1_lib.cc b/Sources/BoringSSL/ssl/t1_lib.cc index 8d0362383..97c0c4b9a 100644 --- a/Sources/BoringSSL/ssl/t1_lib.cc +++ b/Sources/BoringSSL/ssl/t1_lib.cc @@ -4,21 +4,21 @@ * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. - * + * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * + * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +33,10 @@ * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from + * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * + * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -48,7 +48,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence @@ -62,7 +62,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -116,6 +116,7 @@ #include #include +#include #include #include #include @@ -463,29 +464,30 @@ static const uint16_t kSignSignatureAlgorithms[] = { SSL_SIGN_RSA_PKCS1_SHA1, }; -int tls12_add_verify_sigalgs(const SSL *ssl, CBB *out) { - const uint16_t *sigalgs = kVerifySignatureAlgorithms; - size_t num_sigalgs = OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms); - if (ssl->ctx->num_verify_sigalgs != 0) { - sigalgs = ssl->ctx->verify_sigalgs; - num_sigalgs = ssl->ctx->num_verify_sigalgs; +bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out) { + bool use_default = ssl->ctx->num_verify_sigalgs == 0; + Span sigalgs = kVerifySignatureAlgorithms; + if (!use_default) { + sigalgs = MakeConstSpan(ssl->ctx->verify_sigalgs, + ssl->ctx->num_verify_sigalgs); } - for (size_t i = 0; i < num_sigalgs; i++) { - if (sigalgs == kVerifySignatureAlgorithms && - sigalgs[i] == SSL_SIGN_ED25519 && + for (uint16_t sigalg : sigalgs) { + if (use_default && + sigalg == SSL_SIGN_ED25519 && !ssl->ctx->ed25519_enabled) { continue; } - if (!CBB_add_u16(out, sigalgs[i])) { - return 0; + if (!CBB_add_u16(out, sigalg)) { + return false; } } - return 1; + return true; } -int tls12_check_peer_sigalg(SSL *ssl, uint8_t *out_alert, uint16_t sigalg) { +bool tls12_check_peer_sigalg(const SSL *ssl, uint8_t *out_alert, + uint16_t sigalg) { const uint16_t *sigalgs = kVerifySignatureAlgorithms; size_t num_sigalgs = OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms); if (ssl->ctx->num_verify_sigalgs != 0) { @@ -500,13 +502,13 @@ int tls12_check_peer_sigalg(SSL *ssl, uint8_t *out_alert, uint16_t sigalg) { continue; } if (sigalg == sigalgs[i]) { - return 1; + return true; } } OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; + return false; } // tls_extension represents a TLS extension that is handled internally. The @@ -1810,7 +1812,6 @@ static bool ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { // selected cipher in HelloRetryRequest does not match. This avoids performing // the transcript hash transformation for multiple hashes. if (hs->received_hello_retry_request && - ssl_is_draft21(ssl->version) && ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) { return true; } @@ -2033,7 +2034,7 @@ static bool ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs, return false; } - ssl->early_data_accepted = true; + ssl->s3->early_data_accepted = true; return true; } @@ -2055,7 +2056,7 @@ static bool ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs, } static bool ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { - if (!hs->ssl->early_data_accepted) { + if (!hs->ssl->s3->early_data_accepted) { return true; } @@ -2103,7 +2104,7 @@ static bool ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { // Add a fake group. See draft-davidben-tls-grease-01. if (ssl->ctx->grease_enabled && (!CBB_add_u16(&kse_bytes, - ssl_get_grease_value(ssl, ssl_grease_group)) || + ssl_get_grease_value(hs, ssl_grease_group)) || !CBB_add_u16(&kse_bytes, 1 /* length */) || !CBB_add_u8(&kse_bytes, 0 /* one byte key share */))) { return false; @@ -2273,7 +2274,7 @@ static bool ext_supported_versions_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) // Add a fake version. See draft-davidben-tls-grease-01. if (ssl->ctx->grease_enabled && - !CBB_add_u16(&versions, ssl_get_grease_value(ssl, ssl_grease_version))) { + !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) { return false; } @@ -2310,6 +2311,79 @@ static bool ext_cookie_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { } +// Dummy PQ Padding extension +// +// Dummy post-quantum padding invovles the client (and later server) sending +// useless, random-looking bytes in an extension in their ClientHello or +// ServerHello. These extensions are sized to simulate a post-quantum +// key-exchange and so enable measurement of the latency impact of the +// additional bandwidth. + +static bool ext_dummy_pq_padding_add(CBB *out, size_t len) { + CBB contents; + uint8_t *buffer; + if (!CBB_add_u16(out, TLSEXT_TYPE_dummy_pq_padding) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_space(&contents, &buffer, len)) { + return false; + } + + // The length is used as the nonce so that different length extensions have + // different contents. There's no reason this has to be the case, it just + // makes things a little more obvious in a packet dump. + uint8_t nonce[12] = {0}; + memcpy(nonce, &len, sizeof(len)); + + memset(buffer, 0, len); + static const uint8_t kZeroKey[32] = {0}; + CRYPTO_chacha_20(buffer, buffer, len, kZeroKey, nonce, 0); + + return CBB_flush(out); +} + +static bool ext_dummy_pq_padding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { + const size_t len = hs->ssl->dummy_pq_padding_len; + if (len == 0) { + return true; + } + + return ext_dummy_pq_padding_add(out, len); +} + +static bool ext_dummy_pq_padding_parse_serverhello(SSL_HANDSHAKE *hs, + uint8_t *out_alert, + CBS *contents) { + if (contents == nullptr) { + return true; + } + + if (CBS_len(contents) != hs->ssl->dummy_pq_padding_len) { + return false; + } + + hs->ssl->did_dummy_pq_padding = true; + return true; +} + +static bool ext_dummy_pq_padding_parse_clienthello(SSL_HANDSHAKE *hs, + uint8_t *out_alert, + CBS *contents) { + if (contents != nullptr && + 0 < CBS_len(contents) && CBS_len(contents) < (1 << 12)) { + hs->dummy_pq_padding_len = CBS_len(contents); + } + + return true; +} + +static bool ext_dummy_pq_padding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { + if (!hs->dummy_pq_padding_len) { + return true; + } + + return ext_dummy_pq_padding_add(out, hs->dummy_pq_padding_len); +} + // Negotiated Groups // // https://tools.ietf.org/html/rfc4492#section-5.1.2 @@ -2327,7 +2401,7 @@ static bool ext_supported_groups_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { // Add a fake group. See draft-davidben-tls-grease-01. if (ssl->ctx->grease_enabled && !CBB_add_u16(&groups_bytes, - ssl_get_grease_value(ssl, ssl_grease_group))) { + ssl_get_grease_value(hs, ssl_grease_group))) { return false; } @@ -2389,6 +2463,224 @@ static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs, return true; } +// Token Binding +// +// https://tools.ietf.org/html/draft-ietf-tokbind-negotiation-10 + +// The Token Binding version number currently matches the draft number of +// draft-ietf-tokbind-protocol, and when published as an RFC it will be 0x0100. +// Since there are no wire changes to the protocol from draft 13 through the +// current draft (16), this implementation supports all versions in that range. +static uint16_t kTokenBindingMaxVersion = 16; +static uint16_t kTokenBindingMinVersion = 13; + +static bool ext_token_binding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { + SSL *const ssl = hs->ssl; + if (ssl->token_binding_params == nullptr || SSL_is_dtls(ssl)) { + return true; + } + + CBB contents, params; + if (!CBB_add_u16(out, TLSEXT_TYPE_token_binding) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16(&contents, kTokenBindingMaxVersion) || + !CBB_add_u8_length_prefixed(&contents, ¶ms) || + !CBB_add_bytes(¶ms, ssl->token_binding_params, + ssl->token_binding_params_len) || + !CBB_flush(out)) { + return false; + } + + return true; +} + +static bool ext_token_binding_parse_serverhello(SSL_HANDSHAKE *hs, + uint8_t *out_alert, + CBS *contents) { + SSL *const ssl = hs->ssl; + if (contents == nullptr) { + return true; + } + + CBS params_list; + uint16_t version; + uint8_t param; + if (!CBS_get_u16(contents, &version) || + !CBS_get_u8_length_prefixed(contents, ¶ms_list) || + !CBS_get_u8(¶ms_list, ¶m) || + CBS_len(¶ms_list) > 0 || + CBS_len(contents) > 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return false; + } + + // The server-negotiated version must be less than or equal to our version. + if (version > kTokenBindingMaxVersion) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return false; + } + + // If the server-selected version is less than what we support, then Token + // Binding wasn't negotiated (but the extension was parsed successfully). + if (version < kTokenBindingMinVersion) { + return true; + } + + for (size_t i = 0; i < ssl->token_binding_params_len; ++i) { + if (param == ssl->token_binding_params[i]) { + ssl->negotiated_token_binding_param = param; + ssl->token_binding_negotiated = true; + return true; + } + } + + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return false; +} + +// select_tb_param looks for the first token binding param in +// |ssl->token_binding_params| that is also in |params| and puts it in +// |ssl->negotiated_token_binding_param|. It returns true if a token binding +// param is found, and false otherwise. +static bool select_tb_param(SSL *ssl, Span peer_params) { + for (size_t i = 0; i < ssl->token_binding_params_len; ++i) { + uint8_t tb_param = ssl->token_binding_params[i]; + for (uint8_t peer_param : peer_params) { + if (tb_param == peer_param) { + ssl->negotiated_token_binding_param = tb_param; + return true; + } + } + } + return false; +} + +static bool ext_token_binding_parse_clienthello(SSL_HANDSHAKE *hs, + uint8_t *out_alert, + CBS *contents) { + SSL *const ssl = hs->ssl; + if (contents == nullptr || ssl->token_binding_params == nullptr) { + return true; + } + + CBS params; + uint16_t version; + if (!CBS_get_u16(contents, &version) || + !CBS_get_u8_length_prefixed(contents, ¶ms) || + CBS_len(¶ms) == 0 || + CBS_len(contents) > 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return false; + } + + // If the client-selected version is less than what we support, then Token + // Binding wasn't negotiated (but the extension was parsed successfully). + if (version < kTokenBindingMinVersion) { + return true; + } + + // If the client-selected version is higher than we support, use our max + // version. Otherwise, use the client's version. + hs->negotiated_token_binding_version = + std::min(version, kTokenBindingMaxVersion); + if (!select_tb_param(ssl, params)) { + return true; + } + + ssl->token_binding_negotiated = true; + return true; +} + +static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { + SSL *const ssl = hs->ssl; + + if (!ssl->token_binding_negotiated) { + return true; + } + + CBB contents, params; + if (!CBB_add_u16(out, TLSEXT_TYPE_token_binding) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16(&contents, hs->negotiated_token_binding_version) || + !CBB_add_u8_length_prefixed(&contents, ¶ms) || + !CBB_add_u8(¶ms, ssl->negotiated_token_binding_param) || + !CBB_flush(out)) { + return false; + } + + return true; +} + +// QUIC Transport Parameters + +static bool ext_quic_transport_params_add_clienthello(SSL_HANDSHAKE *hs, + CBB *out) { + SSL *const ssl = hs->ssl; + if (!ssl->quic_transport_params || hs->max_version <= TLS1_2_VERSION) { + return true; + } + + CBB contents; + if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_bytes(&contents, ssl->quic_transport_params, + ssl->quic_transport_params_len) || + !CBB_flush(out)) { + return false; + } + return true; +} + +static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs, + uint8_t *out_alert, + CBS *contents) { + SSL *const ssl = hs->ssl; + if (contents == nullptr) { + return true; + } + // QUIC requires TLS 1.3. + if (ssl_protocol_version(ssl) < TLS1_3_VERSION) { + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + return false; + } + + return ssl->s3->peer_quic_transport_params.CopyFrom(*contents); +} + +static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs, + uint8_t *out_alert, + CBS *contents) { + SSL *const ssl = hs->ssl; + if (!contents || !ssl->quic_transport_params) { + return true; + } + // Ignore the extension before TLS 1.3. + if (ssl_protocol_version(ssl) < TLS1_3_VERSION) { + return true; + } + + return ssl->s3->peer_quic_transport_params.CopyFrom(*contents); +} + +static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs, + CBB *out) { + SSL *const ssl = hs->ssl; + if (!ssl->quic_transport_params) { + return true; + } + + CBB contents; + if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_bytes(&contents, ssl->quic_transport_params, + ssl->quic_transport_params_len) || + !CBB_flush(out)) { + return false; + } + + return true; +} + // kExtensions contains all the supported extensions. static const struct tls_extension kExtensions[] = { @@ -2530,6 +2822,22 @@ static const struct tls_extension kExtensions[] = { ignore_parse_clienthello, dont_add_serverhello, }, + { + TLSEXT_TYPE_dummy_pq_padding, + NULL, + ext_dummy_pq_padding_add_clienthello, + ext_dummy_pq_padding_parse_serverhello, + ext_dummy_pq_padding_parse_clienthello, + ext_dummy_pq_padding_add_serverhello, + }, + { + TLSEXT_TYPE_quic_transport_parameters, + NULL, + ext_quic_transport_params_add_clienthello, + ext_quic_transport_params_parse_serverhello, + ext_quic_transport_params_parse_clienthello, + ext_quic_transport_params_add_serverhello, + }, // The final extension must be non-empty. WebSphere Application Server 7.0 is // intolerant to the last extension being zero-length. See // https://crbug.com/363583. @@ -2541,6 +2849,14 @@ static const struct tls_extension kExtensions[] = { ext_supported_groups_parse_clienthello, dont_add_serverhello, }, + { + TLSEXT_TYPE_token_binding, + NULL, + ext_token_binding_add_clienthello, + ext_token_binding_parse_serverhello, + ext_token_binding_parse_clienthello, + ext_token_binding_add_serverhello, + }, }; #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension)) @@ -2591,7 +2907,7 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { uint16_t grease_ext1 = 0; if (ssl->ctx->grease_enabled) { // Add a fake empty extension. See draft-davidben-tls-grease-01. - grease_ext1 = ssl_get_grease_value(ssl, ssl_grease_extension1); + grease_ext1 = ssl_get_grease_value(hs, ssl_grease_extension1); if (!CBB_add_u16(&extensions, grease_ext1) || !CBB_add_u16(&extensions, 0 /* zero length */)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); @@ -2619,7 +2935,7 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { if (ssl->ctx->grease_enabled) { // Add a fake non-empty extension. See draft-davidben-tls-grease-01. - uint16_t grease_ext2 = ssl_get_grease_value(ssl, ssl_grease_extension2); + uint16_t grease_ext2 = ssl_get_grease_value(hs, ssl_grease_extension2); // The two fake extensions must not have the same value. GREASE values are // of the form 0x1a1a, 0x2a2a, 0x3a3a, etc., so XOR to generate a different @@ -2903,6 +3219,15 @@ static int ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs, static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; + + if (ssl->token_binding_negotiated && + !(SSL_get_secure_renegotiation_support(ssl) && + SSL_get_extms_support(ssl))) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); + return -1; + } + int ret = SSL_TLSEXT_ERR_NOACK; int al = SSL_AD_UNRECOGNIZED_NAME; @@ -3138,29 +3463,29 @@ enum ssl_ticket_aead_result_t ssl_process_ticket( return ssl_ticket_aead_success; } -int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) { +bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) { // Extension ignored for inappropriate versions if (ssl_protocol_version(hs->ssl) < TLS1_2_VERSION) { - return 1; + return true; } return parse_u16_array(in_sigalgs, &hs->peer_sigalgs); } -int tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) { +bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) { switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_RSA: *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1; - return 1; + return true; case EVP_PKEY_EC: *out = SSL_SIGN_ECDSA_SHA1; - return 1; + return true; default: - return 0; + return false; } } -int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { +bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { SSL *const ssl = hs->ssl; CERT *cert = ssl->cert; @@ -3169,9 +3494,9 @@ int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { if (ssl_protocol_version(ssl) < TLS1_2_VERSION) { if (!tls1_get_legacy_signature_algorithm(out, hs->local_pubkey.get())) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); - return 0; + return false; } - return 1; + return true; } Span sigalgs = kSignSignatureAlgorithms; @@ -3200,13 +3525,13 @@ int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { for (uint16_t peer_sigalg : peer_sigalgs) { if (sigalg == peer_sigalg) { *out = sigalg; - return 1; + return true; } } } OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); - return 0; + return false; } int tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) { @@ -3264,6 +3589,7 @@ int tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) { int sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get()); #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) sig_ok = 1; + ERR_clear_error(); #endif if (!sig_ok) { OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID); diff --git a/Sources/BoringSSL/ssl/tls13_both.cc b/Sources/BoringSSL/ssl/tls13_both.cc index 57acbcba6..2a5a93574 100644 --- a/Sources/BoringSSL/ssl/tls13_both.cc +++ b/Sources/BoringSSL/ssl/tls13_both.cc @@ -43,6 +43,14 @@ const uint8_t kHelloRetryRequest[SSL3_RANDOM_SIZE] = { 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, }; +// This value was selected by truncating the SHA-256 hash of "Draft TLS 1.3 +// Downgrade" to 8 bytes: +// +// echo -n 'Draft TLS 1.3 Downgrade' | sha256sum | head -c 16 +const uint8_t kDraftDowngradeRandom[8] = {0x95, 0xb9, 0x9f, 0x87, + 0x22, 0xfe, 0x9b, 0x64}; + + bool tls13_get_cert_verify_signature_input( SSL_HANDSHAKE *hs, Array *out, enum ssl_cert_verify_context_t cert_verify_context) { diff --git a/Sources/BoringSSL/ssl/tls13_client.cc b/Sources/BoringSSL/ssl/tls13_client.cc index 688fa061f..aa0545634 100644 --- a/Sources/BoringSSL/ssl/tls13_client.cc +++ b/Sources/BoringSSL/ssl/tls13_client.cc @@ -58,82 +58,62 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) { return ssl_hs_read_message; } - CBS extensions; - uint16_t cipher_suite = 0; - if (ssl_is_draft22(ssl->version)) { - // Queue up a ChangeCipherSpec for whenever we next send something. This - // will be before the second ClientHello. If we offered early data, this was - // already done. - if (!hs->early_data_offered && - !ssl->method->add_change_cipher_spec(ssl)) { - return ssl_hs_error; - } - - if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { - return ssl_hs_error; - } + // Queue up a ChangeCipherSpec for whenever we next send something. This + // will be before the second ClientHello. If we offered early data, this was + // already done. + if (!hs->early_data_offered && + !ssl->method->add_change_cipher_spec(ssl)) { + return ssl_hs_error; + } - CBS body = msg.body, server_random, session_id; - uint16_t server_version; - if (!CBS_get_u16(&body, &server_version) || - !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&body, &session_id) || - !CBS_get_u16(&body, &cipher_suite) || - !CBS_skip(&body, 1) || - !CBS_get_u16_length_prefixed(&body, &extensions) || - CBS_len(&extensions) == 0 || - CBS_len(&body) != 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } + if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { + return ssl_hs_error; + } - if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { - hs->tls13_state = state_read_server_hello; - return ssl_hs_ok; - } - } else { - if (msg.type != SSL3_MT_HELLO_RETRY_REQUEST) { - hs->tls13_state = state_read_server_hello; - return ssl_hs_ok; - } + CBS body = msg.body, extensions, server_random, session_id; + uint16_t server_version, cipher_suite; + uint8_t compression_method; + if (!CBS_get_u16(&body, &server_version) || + !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&body, &session_id) || + !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) || + !CBS_get_u16(&body, &cipher_suite) || + !CBS_get_u8(&body, &compression_method) || + compression_method != 0 || + !CBS_get_u16_length_prefixed(&body, &extensions) || + CBS_len(&extensions) == 0 || + CBS_len(&body) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return ssl_hs_error; + } - CBS body = msg.body; - uint16_t server_version; - if (!CBS_get_u16(&body, &server_version) || - (ssl_is_draft21(ssl->version) && - !CBS_get_u16(&body, &cipher_suite)) || - !CBS_get_u16_length_prefixed(&body, &extensions) || - CBS_len(&body) != 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } + if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { + hs->tls13_state = state_read_server_hello; + return ssl_hs_ok; } - if (ssl_is_draft21(ssl->version)) { - const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); - // Check if the cipher is a TLS 1.3 cipher. - if (cipher == NULL || - SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) || - SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); - return ssl_hs_error; - } + const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); + // Check if the cipher is a TLS 1.3 cipher. + if (cipher == NULL || + SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) || + SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return ssl_hs_error; + } - hs->new_cipher = cipher; + hs->new_cipher = cipher; - if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) || - !hs->transcript.UpdateForHelloRetryRequest()) { - return ssl_hs_error; - } + if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) || + !hs->transcript.UpdateForHelloRetryRequest()) { + return ssl_hs_error; } bool have_cookie, have_key_share, have_supported_versions; CBS cookie, key_share, supported_versions; - const SSL_EXTENSION_TYPE ext_types[] = { + SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_key_share, &have_key_share, &key_share}, {TLSEXT_TYPE_cookie, &have_cookie, &cookie}, {TLSEXT_TYPE_supported_versions, &have_supported_versions, @@ -148,11 +128,6 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (!ssl_is_draft22(ssl->version) && have_supported_versions) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); - return ssl_hs_error; - } if (!have_cookie && !have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_EMPTY_HELLO_RETRY_REQUEST); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); @@ -250,11 +225,11 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { uint8_t compression_method; if (!CBS_get_u16(&body, &server_version) || !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) || - (ssl_is_resumption_experiment(ssl->version) && - !CBS_get_u8_length_prefixed(&body, &session_id)) || + !CBS_get_u8_length_prefixed(&body, &session_id) || + !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) || !CBS_get_u16(&body, &cipher_suite) || - (ssl_is_resumption_experiment(ssl->version) && - (!CBS_get_u8(&body, &compression_method) || compression_method != 0)) || + !CBS_get_u8(&body, &compression_method) || + compression_method != 0 || !CBS_get_u16_length_prefixed(&body, &extensions) || CBS_len(&body) != 0) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -262,18 +237,14 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - uint16_t expected_version = ssl_is_resumption_experiment(ssl->version) - ? TLS1_2_VERSION - : ssl->version; - if (server_version != expected_version) { + if (server_version != TLS1_2_VERSION) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); return ssl_hs_error; } // Forbid a second HelloRetryRequest. - if (ssl_is_draft22(ssl->version) && - CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { + if (CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); return ssl_hs_error; @@ -293,8 +264,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { } // Check that the cipher matches the one in the HelloRetryRequest. - if (ssl_is_draft21(ssl->version) && - hs->received_hello_retry_request && + if (hs->received_hello_retry_request && hs->new_cipher != cipher) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); @@ -305,7 +275,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { bool have_key_share = false, have_pre_shared_key = false, have_supported_versions = false; CBS key_share, pre_shared_key, supported_versions; - const SSL_EXTENSION_TYPE ext_types[] = { + SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_key_share, &have_key_share, &key_share}, {TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key}, {TLSEXT_TYPE_supported_versions, &have_supported_versions, @@ -320,14 +290,6 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - // supported_versions is parsed in handshake_client to select the experimental - // TLS 1.3 version. - if (have_supported_versions && !ssl_is_resumption_experiment(ssl->version)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); - return ssl_hs_error; - } - alert = SSL_AD_DECODE_ERROR; if (have_pre_shared_key) { if (ssl->session == NULL) { @@ -420,14 +382,6 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { } if (!hs->early_data_offered) { - // Earlier versions of the resumption experiment added ChangeCipherSpec just - // before the Finished flight. - if (ssl_is_resumption_client_ccs_experiment(ssl->version) && - !ssl_is_draft22(ssl->version) && - !ssl->method->add_change_cipher_spec(ssl)) { - return ssl_hs_error; - } - // If not sending early data, set client traffic keys now so that alerts are // encrypted. if (!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret, @@ -473,7 +427,7 @@ static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) { hs->new_session->early_alpn_len = ssl->s3->alpn_selected.size(); } - if (ssl->early_data_accepted) { + if (ssl->s3->early_data_accepted) { if (hs->early_session->cipher != hs->new_session->cipher || MakeConstSpan(hs->early_session->early_alpn, hs->early_session->early_alpn_len) != @@ -481,7 +435,8 @@ static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) { OPENSSL_PUT_ERROR(SSL, SSL_R_ALPN_MISMATCH_ON_EARLY_DATA); return ssl_hs_error; } - if (ssl->s3->tlsext_channel_id_valid || hs->received_custom_extension) { + if (ssl->s3->tlsext_channel_id_valid || hs->received_custom_extension || + ssl->token_binding_negotiated) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION_ON_EARLY_DATA); return ssl_hs_error; } @@ -493,7 +448,7 @@ static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) { ssl->method->next_message(ssl); hs->tls13_state = state_read_certificate_request; - if (hs->in_early_data && !ssl->early_data_accepted) { + if (hs->in_early_data && !ssl->s3->early_data_accepted) { return ssl_hs_early_data_rejected; } return ssl_hs_ok; @@ -519,75 +474,45 @@ static enum ssl_hs_wait_t do_read_certificate_request(SSL_HANDSHAKE *hs) { } - if (ssl_is_draft21(ssl->version)) { - bool have_sigalgs = false, have_ca = false; - CBS sigalgs, ca; - const SSL_EXTENSION_TYPE ext_types[] = { - {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs}, - {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca}, - }; - - CBS body = msg.body, context, extensions, supported_signature_algorithms; - uint8_t alert = SSL_AD_DECODE_ERROR; - if (!CBS_get_u8_length_prefixed(&body, &context) || - // The request context is always empty during the handshake. - CBS_len(&context) != 0 || - !CBS_get_u16_length_prefixed(&body, &extensions) || - CBS_len(&body) != 0 || - !ssl_parse_extensions(&extensions, &alert, ext_types, - OPENSSL_ARRAY_SIZE(ext_types), - 1 /* accept unknown */) || - (have_ca && CBS_len(&ca) == 0) || - !have_sigalgs || - !CBS_get_u16_length_prefixed(&sigalgs, - &supported_signature_algorithms) || - CBS_len(&supported_signature_algorithms) == 0 || - !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { - ssl_send_alert(ssl, SSL3_AL_FATAL, alert); - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - return ssl_hs_error; - } + bool have_sigalgs = false, have_ca = false; + CBS sigalgs, ca; + const SSL_EXTENSION_TYPE ext_types[] = { + {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs}, + {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca}, + }; - if (have_ca) { - hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca); - if (!hs->ca_names) { - ssl_send_alert(ssl, SSL3_AL_FATAL, alert); - return ssl_hs_error; - } - } else { - hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null()); - if (!hs->ca_names) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - return ssl_hs_error; - } - } - } else { - CBS body = msg.body, context, supported_signature_algorithms; - if (!CBS_get_u8_length_prefixed(&body, &context) || - // The request context is always empty during the handshake. - CBS_len(&context) != 0 || - !CBS_get_u16_length_prefixed(&body, &supported_signature_algorithms) || - CBS_len(&supported_signature_algorithms) == 0 || - !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - return ssl_hs_error; - } + CBS body = msg.body, context, extensions, supported_signature_algorithms; + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!CBS_get_u8_length_prefixed(&body, &context) || + // The request context is always empty during the handshake. + CBS_len(&context) != 0 || + !CBS_get_u16_length_prefixed(&body, &extensions) || + CBS_len(&body) != 0 || + !ssl_parse_extensions(&extensions, &alert, ext_types, + OPENSSL_ARRAY_SIZE(ext_types), + 1 /* accept unknown */) || + (have_ca && CBS_len(&ca) == 0) || + !have_sigalgs || + !CBS_get_u16_length_prefixed(&sigalgs, + &supported_signature_algorithms) || + CBS_len(&supported_signature_algorithms) == 0 || + !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return ssl_hs_error; + } - uint8_t alert = SSL_AD_DECODE_ERROR; - hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &body); + if (have_ca) { + hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca); if (!hs->ca_names) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } - - // Ignore extensions. - CBS extensions; - if (!CBS_get_u16_length_prefixed(&body, &extensions) || - CBS_len(&body) != 0) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + } else { + hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null()); + if (!hs->ca_names) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } } @@ -672,21 +597,14 @@ static enum ssl_hs_wait_t do_read_server_finished(SSL_HANDSHAKE *hs) { static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - if (ssl->early_data_accepted) { + if (ssl->s3->early_data_accepted) { hs->can_early_write = false; - if (ssl_is_draft21(ssl->version)) { - ScopedCBB cbb; - CBB body; - if (!ssl->method->init_message(ssl, cbb.get(), &body, - SSL3_MT_END_OF_EARLY_DATA) || - !ssl_add_message_cbb(ssl, cbb.get())) { - return ssl_hs_error; - } - } else { - if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING, - TLS1_AD_END_OF_EARLY_DATA)) { - return ssl_hs_error; - } + ScopedCBB cbb; + CBB body; + if (!ssl->method->init_message(ssl, cbb.get(), &body, + SSL3_MT_END_OF_EARLY_DATA) || + !ssl_add_message_cbb(ssl, cbb.get())) { + return ssl_hs_error; } } @@ -913,8 +831,7 @@ int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) { CBS body = msg.body, ticket_nonce, ticket, extensions; if (!CBS_get_u32(&body, &server_timeout) || !CBS_get_u32(&body, &session->ticket_age_add) || - (ssl_is_draft21(ssl->version) && - !CBS_get_u8_length_prefixed(&body, &ticket_nonce)) || + !CBS_get_u8_length_prefixed(&body, &ticket_nonce) || !CBS_get_u16_length_prefixed(&body, &ticket) || !CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) || !CBS_get_u16_length_prefixed(&body, &extensions) || @@ -937,11 +854,8 @@ int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) { // Parse out the extensions. bool have_early_data_info = false; CBS early_data_info; - uint16_t ext_id = ssl_is_draft21(ssl->version) - ? TLSEXT_TYPE_early_data - : TLSEXT_TYPE_ticket_early_data_info; const SSL_EXTENSION_TYPE ext_types[] = { - {ext_id, &have_early_data_info, &early_data_info}, + {TLSEXT_TYPE_early_data, &have_early_data_info, &early_data_info}, }; uint8_t alert = SSL_AD_DECODE_ERROR; diff --git a/Sources/BoringSSL/ssl/tls13_enc.cc b/Sources/BoringSSL/ssl/tls13_enc.cc index 14f4a7879..cc7afb8d3 100644 --- a/Sources/BoringSSL/ssl/tls13_enc.cc +++ b/Sources/BoringSSL/ssl/tls13_enc.cc @@ -66,13 +66,11 @@ int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *psk, psk_len, hs->secret, hs->hash_len); } -static int hkdf_expand_label(uint8_t *out, uint16_t version, - const EVP_MD *digest, const uint8_t *secret, - size_t secret_len, const uint8_t *label, - size_t label_len, const uint8_t *hash, - size_t hash_len, size_t len) { - const char *kTLS13LabelVersion = - ssl_is_draft21(version) ? "tls13 " : "TLS 1.3, "; +static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, + const char *label, size_t label_len, + const uint8_t *hash, size_t hash_len, size_t len) { + static const char kTLS13LabelVersion[] = "tls13 "; ScopedCBB cbb; CBB child; @@ -84,7 +82,7 @@ static int hkdf_expand_label(uint8_t *out, uint16_t version, !CBB_add_u8_length_prefixed(cbb.get(), &child) || !CBB_add_bytes(&child, (const uint8_t *)kTLS13LabelVersion, strlen(kTLS13LabelVersion)) || - !CBB_add_bytes(&child, label, label_len) || + !CBB_add_bytes(&child, (const uint8_t *)label, label_len) || !CBB_add_u8_length_prefixed(cbb.get(), &child) || !CBB_add_bytes(&child, hash, hash_len) || !CBB_finish(cbb.get(), &hkdf_label, &hkdf_label_len)) { @@ -101,24 +99,18 @@ static const char kTLS13LabelDerived[] = "derived"; int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in, size_t len) { - SSL *const ssl = hs->ssl; - - // Draft 18 does not include the extra Derive-Secret step. - if (ssl_is_draft21(ssl->version)) { - uint8_t derive_context[EVP_MAX_MD_SIZE]; - unsigned derive_context_len; - if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len, - hs->transcript.Digest(), nullptr)) { - return 0; - } + uint8_t derive_context[EVP_MAX_MD_SIZE]; + unsigned derive_context_len; + if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len, + hs->transcript.Digest(), nullptr)) { + return 0; + } - if (!hkdf_expand_label(hs->secret, ssl->version, hs->transcript.Digest(), - hs->secret, hs->hash_len, - (const uint8_t *)kTLS13LabelDerived, - strlen(kTLS13LabelDerived), derive_context, - derive_context_len, hs->hash_len)) { - return 0; - } + if (!hkdf_expand_label(hs->secret, hs->transcript.Digest(), hs->secret, + hs->hash_len, kTLS13LabelDerived, + strlen(kTLS13LabelDerived), derive_context, + derive_context_len, hs->hash_len)) { + return 0; } return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in, @@ -129,17 +121,16 @@ int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in, // with the given label and the current base secret and most recently-saved // handshake context. It returns one on success and zero on error. static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len, - const uint8_t *label, size_t label_len) { + const char *label, size_t label_len) { uint8_t context_hash[EVP_MAX_MD_SIZE]; size_t context_hash_len; if (!hs->transcript.GetHash(context_hash, &context_hash_len)) { return 0; } - return hkdf_expand_label(out, SSL_get_session(hs->ssl)->ssl_version, - hs->transcript.Digest(), hs->secret, hs->hash_len, - label, label_len, context_hash, context_hash_len, - len); + return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret, + hs->hash_len, label, label_len, context_hash, + context_hash_len, len); } int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction, @@ -166,18 +157,16 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction, // Derive the key. size_t key_len = EVP_AEAD_key_length(aead); uint8_t key[EVP_AEAD_MAX_KEY_LENGTH]; - if (!hkdf_expand_label(key, session->ssl_version, digest, traffic_secret, - traffic_secret_len, (const uint8_t *)"key", 3, NULL, 0, - key_len)) { + if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, "key", + 3, NULL, 0, key_len)) { return 0; } // Derive the IV. size_t iv_len = EVP_AEAD_nonce_length(aead); uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH]; - if (!hkdf_expand_label(iv, session->ssl_version, digest, traffic_secret, - traffic_secret_len, (const uint8_t *)"iv", 2, NULL, 0, - iv_len)) { + if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, "iv", + 2, NULL, 0, iv_len)) { return 0; } @@ -213,63 +202,42 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction, return 1; } -static const char kTLS13LabelExporter[] = "exporter master secret"; -static const char kTLS13LabelEarlyExporter[] = "early exporter master secret"; - -static const char kTLS13LabelClientEarlyTraffic[] = - "client early traffic secret"; -static const char kTLS13LabelClientHandshakeTraffic[] = - "client handshake traffic secret"; -static const char kTLS13LabelServerHandshakeTraffic[] = - "server handshake traffic secret"; -static const char kTLS13LabelClientApplicationTraffic[] = - "client application traffic secret"; -static const char kTLS13LabelServerApplicationTraffic[] = - "server application traffic secret"; - -static const char kTLS13Draft21LabelExporter[] = "exp master"; -static const char kTLS13Draft21LabelEarlyExporter[] = "e exp master"; - -static const char kTLS13Draft21LabelClientEarlyTraffic[] = "c e traffic"; -static const char kTLS13Draft21LabelClientHandshakeTraffic[] = "c hs traffic"; -static const char kTLS13Draft21LabelServerHandshakeTraffic[] = "s hs traffic"; -static const char kTLS13Draft21LabelClientApplicationTraffic[] = "c ap traffic"; -static const char kTLS13Draft21LabelServerApplicationTraffic[] = "s ap traffic"; + +static const char kTLS13LabelExporter[] = "exp master"; +static const char kTLS13LabelEarlyExporter[] = "e exp master"; + +static const char kTLS13LabelClientEarlyTraffic[] = "c e traffic"; +static const char kTLS13LabelClientHandshakeTraffic[] = "c hs traffic"; +static const char kTLS13LabelServerHandshakeTraffic[] = "s hs traffic"; +static const char kTLS13LabelClientApplicationTraffic[] = "c ap traffic"; +static const char kTLS13LabelServerApplicationTraffic[] = "s ap traffic"; int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - uint16_t version = SSL_get_session(ssl)->ssl_version; - - const char *early_traffic_label = ssl_is_draft21(version) - ? kTLS13Draft21LabelClientEarlyTraffic - : kTLS13LabelClientEarlyTraffic; - const char *early_exporter_label = ssl_is_draft21(version) - ? kTLS13Draft21LabelEarlyExporter - : kTLS13LabelEarlyExporter; - return derive_secret(hs, hs->early_traffic_secret, hs->hash_len, - (const uint8_t *)early_traffic_label, - strlen(early_traffic_label)) && - ssl_log_secret(ssl, "CLIENT_EARLY_TRAFFIC_SECRET", - hs->early_traffic_secret, hs->hash_len) && - derive_secret(hs, ssl->s3->early_exporter_secret, hs->hash_len, - (const uint8_t *)early_exporter_label, - strlen(early_exporter_label)); + if (!derive_secret(hs, hs->early_traffic_secret, hs->hash_len, + kTLS13LabelClientEarlyTraffic, + strlen(kTLS13LabelClientEarlyTraffic)) || + !ssl_log_secret(ssl, "CLIENT_EARLY_TRAFFIC_SECRET", + hs->early_traffic_secret, hs->hash_len) || + !derive_secret(hs, ssl->s3->early_exporter_secret, hs->hash_len, + kTLS13LabelEarlyExporter, + strlen(kTLS13LabelEarlyExporter))) { + return 0; + } + ssl->s3->early_exporter_secret_len = hs->hash_len; + return 1; } int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - const char *client_label = ssl_is_draft21(ssl->version) - ? kTLS13Draft21LabelClientHandshakeTraffic - : kTLS13LabelClientHandshakeTraffic; - const char *server_label = ssl_is_draft21(ssl->version) - ? kTLS13Draft21LabelServerHandshakeTraffic - : kTLS13LabelServerHandshakeTraffic; return derive_secret(hs, hs->client_handshake_secret, hs->hash_len, - (const uint8_t *)client_label, strlen(client_label)) && + kTLS13LabelClientHandshakeTraffic, + strlen(kTLS13LabelClientHandshakeTraffic)) && ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET", hs->client_handshake_secret, hs->hash_len) && derive_secret(hs, hs->server_handshake_secret, hs->hash_len, - (const uint8_t *)server_label, strlen(server_label)) && + kTLS13LabelServerHandshakeTraffic, + strlen(kTLS13LabelServerHandshakeTraffic)) && ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET", hs->server_handshake_secret, hs->hash_len); } @@ -277,33 +245,23 @@ int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) { int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; ssl->s3->exporter_secret_len = hs->hash_len; - const char *client_label = ssl_is_draft21(ssl->version) - ? kTLS13Draft21LabelClientApplicationTraffic - : kTLS13LabelClientApplicationTraffic; - const char *server_label = ssl_is_draft21(ssl->version) - ? kTLS13Draft21LabelServerApplicationTraffic - : kTLS13LabelServerApplicationTraffic; - const char *exporter_label = ssl_is_draft21(ssl->version) - ? kTLS13Draft21LabelExporter - : kTLS13LabelExporter; return derive_secret(hs, hs->client_traffic_secret_0, hs->hash_len, - (const uint8_t *)client_label, strlen(client_label)) && + kTLS13LabelClientApplicationTraffic, + strlen(kTLS13LabelClientApplicationTraffic)) && ssl_log_secret(ssl, "CLIENT_TRAFFIC_SECRET_0", hs->client_traffic_secret_0, hs->hash_len) && derive_secret(hs, hs->server_traffic_secret_0, hs->hash_len, - (const uint8_t *)server_label, strlen(server_label)) && + kTLS13LabelServerApplicationTraffic, + strlen(kTLS13LabelServerApplicationTraffic)) && ssl_log_secret(ssl, "SERVER_TRAFFIC_SECRET_0", hs->server_traffic_secret_0, hs->hash_len) && derive_secret(hs, ssl->s3->exporter_secret, hs->hash_len, - (const uint8_t *)exporter_label, - strlen(exporter_label)) && + kTLS13LabelExporter, strlen(kTLS13LabelExporter)) && ssl_log_secret(ssl, "EXPORTER_SECRET", ssl->s3->exporter_secret, hs->hash_len); } -static const char kTLS13LabelApplicationTraffic[] = - "application traffic secret"; -static const char kTLS13Draft21LabelApplicationTraffic[] = "traffic upd"; +static const char kTLS13LabelApplicationTraffic[] = "traffic upd"; int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) { uint8_t *secret; @@ -316,35 +274,27 @@ int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) { secret_len = ssl->s3->write_traffic_secret_len; } - const char *traffic_label = ssl_is_draft21(ssl->version) - ? kTLS13Draft21LabelApplicationTraffic - : kTLS13LabelApplicationTraffic; - const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl)); - if (!hkdf_expand_label(secret, ssl->version, digest, secret, secret_len, - (const uint8_t *)traffic_label, strlen(traffic_label), - NULL, 0, secret_len)) { + if (!hkdf_expand_label( + secret, digest, secret, secret_len, kTLS13LabelApplicationTraffic, + strlen(kTLS13LabelApplicationTraffic), NULL, 0, secret_len)) { return 0; } return tls13_set_traffic_key(ssl, direction, secret, secret_len); } -static const char kTLS13LabelResumption[] = "resumption master secret"; -static const char kTLS13Draft21LabelResumption[] = "res master"; +static const char kTLS13LabelResumption[] = "res master"; int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) { if (hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } - const char *resumption_label = ssl_is_draft21(hs->ssl->version) - ? kTLS13Draft21LabelResumption - : kTLS13LabelResumption; hs->new_session->master_key_length = hs->hash_len; - return derive_secret( - hs, hs->new_session->master_key, hs->new_session->master_key_length, - (const uint8_t *)resumption_label, strlen(resumption_label)); + return derive_secret(hs, hs->new_session->master_key, + hs->new_session->master_key_length, + kTLS13LabelResumption, strlen(kTLS13LabelResumption)); } static const char kTLS13LabelFinished[] = "finished"; @@ -357,8 +307,7 @@ static int tls13_verify_data(const EVP_MD *digest, uint16_t version, uint8_t *context, size_t context_len) { uint8_t key[EVP_MAX_MD_SIZE]; unsigned len; - if (!hkdf_expand_label(key, version, digest, secret, hash_len, - (const uint8_t *)kTLS13LabelFinished, + if (!hkdf_expand_label(key, digest, secret, hash_len, kTLS13LabelFinished, strlen(kTLS13LabelFinished), NULL, 0, hash_len) || HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) { return 0; @@ -390,37 +339,23 @@ int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, static const char kTLS13LabelResumptionPSK[] = "resumption"; bool tls13_derive_session_psk(SSL_SESSION *session, Span nonce) { - if (!ssl_is_draft21(session->ssl_version)) { - return true; - } - const EVP_MD *digest = ssl_session_get_digest(session); - return hkdf_expand_label(session->master_key, session->ssl_version, digest, - session->master_key, session->master_key_length, - (const uint8_t *)kTLS13LabelResumptionPSK, + return hkdf_expand_label(session->master_key, digest, session->master_key, + session->master_key_length, kTLS13LabelResumptionPSK, strlen(kTLS13LabelResumptionPSK), nonce.data(), nonce.size(), session->master_key_length); } static const char kTLS13LabelExportKeying[] = "exporter"; -int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, - const char *label, size_t label_len, - const uint8_t *context_in, - size_t context_in_len, int use_context) { - const uint8_t *context = NULL; - size_t context_len = 0; - if (use_context) { - context = context_in; - context_len = context_in_len; - } - - if (!ssl_is_draft21(ssl->version)) { - const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl)); - return hkdf_expand_label( - out, ssl->version, digest, ssl->s3->exporter_secret, - ssl->s3->exporter_secret_len, (const uint8_t *)label, label_len, - context, context_len, out_len); +int tls13_export_keying_material(SSL *ssl, Span out, + Span secret, + Span label, + Span context) { + if (secret.empty()) { + assert(0); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl)); @@ -431,22 +366,20 @@ int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, unsigned hash_len; unsigned export_context_len; unsigned derived_secret_len = EVP_MD_size(digest); - if (!EVP_Digest(context, context_len, hash, &hash_len, digest, NULL) || - !EVP_Digest(NULL, 0, export_context, &export_context_len, digest, NULL)) { - return 0; - } - return hkdf_expand_label( - derived_secret, ssl->version, digest, ssl->s3->exporter_secret, - ssl->s3->exporter_secret_len, (const uint8_t *)label, label_len, - export_context, export_context_len, derived_secret_len) && - hkdf_expand_label( - out, ssl->version, digest, derived_secret, derived_secret_len, - (const uint8_t *)kTLS13LabelExportKeying, - strlen(kTLS13LabelExportKeying), hash, hash_len, out_len); + return EVP_Digest(context.data(), context.size(), hash, &hash_len, digest, + nullptr) && + EVP_Digest(nullptr, 0, export_context, &export_context_len, digest, + nullptr) && + hkdf_expand_label(derived_secret, digest, secret.data(), secret.size(), + label.data(), label.size(), export_context, + export_context_len, derived_secret_len) && + hkdf_expand_label(out.data(), digest, derived_secret, + derived_secret_len, kTLS13LabelExportKeying, + strlen(kTLS13LabelExportKeying), hash, hash_len, + out.size()); } -static const char kTLS13LabelPSKBinder[] = "resumption psk binder key"; -static const char kTLS13Draft21LabelPSKBinder[] = "res binder"; +static const char kTLS13LabelPSKBinder[] = "res binder"; static int tls13_psk_binder(uint8_t *out, uint16_t version, const EVP_MD *digest, uint8_t *psk, size_t psk_len, @@ -464,14 +397,11 @@ static int tls13_psk_binder(uint8_t *out, uint16_t version, NULL, 0)) { return 0; } - const char *binder_label = ssl_is_draft21(version) - ? kTLS13Draft21LabelPSKBinder - : kTLS13LabelPSKBinder; uint8_t binder_key[EVP_MAX_MD_SIZE] = {0}; size_t len; - if (!hkdf_expand_label(binder_key, version, digest, early_secret, hash_len, - (const uint8_t *)binder_label, strlen(binder_label), + if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len, + kTLS13LabelPSKBinder, strlen(kTLS13LabelPSKBinder), binder_context, binder_context_len, hash_len) || !tls13_verify_data(digest, version, out, &len, binder_key, hash_len, context, context_len)) { diff --git a/Sources/BoringSSL/ssl/tls13_server.cc b/Sources/BoringSSL/ssl/tls13_server.cc index 1040ace03..3bd67866f 100644 --- a/Sources/BoringSSL/ssl/tls13_server.cc +++ b/Sources/BoringSSL/ssl/tls13_server.cc @@ -182,9 +182,8 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) { SSL3_MT_NEW_SESSION_TICKET) || !CBB_add_u32(&body, session->timeout) || !CBB_add_u32(&body, session->ticket_age_add) || - (ssl_is_draft21(ssl->version) && - (!CBB_add_u8_length_prefixed(&body, &nonce_cbb) || - !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)))) || + !CBB_add_u8_length_prefixed(&body, &nonce_cbb) || + !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) || !CBB_add_u16_length_prefixed(&body, &ticket) || !tls13_derive_session_psk(session.get(), nonce) || !ssl_encrypt_ticket(ssl, &ticket, session.get()) || @@ -194,9 +193,7 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) { if (ssl->cert->enable_early_data) { CBB early_data_info; - if (!CBB_add_u16(&extensions, ssl_is_draft21(ssl->version) - ? TLSEXT_TYPE_early_data - : TLSEXT_TYPE_ticket_early_data_info) || + if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) || !CBB_add_u16_length_prefixed(&extensions, &early_data_info) || !CBB_add_u32(&early_data_info, session->ticket_max_early_data) || !CBB_flush(&extensions)) { @@ -206,7 +203,7 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) { // Add a fake extension. See draft-davidben-tls-grease-01. if (!CBB_add_u16(&extensions, - ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) || + ssl_get_grease_value(hs, ssl_grease_ticket_extension)) || !CBB_add_u16(&extensions, 0 /* empty */)) { return 0; } @@ -393,12 +390,14 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { hs->early_data_offered && // Channel ID is incompatible with 0-RTT. !ssl->s3->tlsext_channel_id_valid && + // If Token Binding is negotiated, reject 0-RTT. + !ssl->token_binding_negotiated && // Custom extensions is incompatible with 0-RTT. hs->custom_extensions.received == 0 && // The negotiated ALPN must match the one in the ticket. ssl->s3->alpn_selected == MakeConstSpan(session->early_alpn, session->early_alpn_len)) { - ssl->early_data_accepted = true; + ssl->s3->early_data_accepted = true; } if (hs->new_session == NULL) { @@ -457,7 +456,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (ssl->early_data_accepted) { + if (ssl->s3->early_data_accepted) { if (!tls13_derive_early_secrets(hs)) { return ssl_hs_error; } @@ -469,11 +468,10 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { bool need_retry; if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) { if (need_retry) { - ssl->early_data_accepted = false; + ssl->s3->early_data_accepted = false; ssl->s3->skip_early_data = true; ssl->method->next_message(ssl); - if (ssl_is_draft21(ssl->version) && - !hs->transcript.UpdateForHelloRetryRequest()) { + if (!hs->transcript.UpdateForHelloRetryRequest()) { return ssl_hs_error; } hs->tls13_state = state_send_hello_retry_request; @@ -491,50 +489,30 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - if (ssl_is_draft22(ssl->version)) { - ScopedCBB cbb; - CBB body, session_id, extensions; - uint16_t group_id; - if (!ssl->method->init_message(ssl, cbb.get(), &body, - SSL3_MT_SERVER_HELLO) || - !CBB_add_u16(&body, TLS1_2_VERSION) || - !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) || - !CBB_add_u8_length_prefixed(&body, &session_id) || - !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || - !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) || - !CBB_add_u8(&body, 0 /* no compression */) || - !tls1_get_shared_group(hs, &group_id) || - !CBB_add_u16_length_prefixed(&body, &extensions) || - !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) || - !CBB_add_u16(&extensions, 2 /* length */) || - !CBB_add_u16(&extensions, ssl->version) || - !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) || - !CBB_add_u16(&extensions, 2 /* length */) || - !CBB_add_u16(&extensions, group_id) || - !ssl_add_message_cbb(ssl, cbb.get())) { - return ssl_hs_error; - } + ScopedCBB cbb; + CBB body, session_id, extensions; + uint16_t group_id; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) || + !CBB_add_u16(&body, TLS1_2_VERSION) || + !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) || + !CBB_add_u8_length_prefixed(&body, &session_id) || + !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || + !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) || + !CBB_add_u8(&body, 0 /* no compression */) || + !tls1_get_shared_group(hs, &group_id) || + !CBB_add_u16_length_prefixed(&body, &extensions) || + !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) || + !CBB_add_u16(&extensions, 2 /* length */) || + !CBB_add_u16(&extensions, ssl->version) || + !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) || + !CBB_add_u16(&extensions, 2 /* length */) || + !CBB_add_u16(&extensions, group_id) || + !ssl_add_message_cbb(ssl, cbb.get())) { + return ssl_hs_error; + } - if (!ssl->method->add_change_cipher_spec(ssl)) { - return ssl_hs_error; - } - } else { - ScopedCBB cbb; - CBB body, extensions; - uint16_t group_id; - if (!ssl->method->init_message(ssl, cbb.get(), &body, - SSL3_MT_HELLO_RETRY_REQUEST) || - !CBB_add_u16(&body, ssl->version) || - (ssl_is_draft21(ssl->version) && - !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) || - !tls1_get_shared_group(hs, &group_id) || - !CBB_add_u16_length_prefixed(&body, &extensions) || - !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) || - !CBB_add_u16(&extensions, 2 /* length */) || - !CBB_add_u16(&extensions, group_id) || - !ssl_add_message_cbb(ssl, cbb.get())) { - return ssl_hs_error; - } + if (!ssl->method->add_change_cipher_spec(ssl)) { + return ssl_hs_error; } hs->sent_hello_retry_request = true; @@ -580,34 +558,26 @@ static enum ssl_hs_wait_t do_read_second_client_hello(SSL_HANDSHAKE *hs) { static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - uint16_t version = ssl->version; - if (ssl_is_resumption_experiment(ssl->version)) { - version = TLS1_2_VERSION; - } - // Send a ServerHello. ScopedCBB cbb; CBB body, extensions, session_id; if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) || - !CBB_add_u16(&body, version) || + !CBB_add_u16(&body, TLS1_2_VERSION) || !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) || !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) || - (ssl_is_resumption_experiment(ssl->version) && - (!CBB_add_u8_length_prefixed(&body, &session_id) || - !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len))) || + !CBB_add_u8_length_prefixed(&body, &session_id) || + !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) || - (ssl_is_resumption_experiment(ssl->version) && !CBB_add_u8(&body, 0)) || + !CBB_add_u8(&body, 0) || !CBB_add_u16_length_prefixed(&body, &extensions) || !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || !ssl_ext_key_share_add_serverhello(hs, &extensions) || - (ssl_is_resumption_experiment(ssl->version) && - !ssl_ext_supported_versions_add_serverhello(hs, &extensions)) || + !ssl_ext_supported_versions_add_serverhello(hs, &extensions) || !ssl_add_message_cbb(ssl, cbb.get())) { return ssl_hs_error; } - if (ssl_is_resumption_experiment(ssl->version) && - (!ssl_is_draft22(ssl->version) || !hs->sent_hello_retry_request) && + if (!hs->sent_hello_retry_request && !ssl->method->add_change_cipher_spec(ssl)) { return ssl_hs_error; } @@ -639,48 +609,34 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { // Send a CertificateRequest, if necessary. if (hs->cert_request) { - if (ssl_is_draft21(ssl->version)) { - CBB cert_request_extensions, sigalg_contents, sigalgs_cbb; - if (!ssl->method->init_message(ssl, cbb.get(), &body, - SSL3_MT_CERTIFICATE_REQUEST) || - !CBB_add_u8(&body, 0 /* no certificate_request_context. */) || - !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) || - !CBB_add_u16(&cert_request_extensions, - TLSEXT_TYPE_signature_algorithms) || + CBB cert_request_extensions, sigalg_contents, sigalgs_cbb; + if (!ssl->method->init_message(ssl, cbb.get(), &body, + SSL3_MT_CERTIFICATE_REQUEST) || + !CBB_add_u8(&body, 0 /* no certificate_request_context. */) || + !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) || + !CBB_add_u16(&cert_request_extensions, + TLSEXT_TYPE_signature_algorithms) || + !CBB_add_u16_length_prefixed(&cert_request_extensions, + &sigalg_contents) || + !CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) || + !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) { + return ssl_hs_error; + } + + if (ssl_has_client_CAs(ssl)) { + CBB ca_contents; + if (!CBB_add_u16(&cert_request_extensions, + TLSEXT_TYPE_certificate_authorities) || !CBB_add_u16_length_prefixed(&cert_request_extensions, - &sigalg_contents) || - !CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) || - !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) { + &ca_contents) || + !ssl_add_client_CA_list(ssl, &ca_contents) || + !CBB_flush(&cert_request_extensions)) { return ssl_hs_error; } + } - if (ssl_has_client_CAs(ssl)) { - CBB ca_contents; - if (!CBB_add_u16(&cert_request_extensions, - TLSEXT_TYPE_certificate_authorities) || - !CBB_add_u16_length_prefixed(&cert_request_extensions, - &ca_contents) || - !ssl_add_client_CA_list(ssl, &ca_contents) || - !CBB_flush(&cert_request_extensions)) { - return ssl_hs_error; - } - } - - if (!ssl_add_message_cbb(ssl, cbb.get())) { - return ssl_hs_error; - } - } else { - CBB sigalgs_cbb; - if (!ssl->method->init_message(ssl, cbb.get(), &body, - SSL3_MT_CERTIFICATE_REQUEST) || - !CBB_add_u8(&body, 0 /* no certificate_request_context. */) || - !CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) || - !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) || - !ssl_add_client_CA_list(ssl, &body) || - !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) || - !ssl_add_message_cbb(ssl, cbb.get())) { - return ssl_hs_error; - } + if (!ssl_add_message_cbb(ssl, cbb.get())) { + return ssl_hs_error; } } @@ -732,18 +688,16 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (ssl->early_data_accepted) { + if (ssl->s3->early_data_accepted) { // If accepting 0-RTT, we send tickets half-RTT. This gets the tickets on // the wire sooner and also avoids triggering a write on |SSL_read| when // processing the client Finished. This requires computing the client // Finished early. See draft-ietf-tls-tls13-18, section 4.5.1. - if (ssl_is_draft21(ssl->version)) { - static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0, - 0, 0}; - if (!hs->transcript.Update(kEndOfEarlyData)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return ssl_hs_error; - } + static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0, + 0, 0}; + if (!hs->transcript.Update(kEndOfEarlyData)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return ssl_hs_error; } size_t finished_len; @@ -780,7 +734,7 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - if (ssl->early_data_accepted) { + if (ssl->s3->early_data_accepted) { if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->early_traffic_secret, hs->hash_len)) { return ssl_hs_error; @@ -790,7 +744,8 @@ static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) { hs->in_early_data = true; } hs->tls13_state = state_process_end_of_early_data; - return ssl->early_data_accepted ? ssl_hs_read_end_of_early_data : ssl_hs_ok; + return ssl->s3->early_data_accepted ? ssl_hs_read_end_of_early_data + : ssl_hs_ok; } static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) { @@ -798,31 +753,30 @@ static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) { if (hs->early_data_offered) { // If early data was not accepted, the EndOfEarlyData and ChangeCipherSpec // message will be in the discarded early data. - if (hs->ssl->early_data_accepted) { - if (ssl_is_draft21(ssl->version)) { - SSLMessage msg; - if (!ssl->method->get_message(ssl, &msg)) { - return ssl_hs_read_message; - } - - if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) { - return ssl_hs_error; - } - if (CBS_len(&msg.body) != 0) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - return ssl_hs_error; - } - ssl->method->next_message(ssl); + if (hs->ssl->s3->early_data_accepted) { + SSLMessage msg; + if (!ssl->method->get_message(ssl, &msg)) { + return ssl_hs_read_message; } + + if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) { + return ssl_hs_error; + } + if (CBS_len(&msg.body) != 0) { + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return ssl_hs_error; + } + ssl->method->next_message(ssl); } } if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, hs->hash_len)) { return ssl_hs_error; } - hs->tls13_state = ssl->early_data_accepted ? state_read_client_finished - : state_read_client_certificate; + hs->tls13_state = ssl->s3->early_data_accepted + ? state_read_client_finished + : state_read_client_certificate; return ssl_hs_ok; } @@ -921,14 +875,14 @@ static enum ssl_hs_wait_t do_read_client_finished(SSL_HANDSHAKE *hs) { if (!ssl_check_message_type(ssl, msg, SSL3_MT_FINISHED) || // If early data was accepted, we've already computed the client Finished // and derived the resumption secret. - !tls13_process_finished(hs, msg, ssl->early_data_accepted) || + !tls13_process_finished(hs, msg, ssl->s3->early_data_accepted) || // evp_aead_seal keys have already been switched. !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0, hs->hash_len)) { return ssl_hs_error; } - if (!ssl->early_data_accepted) { + if (!ssl->s3->early_data_accepted) { if (!ssl_hash_message(hs, msg) || !tls13_derive_resumption_secret(hs)) { return ssl_hs_error; diff --git a/Sources/BoringSSL/ssl/tls_method.cc b/Sources/BoringSSL/ssl/tls_method.cc index 4eacf646f..2ad2817c6 100644 --- a/Sources/BoringSSL/ssl/tls_method.cc +++ b/Sources/BoringSSL/ssl/tls_method.cc @@ -231,15 +231,6 @@ const SSL_METHOD *TLSv1_method(void) { return &kMethod; } -const SSL_METHOD *SSLv3_method(void) { - static const SSL_METHOD kMethod = { - SSL3_VERSION, - &kTLSProtocolMethod, - &ssl_crypto_x509_method, - }; - return &kMethod; -} - // Legacy side-specific methods. const SSL_METHOD *TLSv1_2_server_method(void) { @@ -254,10 +245,6 @@ const SSL_METHOD *TLSv1_server_method(void) { return TLSv1_method(); } -const SSL_METHOD *SSLv3_server_method(void) { - return SSLv3_method(); -} - const SSL_METHOD *TLSv1_2_client_method(void) { return TLSv1_2_method(); } @@ -270,10 +257,6 @@ const SSL_METHOD *TLSv1_client_method(void) { return TLSv1_method(); } -const SSL_METHOD *SSLv3_client_method(void) { - return SSLv3_method(); -} - const SSL_METHOD *SSLv23_server_method(void) { return SSLv23_method(); } diff --git a/Sources/BoringSSL/ssl/tls_record.cc b/Sources/BoringSSL/ssl/tls_record.cc index a1363fa6f..05a3d569d 100644 --- a/Sources/BoringSSL/ssl/tls_record.cc +++ b/Sources/BoringSSL/ssl/tls_record.cc @@ -264,7 +264,7 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, *out_consumed = in.size() - CBS_len(&cbs); if (ssl->s3->have_version && - ssl_is_resumption_experiment(ssl->version) && + ssl_protocol_version(ssl) >= TLS1_3_VERSION && SSL_in_init(ssl) && type == SSL3_RT_CHANGE_CIPHER_SPEC && ciphertext_len == 1 && @@ -356,15 +356,6 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, } if (type == SSL3_RT_ALERT) { - // Return end_of_early_data alerts as-is for the caller to process. - if (!ssl_is_draft21(ssl->version) && - out->size() == 2 && - (*out)[0] == SSL3_AL_WARNING && - (*out)[1] == TLS1_AD_END_OF_EARLY_DATA) { - *out_type = type; - return ssl_open_record_success; - } - return ssl_process_alert(ssl, out_alert, *out); } diff --git a/Sources/BoringSSL/third_party/fiat/curve25519.c b/Sources/BoringSSL/third_party/fiat/curve25519.c index d54aa839e..0fdf1d930 100644 --- a/Sources/BoringSSL/third_party/fiat/curve25519.c +++ b/Sources/BoringSSL/third_party/fiat/curve25519.c @@ -36,13 +36,17 @@ #include #include #include +#include #include "internal.h" #include "../../crypto/internal.h" -static const int64_t kBottom25Bits = INT64_C(0x1ffffff); -static const int64_t kBottom26Bits = INT64_C(0x3ffffff); +// Various pre-computed constants. +#include "./curve25519_tables.h" + + +// Low-level intrinsic operations (hand-written). static uint64_t load_3(const uint8_t *in) { uint64_t result; @@ -61,6 +65,568 @@ static uint64_t load_4(const uint8_t *in) { return result; } +#if defined(BORINGSSL_CURVE25519_64BIT) +static uint64_t load_8(const uint8_t *in) { + uint64_t result; + result = (uint64_t)in[0]; + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + result |= ((uint64_t)in[3]) << 24; + result |= ((uint64_t)in[4]) << 32; + result |= ((uint64_t)in[5]) << 40; + result |= ((uint64_t)in[6]) << 48; + result |= ((uint64_t)in[7]) << 56; + return result; +} + +static uint8_t /*bool*/ addcarryx_u51(uint8_t /*bool*/ c, uint64_t a, + uint64_t b, uint64_t *low) { + // This function extracts 51 bits of result and 1 bit of carry (52 total), so + // a 64-bit intermediate is sufficient. + uint64_t x = a + b + c; + *low = x & ((UINT64_C(1) << 51) - 1); + return (x >> 51) & 1; +} + +static uint8_t /*bool*/ subborrow_u51(uint8_t /*bool*/ c, uint64_t a, + uint64_t b, uint64_t *low) { + // This function extracts 51 bits of result and 1 bit of borrow (52 total), so + // a 64-bit intermediate is sufficient. + uint64_t x = a - b - c; + *low = x & ((UINT64_C(1) << 51) - 1); + return x >> 63; +} + +static uint64_t cmovznz64(uint64_t t, uint64_t z, uint64_t nz) { + t = -!!t; // all set if nonzero, 0 if 0 + return (t&nz) | ((~t)&z); +} + +#else + +static uint8_t /*bool*/ addcarryx_u25(uint8_t /*bool*/ c, uint32_t a, + uint32_t b, uint32_t *low) { + // This function extracts 25 bits of result and 1 bit of carry (26 total), so + // a 32-bit intermediate is sufficient. + uint32_t x = a + b + c; + *low = x & ((1 << 25) - 1); + return (x >> 25) & 1; +} + +static uint8_t /*bool*/ addcarryx_u26(uint8_t /*bool*/ c, uint32_t a, + uint32_t b, uint32_t *low) { + // This function extracts 26 bits of result and 1 bit of carry (27 total), so + // a 32-bit intermediate is sufficient. + uint32_t x = a + b + c; + *low = x & ((1 << 26) - 1); + return (x >> 26) & 1; +} + +static uint8_t /*bool*/ subborrow_u25(uint8_t /*bool*/ c, uint32_t a, + uint32_t b, uint32_t *low) { + // This function extracts 25 bits of result and 1 bit of borrow (26 total), so + // a 32-bit intermediate is sufficient. + uint32_t x = a - b - c; + *low = x & ((1 << 25) - 1); + return x >> 31; +} + +static uint8_t /*bool*/ subborrow_u26(uint8_t /*bool*/ c, uint32_t a, + uint32_t b, uint32_t *low) { + // This function extracts 26 bits of result and 1 bit of borrow (27 total), so + // a 32-bit intermediate is sufficient. + uint32_t x = a - b - c; + *low = x & ((1 << 26) - 1); + return x >> 31; +} + +static uint32_t cmovznz32(uint32_t t, uint32_t z, uint32_t nz) { + t = -!!t; // all set if nonzero, 0 if 0 + return (t&nz) | ((~t)&z); +} + +#endif + + +// Field operations. + +#if defined(BORINGSSL_CURVE25519_64BIT) + +#define assert_fe(f) do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i< 5; _assert_fe_i++) { \ + assert(f[_assert_fe_i] < 1.125*(UINT64_C(1)<<51)); \ + } \ +} while (0) + +#define assert_fe_loose(f) do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i< 5; _assert_fe_i++) { \ + assert(f[_assert_fe_i] < 3.375*(UINT64_C(1)<<51)); \ + } \ +} while (0) + +#define assert_fe_frozen(f) do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i< 5; _assert_fe_i++) { \ + assert(f[_assert_fe_i] < (UINT64_C(1)<<51)); \ + } \ +} while (0) + +static void fe_frombytes_impl(uint64_t h[5], const uint8_t *s) { + // Ignores top bit of s. + uint64_t a0 = load_8(s); + uint64_t a1 = load_8(s+8); + uint64_t a2 = load_8(s+16); + uint64_t a3 = load_8(s+24); + // Use 51 bits, 64-51 = 13 left. + h[0] = a0 & ((UINT64_C(1) << 51) - 1); + // (64-51) + 38 = 13 + 38 = 51 + h[1] = (a0 >> 51) | ((a1 & ((UINT64_C(1) << 38) - 1)) << 13); + // (64-38) + 25 = 26 + 25 = 51 + h[2] = (a1 >> 38) | ((a2 & ((UINT64_C(1) << 25) - 1)) << 26); + // (64-25) + 12 = 39 + 12 = 51 + h[3] = (a2 >> 25) | ((a3 & ((UINT64_C(1) << 12) - 1)) << 39); + // (64-12) = 52, ignore top bit + h[4] = (a3 >> 12) & ((UINT64_C(1) << 51) - 1); + assert_fe(h); +} + +static void fe_frombytes(fe *h, const uint8_t *s) { + fe_frombytes_impl(h->v, s); +} + +static void fe_freeze(uint64_t out[5], const uint64_t in1[5]) { + { const uint64_t x7 = in1[4]; + { const uint64_t x8 = in1[3]; + { const uint64_t x6 = in1[2]; + { const uint64_t x4 = in1[1]; + { const uint64_t x2 = in1[0]; + { uint64_t x10; uint8_t/*bool*/ x11 = subborrow_u51(0x0, x2, 0x7ffffffffffed, &x10); + { uint64_t x13; uint8_t/*bool*/ x14 = subborrow_u51(x11, x4, 0x7ffffffffffff, &x13); + { uint64_t x16; uint8_t/*bool*/ x17 = subborrow_u51(x14, x6, 0x7ffffffffffff, &x16); + { uint64_t x19; uint8_t/*bool*/ x20 = subborrow_u51(x17, x8, 0x7ffffffffffff, &x19); + { uint64_t x22; uint8_t/*bool*/ x23 = subborrow_u51(x20, x7, 0x7ffffffffffff, &x22); + { uint64_t x24 = cmovznz64(x23, 0x0, 0xffffffffffffffffL); + { uint64_t x25 = (x24 & 0x7ffffffffffed); + { uint64_t x27; uint8_t/*bool*/ x28 = addcarryx_u51(0x0, x10, x25, &x27); + { uint64_t x29 = (x24 & 0x7ffffffffffff); + { uint64_t x31; uint8_t/*bool*/ x32 = addcarryx_u51(x28, x13, x29, &x31); + { uint64_t x33 = (x24 & 0x7ffffffffffff); + { uint64_t x35; uint8_t/*bool*/ x36 = addcarryx_u51(x32, x16, x33, &x35); + { uint64_t x37 = (x24 & 0x7ffffffffffff); + { uint64_t x39; uint8_t/*bool*/ x40 = addcarryx_u51(x36, x19, x37, &x39); + { uint64_t x41 = (x24 & 0x7ffffffffffff); + { uint64_t x43; addcarryx_u51(x40, x22, x41, &x43); + out[0] = x27; + out[1] = x31; + out[2] = x35; + out[3] = x39; + out[4] = x43; + }}}}}}}}}}}}}}}}}}}}} +} + +static void fe_tobytes(uint8_t s[32], const fe *f) { + assert_fe(f->v); + uint64_t h[5]; + fe_freeze(h, f->v); + assert_fe_frozen(h); + + s[0] = h[0] >> 0; + s[1] = h[0] >> 8; + s[2] = h[0] >> 16; + s[3] = h[0] >> 24; + s[4] = h[0] >> 32; + s[5] = h[0] >> 40; + s[6] = (h[0] >> 48) | (h[1] << 3); + s[7] = h[1] >> 5; + s[8] = h[1] >> 13; + s[9] = h[1] >> 21; + s[10] = h[1] >> 29; + s[11] = h[1] >> 37; + s[12] = (h[1] >> 45) | (h[2] << 6); + s[13] = h[2] >> 2; + s[14] = h[2] >> 10; + s[15] = h[2] >> 18; + s[16] = h[2] >> 26; + s[17] = h[2] >> 34; + s[18] = h[2] >> 42; + s[19] = (h[2] >> 50) | (h[3] << 1); + s[20] = h[3] >> 7; + s[21] = h[3] >> 15; + s[22] = h[3] >> 23; + s[23] = h[3] >> 31; + s[24] = h[3] >> 39; + s[25] = (h[3] >> 47) | (h[4] << 4); + s[26] = h[4] >> 4; + s[27] = h[4] >> 12; + s[28] = h[4] >> 20; + s[29] = h[4] >> 28; + s[30] = h[4] >> 36; + s[31] = h[4] >> 44; +} + +// h = 0 +static void fe_0(fe *h) { + OPENSSL_memset(h, 0, sizeof(fe)); +} + +static void fe_loose_0(fe_loose *h) { + OPENSSL_memset(h, 0, sizeof(fe_loose)); +} + +// h = 1 +static void fe_1(fe *h) { + OPENSSL_memset(h, 0, sizeof(fe)); + h->v[0] = 1; +} + +static void fe_loose_1(fe_loose *h) { + OPENSSL_memset(h, 0, sizeof(fe_loose)); + h->v[0] = 1; +} + +static void fe_add_impl(uint64_t out[5], const uint64_t in1[5], const uint64_t in2[5]) { + { const uint64_t x10 = in1[4]; + { const uint64_t x11 = in1[3]; + { const uint64_t x9 = in1[2]; + { const uint64_t x7 = in1[1]; + { const uint64_t x5 = in1[0]; + { const uint64_t x18 = in2[4]; + { const uint64_t x19 = in2[3]; + { const uint64_t x17 = in2[2]; + { const uint64_t x15 = in2[1]; + { const uint64_t x13 = in2[0]; + out[0] = (x5 + x13); + out[1] = (x7 + x15); + out[2] = (x9 + x17); + out[3] = (x11 + x19); + out[4] = (x10 + x18); + }}}}}}}}}} +} + +// h = f + g +// Can overlap h with f or g. +static void fe_add(fe_loose *h, const fe *f, const fe *g) { + assert_fe(f->v); + assert_fe(g->v); + fe_add_impl(h->v, f->v, g->v); + assert_fe_loose(h->v); +} + +static void fe_sub_impl(uint64_t out[5], const uint64_t in1[5], const uint64_t in2[5]) { + { const uint64_t x10 = in1[4]; + { const uint64_t x11 = in1[3]; + { const uint64_t x9 = in1[2]; + { const uint64_t x7 = in1[1]; + { const uint64_t x5 = in1[0]; + { const uint64_t x18 = in2[4]; + { const uint64_t x19 = in2[3]; + { const uint64_t x17 = in2[2]; + { const uint64_t x15 = in2[1]; + { const uint64_t x13 = in2[0]; + out[0] = ((0xfffffffffffda + x5) - x13); + out[1] = ((0xffffffffffffe + x7) - x15); + out[2] = ((0xffffffffffffe + x9) - x17); + out[3] = ((0xffffffffffffe + x11) - x19); + out[4] = ((0xffffffffffffe + x10) - x18); + }}}}}}}}}} +} + +// h = f - g +// Can overlap h with f or g. +static void fe_sub(fe_loose *h, const fe *f, const fe *g) { + assert_fe(f->v); + assert_fe(g->v); + fe_sub_impl(h->v, f->v, g->v); + assert_fe_loose(h->v); +} + +static void fe_carry_impl(uint64_t out[5], const uint64_t in1[5]) { + { const uint64_t x7 = in1[4]; + { const uint64_t x8 = in1[3]; + { const uint64_t x6 = in1[2]; + { const uint64_t x4 = in1[1]; + { const uint64_t x2 = in1[0]; + { uint64_t x9 = (x2 >> 0x33); + { uint64_t x10 = (x2 & 0x7ffffffffffff); + { uint64_t x11 = (x9 + x4); + { uint64_t x12 = (x11 >> 0x33); + { uint64_t x13 = (x11 & 0x7ffffffffffff); + { uint64_t x14 = (x12 + x6); + { uint64_t x15 = (x14 >> 0x33); + { uint64_t x16 = (x14 & 0x7ffffffffffff); + { uint64_t x17 = (x15 + x8); + { uint64_t x18 = (x17 >> 0x33); + { uint64_t x19 = (x17 & 0x7ffffffffffff); + { uint64_t x20 = (x18 + x7); + { uint64_t x21 = (x20 >> 0x33); + { uint64_t x22 = (x20 & 0x7ffffffffffff); + { uint64_t x23 = (x10 + (0x13 * x21)); + { uint64_t x24 = (x23 >> 0x33); + { uint64_t x25 = (x23 & 0x7ffffffffffff); + { uint64_t x26 = (x24 + x13); + { uint64_t x27 = (x26 >> 0x33); + { uint64_t x28 = (x26 & 0x7ffffffffffff); + out[0] = x25; + out[1] = x28; + out[2] = (x27 + x16); + out[3] = x19; + out[4] = x22; + }}}}}}}}}}}}}}}}}}}}}}}}} +} + +static void fe_carry(fe *h, const fe_loose* f) { + assert_fe_loose(f->v); + fe_carry_impl(h->v, f->v); + assert_fe(h->v); +} + +static void fe_mul_impl(uint64_t out[5], const uint64_t in1[5], const uint64_t in2[5]) { + assert_fe_loose(in1); + assert_fe_loose(in2); + { const uint64_t x10 = in1[4]; + { const uint64_t x11 = in1[3]; + { const uint64_t x9 = in1[2]; + { const uint64_t x7 = in1[1]; + { const uint64_t x5 = in1[0]; + { const uint64_t x18 = in2[4]; + { const uint64_t x19 = in2[3]; + { const uint64_t x17 = in2[2]; + { const uint64_t x15 = in2[1]; + { const uint64_t x13 = in2[0]; + { uint128_t x20 = ((uint128_t)x5 * x13); + { uint128_t x21 = (((uint128_t)x5 * x15) + ((uint128_t)x7 * x13)); + { uint128_t x22 = ((((uint128_t)x5 * x17) + ((uint128_t)x9 * x13)) + ((uint128_t)x7 * x15)); + { uint128_t x23 = (((((uint128_t)x5 * x19) + ((uint128_t)x11 * x13)) + ((uint128_t)x7 * x17)) + ((uint128_t)x9 * x15)); + { uint128_t x24 = ((((((uint128_t)x5 * x18) + ((uint128_t)x10 * x13)) + ((uint128_t)x11 * x15)) + ((uint128_t)x7 * x19)) + ((uint128_t)x9 * x17)); + { uint64_t x25 = (x10 * 0x13); + { uint64_t x26 = (x7 * 0x13); + { uint64_t x27 = (x9 * 0x13); + { uint64_t x28 = (x11 * 0x13); + { uint128_t x29 = ((((x20 + ((uint128_t)x25 * x15)) + ((uint128_t)x26 * x18)) + ((uint128_t)x27 * x19)) + ((uint128_t)x28 * x17)); + { uint128_t x30 = (((x21 + ((uint128_t)x25 * x17)) + ((uint128_t)x27 * x18)) + ((uint128_t)x28 * x19)); + { uint128_t x31 = ((x22 + ((uint128_t)x25 * x19)) + ((uint128_t)x28 * x18)); + { uint128_t x32 = (x23 + ((uint128_t)x25 * x18)); + { uint64_t x33 = (uint64_t) (x29 >> 0x33); + { uint64_t x34 = ((uint64_t)x29 & 0x7ffffffffffff); + { uint128_t x35 = (x33 + x30); + { uint64_t x36 = (uint64_t) (x35 >> 0x33); + { uint64_t x37 = ((uint64_t)x35 & 0x7ffffffffffff); + { uint128_t x38 = (x36 + x31); + { uint64_t x39 = (uint64_t) (x38 >> 0x33); + { uint64_t x40 = ((uint64_t)x38 & 0x7ffffffffffff); + { uint128_t x41 = (x39 + x32); + { uint64_t x42 = (uint64_t) (x41 >> 0x33); + { uint64_t x43 = ((uint64_t)x41 & 0x7ffffffffffff); + { uint128_t x44 = (x42 + x24); + { uint64_t x45 = (uint64_t) (x44 >> 0x33); + { uint64_t x46 = ((uint64_t)x44 & 0x7ffffffffffff); + { uint64_t x47 = (x34 + (0x13 * x45)); + { uint64_t x48 = (x47 >> 0x33); + { uint64_t x49 = (x47 & 0x7ffffffffffff); + { uint64_t x50 = (x48 + x37); + { uint64_t x51 = (x50 >> 0x33); + { uint64_t x52 = (x50 & 0x7ffffffffffff); + out[0] = x49; + out[1] = x52; + out[2] = (x51 + x40); + out[3] = x43; + out[4] = x46; + }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} + assert_fe(out); +} + +static void fe_mul_ltt(fe_loose *h, const fe *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_llt(fe_loose *h, const fe_loose *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_ttt(fe *h, const fe *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_tlt(fe *h, const fe_loose *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_ttl(fe *h, const fe *f, const fe_loose *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_sqr_impl(uint64_t out[5], const uint64_t in1[5]) { + assert_fe_loose(in1); + { const uint64_t x7 = in1[4]; + { const uint64_t x8 = in1[3]; + { const uint64_t x6 = in1[2]; + { const uint64_t x4 = in1[1]; + { const uint64_t x2 = in1[0]; + { uint64_t x9 = (x2 * 0x2); + { uint64_t x10 = (x4 * 0x2); + { uint64_t x11 = ((x6 * 0x2) * 0x13); + { uint64_t x12 = (x7 * 0x13); + { uint64_t x13 = (x12 * 0x2); + { uint128_t x14 = ((((uint128_t)x2 * x2) + ((uint128_t)x13 * x4)) + ((uint128_t)x11 * x8)); + { uint128_t x15 = ((((uint128_t)x9 * x4) + ((uint128_t)x13 * x6)) + ((uint128_t)x8 * (x8 * 0x13))); + { uint128_t x16 = ((((uint128_t)x9 * x6) + ((uint128_t)x4 * x4)) + ((uint128_t)x13 * x8)); + { uint128_t x17 = ((((uint128_t)x9 * x8) + ((uint128_t)x10 * x6)) + ((uint128_t)x7 * x12)); + { uint128_t x18 = ((((uint128_t)x9 * x7) + ((uint128_t)x10 * x8)) + ((uint128_t)x6 * x6)); + { uint64_t x19 = (uint64_t) (x14 >> 0x33); + { uint64_t x20 = ((uint64_t)x14 & 0x7ffffffffffff); + { uint128_t x21 = (x19 + x15); + { uint64_t x22 = (uint64_t) (x21 >> 0x33); + { uint64_t x23 = ((uint64_t)x21 & 0x7ffffffffffff); + { uint128_t x24 = (x22 + x16); + { uint64_t x25 = (uint64_t) (x24 >> 0x33); + { uint64_t x26 = ((uint64_t)x24 & 0x7ffffffffffff); + { uint128_t x27 = (x25 + x17); + { uint64_t x28 = (uint64_t) (x27 >> 0x33); + { uint64_t x29 = ((uint64_t)x27 & 0x7ffffffffffff); + { uint128_t x30 = (x28 + x18); + { uint64_t x31 = (uint64_t) (x30 >> 0x33); + { uint64_t x32 = ((uint64_t)x30 & 0x7ffffffffffff); + { uint64_t x33 = (x20 + (0x13 * x31)); + { uint64_t x34 = (x33 >> 0x33); + { uint64_t x35 = (x33 & 0x7ffffffffffff); + { uint64_t x36 = (x34 + x23); + { uint64_t x37 = (x36 >> 0x33); + { uint64_t x38 = (x36 & 0x7ffffffffffff); + out[0] = x35; + out[1] = x38; + out[2] = (x37 + x26); + out[3] = x29; + out[4] = x32; + }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} + assert_fe(out); +} + +static void fe_sq_tl(fe *h, const fe_loose *f) { + fe_sqr_impl(h->v, f->v); +} + +static void fe_sq_tt(fe *h, const fe *f) { + fe_sqr_impl(h->v, f->v); +} + +// Replace (f,g) with (g,f) if b == 1; +// replace (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +static void fe_cswap(fe *f, fe *g, uint64_t b) { + b = 0-b; + for (unsigned i = 0; i < 5; i++) { + uint64_t x = f->v[i] ^ g->v[i]; + x &= b; + f->v[i] ^= x; + g->v[i] ^= x; + } +} + +// NOTE: based on fiat-crypto fe_mul, edited for in2=121666, 0, 0.. +static void fe_mul_121666_impl(uint64_t out[5], const uint64_t in1[5]) { + { const uint64_t x10 = in1[4]; + { const uint64_t x11 = in1[3]; + { const uint64_t x9 = in1[2]; + { const uint64_t x7 = in1[1]; + { const uint64_t x5 = in1[0]; + { const uint64_t x18 = 0; + { const uint64_t x19 = 0; + { const uint64_t x17 = 0; + { const uint64_t x15 = 0; + { const uint64_t x13 = 121666; + { uint128_t x20 = ((uint128_t)x5 * x13); + { uint128_t x21 = (((uint128_t)x5 * x15) + ((uint128_t)x7 * x13)); + { uint128_t x22 = ((((uint128_t)x5 * x17) + ((uint128_t)x9 * x13)) + ((uint128_t)x7 * x15)); + { uint128_t x23 = (((((uint128_t)x5 * x19) + ((uint128_t)x11 * x13)) + ((uint128_t)x7 * x17)) + ((uint128_t)x9 * x15)); + { uint128_t x24 = ((((((uint128_t)x5 * x18) + ((uint128_t)x10 * x13)) + ((uint128_t)x11 * x15)) + ((uint128_t)x7 * x19)) + ((uint128_t)x9 * x17)); + { uint64_t x25 = (x10 * 0x13); + { uint64_t x26 = (x7 * 0x13); + { uint64_t x27 = (x9 * 0x13); + { uint64_t x28 = (x11 * 0x13); + { uint128_t x29 = ((((x20 + ((uint128_t)x25 * x15)) + ((uint128_t)x26 * x18)) + ((uint128_t)x27 * x19)) + ((uint128_t)x28 * x17)); + { uint128_t x30 = (((x21 + ((uint128_t)x25 * x17)) + ((uint128_t)x27 * x18)) + ((uint128_t)x28 * x19)); + { uint128_t x31 = ((x22 + ((uint128_t)x25 * x19)) + ((uint128_t)x28 * x18)); + { uint128_t x32 = (x23 + ((uint128_t)x25 * x18)); + { uint64_t x33 = (uint64_t) (x29 >> 0x33); + { uint64_t x34 = ((uint64_t)x29 & 0x7ffffffffffff); + { uint128_t x35 = (x33 + x30); + { uint64_t x36 = (uint64_t) (x35 >> 0x33); + { uint64_t x37 = ((uint64_t)x35 & 0x7ffffffffffff); + { uint128_t x38 = (x36 + x31); + { uint64_t x39 = (uint64_t) (x38 >> 0x33); + { uint64_t x40 = ((uint64_t)x38 & 0x7ffffffffffff); + { uint128_t x41 = (x39 + x32); + { uint64_t x42 = (uint64_t) (x41 >> 0x33); + { uint64_t x43 = ((uint64_t)x41 & 0x7ffffffffffff); + { uint128_t x44 = (x42 + x24); + { uint64_t x45 = (uint64_t) (x44 >> 0x33); + { uint64_t x46 = ((uint64_t)x44 & 0x7ffffffffffff); + { uint64_t x47 = (x34 + (0x13 * x45)); + { uint64_t x48 = (x47 >> 0x33); + { uint64_t x49 = (x47 & 0x7ffffffffffff); + { uint64_t x50 = (x48 + x37); + { uint64_t x51 = (x50 >> 0x33); + { uint64_t x52 = (x50 & 0x7ffffffffffff); + out[0] = x49; + out[1] = x52; + out[2] = (x51 + x40); + out[3] = x43; + out[4] = x46; + }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} +} + +static void fe_mul121666(fe *h, const fe_loose *f) { + assert_fe_loose(f->v); + fe_mul_121666_impl(h->v, f->v); + assert_fe(h->v); +} + +// Adapted from Fiat-synthesized |fe_sub_impl| with |out| = 0. +static void fe_neg_impl(uint64_t out[5], const uint64_t in2[5]) { + { const uint64_t x10 = 0; + { const uint64_t x11 = 0; + { const uint64_t x9 = 0; + { const uint64_t x7 = 0; + { const uint64_t x5 = 0; + { const uint64_t x18 = in2[4]; + { const uint64_t x19 = in2[3]; + { const uint64_t x17 = in2[2]; + { const uint64_t x15 = in2[1]; + { const uint64_t x13 = in2[0]; + out[0] = ((0xfffffffffffda + x5) - x13); + out[1] = ((0xffffffffffffe + x7) - x15); + out[2] = ((0xffffffffffffe + x9) - x17); + out[3] = ((0xffffffffffffe + x11) - x19); + out[4] = ((0xffffffffffffe + x10) - x18); + }}}}}}}}}} +} + +// h = -f +static void fe_neg(fe_loose *h, const fe *f) { + assert_fe(f->v); + fe_neg_impl(h->v, f->v); + assert_fe_loose(h->v); +} + +// Replace (f,g) with (g,g) if b == 1; +// replace (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +static void fe_cmov(fe_loose *f, const fe_loose *g, uint64_t b) { + b = 0-b; + for (unsigned i = 0; i < 5; i++) { + uint64_t x = f->v[i] ^ g->v[i]; + x &= b; + f->v[i] ^= x; + } +} + +#else + #define assert_fe(f) do { \ for (unsigned _assert_fe_i = 0; _assert_fe_i< 10; _assert_fe_i++) { \ assert(f[_assert_fe_i] < 1.125*(1<<(26-(_assert_fe_i&1)))); \ @@ -73,6 +639,12 @@ static uint64_t load_4(const uint8_t *in) { } \ } while (0) +#define assert_fe_frozen(f) do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i< 10; _assert_fe_i++) { \ + assert(f[_assert_fe_i] < (1u<<(26-(_assert_fe_i&1)))); \ + } \ +} while (0) + static void fe_frombytes_impl(uint32_t h[10], const uint8_t *s) { // Ignores top bit of s. uint32_t a0 = load_4(s); @@ -100,148 +672,118 @@ static void fe_frombytes(fe *h, const uint8_t *s) { fe_frombytes_impl(h->v, s); } -// Preconditions: -// |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25; - q = (h0 + q) >> 26; - q = (h1 + q) >> 25; - q = (h2 + q) >> 26; - q = (h3 + q) >> 25; - q = (h4 + q) >> 26; - q = (h5 + q) >> 25; - q = (h6 + q) >> 26; - q = (h7 + q) >> 25; - q = (h8 + q) >> 26; - q = (h9 + q) >> 25; - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h0 += 19 * q; - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - h1 += h0 >> 26; h0 &= kBottom26Bits; - h2 += h1 >> 25; h1 &= kBottom25Bits; - h3 += h2 >> 26; h2 &= kBottom26Bits; - h4 += h3 >> 25; h3 &= kBottom25Bits; - h5 += h4 >> 26; h4 &= kBottom26Bits; - h6 += h5 >> 25; h5 &= kBottom25Bits; - h7 += h6 >> 26; h6 &= kBottom26Bits; - h8 += h7 >> 25; h7 &= kBottom25Bits; - h9 += h8 >> 26; h8 &= kBottom26Bits; - h9 &= kBottom25Bits; - // h10 = carry9 - - // Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h0+...+2^230 h9 between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h0+...+2^230 h9. - - s[0] = h0 >> 0; - s[1] = h0 >> 8; - s[2] = h0 >> 16; - s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2); - s[4] = h1 >> 6; - s[5] = h1 >> 14; - s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3); - s[7] = h2 >> 5; - s[8] = h2 >> 13; - s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5); - s[10] = h3 >> 3; - s[11] = h3 >> 11; - s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6); - s[13] = h4 >> 2; - s[14] = h4 >> 10; - s[15] = h4 >> 18; - s[16] = h5 >> 0; - s[17] = h5 >> 8; - s[18] = h5 >> 16; - s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1); - s[20] = h6 >> 7; - s[21] = h6 >> 15; - s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3); - s[23] = h7 >> 5; - s[24] = h7 >> 13; - s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4); - s[26] = h8 >> 4; - s[27] = h8 >> 12; - s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6); - s[29] = h9 >> 2; - s[30] = h9 >> 10; - s[31] = h9 >> 18; -} - -static void fe_tobytes(uint8_t *s, const fe *h) { - fe_tobytes_impl(s, h->v); -} - -static void fe_loose_tobytes(uint8_t *s, const fe_loose *h) { - fe_tobytes_impl(s, h->v); -} - -// h = f -static void fe_copy(fe *h, const fe *f) { - OPENSSL_memmove(h, f, sizeof(uint32_t) * 10); -} - -static void fe_copy_lt(fe_loose *h, const fe *f) { - OPENSSL_memmove(h, f, sizeof(uint32_t) * 10); -} -#if !defined(OPENSSL_SMALL) -static void fe_copy_ll(fe_loose *h, const fe_loose *f) { - OPENSSL_memmove(h, f, sizeof(uint32_t) * 10); +static void fe_freeze(uint32_t out[10], const uint32_t in1[10]) { + { const uint32_t x17 = in1[9]; + { const uint32_t x18 = in1[8]; + { const uint32_t x16 = in1[7]; + { const uint32_t x14 = in1[6]; + { const uint32_t x12 = in1[5]; + { const uint32_t x10 = in1[4]; + { const uint32_t x8 = in1[3]; + { const uint32_t x6 = in1[2]; + { const uint32_t x4 = in1[1]; + { const uint32_t x2 = in1[0]; + { uint32_t x20; uint8_t/*bool*/ x21 = subborrow_u26(0x0, x2, 0x3ffffed, &x20); + { uint32_t x23; uint8_t/*bool*/ x24 = subborrow_u25(x21, x4, 0x1ffffff, &x23); + { uint32_t x26; uint8_t/*bool*/ x27 = subborrow_u26(x24, x6, 0x3ffffff, &x26); + { uint32_t x29; uint8_t/*bool*/ x30 = subborrow_u25(x27, x8, 0x1ffffff, &x29); + { uint32_t x32; uint8_t/*bool*/ x33 = subborrow_u26(x30, x10, 0x3ffffff, &x32); + { uint32_t x35; uint8_t/*bool*/ x36 = subborrow_u25(x33, x12, 0x1ffffff, &x35); + { uint32_t x38; uint8_t/*bool*/ x39 = subborrow_u26(x36, x14, 0x3ffffff, &x38); + { uint32_t x41; uint8_t/*bool*/ x42 = subborrow_u25(x39, x16, 0x1ffffff, &x41); + { uint32_t x44; uint8_t/*bool*/ x45 = subborrow_u26(x42, x18, 0x3ffffff, &x44); + { uint32_t x47; uint8_t/*bool*/ x48 = subborrow_u25(x45, x17, 0x1ffffff, &x47); + { uint32_t x49 = cmovznz32(x48, 0x0, 0xffffffff); + { uint32_t x50 = (x49 & 0x3ffffed); + { uint32_t x52; uint8_t/*bool*/ x53 = addcarryx_u26(0x0, x20, x50, &x52); + { uint32_t x54 = (x49 & 0x1ffffff); + { uint32_t x56; uint8_t/*bool*/ x57 = addcarryx_u25(x53, x23, x54, &x56); + { uint32_t x58 = (x49 & 0x3ffffff); + { uint32_t x60; uint8_t/*bool*/ x61 = addcarryx_u26(x57, x26, x58, &x60); + { uint32_t x62 = (x49 & 0x1ffffff); + { uint32_t x64; uint8_t/*bool*/ x65 = addcarryx_u25(x61, x29, x62, &x64); + { uint32_t x66 = (x49 & 0x3ffffff); + { uint32_t x68; uint8_t/*bool*/ x69 = addcarryx_u26(x65, x32, x66, &x68); + { uint32_t x70 = (x49 & 0x1ffffff); + { uint32_t x72; uint8_t/*bool*/ x73 = addcarryx_u25(x69, x35, x70, &x72); + { uint32_t x74 = (x49 & 0x3ffffff); + { uint32_t x76; uint8_t/*bool*/ x77 = addcarryx_u26(x73, x38, x74, &x76); + { uint32_t x78 = (x49 & 0x1ffffff); + { uint32_t x80; uint8_t/*bool*/ x81 = addcarryx_u25(x77, x41, x78, &x80); + { uint32_t x82 = (x49 & 0x3ffffff); + { uint32_t x84; uint8_t/*bool*/ x85 = addcarryx_u26(x81, x44, x82, &x84); + { uint32_t x86 = (x49 & 0x1ffffff); + { uint32_t x88; addcarryx_u25(x85, x47, x86, &x88); + out[0] = x52; + out[1] = x56; + out[2] = x60; + out[3] = x64; + out[4] = x68; + out[5] = x72; + out[6] = x76; + out[7] = x80; + out[8] = x84; + out[9] = x88; + }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} +} + +static void fe_tobytes(uint8_t s[32], const fe *f) { + assert_fe(f->v); + uint32_t h[10]; + fe_freeze(h, f->v); + assert_fe_frozen(h); + + s[0] = h[0] >> 0; + s[1] = h[0] >> 8; + s[2] = h[0] >> 16; + s[3] = (h[0] >> 24) | (h[1] << 2); + s[4] = h[1] >> 6; + s[5] = h[1] >> 14; + s[6] = (h[1] >> 22) | (h[2] << 3); + s[7] = h[2] >> 5; + s[8] = h[2] >> 13; + s[9] = (h[2] >> 21) | (h[3] << 5); + s[10] = h[3] >> 3; + s[11] = h[3] >> 11; + s[12] = (h[3] >> 19) | (h[4] << 6); + s[13] = h[4] >> 2; + s[14] = h[4] >> 10; + s[15] = h[4] >> 18; + s[16] = h[5] >> 0; + s[17] = h[5] >> 8; + s[18] = h[5] >> 16; + s[19] = (h[5] >> 24) | (h[6] << 1); + s[20] = h[6] >> 7; + s[21] = h[6] >> 15; + s[22] = (h[6] >> 23) | (h[7] << 3); + s[23] = h[7] >> 5; + s[24] = h[7] >> 13; + s[25] = (h[7] >> 21) | (h[8] << 4); + s[26] = h[8] >> 4; + s[27] = h[8] >> 12; + s[28] = (h[8] >> 20) | (h[9] << 6); + s[29] = h[9] >> 2; + s[30] = h[9] >> 10; + s[31] = h[9] >> 18; } -#endif // !defined(OPENSSL_SMALL) // h = 0 static void fe_0(fe *h) { - OPENSSL_memset(h, 0, sizeof(uint32_t) * 10); + OPENSSL_memset(h, 0, sizeof(fe)); } static void fe_loose_0(fe_loose *h) { - OPENSSL_memset(h, 0, sizeof(uint32_t) * 10); + OPENSSL_memset(h, 0, sizeof(fe_loose)); } // h = 1 static void fe_1(fe *h) { - OPENSSL_memset(h, 0, sizeof(uint32_t) * 10); + OPENSSL_memset(h, 0, sizeof(fe)); h->v[0] = 1; } static void fe_loose_1(fe_loose *h) { - OPENSSL_memset(h, 0, sizeof(uint32_t) * 10); + OPENSSL_memset(h, 0, sizeof(fe_loose)); h->v[0] = 1; } @@ -281,13 +823,6 @@ static void fe_add_impl(uint32_t out[10], const uint32_t in1[10], const uint32_t // h = f + g // Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. static void fe_add(fe_loose *h, const fe *f, const fe *g) { assert_fe(f->v); assert_fe(g->v); @@ -331,13 +866,6 @@ static void fe_sub_impl(uint32_t out[10], const uint32_t in1[10], const uint32_t // h = f - g // Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. static void fe_sub(fe_loose *h, const fe *f, const fe *g) { assert_fe(f->v); assert_fe(g->v); @@ -667,158 +1195,23 @@ static void fe_sq_tt(fe *h, const fe *f) { fe_sqr_impl(h->v, f->v); } -static void fe_loose_invert(fe *out, const fe_loose *z) { - fe t0; - fe t1; - fe t2; - fe t3; - int i; - - fe_sq_tl(&t0, z); - fe_sq_tt(&t1, &t0); - for (i = 1; i < 2; ++i) { - fe_sq_tt(&t1, &t1); - } - fe_mul_tlt(&t1, z, &t1); - fe_mul_ttt(&t0, &t0, &t1); - fe_sq_tt(&t2, &t0); - fe_mul_ttt(&t1, &t1, &t2); - fe_sq_tt(&t2, &t1); - for (i = 1; i < 5; ++i) { - fe_sq_tt(&t2, &t2); - } - fe_mul_ttt(&t1, &t2, &t1); - fe_sq_tt(&t2, &t1); - for (i = 1; i < 10; ++i) { - fe_sq_tt(&t2, &t2); - } - fe_mul_ttt(&t2, &t2, &t1); - fe_sq_tt(&t3, &t2); - for (i = 1; i < 20; ++i) { - fe_sq_tt(&t3, &t3); - } - fe_mul_ttt(&t2, &t3, &t2); - fe_sq_tt(&t2, &t2); - for (i = 1; i < 10; ++i) { - fe_sq_tt(&t2, &t2); - } - fe_mul_ttt(&t1, &t2, &t1); - fe_sq_tt(&t2, &t1); - for (i = 1; i < 50; ++i) { - fe_sq_tt(&t2, &t2); - } - fe_mul_ttt(&t2, &t2, &t1); - fe_sq_tt(&t3, &t2); - for (i = 1; i < 100; ++i) { - fe_sq_tt(&t3, &t3); - } - fe_mul_ttt(&t2, &t3, &t2); - fe_sq_tt(&t2, &t2); - for (i = 1; i < 50; ++i) { - fe_sq_tt(&t2, &t2); - } - fe_mul_ttt(&t1, &t2, &t1); - fe_sq_tt(&t1, &t1); - for (i = 1; i < 5; ++i) { - fe_sq_tt(&t1, &t1); - } - fe_mul_ttt(out, &t1, &t0); -} - -static void fe_invert(fe *out, const fe *z) { - fe_loose l; - fe_copy_lt(&l, z); - fe_loose_invert(out, &l); -} - -static void fe_neg_impl(uint32_t out[10], const uint32_t in2[10]) { - { const uint32_t x20 = 0; - { const uint32_t x21 = 0; - { const uint32_t x19 = 0; - { const uint32_t x17 = 0; - { const uint32_t x15 = 0; - { const uint32_t x13 = 0; - { const uint32_t x11 = 0; - { const uint32_t x9 = 0; - { const uint32_t x7 = 0; - { const uint32_t x5 = 0; - { const uint32_t x38 = in2[9]; - { const uint32_t x39 = in2[8]; - { const uint32_t x37 = in2[7]; - { const uint32_t x35 = in2[6]; - { const uint32_t x33 = in2[5]; - { const uint32_t x31 = in2[4]; - { const uint32_t x29 = in2[3]; - { const uint32_t x27 = in2[2]; - { const uint32_t x25 = in2[1]; - { const uint32_t x23 = in2[0]; - out[0] = ((0x7ffffda + x5) - x23); - out[1] = ((0x3fffffe + x7) - x25); - out[2] = ((0x7fffffe + x9) - x27); - out[3] = ((0x3fffffe + x11) - x29); - out[4] = ((0x7fffffe + x13) - x31); - out[5] = ((0x3fffffe + x15) - x33); - out[6] = ((0x7fffffe + x17) - x35); - out[7] = ((0x3fffffe + x19) - x37); - out[8] = ((0x7fffffe + x21) - x39); - out[9] = ((0x3fffffe + x20) - x38); - }}}}}}}}}}}}}}}}}}}} -} - -// h = -f -// -// Preconditions: -// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -static void fe_neg(fe_loose *h, const fe *f) { - assert_fe(f->v); - fe_neg_impl(h->v, f->v); - assert_fe_loose(h->v); -} - -// Replace (f,g) with (g,g) if b == 1; +// Replace (f,g) with (g,f) if b == 1; // replace (f,g) with (f,g) if b == 0. // // Preconditions: b in {0,1}. -static void fe_cmov(fe_loose *f, const fe_loose *g, unsigned b) { +static void fe_cswap(fe *f, fe *g, unsigned int b) { b = 0-b; unsigned i; for (i = 0; i < 10; i++) { uint32_t x = f->v[i] ^ g->v[i]; x &= b; f->v[i] ^= x; + g->v[i] ^= x; } } -// return 0 if f == 0 -// return 1 if f != 0 -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -static int fe_isnonzero(const fe_loose *f) { - uint8_t s[32]; - fe_loose_tobytes(s, f); - - static const uint8_t zero[32] = {0}; - return CRYPTO_memcmp(s, zero, sizeof(zero)) != 0; -} - -// return 1 if f is in {1,3,5,...,q-2} -// return 0 if f is in {0,2,4,...,q-1} -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -static int fe_isnegative(const fe *f) { - uint8_t s[32]; - fe_tobytes(s, f); - return s[0] & 1; -} - -// NOTE: based on fiat-crypto fe_mul, edited for in2=2*in1 -static void fe_sq2_impl(uint32_t out[10], const uint32_t in1[10]) { - assert_fe_loose(in1); +// NOTE: based on fiat-crypto fe_mul, edited for in2=121666, 0, 0.. +static void fe_mul_121666_impl(uint32_t out[10], const uint32_t in1[10]) { { const uint32_t x20 = in1[9]; { const uint32_t x21 = in1[8]; { const uint32_t x19 = in1[7]; @@ -829,16 +1222,16 @@ static void fe_sq2_impl(uint32_t out[10], const uint32_t in1[10]) { { const uint32_t x9 = in1[2]; { const uint32_t x7 = in1[1]; { const uint32_t x5 = in1[0]; - { const uint32_t x38 = 2*in1[9]; - { const uint32_t x39 = 2*in1[8]; - { const uint32_t x37 = 2*in1[7]; - { const uint32_t x35 = 2*in1[6]; - { const uint32_t x33 = 2*in1[5]; - { const uint32_t x31 = 2*in1[4]; - { const uint32_t x29 = 2*in1[3]; - { const uint32_t x27 = 2*in1[2]; - { const uint32_t x25 = 2*in1[1]; - { const uint32_t x23 = 2*in1[0]; + { const uint32_t x38 = 0; + { const uint32_t x39 = 0; + { const uint32_t x37 = 0; + { const uint32_t x35 = 0; + { const uint32_t x33 = 0; + { const uint32_t x31 = 0; + { const uint32_t x29 = 0; + { const uint32_t x27 = 0; + { const uint32_t x25 = 0; + { const uint32_t x23 = 121666; { uint64_t x40 = ((uint64_t)x23 * x5); { uint64_t x41 = (((uint64_t)x23 * x7) + ((uint64_t)x25 * x5)); { uint64_t x42 = ((((uint64_t)(0x2 * x25) * x7) + ((uint64_t)x23 * x9)) + ((uint64_t)x27 * x5)); @@ -931,11 +1324,180 @@ static void fe_sq2_impl(uint32_t out[10], const uint32_t in1[10]) { out[8] = x111; out[9] = x114; }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} - assert_fe(out); +} + +static void fe_mul121666(fe *h, const fe_loose *f) { + assert_fe_loose(f->v); + fe_mul_121666_impl(h->v, f->v); + assert_fe(h->v); +} + +// Adapted from Fiat-synthesized |fe_sub_impl| with |out| = 0. +static void fe_neg_impl(uint32_t out[10], const uint32_t in2[10]) { + { const uint32_t x20 = 0; + { const uint32_t x21 = 0; + { const uint32_t x19 = 0; + { const uint32_t x17 = 0; + { const uint32_t x15 = 0; + { const uint32_t x13 = 0; + { const uint32_t x11 = 0; + { const uint32_t x9 = 0; + { const uint32_t x7 = 0; + { const uint32_t x5 = 0; + { const uint32_t x38 = in2[9]; + { const uint32_t x39 = in2[8]; + { const uint32_t x37 = in2[7]; + { const uint32_t x35 = in2[6]; + { const uint32_t x33 = in2[5]; + { const uint32_t x31 = in2[4]; + { const uint32_t x29 = in2[3]; + { const uint32_t x27 = in2[2]; + { const uint32_t x25 = in2[1]; + { const uint32_t x23 = in2[0]; + out[0] = ((0x7ffffda + x5) - x23); + out[1] = ((0x3fffffe + x7) - x25); + out[2] = ((0x7fffffe + x9) - x27); + out[3] = ((0x3fffffe + x11) - x29); + out[4] = ((0x7fffffe + x13) - x31); + out[5] = ((0x3fffffe + x15) - x33); + out[6] = ((0x7fffffe + x17) - x35); + out[7] = ((0x3fffffe + x19) - x37); + out[8] = ((0x7fffffe + x21) - x39); + out[9] = ((0x3fffffe + x20) - x38); + }}}}}}}}}}}}}}}}}}}} +} + +// h = -f +static void fe_neg(fe_loose *h, const fe *f) { + assert_fe(f->v); + fe_neg_impl(h->v, f->v); + assert_fe_loose(h->v); +} + +// Replace (f,g) with (g,g) if b == 1; +// replace (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +static void fe_cmov(fe_loose *f, const fe_loose *g, unsigned b) { + b = 0-b; + unsigned i; + for (i = 0; i < 10; i++) { + uint32_t x = f->v[i] ^ g->v[i]; + x &= b; + f->v[i] ^= x; + } +} + +#endif // BORINGSSL_CURVE25519_64BIT + +// h = f +static void fe_copy(fe *h, const fe *f) { + OPENSSL_memmove(h, f, sizeof(fe)); +} + +static void fe_copy_lt(fe_loose *h, const fe *f) { + OPENSSL_COMPILE_ASSERT(sizeof(fe_loose) == sizeof(fe), + fe_and_fe_loose_mismatch); + OPENSSL_memmove(h, f, sizeof(fe)); +} +#if !defined(OPENSSL_SMALL) +static void fe_copy_ll(fe_loose *h, const fe_loose *f) { + OPENSSL_memmove(h, f, sizeof(fe_loose)); +} +#endif // !defined(OPENSSL_SMALL) + +static void fe_loose_invert(fe *out, const fe_loose *z) { + fe t0; + fe t1; + fe t2; + fe t3; + int i; + + fe_sq_tl(&t0, z); + fe_sq_tt(&t1, &t0); + for (i = 1; i < 2; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_tlt(&t1, z, &t1); + fe_mul_ttt(&t0, &t0, &t1); + fe_sq_tt(&t2, &t0); + fe_mul_ttt(&t1, &t1, &t2); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 5; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 10; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t2, &t2, &t1); + fe_sq_tt(&t3, &t2); + for (i = 1; i < 20; ++i) { + fe_sq_tt(&t3, &t3); + } + fe_mul_ttt(&t2, &t3, &t2); + fe_sq_tt(&t2, &t2); + for (i = 1; i < 10; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 50; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t2, &t2, &t1); + fe_sq_tt(&t3, &t2); + for (i = 1; i < 100; ++i) { + fe_sq_tt(&t3, &t3); + } + fe_mul_ttt(&t2, &t3, &t2); + fe_sq_tt(&t2, &t2); + for (i = 1; i < 50; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t1, &t1); + for (i = 1; i < 5; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(out, &t1, &t0); +} + +static void fe_invert(fe *out, const fe *z) { + fe_loose l; + fe_copy_lt(&l, z); + fe_loose_invert(out, &l); +} + +// return 0 if f == 0 +// return 1 if f != 0 +static int fe_isnonzero(const fe_loose *f) { + fe tight; + fe_carry(&tight, f); + uint8_t s[32]; + fe_tobytes(s, &tight); + + static const uint8_t zero[32] = {0}; + return CRYPTO_memcmp(s, zero, sizeof(zero)) != 0; +} + +// return 1 if f is in {1,3,5,...,q-2} +// return 0 if f is in {0,2,4,...,q-1} +static int fe_isnegative(const fe *f) { + uint8_t s[32]; + fe_tobytes(s, f); + return s[0] & 1; } static void fe_sq2_tt(fe *h, const fe *f) { - fe_sq2_impl(h->v, f->v); + // h = f^2 + fe_sq_tt(h, f); + + // h = h + h + fe_loose tmp; + fe_add(&tmp, h, h); + fe_carry(h, &tmp); } static void fe_pow22523(fe *out, const fe *z) { @@ -995,7 +1557,10 @@ static void fe_pow22523(fe *out, const fe *z) { fe_mul_ttt(out, &t0, z); } -void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) { + +// Group operations. + +void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h) { fe recip; fe x; fe y; @@ -1007,7 +1572,7 @@ void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) { s[31] ^= fe_isnegative(&x) << 7; } -static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) { +static void ge_p3_tobytes(uint8_t s[32], const ge_p3 *h) { fe recip; fe x; fe y; @@ -1019,12 +1584,6 @@ static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) { s[31] ^= fe_isnegative(&x) << 7; } -static const fe d = {{56195235, 13857412, 51736253, 6949390, 114729, - 24766616, 60832955, 30306712, 48412415, 21499315}}; - -static const fe sqrtm1 = {{34513072, 25610706, 9377949, 3500415, 12389472, - 33281959, 41962654, 31548777, 326685, 11406482}}; - int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) { fe u; fe_loose v; @@ -1104,9 +1663,6 @@ static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { fe_copy(&r->Z, &p->Z); } -static const fe d2 = {{45281625, 27714825, 36363642, 13898781, 229458, - 15978800, 54557047, 27058993, 29715967, 9444199}}; - // r = p void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { fe_add(&r->YplusX, &p->Y, &p->X); @@ -1303,2219 +1859,12 @@ void x25519_ge_scalarmult_small_precomp( #if defined(OPENSSL_SMALL) -// This block of code replaces the standard base-point table with a much smaller -// one. The standard table is 30,720 bytes while this one is just 960. -// -// This table contains 15 pairs of group elements, (x, y), where each field -// element is serialised with |fe_tobytes|. If |i| is the index of the group -// element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀ -// is the most significant bit). The value of the group element is then: -// (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator. -static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = { - 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, - 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, - 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e, - 0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4, - 0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62, - 0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba, - 0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd, - 0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03, 0xa2, 0xfb, 0xcc, 0x61, - 0x67, 0x06, 0x70, 0x1a, 0xc4, 0x78, 0x3a, 0xff, 0x32, 0x62, 0xdd, 0x2c, - 0xab, 0x50, 0x19, 0x3b, 0xf2, 0x9b, 0x7d, 0xb8, 0xfd, 0x4f, 0x29, 0x9c, - 0xa7, 0x91, 0xba, 0x0e, 0x46, 0x5e, 0x51, 0xfe, 0x1d, 0xbf, 0xe5, 0xe5, - 0x9b, 0x95, 0x0d, 0x67, 0xf8, 0xd1, 0xb5, 0x5a, 0xa1, 0x93, 0x2c, 0xc3, - 0xde, 0x0e, 0x97, 0x85, 0x2d, 0x7f, 0xea, 0xab, 0x3e, 0x47, 0x30, 0x18, - 0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, - 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, - 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c, 0x6b, 0xa6, 0xf5, 0x4b, - 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, - 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, - 0xe6, 0x99, 0x2c, 0x5f, 0x9a, 0x96, 0x0c, 0x68, 0x29, 0xfd, 0xe2, 0xfb, - 0xe6, 0xbc, 0xec, 0x31, 0x08, 0xec, 0xe6, 0xb0, 0x53, 0x60, 0xc3, 0x8c, - 0xbe, 0xc1, 0xb3, 0x8a, 0x8f, 0xe4, 0x88, 0x2b, 0x55, 0xe5, 0x64, 0x6e, - 0x9b, 0xd0, 0xaf, 0x7b, 0x64, 0x2a, 0x35, 0x25, 0x10, 0x52, 0xc5, 0x9e, - 0x58, 0x11, 0x39, 0x36, 0x45, 0x51, 0xb8, 0x39, 0x93, 0xfc, 0x9d, 0x6a, - 0xbe, 0x58, 0xcb, 0xa4, 0x0f, 0x51, 0x3c, 0x38, 0x05, 0xca, 0xab, 0x43, - 0x63, 0x0e, 0xf3, 0x8b, 0x41, 0xa6, 0xf8, 0x9b, 0x53, 0x70, 0x80, 0x53, - 0x86, 0x5e, 0x8f, 0xe3, 0xc3, 0x0d, 0x18, 0xc8, 0x4b, 0x34, 0x1f, 0xd8, - 0x1d, 0xbc, 0xf2, 0x6d, 0x34, 0x3a, 0xbe, 0xdf, 0xd9, 0xf6, 0xf3, 0x89, - 0xa1, 0xe1, 0x94, 0x9f, 0x5d, 0x4c, 0x5d, 0xe9, 0xa1, 0x49, 0x92, 0xef, - 0x0e, 0x53, 0x81, 0x89, 0x58, 0x87, 0xa6, 0x37, 0xf1, 0xdd, 0x62, 0x60, - 0x63, 0x5a, 0x9d, 0x1b, 0x8c, 0xc6, 0x7d, 0x52, 0xea, 0x70, 0x09, 0x6a, - 0xe1, 0x32, 0xf3, 0x73, 0x21, 0x1f, 0x07, 0x7b, 0x7c, 0x9b, 0x49, 0xd8, - 0xc0, 0xf3, 0x25, 0x72, 0x6f, 0x9d, 0xed, 0x31, 0x67, 0x36, 0x36, 0x54, - 0x40, 0x92, 0x71, 0xe6, 0x11, 0x28, 0x11, 0xad, 0x93, 0x32, 0x85, 0x7b, - 0x3e, 0xb7, 0x3b, 0x49, 0x13, 0x1c, 0x07, 0xb0, 0x2e, 0x93, 0xaa, 0xfd, - 0xfd, 0x28, 0x47, 0x3d, 0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, - 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, - 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b, - 0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, - 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, - 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61, 0x38, 0x68, 0xb0, 0x07, - 0xa3, 0xfc, 0xcc, 0x85, 0x10, 0x7f, 0x4c, 0x65, 0x65, 0xb3, 0xfa, 0xfa, - 0xa5, 0x53, 0x6f, 0xdb, 0x74, 0x4c, 0x56, 0x46, 0x03, 0xe2, 0xd5, 0x7a, - 0x29, 0x1c, 0xc6, 0x02, 0xbc, 0x59, 0xf2, 0x04, 0x75, 0x63, 0xc0, 0x84, - 0x2f, 0x60, 0x1c, 0x67, 0x76, 0xfd, 0x63, 0x86, 0xf3, 0xfa, 0xbf, 0xdc, - 0xd2, 0x2d, 0x90, 0x91, 0xbd, 0x33, 0xa9, 0xe5, 0x66, 0x0c, 0xda, 0x42, - 0x27, 0xca, 0xf4, 0x66, 0xc2, 0xec, 0x92, 0x14, 0x57, 0x06, 0x63, 0xd0, - 0x4d, 0x15, 0x06, 0xeb, 0x69, 0x58, 0x4f, 0x77, 0xc5, 0x8b, 0xc7, 0xf0, - 0x8e, 0xed, 0x64, 0xa0, 0xb3, 0x3c, 0x66, 0x71, 0xc6, 0x2d, 0xda, 0x0a, - 0x0d, 0xfe, 0x70, 0x27, 0x64, 0xf8, 0x27, 0xfa, 0xf6, 0x5f, 0x30, 0xa5, - 0x0d, 0x6c, 0xda, 0xf2, 0x62, 0x5e, 0x78, 0x47, 0xd3, 0x66, 0x00, 0x1c, - 0xfd, 0x56, 0x1f, 0x5d, 0x3f, 0x6f, 0xf4, 0x4c, 0xd8, 0xfd, 0x0e, 0x27, - 0xc9, 0x5c, 0x2b, 0xbc, 0xc0, 0xa4, 0xe7, 0x23, 0x29, 0x02, 0x9f, 0x31, - 0xd6, 0xe9, 0xd7, 0x96, 0xf4, 0xe0, 0x5e, 0x0b, 0x0e, 0x13, 0xee, 0x3c, - 0x09, 0xed, 0xf2, 0x3d, 0x76, 0x91, 0xc3, 0xa4, 0x97, 0xae, 0xd4, 0x87, - 0xd0, 0x5d, 0xf6, 0x18, 0x47, 0x1f, 0x1d, 0x67, 0xf2, 0xcf, 0x63, 0xa0, - 0x91, 0x27, 0xf8, 0x93, 0x45, 0x75, 0x23, 0x3f, 0xd1, 0xf1, 0xad, 0x23, - 0xdd, 0x64, 0x93, 0x96, 0x41, 0x70, 0x7f, 0xf7, 0xf5, 0xa9, 0x89, 0xa2, - 0x34, 0xb0, 0x8d, 0x1b, 0xae, 0x19, 0x15, 0x49, 0x58, 0x23, 0x6d, 0x87, - 0x15, 0x4f, 0x81, 0x76, 0xfb, 0x23, 0xb5, 0xea, 0xcf, 0xac, 0x54, 0x8d, - 0x4e, 0x42, 0x2f, 0xeb, 0x0f, 0x63, 0xdb, 0x68, 0x37, 0xa8, 0xcf, 0x8b, - 0xab, 0xf5, 0xa4, 0x6e, 0x96, 0x2a, 0xb2, 0xd6, 0xbe, 0x9e, 0xbd, 0x0d, - 0xb4, 0x42, 0xa9, 0xcf, 0x01, 0x83, 0x8a, 0x17, 0x47, 0x76, 0xc4, 0xc6, - 0x83, 0x04, 0x95, 0x0b, 0xfc, 0x11, 0xc9, 0x62, 0xb8, 0x0c, 0x76, 0x84, - 0xd9, 0xb9, 0x37, 0xfa, 0xfc, 0x7c, 0xc2, 0x6d, 0x58, 0x3e, 0xb3, 0x04, - 0xbb, 0x8c, 0x8f, 0x48, 0xbc, 0x91, 0x27, 0xcc, 0xf9, 0xb7, 0x22, 0x19, - 0x83, 0x2e, 0x09, 0xb5, 0x72, 0xd9, 0x54, 0x1c, 0x4d, 0xa1, 0xea, 0x0b, - 0xf1, 0xc6, 0x08, 0x72, 0x46, 0x87, 0x7a, 0x6e, 0x80, 0x56, 0x0a, 0x8a, - 0xc0, 0xdd, 0x11, 0x6b, 0xd6, 0xdd, 0x47, 0xdf, 0x10, 0xd9, 0xd8, 0xea, - 0x7c, 0xb0, 0x8f, 0x03, 0x00, 0x2e, 0xc1, 0x8f, 0x44, 0xa8, 0xd3, 0x30, - 0x06, 0x89, 0xa2, 0xf9, 0x34, 0xad, 0xdc, 0x03, 0x85, 0xed, 0x51, 0xa7, - 0x82, 0x9c, 0xe7, 0x5d, 0x52, 0x93, 0x0c, 0x32, 0x9a, 0x5b, 0xe1, 0xaa, - 0xca, 0xb8, 0x02, 0x6d, 0x3a, 0xd4, 0xb1, 0x3a, 0xf0, 0x5f, 0xbe, 0xb5, - 0x0d, 0x10, 0x6b, 0x38, 0x32, 0xac, 0x76, 0x80, 0xbd, 0xca, 0x94, 0x71, - 0x7a, 0xf2, 0xc9, 0x35, 0x2a, 0xde, 0x9f, 0x42, 0x49, 0x18, 0x01, 0xab, - 0xbc, 0xef, 0x7c, 0x64, 0x3f, 0x58, 0x3d, 0x92, 0x59, 0xdb, 0x13, 0xdb, - 0x58, 0x6e, 0x0a, 0xe0, 0xb7, 0x91, 0x4a, 0x08, 0x20, 0xd6, 0x2e, 0x3c, - 0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25, -}; - void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) { x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp); } #else -// k25519Precomp[i][j] = (j+1)*256^i*B -static const ge_precomp k25519Precomp[32][8] = { - { - { - {{25967493, 19198397, 29566455, 3660896, 54414519, 4014786, - 27544626, 21800161, 61029707, 2047604}}, - {{54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, - 5043384, 19500929, 18085054}}, - {{58370664, 4489569, 9688441, 18769238, 10184608, 21191052, - 29287918, 11864899, 42594502, 29115885}}, - }, - { - {{54292951, 20578084, 45527620, 11784319, 41753206, 30803714, - 55390960, 29739860, 66750418, 23343128}}, - {{45405608, 6903824, 27185491, 6451973, 37531140, 24000426, - 51492312, 11189267, 40279186, 28235350}}, - {{26966623, 11152617, 32442495, 15396054, 14353839, 20802097, - 63980037, 24013313, 51636816, 29387734}}, - }, - { - {{15636272, 23865875, 24204772, 25642034, 616976, 16869170, - 27787599, 18782243, 28944399, 32004408}}, - {{16568933, 4717097, 55552716, 32452109, 15682895, 21747389, - 16354576, 21778470, 7689661, 11199574}}, - {{30464137, 27578307, 55329429, 17883566, 23220364, 15915852, - 7512774, 10017326, 49359771, 23634074}}, - }, - { - {{50071967, 13921891, 10945806, 27521001, 27105051, 17470053, - 38182653, 15006022, 3284568, 27277892}}, - {{23599295, 25248385, 55915199, 25867015, 13236773, 10506355, - 7464579, 9656445, 13059162, 10374397}}, - {{7798537, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, - 29715387, 66467155, 33453106}}, - }, - { - {{10861363, 11473154, 27284546, 1981175, 37044515, 12577860, - 32867885, 14515107, 51670560, 10819379}}, - {{4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, - 12483687, 54440373, 5581305}}, - {{19563141, 16186464, 37722007, 4097518, 10237984, 29206317, - 28542349, 13850243, 43430843, 17738489}}, - }, - { - {{51736881, 20691677, 32573249, 4720197, 40672342, 5875510, - 47920237, 18329612, 57289923, 21468654}}, - {{58559652, 109982, 15149363, 2178705, 22900618, 4543417, 3044240, - 17864545, 1762327, 14866737}}, - {{48909169, 17603008, 56635573, 1707277, 49922944, 3916100, - 38872452, 3959420, 27914454, 4383652}}, - }, - { - {{5153727, 9909285, 1723747, 30776558, 30523604, 5516873, 19480852, - 5230134, 43156425, 18378665}}, - {{36839857, 30090922, 7665485, 10083793, 28475525, 1649722, - 20654025, 16520125, 30598449, 7715701}}, - {{28881826, 14381568, 9657904, 3680757, 46927229, 7843315, - 35708204, 1370707, 29794553, 32145132}}, - }, - { - {{14499471, 30824833, 33917750, 29299779, 28494861, 14271267, - 30290735, 10876454, 33954766, 2381725}}, - {{59913433, 30899068, 52378708, 462250, 39384538, 3941371, - 60872247, 3696004, 34808032, 15351954}}, - {{27431194, 8222322, 16448760, 29646437, 48401861, 11938354, - 34147463, 30583916, 29551812, 10109425}}, - }, - }, - { - { - {{53451805, 20399000, 35825113, 11777097, 21447386, 6519384, - 64730580, 31926875, 10092782, 28790261}}, - {{27939166, 14210322, 4677035, 16277044, 44144402, 21156292, - 34600109, 12005537, 49298737, 12803509}}, - {{17228999, 17892808, 65875336, 300139, 65883994, 21839654, - 30364212, 24516238, 18016356, 4397660}}, - }, - { - {{56150021, 25864224, 4776340, 18600194, 27850027, 17952220, - 40489757, 14544524, 49631360, 982638}}, - {{29253598, 15796703, 64244882, 23645547, 10057022, 3163536, 7332899, - 29434304, 46061167, 9934962}}, - {{5793284, 16271923, 42977250, 23438027, 29188559, 1206517, - 52360934, 4559894, 36984942, 22656481}}, - }, - { - {{39464912, 22061425, 16282656, 22517939, 28414020, 18542168, - 24191033, 4541697, 53770555, 5500567}}, - {{12650548, 32057319, 9052870, 11355358, 49428827, 25154267, - 49678271, 12264342, 10874051, 13524335}}, - {{25556948, 30508442, 714650, 2510400, 23394682, 23139102, 33119037, - 5080568, 44580805, 5376627}}, - }, - { - {{41020600, 29543379, 50095164, 30016803, 60382070, 1920896, - 44787559, 24106988, 4535767, 1569007}}, - {{64853442, 14606629, 45416424, 25514613, 28430648, 8775819, - 36614302, 3044289, 31848280, 12543772}}, - {{45080285, 2943892, 35251351, 6777305, 13784462, 29262229, - 39731668, 31491700, 7718481, 14474653}}, - }, - { - {{2385296, 2454213, 44477544, 46602, 62670929, 17874016, 656964, - 26317767, 24316167, 28300865}}, - {{13741529, 10911568, 33875447, 24950694, 46931033, 32521134, - 33040650, 20129900, 46379407, 8321685}}, - {{21060490, 31341688, 15712756, 29218333, 1639039, 10656336, - 23845965, 21679594, 57124405, 608371}}, - }, - { - {{53436132, 18466845, 56219170, 25997372, 61071954, 11305546, - 1123968, 26773855, 27229398, 23887}}, - {{43864724, 33260226, 55364135, 14712570, 37643165, 31524814, - 12797023, 27114124, 65475458, 16678953}}, - {{37608244, 4770661, 51054477, 14001337, 7830047, 9564805, - 65600720, 28759386, 49939598, 4904952}}, - }, - { - {{24059538, 14617003, 19037157, 18514524, 19766092, 18648003, - 5169210, 16191880, 2128236, 29227599}}, - {{50127693, 4124965, 58568254, 22900634, 30336521, 19449185, - 37302527, 916032, 60226322, 30567899}}, - {{44477957, 12419371, 59974635, 26081060, 50629959, 16739174, - 285431, 2763829, 15736322, 4143876}}, - }, - { - {{2379333, 11839345, 62998462, 27565766, 11274297, 794957, 212801, - 18959769, 23527083, 17096164}}, - {{33431108, 22423954, 49269897, 17927531, 8909498, 8376530, - 34483524, 4087880, 51919953, 19138217}}, - {{1767664, 7197987, 53903638, 31531796, 54017513, 448825, 5799055, - 4357868, 62334673, 17231393}}, - }, - }, - { - { - {{6721966, 13833823, 43585476, 32003117, 26354292, 21691111, - 23365146, 29604700, 7390889, 2759800}}, - {{4409022, 2052381, 23373853, 10530217, 7676779, 20668478, 21302352, - 29290375, 1244379, 20634787}}, - {{62687625, 7169618, 4982368, 30596842, 30256824, 30776892, 14086412, - 9208236, 15886429, 16489664}}, - }, - { - {{1996056, 10375649, 14346367, 13311202, 60234729, 17116020, - 53415665, 398368, 36502409, 32841498}}, - {{41801399, 9795879, 64331450, 14878808, 33577029, 14780362, - 13348553, 12076947, 36272402, 5113181}}, - {{49338080, 11797795, 31950843, 13929123, 41220562, 12288343, - 36767763, 26218045, 13847710, 5387222}}, - }, - { - {{48526701, 30138214, 17824842, 31213466, 22744342, 23111821, - 8763060, 3617786, 47508202, 10370990}}, - {{20246567, 19185054, 22358228, 33010720, 18507282, 23140436, - 14554436, 24808340, 32232923, 16763880}}, - {{9648486, 10094563, 26416693, 14745928, 36734546, 27081810, - 11094160, 15689506, 3140038, 17044340}}, - }, - { - {{50948792, 5472694, 31895588, 4744994, 8823515, 10365685, - 39884064, 9448612, 38334410, 366294}}, - {{19153450, 11523972, 56012374, 27051289, 42461232, 5420646, - 28344573, 8041113, 719605, 11671788}}, - {{8678006, 2694440, 60300850, 2517371, 4964326, 11152271, 51675948, - 18287915, 27000812, 23358879}}, - }, - { - {{51950941, 7134311, 8639287, 30739555, 59873175, 10421741, 564065, - 5336097, 6750977, 19033406}}, - {{11836410, 29574944, 26297893, 16080799, 23455045, 15735944, - 1695823, 24735310, 8169719, 16220347}}, - {{48993007, 8653646, 17578566, 27461813, 59083086, 17541668, - 55964556, 30926767, 61118155, 19388398}}, - }, - { - {{43800366, 22586119, 15213227, 23473218, 36255258, 22504427, - 27884328, 2847284, 2655861, 1738395}}, - {{39571412, 19301410, 41772562, 25551651, 57738101, 8129820, - 21651608, 30315096, 48021414, 22549153}}, - {{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, - 5821408, 10478196, 8544890}}, - }, - { - {{32173102, 17425121, 24896206, 3921497, 22579056, 30143578, - 19270448, 12217473, 17789017, 30158437}}, - {{36555903, 31326030, 51530034, 23407230, 13243888, 517024, - 15479401, 29701199, 30460519, 1052596}}, - {{55493970, 13323617, 32618793, 8175907, 51878691, 12596686, - 27491595, 28942073, 3179267, 24075541}}, - }, - { - {{31947050, 19187781, 62468280, 18214510, 51982886, 27514722, - 52352086, 17142691, 19072639, 24043372}}, - {{11685058, 11822410, 3158003, 19601838, 33402193, 29389366, - 5977895, 28339415, 473098, 5040608}}, - {{46817982, 8198641, 39698732, 11602122, 1290375, 30754672, - 28326861, 1721092, 47550222, 30422825}}, - }, - }, - { - { - {{7881532, 10687937, 7578723, 7738378, 48157852, 31000479, 21820785, - 8076149, 39240368, 11538388}}, - {{47173198, 3899860, 18283497, 26752864, 51380203, 22305220, - 8754524, 7446702, 61432810, 5797015}}, - {{55813245, 29760862, 51326753, 25589858, 12708868, 25098233, - 2014098, 24503858, 64739691, 27677090}}, - }, - { - {{44636488, 21985690, 39426843, 1146374, 18956691, 16640559, - 1192730, 29840233, 15123618, 10811505}}, - {{14352079, 30134717, 48166819, 10822654, 32750596, 4699007, 67038501, - 15776355, 38222085, 21579878}}, - {{38867681, 25481956, 62129901, 28239114, 29416930, 1847569, - 46454691, 17069576, 4714546, 23953777}}, - }, - { - {{15200332, 8368572, 19679101, 15970074, 35236190, 1959450, - 24611599, 29010600, 55362987, 12340219}}, - {{12876937, 23074376, 33134380, 6590940, 60801088, 14872439, - 9613953, 8241152, 15370987, 9608631}}, - {{62965568, 21540023, 8446280, 33162829, 4407737, 13629032, 59383996, - 15866073, 38898243, 24740332}}, - }, - { - {{26660628, 17876777, 8393733, 358047, 59707573, 992987, 43204631, - 858696, 20571223, 8420556}}, - {{14620696, 13067227, 51661590, 8264466, 14106269, 15080814, - 33531827, 12516406, 45534429, 21077682}}, - {{236881, 10476226, 57258, 18877408, 6472997, 2466984, 17258519, - 7256740, 8791136, 15069930}}, - }, - { - {{1276391, 24182514, 22949634, 17231625, 43615824, 27852245, - 14711874, 4874229, 36445724, 31223040}}, - {{5855666, 4990204, 53397016, 7294283, 59304582, 1924646, 65685689, - 25642053, 34039526, 9234252}}, - {{20590503, 24535444, 31529743, 26201766, 64402029, 10650547, - 31559055, 21944845, 18979185, 13396066}}, - }, - { - {{24474287, 4968103, 22267082, 4407354, 24063882, 25229252, - 48291976, 13594781, 33514650, 7021958}}, - {{55541958, 26988926, 45743778, 15928891, 40950559, 4315420, - 41160136, 29637754, 45628383, 12868081}}, - {{38473832, 13504660, 19988037, 31421671, 21078224, 6443208, - 45662757, 2244499, 54653067, 25465048}}, - }, - { - {{36513336, 13793478, 61256044, 319135, 41385692, 27290532, - 33086545, 8957937, 51875216, 5540520}}, - {{55478669, 22050529, 58989363, 25911358, 2620055, 1022908, - 43398120, 31985447, 50980335, 18591624}}, - {{23152952, 775386, 27395463, 14006635, 57407746, 4649511, 1689819, - 892185, 55595587, 18348483}}, - }, - { - {{9770129, 9586738, 26496094, 4324120, 1556511, 30004408, 27453818, - 4763127, 47929250, 5867133}}, - {{34343820, 1927589, 31726409, 28801137, 23962433, 17534932, - 27846558, 5931263, 37359161, 17445976}}, - {{27461885, 30576896, 22380809, 1815854, 44075111, 30522493, - 7283489, 18406359, 47582163, 7734628}}, - }, - }, - { - { - {{59098600, 23963614, 55988460, 6196037, 29344158, 20123547, - 7585294, 30377806, 18549496, 15302069}}, - {{34450527, 27383209, 59436070, 22502750, 6258877, 13504381, - 10458790, 27135971, 58236621, 8424745}}, - {{24687186, 8613276, 36441818, 30320886, 1863891, 31723888, - 19206233, 7134917, 55824382, 32725512}}, - }, - { - {{11334899, 24336410, 8025292, 12707519, 17523892, 23078361, - 10243737, 18868971, 62042829, 16498836}}, - {{8911542, 6887158, 57524604, 26595841, 11145640, 24010752, 17303924, - 19430194, 6536640, 10543906}}, - {{38162480, 15479762, 49642029, 568875, 65611181, 11223453, - 64439674, 16928857, 39873154, 8876770}}, - }, - { - {{41365946, 20987567, 51458897, 32707824, 34082177, 32758143, - 33627041, 15824473, 66504438, 24514614}}, - {{10330056, 70051, 7957388, 24551765, 9764901, 15609756, 27698697, - 28664395, 1657393, 3084098}}, - {{10477963, 26084172, 12119565, 20303627, 29016246, 28188843, - 31280318, 14396151, 36875289, 15272408}}, - }, - { - {{54820555, 3169462, 28813183, 16658753, 25116432, 27923966, - 41934906, 20918293, 42094106, 1950503}}, - {{40928506, 9489186, 11053416, 18808271, 36055143, 5825629, - 58724558, 24786899, 15341278, 8373727}}, - {{28685821, 7759505, 52730348, 21551571, 35137043, 4079241, - 298136, 23321830, 64230656, 15190419}}, - }, - { - {{34175969, 13806335, 52771379, 17760000, 43104243, 10940927, - 8669718, 2742393, 41075551, 26679428}}, - {{65528476, 21825014, 41129205, 22109408, 49696989, 22641577, - 9291593, 17306653, 54954121, 6048604}}, - {{36803549, 14843443, 1539301, 11864366, 20201677, 1900163, - 13934231, 5128323, 11213262, 9168384}}, - }, - { - {{40828332, 11007846, 19408960, 32613674, 48515898, 29225851, - 62020803, 22449281, 20470156, 17155731}}, - {{43972811, 9282191, 14855179, 18164354, 59746048, 19145871, - 44324911, 14461607, 14042978, 5230683}}, - {{29969548, 30812838, 50396996, 25001989, 9175485, 31085458, - 21556950, 3506042, 61174973, 21104723}}, - }, - { - {{63964118, 8744660, 19704003, 4581278, 46678178, 6830682, - 45824694, 8971512, 38569675, 15326562}}, - {{47644235, 10110287, 49846336, 30050539, 43608476, 1355668, - 51585814, 15300987, 46594746, 9168259}}, - {{61755510, 4488612, 43305616, 16314346, 7780487, 17915493, - 38160505, 9601604, 33087103, 24543045}}, - }, - { - {{47665694, 18041531, 46311396, 21109108, 37284416, 10229460, - 39664535, 18553900, 61111993, 15664671}}, - {{23294591, 16921819, 44458082, 25083453, 27844203, 11461195, - 13099750, 31094076, 18151675, 13417686}}, - {{42385932, 29377914, 35958184, 5988918, 40250079, 6685064, - 1661597, 21002991, 15271675, 18101767}}, - }, - }, - { - { - {{11433023, 20325767, 8239630, 28274915, 65123427, 32828713, - 48410099, 2167543, 60187563, 20114249}}, - {{35672693, 15575145, 30436815, 12192228, 44645511, 9395378, - 57191156, 24915434, 12215109, 12028277}}, - {{14098381, 6555944, 23007258, 5757252, 51681032, 20603929, - 30123439, 4617780, 50208775, 32898803}}, - }, - { - {{63082644, 18313596, 11893167, 13718664, 52299402, 1847384, - 51288865, 10154008, 23973261, 20869958}}, - {{40577025, 29858441, 65199965, 2534300, 35238307, 17004076, - 18341389, 22134481, 32013173, 23450893}}, - {{41629544, 10876442, 55337778, 18929291, 54739296, 1838103, - 21911214, 6354752, 4425632, 32716610}}, - }, - { - {{56675475, 18941465, 22229857, 30463385, 53917697, 776728, - 49693489, 21533969, 4725004, 14044970}}, - {{19268631, 26250011, 1555348, 8692754, 45634805, 23643767, 6347389, - 32142648, 47586572, 17444675}}, - {{42244775, 12986007, 56209986, 27995847, 55796492, 33405905, - 19541417, 8180106, 9282262, 10282508}}, - }, - { - {{40903763, 4428546, 58447668, 20360168, 4098401, 19389175, - 15522534, 8372215, 5542595, 22851749}}, - {{56546323, 14895632, 26814552, 16880582, 49628109, 31065071, - 64326972, 6993760, 49014979, 10114654}}, - {{47001790, 32625013, 31422703, 10427861, 59998115, 6150668, - 38017109, 22025285, 25953724, 33448274}}, - }, - { - {{62874467, 25515139, 57989738, 3045999, 2101609, 20947138, - 19390019, 6094296, 63793585, 12831124}}, - {{51110167, 7578151, 5310217, 14408357, 33560244, 33329692, - 31575953, 6326196, 7381791, 31132593}}, - {{46206085, 3296810, 24736065, 17226043, 18374253, 7318640, - 6295303, 8082724, 51746375, 12339663}}, - }, - { - {{27724736, 2291157, 6088201, 19369634, 1792726, 5857634, 13848414, - 15768922, 25091167, 14856294}}, - {{48242193, 8331042, 24373479, 8541013, 66406866, 24284974, 12927299, - 20858939, 44926390, 24541532}}, - {{55685435, 28132841, 11632844, 3405020, 30536730, 21880393, - 39848098, 13866389, 30146206, 9142070}}, - }, - { - {{3924129, 18246916, 53291741, 23499471, 12291819, 32886066, - 39406089, 9326383, 58871006, 4171293}}, - {{51186905, 16037936, 6713787, 16606682, 45496729, 2790943, - 26396185, 3731949, 345228, 28091483}}, - {{45781307, 13448258, 25284571, 1143661, 20614966, 24705045, - 2031538, 21163201, 50855680, 19972348}}, - }, - { - {{31016192, 16832003, 26371391, 19103199, 62081514, 14854136, - 17477601, 3842657, 28012650, 17149012}}, - {{62033029, 9368965, 58546785, 28953529, 51858910, 6970559, - 57918991, 16292056, 58241707, 3507939}}, - {{29439664, 3537914, 23333589, 6997794, 49553303, 22536363, - 51899661, 18503164, 57943934, 6580395}}, - }, - }, - { - { - {{54923003, 25874643, 16438268, 10826160, 58412047, 27318820, - 17860443, 24280586, 65013061, 9304566}}, - {{20714545, 29217521, 29088194, 7406487, 11426967, 28458727, - 14792666, 18945815, 5289420, 33077305}}, - {{50443312, 22903641, 60948518, 20248671, 9192019, 31751970, - 17271489, 12349094, 26939669, 29802138}}, - }, - { - {{54218966, 9373457, 31595848, 16374215, 21471720, 13221525, - 39825369, 21205872, 63410057, 117886}}, - {{22263325, 26994382, 3984569, 22379786, 51994855, 32987646, - 28311252, 5358056, 43789084, 541963}}, - {{16259200, 3261970, 2309254, 18019958, 50223152, 28972515, - 24134069, 16848603, 53771797, 20002236}}, - }, - { - {{9378160, 20414246, 44262881, 20809167, 28198280, 26310334, - 64709179, 32837080, 690425, 14876244}}, - {{24977353, 33240048, 58884894, 20089345, 28432342, 32378079, - 54040059, 21257083, 44727879, 6618998}}, - {{65570671, 11685645, 12944378, 13682314, 42719353, 19141238, - 8044828, 19737104, 32239828, 27901670}}, - }, - { - {{48505798, 4762989, 66182614, 8885303, 38696384, 30367116, 9781646, - 23204373, 32779358, 5095274}}, - {{34100715, 28339925, 34843976, 29869215, 9460460, 24227009, - 42507207, 14506723, 21639561, 30924196}}, - {{50707921, 20442216, 25239337, 15531969, 3987758, 29055114, - 65819361, 26690896, 17874573, 558605}}, - }, - { - {{53508735, 10240080, 9171883, 16131053, 46239610, 9599699, - 33499487, 5080151, 2085892, 5119761}}, - {{44903700, 31034903, 50727262, 414690, 42089314, 2170429, - 30634760, 25190818, 35108870, 27794547}}, - {{60263160, 15791201, 8550074, 32241778, 29928808, 21462176, - 27534429, 26362287, 44757485, 12961481}}, - }, - { - {{42616785, 23983660, 10368193, 11582341, 43711571, 31309144, - 16533929, 8206996, 36914212, 28394793}}, - {{55987368, 30172197, 2307365, 6362031, 66973409, 8868176, 50273234, - 7031274, 7589640, 8945490}}, - {{34956097, 8917966, 6661220, 21876816, 65916803, 17761038, - 7251488, 22372252, 24099108, 19098262}}, - }, - { - {{5019539, 25646962, 4244126, 18840076, 40175591, 6453164, - 47990682, 20265406, 60876967, 23273695}}, - {{10853575, 10721687, 26480089, 5861829, 44113045, 1972174, - 65242217, 22996533, 63745412, 27113307}}, - {{50106456, 5906789, 221599, 26991285, 7828207, 20305514, 24362660, - 31546264, 53242455, 7421391}}, - }, - { - {{8139908, 27007935, 32257645, 27663886, 30375718, 1886181, - 45933756, 15441251, 28826358, 29431403}}, - {{6267067, 9695052, 7709135, 16950835, 34239795, 31668296, - 14795159, 25714308, 13746020, 31812384}}, - {{28584883, 7787108, 60375922, 18503702, 22846040, 25983196, - 63926927, 33190907, 4771361, 25134474}}, - }, - }, - { - { - {{24949256, 6376279, 39642383, 25379823, 48462709, 23623825, - 33543568, 21412737, 3569626, 11342593}}, - {{26514970, 4740088, 27912651, 3697550, 19331575, 22082093, 6809885, - 4608608, 7325975, 18753361}}, - {{55490446, 19000001, 42787651, 7655127, 65739590, 5214311, - 39708324, 10258389, 49462170, 25367739}}, - }, - { - {{11431185, 15823007, 26570245, 14329124, 18029990, 4796082, - 35662685, 15580663, 9280358, 29580745}}, - {{66948081, 23228174, 44253547, 29249434, 46247496, 19933429, - 34297962, 22372809, 51563772, 4387440}}, - {{46309467, 12194511, 3937617, 27748540, 39954043, 9340369, - 42594872, 8548136, 20617071, 26072431}}, - }, - { - {{66170039, 29623845, 58394552, 16124717, 24603125, 27329039, - 53333511, 21678609, 24345682, 10325460}}, - {{47253587, 31985546, 44906155, 8714033, 14007766, 6928528, - 16318175, 32543743, 4766742, 3552007}}, - {{45357481, 16823515, 1351762, 32751011, 63099193, 3950934, 3217514, - 14481909, 10988822, 29559670}}, - }, - { - {{15564307, 19242862, 3101242, 5684148, 30446780, 25503076, - 12677126, 27049089, 58813011, 13296004}}, - {{57666574, 6624295, 36809900, 21640754, 62437882, 31497052, - 31521203, 9614054, 37108040, 12074673}}, - {{4771172, 33419193, 14290748, 20464580, 27992297, 14998318, - 65694928, 31997715, 29832612, 17163397}}, - }, - { - {{7064884, 26013258, 47946901, 28486894, 48217594, 30641695, - 25825241, 5293297, 39986204, 13101589}}, - {{64810282, 2439669, 59642254, 1719964, 39841323, 17225986, - 32512468, 28236839, 36752793, 29363474}}, - {{37102324, 10162315, 33928688, 3981722, 50626726, 20484387, - 14413973, 9515896, 19568978, 9628812}}, - }, - { - {{33053803, 199357, 15894591, 1583059, 27380243, 28973997, 49269969, - 27447592, 60817077, 3437739}}, - {{48129987, 3884492, 19469877, 12726490, 15913552, 13614290, - 44147131, 70103, 7463304, 4176122}}, - {{39984863, 10659916, 11482427, 17484051, 12771466, 26919315, - 34389459, 28231680, 24216881, 5944158}}, - }, - { - {{8894125, 7450974, 64444715, 23788679, 39028346, 21165316, - 19345745, 14680796, 11632993, 5847885}}, - {{26942781, 31239115, 9129563, 28647825, 26024104, 11769399, - 55590027, 6367193, 57381634, 4782139}}, - {{19916442, 28726022, 44198159, 22140040, 25606323, 27581991, - 33253852, 8220911, 6358847, 31680575}}, - }, - { - {{801428, 31472730, 16569427, 11065167, 29875704, 96627, 7908388, - 29073952, 53570360, 1387154}}, - {{19646058, 5720633, 55692158, 12814208, 11607948, 12749789, - 14147075, 15156355, 45242033, 11835259}}, - {{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, - 15467869, 40548314, 5052482}}, - }, - }, - { - { - {{64091413, 10058205, 1980837, 3964243, 22160966, 12322533, 60677741, - 20936246, 12228556, 26550755}}, - {{32944382, 14922211, 44263970, 5188527, 21913450, 24834489, - 4001464, 13238564, 60994061, 8653814}}, - {{22865569, 28901697, 27603667, 21009037, 14348957, 8234005, - 24808405, 5719875, 28483275, 2841751}}, - }, - { - {{50687877, 32441126, 66781144, 21446575, 21886281, 18001658, - 65220897, 33238773, 19932057, 20815229}}, - {{55452759, 10087520, 58243976, 28018288, 47830290, 30498519, - 3999227, 13239134, 62331395, 19644223}}, - {{1382174, 21859713, 17266789, 9194690, 53784508, 9720080, - 20403944, 11284705, 53095046, 3093229}}, - }, - { - {{16650902, 22516500, 66044685, 1570628, 58779118, 7352752, 66806440, - 16271224, 43059443, 26862581}}, - {{45197768, 27626490, 62497547, 27994275, 35364760, 22769138, - 24123613, 15193618, 45456747, 16815042}}, - {{57172930, 29264984, 41829040, 4372841, 2087473, 10399484, - 31870908, 14690798, 17361620, 11864968}}, - }, - { - {{55801235, 6210371, 13206574, 5806320, 38091172, 19587231, - 54777658, 26067830, 41530403, 17313742}}, - {{14668443, 21284197, 26039038, 15305210, 25515617, 4542480, - 10453892, 6577524, 9145645, 27110552}}, - {{5974855, 3053895, 57675815, 23169240, 35243739, 3225008, - 59136222, 3936127, 61456591, 30504127}}, - }, - { - {{30625386, 28825032, 41552902, 20761565, 46624288, 7695098, - 17097188, 17250936, 39109084, 1803631}}, - {{63555773, 9865098, 61880298, 4272700, 61435032, 16864731, - 14911343, 12196514, 45703375, 7047411}}, - {{20093258, 9920966, 55970670, 28210574, 13161586, 12044805, - 34252013, 4124600, 34765036, 23296865}}, - }, - { - {{46320040, 14084653, 53577151, 7842146, 19119038, 19731827, - 4752376, 24839792, 45429205, 2288037}}, - {{40289628, 30270716, 29965058, 3039786, 52635099, 2540456, - 29457502, 14625692, 42289247, 12570231}}, - {{66045306, 22002608, 16920317, 12494842, 1278292, 27685323, - 45948920, 30055751, 55134159, 4724942}}, - }, - { - {{17960970, 21778898, 62967895, 23851901, 58232301, 32143814, - 54201480, 24894499, 37532563, 1903855}}, - {{23134274, 19275300, 56426866, 31942495, 20684484, 15770816, - 54119114, 3190295, 26955097, 14109738}}, - {{15308788, 5320727, 36995055, 19235554, 22902007, 7767164, - 29425325, 22276870, 31960941, 11934971}}, - }, - { - {{39713153, 8435795, 4109644, 12222639, 42480996, 14818668, - 20638173, 4875028, 10491392, 1379718}}, - {{53949449, 9197840, 3875503, 24618324, 65725151, 27674630, - 33518458, 16176658, 21432314, 12180697}}, - {{55321537, 11500837, 13787581, 19721842, 44678184, 10140204, - 1465425, 12689540, 56807545, 19681548}}, - }, - }, - { - { - {{5414091, 18168391, 46101199, 9643569, 12834970, 1186149, - 64485948, 32212200, 26128230, 6032912}}, - {{40771450, 19788269, 32496024, 19900513, 17847800, 20885276, - 3604024, 8316894, 41233830, 23117073}}, - {{3296484, 6223048, 24680646, 21307972, 44056843, 5903204, - 58246567, 28915267, 12376616, 3188849}}, - }, - { - {{29190469, 18895386, 27549112, 32370916, 3520065, 22857131, - 32049514, 26245319, 50999629, 23702124}}, - {{52364359, 24245275, 735817, 32955454, 46701176, 28496527, - 25246077, 17758763, 18640740, 32593455}}, - {{60180029, 17123636, 10361373, 5642961, 4910474, 12345252, - 35470478, 33060001, 10530746, 1053335}}, - }, - { - {{37842897, 19367626, 53570647, 21437058, 47651804, 22899047, - 35646494, 30605446, 24018830, 15026644}}, - {{44516310, 30409154, 64819587, 5953842, 53668675, 9425630, - 25310643, 13003497, 64794073, 18408815}}, - {{39688860, 32951110, 59064879, 31885314, 41016598, 13987818, - 39811242, 187898, 43942445, 31022696}}, - }, - { - {{45364466, 19743956, 1844839, 5021428, 56674465, 17642958, - 9716666, 16266922, 62038647, 726098}}, - {{29370903, 27500434, 7334070, 18212173, 9385286, 2247707, - 53446902, 28714970, 30007387, 17731091}}, - {{66172485, 16086690, 23751945, 33011114, 65941325, 28365395, 9137108, - 730663, 9835848, 4555336}}, - }, - { - {{43732429, 1410445, 44855111, 20654817, 30867634, 15826977, - 17693930, 544696, 55123566, 12422645}}, - {{31117226, 21338698, 53606025, 6561946, 57231997, 20796761, - 61990178, 29457725, 29120152, 13924425}}, - {{49707966, 19321222, 19675798, 30819676, 56101901, 27695611, - 57724924, 22236731, 7240930, 33317044}}, - }, - { - {{35747106, 22207651, 52101416, 27698213, 44655523, 21401660, - 1222335, 4389483, 3293637, 18002689}}, - {{50424044, 19110186, 11038543, 11054958, 53307689, 30215898, - 42789283, 7733546, 12796905, 27218610}}, - {{58349431, 22736595, 41689999, 10783768, 36493307, 23807620, - 38855524, 3647835, 3222231, 22393970}}, - }, - { - {{18606113, 1693100, 41660478, 18384159, 4112352, 10045021, - 23603893, 31506198, 59558087, 2484984}}, - {{9255298, 30423235, 54952701, 32550175, 13098012, 24339566, - 16377219, 31451620, 47306788, 30519729}}, - {{44379556, 7496159, 61366665, 11329248, 19991973, 30206930, - 35390715, 9936965, 37011176, 22935634}}, - }, - { - {{21878571, 28553135, 4338335, 13643897, 64071999, 13160959, - 19708896, 5415497, 59748361, 29445138}}, - {{27736842, 10103576, 12500508, 8502413, 63695848, 23920873, - 10436917, 32004156, 43449720, 25422331}}, - {{19492550, 21450067, 37426887, 32701801, 63900692, 12403436, - 30066266, 8367329, 13243957, 8709688}}, - }, - }, - { - { - {{12015105, 2801261, 28198131, 10151021, 24818120, 28811299, - 55914672, 27908697, 5150967, 7274186}}, - {{2831347, 21062286, 1478974, 6122054, 23825128, 20820846, - 31097298, 6083058, 31021603, 23760822}}, - {{64578913, 31324785, 445612, 10720828, 53259337, 22048494, - 43601132, 16354464, 15067285, 19406725}}, - }, - { - {{7840923, 14037873, 33744001, 15934015, 66380651, 29911725, - 21403987, 1057586, 47729402, 21151211}}, - {{915865, 17085158, 15608284, 24765302, 42751837, 6060029, - 49737545, 8410996, 59888403, 16527024}}, - {{32922597, 32997445, 20336073, 17369864, 10903704, 28169945, - 16957573, 52992, 23834301, 6588044}}, - }, - { - {{32752011, 11232950, 3381995, 24839566, 22652987, 22810329, - 17159698, 16689107, 46794284, 32248439}}, - {{62419196, 9166775, 41398568, 22707125, 11576751, 12733943, - 7924251, 30802151, 1976122, 26305405}}, - {{21251203, 16309901, 64125849, 26771309, 30810596, 12967303, 156041, - 30183180, 12331344, 25317235}}, - }, - { - {{8651595, 29077400, 51023227, 28557437, 13002506, 2950805, - 29054427, 28447462, 10008135, 28886531}}, - {{31486061, 15114593, 52847614, 12951353, 14369431, 26166587, - 16347320, 19892343, 8684154, 23021480}}, - {{19443825, 11385320, 24468943, 23895364, 43189605, 2187568, - 40845657, 27467510, 31316347, 14219878}}, - }, - { - {{38514374, 1193784, 32245219, 11392485, 31092169, 15722801, - 27146014, 6992409, 29126555, 9207390}}, - {{32382916, 1110093, 18477781, 11028262, 39697101, 26006320, - 62128346, 10843781, 59151264, 19118701}}, - {{2814918, 7836403, 27519878, 25686276, 46214848, 22000742, - 45614304, 8550129, 28346258, 1994730}}, - }, - { - {{47530565, 8085544, 53108345, 29605809, 2785837, 17323125, - 47591912, 7174893, 22628102, 8115180}}, - {{36703732, 955510, 55975026, 18476362, 34661776, 20276352, - 41457285, 3317159, 57165847, 930271}}, - {{51805164, 26720662, 28856489, 1357446, 23421993, 1057177, - 24091212, 32165462, 44343487, 22903716}}, - }, - { - {{44357633, 28250434, 54201256, 20785565, 51297352, 25757378, - 52269845, 17000211, 65241845, 8398969}}, - {{35139535, 2106402, 62372504, 1362500, 12813763, 16200670, - 22981545, 27263159, 18009407, 17781660}}, - {{49887941, 24009210, 39324209, 14166834, 29815394, 7444469, - 29551787, 29827013, 19288548, 1325865}}, - }, - { - {{15100138, 17718680, 43184885, 32549333, 40658671, 15509407, - 12376730, 30075286, 33166106, 25511682}}, - {{20909212, 13023121, 57899112, 16251777, 61330449, 25459517, - 12412150, 10018715, 2213263, 19676059}}, - {{32529814, 22479743, 30361438, 16864679, 57972923, 1513225, - 22922121, 6382134, 61341936, 8371347}}, - }, - }, - { - { - {{9923462, 11271500, 12616794, 3544722, 37110496, 31832805, - 12891686, 25361300, 40665920, 10486143}}, - {{44511638, 26541766, 8587002, 25296571, 4084308, 20584370, 361725, - 2610596, 43187334, 22099236}}, - {{5408392, 32417741, 62139741, 10561667, 24145918, 14240566, - 31319731, 29318891, 19985174, 30118346}}, - }, - { - {{53114407, 16616820, 14549246, 3341099, 32155958, 13648976, - 49531796, 8849296, 65030, 8370684}}, - {{58787919, 21504805, 31204562, 5839400, 46481576, 32497154, - 47665921, 6922163, 12743482, 23753914}}, - {{64747493, 12678784, 28815050, 4759974, 43215817, 4884716, - 23783145, 11038569, 18800704, 255233}}, - }, - { - {{61839187, 31780545, 13957885, 7990715, 23132995, 728773, 13393847, - 9066957, 19258688, 18800639}}, - {{64172210, 22726896, 56676774, 14516792, 63468078, 4372540, - 35173943, 2209389, 65584811, 2055793}}, - {{580882, 16705327, 5468415, 30871414, 36182444, 18858431, - 59905517, 24560042, 37087844, 7394434}}, - }, - { - {{23838809, 1822728, 51370421, 15242726, 8318092, 29821328, - 45436683, 30062226, 62287122, 14799920}}, - {{13345610, 9759151, 3371034, 17416641, 16353038, 8577942, 31129804, - 13496856, 58052846, 7402517}}, - {{2286874, 29118501, 47066405, 31546095, 53412636, 5038121, - 11006906, 17794080, 8205060, 1607563}}, - }, - { - {{14414067, 25552300, 3331829, 30346215, 22249150, 27960244, - 18364660, 30647474, 30019586, 24525154}}, - {{39420813, 1585952, 56333811, 931068, 37988643, 22552112, - 52698034, 12029092, 9944378, 8024}}, - {{4368715, 29844802, 29874199, 18531449, 46878477, 22143727, - 50994269, 32555346, 58966475, 5640029}}, - }, - { - {{10299591, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, - 16859868, 15219797, 19226649}}, - {{27425505, 27835351, 3055005, 10660664, 23458024, 595578, 51710259, - 32381236, 48766680, 9742716}}, - {{6744077, 2427284, 26042789, 2720740, 66260958, 1118973, 32324614, - 7406442, 12420155, 1994844}}, - }, - { - {{14012502, 28529712, 48724410, 23975962, 40623521, 29617992, - 54075385, 22644628, 24319928, 27108099}}, - {{16412671, 29047065, 10772640, 15929391, 50040076, 28895810, - 10555944, 23070383, 37006495, 28815383}}, - {{22397363, 25786748, 57815702, 20761563, 17166286, 23799296, - 39775798, 6199365, 21880021, 21303672}}, - }, - { - {{62825557, 5368522, 35991846, 8163388, 36785801, 3209127, - 16557151, 8890729, 8840445, 4957760}}, - {{51661137, 709326, 60189418, 22684253, 37330941, 6522331, - 45388683, 12130071, 52312361, 5005756}}, - {{64994094, 19246303, 23019041, 15765735, 41839181, 6002751, - 10183197, 20315106, 50713577, 31378319}}, - }, - }, - { - { - {{48083108, 1632004, 13466291, 25559332, 43468412, 16573536, - 35094956, 30497327, 22208661, 2000468}}, - {{3065054, 32141671, 41510189, 33192999, 49425798, 27851016, - 58944651, 11248526, 63417650, 26140247}}, - {{10379208, 27508878, 8877318, 1473647, 37817580, 21046851, - 16690914, 2553332, 63976176, 16400288}}, - }, - { - {{15716668, 1254266, 48636174, 7446273, 58659946, 6344163, - 45011593, 26268851, 26894936, 9132066}}, - {{24158868, 12938817, 11085297, 25376834, 39045385, 29097348, - 36532400, 64451, 60291780, 30861549}}, - {{13488534, 7794716, 22236231, 5989356, 25426474, 20976224, 2350709, - 30135921, 62420857, 2364225}}, - }, - { - {{16335033, 9132434, 25640582, 6678888, 1725628, 8517937, 55301840, - 21856974, 15445874, 25756331}}, - {{29004188, 25687351, 28661401, 32914020, 54314860, 25611345, - 31863254, 29418892, 66830813, 17795152}}, - {{60986784, 18687766, 38493958, 14569918, 56250865, 29962602, - 10343411, 26578142, 37280576, 22738620}}, - }, - { - {{27081650, 3463984, 14099042, 29036828, 1616302, 27348828, 29542635, - 15372179, 17293797, 960709}}, - {{20263915, 11434237, 61343429, 11236809, 13505955, 22697330, - 50997518, 6493121, 47724353, 7639713}}, - {{64278047, 18715199, 25403037, 25339236, 58791851, 17380732, - 18006286, 17510682, 29994676, 17746311}}, - }, - { - {{9769828, 5202651, 42951466, 19923039, 39057860, 21992807, - 42495722, 19693649, 35924288, 709463}}, - {{12286395, 13076066, 45333675, 32377809, 42105665, 4057651, - 35090736, 24663557, 16102006, 13205847}}, - {{13733362, 5599946, 10557076, 3195751, 61550873, 8536969, 41568694, - 8525971, 10151379, 10394400}}, - }, - { - {{4024660, 17416881, 22436261, 12276534, 58009849, 30868332, - 19698228, 11743039, 33806530, 8934413}}, - {{51229064, 29029191, 58528116, 30620370, 14634844, 32856154, - 57659786, 3137093, 55571978, 11721157}}, - {{17555920, 28540494, 8268605, 2331751, 44370049, 9761012, 9319229, - 8835153, 57903375, 32274386}}, - }, - { - {{66647436, 25724417, 20614117, 16688288, 59594098, 28747312, - 22300303, 505429, 6108462, 27371017}}, - {{62038564, 12367916, 36445330, 3234472, 32617080, 25131790, - 29880582, 20071101, 40210373, 25686972}}, - {{35133562, 5726538, 26934134, 10237677, 63935147, 32949378, - 24199303, 3795095, 7592688, 18562353}}, - }, - { - {{21594432, 18590204, 17466407, 29477210, 32537083, 2739898, - 6407723, 12018833, 38852812, 4298411}}, - {{46458361, 21592935, 39872588, 570497, 3767144, 31836892, - 13891941, 31985238, 13717173, 10805743}}, - {{52432215, 17910135, 15287173, 11927123, 24177847, 25378864, - 66312432, 14860608, 40169934, 27690595}}, - }, - }, - { - { - {{12962541, 5311799, 57048096, 11658279, 18855286, 25600231, - 13286262, 20745728, 62727807, 9882021}}, - {{18512060, 11319350, 46985740, 15090308, 18818594, 5271736, - 44380960, 3666878, 43141434, 30255002}}, - {{60319844, 30408388, 16192428, 13241070, 15898607, 19348318, - 57023983, 26893321, 64705764, 5276064}}, - }, - { - {{30169808, 28236784, 26306205, 21803573, 27814963, 7069267, - 7152851, 3684982, 1449224, 13082861}}, - {{10342807, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, - 15056736, 46092426, 25352431}}, - {{33958735, 3261607, 22745853, 7948688, 19370557, 18376767, - 40936887, 6482813, 56808784, 22494330}}, - }, - { - {{32869458, 28145887, 25609742, 15678670, 56421095, 18083360, - 26112420, 2521008, 44444576, 6904814}}, - {{29506904, 4457497, 3377935, 23757988, 36598817, 12935079, 1561737, - 3841096, 38105225, 26896789}}, - {{10340844, 26924055, 48452231, 31276001, 12621150, 20215377, - 30878496, 21730062, 41524312, 5181965}}, - }, - { - {{25940096, 20896407, 17324187, 23247058, 58437395, 15029093, - 24396252, 17103510, 64786011, 21165857}}, - {{45343161, 9916822, 65808455, 4079497, 66080518, 11909558, 1782390, - 12641087, 20603771, 26992690}}, - {{48226577, 21881051, 24849421, 11501709, 13161720, 28785558, - 1925522, 11914390, 4662781, 7820689}}, - }, - { - {{12241050, 33128450, 8132690, 9393934, 32846760, 31954812, 29749455, - 12172924, 16136752, 15264020}}, - {{56758909, 18873868, 58896884, 2330219, 49446315, 19008651, - 10658212, 6671822, 19012087, 3772772}}, - {{3753511, 30133366, 10617073, 2028709, 14841030, 26832768, 28718731, - 17791548, 20527770, 12988982}}, - }, - { - {{52286360, 27757162, 63400876, 12689772, 66209881, 22639565, - 42925817, 22989488, 3299664, 21129479}}, - {{50331161, 18301130, 57466446, 4978982, 3308785, 8755439, 6943197, - 6461331, 41525717, 8991217}}, - {{49882601, 1816361, 65435576, 27467992, 31783887, 25378441, - 34160718, 7417949, 36866577, 1507264}}, - }, - { - {{29692644, 6829891, 56610064, 4334895, 20945975, 21647936, - 38221255, 8209390, 14606362, 22907359}}, - {{63627275, 8707080, 32188102, 5672294, 22096700, 1711240, 34088169, - 9761486, 4170404, 31469107}}, - {{55521375, 14855944, 62981086, 32022574, 40459774, 15084045, - 22186522, 16002000, 52832027, 25153633}}, - }, - { - {{62297408, 13761028, 35404987, 31070512, 63796392, 7869046, - 59995292, 23934339, 13240844, 10965870}}, - {{59366301, 25297669, 52340529, 19898171, 43876480, 12387165, - 4498947, 14147411, 29514390, 4302863}}, - {{53695440, 21146572, 20757301, 19752600, 14785142, 8976368, - 62047588, 31410058, 17846987, 19582505}}, - }, - }, - { - { - {{64864412, 32799703, 62511833, 32488122, 60861691, 1455298, - 45461136, 24339642, 61886162, 12650266}}, - {{57202067, 17484121, 21134159, 12198166, 40044289, 708125, 387813, - 13770293, 47974538, 10958662}}, - {{22470984, 12369526, 23446014, 28113323, 45588061, 23855708, - 55336367, 21979976, 42025033, 4271861}}, - }, - { - {{41939299, 23500789, 47199531, 15361594, 61124506, 2159191, - 75375, 29275903, 34582642, 8469672}}, - {{15854951, 4148314, 58214974, 7259001, 11666551, 13824734, - 36577666, 2697371, 24154791, 24093489}}, - {{15446137, 17747788, 29759746, 14019369, 30811221, 23944241, - 35526855, 12840103, 24913809, 9815020}}, - }, - { - {{62399578, 27940162, 35267365, 21265538, 52665326, 10799413, - 58005188, 13438768, 18735128, 9466238}}, - {{11933045, 9281483, 5081055, 28370608, 64480701, 28648802, 59381042, - 22658328, 44380208, 16199063}}, - {{14576810, 379472, 40322331, 25237195, 37682355, 22741457, - 67006097, 1876698, 30801119, 2164795}}, - }, - { - {{15995086, 3199873, 13672555, 13712240, 47730029, 28906785, - 54027253, 18058162, 53616056, 1268051}}, - {{56818250, 29895392, 63822271, 10948817, 23037027, 3794475, - 63638526, 20954210, 50053494, 3565903}}, - {{29210069, 24135095, 61189071, 28601646, 10834810, 20226706, - 50596761, 22733718, 39946641, 19523900}}, - }, - { - {{53946955, 15508587, 16663704, 25398282, 38758921, 9019122, - 37925443, 29785008, 2244110, 19552453}}, - {{61955989, 29753495, 57802388, 27482848, 16243068, 14684434, - 41435776, 17373631, 13491505, 4641841}}, - {{10813398, 643330, 47920349, 32825515, 30292061, 16954354, - 27548446, 25833190, 14476988, 20787001}}, - }, - { - {{10292079, 9984945, 6481436, 8279905, 59857350, 7032742, 27282937, - 31910173, 39196053, 12651323}}, - {{35923332, 32741048, 22271203, 11835308, 10201545, 15351028, - 17099662, 3988035, 21721536, 30405492}}, - {{10202177, 27008593, 35735631, 23979793, 34958221, 25434748, - 54202543, 3852693, 13216206, 14842320}}, - }, - { - {{51293224, 22953365, 60569911, 26295436, 60124204, 26972653, - 35608016, 13765823, 39674467, 9900183}}, - {{14465486, 19721101, 34974879, 18815558, 39665676, 12990491, - 33046193, 15796406, 60056998, 25514317}}, - {{30924398, 25274812, 6359015, 20738097, 16508376, 9071735, - 41620263, 15413634, 9524356, 26535554}}, - }, - { - {{12274201, 20378885, 32627640, 31769106, 6736624, 13267305, - 5237659, 28444949, 15663515, 4035784}}, - {{64157555, 8903984, 17349946, 601635, 50676049, 28941875, - 53376124, 17665097, 44850385, 4659090}}, - {{50192582, 28601458, 36715152, 18395610, 20774811, 15897498, - 5736189, 15026997, 64930608, 20098846}}, - }, - }, - { - { - {{58249865, 31335375, 28571665, 23398914, 66634396, 23448733, - 63307367, 278094, 23440562, 33264224}}, - {{10226222, 27625730, 15139955, 120818, 52241171, 5218602, 32937275, - 11551483, 50536904, 26111567}}, - {{17932739, 21117156, 43069306, 10749059, 11316803, 7535897, - 22503767, 5561594, 63462240, 3898660}}, - }, - { - {{7749907, 32584865, 50769132, 33537967, 42090752, 15122142, 65535333, - 7152529, 21831162, 1245233}}, - {{26958440, 18896406, 4314585, 8346991, 61431100, 11960071, - 34519569, 32934396, 36706772, 16838219}}, - {{54942968, 9166946, 33491384, 13673479, 29787085, 13096535, - 6280834, 14587357, 44770839, 13987524}}, - }, - { - {{42758936, 7778774, 21116000, 15572597, 62275598, 28196653, - 62807965, 28429792, 59639082, 30696363}}, - {{9681908, 26817309, 35157219, 13591837, 60225043, 386949, 31622781, - 6439245, 52527852, 4091396}}, - {{58682418, 1470726, 38999185, 31957441, 3978626, 28430809, - 47486180, 12092162, 29077877, 18812444}}, - }, - { - {{5269168, 26694706, 53878652, 25533716, 25932562, 1763552, - 61502754, 28048550, 47091016, 2357888}}, - {{32264008, 18146780, 61721128, 32394338, 65017541, 29607531, - 23104803, 20684524, 5727337, 189038}}, - {{14609104, 24599962, 61108297, 16931650, 52531476, 25810533, - 40363694, 10942114, 41219933, 18669734}}, - }, - { - {{20513481, 5557931, 51504251, 7829530, 26413943, 31535028, - 45729895, 7471780, 13913677, 28416557}}, - {{41534488, 11967825, 29233242, 12948236, 60354399, 4713226, - 58167894, 14059179, 12878652, 8511905}}, - {{41452044, 3393630, 64153449, 26478905, 64858154, 9366907, - 36885446, 6812973, 5568676, 30426776}}, - }, - { - {{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, - 49700111, 20050058, 52713667, 8070817}}, - {{27117677, 23547054, 35826092, 27984343, 1127281, 12772488, - 37262958, 10483305, 55556115, 32525717}}, - {{10637467, 27866368, 5674780, 1072708, 40765276, 26572129, - 65424888, 9177852, 39615702, 15431202}}, - }, - { - {{20525126, 10892566, 54366392, 12779442, 37615830, 16150074, - 38868345, 14943141, 52052074, 25618500}}, - {{37084402, 5626925, 66557297, 23573344, 753597, 11981191, 25244767, - 30314666, 63752313, 9594023}}, - {{43356201, 2636869, 61944954, 23450613, 585133, 7877383, 11345683, - 27062142, 13352334, 22577348}}, - }, - { - {{65177046, 28146973, 3304648, 20669563, 17015805, 28677341, - 37325013, 25801949, 53893326, 33235227}}, - {{20239939, 6607058, 6203985, 3483793, 48721888, 32775202, 46385121, - 15077869, 44358105, 14523816}}, - {{27406023, 27512775, 27423595, 29057038, 4996213, 10002360, - 38266833, 29008937, 36936121, 28748764}}, - }, - }, - { - { - {{11374242, 12660715, 17861383, 21013599, 10935567, 1099227, - 53222788, 24462691, 39381819, 11358503}}, - {{54378055, 10311866, 1510375, 10778093, 64989409, 24408729, - 32676002, 11149336, 40985213, 4985767}}, - {{48012542, 341146, 60911379, 33315398, 15756972, 24757770, 66125820, - 13794113, 47694557, 17933176}}, - }, - { - {{6490062, 11940286, 25495923, 25828072, 8668372, 24803116, 3367602, - 6970005, 65417799, 24549641}}, - {{1656478, 13457317, 15370807, 6364910, 13605745, 8362338, 47934242, - 28078708, 50312267, 28522993}}, - {{44835530, 20030007, 67044178, 29220208, 48503227, 22632463, - 46537798, 26546453, 67009010, 23317098}}, - }, - { - {{17747446, 10039260, 19368299, 29503841, 46478228, 17513145, - 31992682, 17696456, 37848500, 28042460}}, - {{31932008, 28568291, 47496481, 16366579, 22023614, 88450, 11371999, - 29810185, 4882241, 22927527}}, - {{29796488, 37186, 19818052, 10115756, 55279832, 3352735, 18551198, - 3272828, 61917932, 29392022}}, - }, - { - {{12501267, 4044383, 58495907, 20162046, 34678811, 5136598, - 47878486, 30024734, 330069, 29895023}}, - {{6384877, 2899513, 17807477, 7663917, 64749976, 12363164, 25366522, - 24980540, 66837568, 12071498}}, - {{58743349, 29511910, 25133447, 29037077, 60897836, 2265926, - 34339246, 1936674, 61949167, 3829362}}, - }, - { - {{28425966, 27718999, 66531773, 28857233, 52891308, 6870929, 7921550, - 26986645, 26333139, 14267664}}, - {{56041645, 11871230, 27385719, 22994888, 62522949, 22365119, - 10004785, 24844944, 45347639, 8930323}}, - {{45911060, 17158396, 25654215, 31829035, 12282011, 11008919, - 1541940, 4757911, 40617363, 17145491}}, - }, - { - {{13537262, 25794942, 46504023, 10961926, 61186044, 20336366, - 53952279, 6217253, 51165165, 13814989}}, - {{49686272, 15157789, 18705543, 29619, 24409717, 33293956, 27361680, - 9257833, 65152338, 31777517}}, - {{42063564, 23362465, 15366584, 15166509, 54003778, 8423555, - 37937324, 12361134, 48422886, 4578289}}, - }, - { - {{24579768, 3711570, 1342322, 22374306, 40103728, 14124955, - 44564335, 14074918, 21964432, 8235257}}, - {{60580251, 31142934, 9442965, 27628844, 12025639, 32067012, - 64127349, 31885225, 13006805, 2355433}}, - {{50803946, 19949172, 60476436, 28412082, 16974358, 22643349, - 27202043, 1719366, 1141648, 20758196}}, - }, - { - {{54244920, 20334445, 58790597, 22536340, 60298718, 28710537, - 13475065, 30420460, 32674894, 13715045}}, - {{11423316, 28086373, 32344215, 8962751, 24989809, 9241752, - 53843611, 16086211, 38367983, 17912338}}, - {{65699196, 12530727, 60740138, 10847386, 19531186, 19422272, - 55399715, 7791793, 39862921, 4383346}}, - }, - }, - { - { - {{38137966, 5271446, 65842855, 23817442, 54653627, 16732598, - 62246457, 28647982, 27193556, 6245191}}, - {{51914908, 5362277, 65324971, 2695833, 4960227, 12840725, 23061898, - 3260492, 22510453, 8577507}}, - {{54476394, 11257345, 34415870, 13548176, 66387860, 10879010, - 31168030, 13952092, 37537372, 29918525}}, - }, - { - {{3877321, 23981693, 32416691, 5405324, 56104457, 19897796, - 3759768, 11935320, 5611860, 8164018}}, - {{50833043, 14667796, 15906460, 12155291, 44997715, 24514713, - 32003001, 24722143, 5773084, 25132323}}, - {{43320746, 25300131, 1950874, 8937633, 18686727, 16459170, 66203139, - 12376319, 31632953, 190926}}, - }, - { - {{42515238, 17415546, 58684872, 13378745, 14162407, 6901328, - 58820115, 4508563, 41767309, 29926903}}, - {{8884438, 27670423, 6023973, 10104341, 60227295, 28612898, 18722940, - 18768427, 65436375, 827624}}, - {{34388281, 17265135, 34605316, 7101209, 13354605, 2659080, - 65308289, 19446395, 42230385, 1541285}}, - }, - { - {{2901328, 32436745, 3880375, 23495044, 49487923, 29941650, - 45306746, 29986950, 20456844, 31669399}}, - {{27019610, 12299467, 53450576, 31951197, 54247203, 28692960, - 47568713, 28538373, 29439640, 15138866}}, - {{21536104, 26928012, 34661045, 22864223, 44700786, 5175813, - 61688824, 17193268, 7779327, 109896}}, - }, - { - {{30279725, 14648750, 59063993, 6425557, 13639621, 32810923, 28698389, - 12180118, 23177719, 33000357}}, - {{26572828, 3405927, 35407164, 12890904, 47843196, 5335865, - 60615096, 2378491, 4439158, 20275085}}, - {{44392139, 3489069, 57883598, 33221678, 18875721, 32414337, - 14819433, 20822905, 49391106, 28092994}}, - }, - { - {{62052362, 16566550, 15953661, 3767752, 56672365, 15627059, - 66287910, 2177224, 8550082, 18440267}}, - {{48635543, 16596774, 66727204, 15663610, 22860960, 15585581, - 39264755, 29971692, 43848403, 25125843}}, - {{34628313, 15707274, 58902952, 27902350, 29464557, 2713815, - 44383727, 15860481, 45206294, 1494192}}, - }, - { - {{47546773, 19467038, 41524991, 24254879, 13127841, 759709, - 21923482, 16529112, 8742704, 12967017}}, - {{38643965, 1553204, 32536856, 23080703, 42417258, 33148257, - 58194238, 30620535, 37205105, 15553882}}, - {{21877890, 3230008, 9881174, 10539357, 62311749, 2841331, 11543572, - 14513274, 19375923, 20906471}}, - }, - { - {{8832269, 19058947, 13253510, 5137575, 5037871, 4078777, 24880818, - 27331716, 2862652, 9455043}}, - {{29306751, 5123106, 20245049, 19404543, 9592565, 8447059, 65031740, - 30564351, 15511448, 4789663}}, - {{46429108, 7004546, 8824831, 24119455, 63063159, 29803695, - 61354101, 108892, 23513200, 16652362}}, - }, - }, - { - { - {{33852691, 4144781, 62632835, 26975308, 10770038, 26398890, - 60458447, 20618131, 48789665, 10212859}}, - {{2756062, 8598110, 7383731, 26694540, 22312758, 32449420, 21179800, - 2600940, 57120566, 21047965}}, - {{42463153, 13317461, 36659605, 17900503, 21365573, 22684775, - 11344423, 864440, 64609187, 16844368}}, - }, - { - {{40676061, 6148328, 49924452, 19080277, 18782928, 33278435, - 44547329, 211299, 2719757, 4940997}}, - {{65784982, 3911312, 60160120, 14759764, 37081714, 7851206, - 21690126, 8518463, 26699843, 5276295}}, - {{53958991, 27125364, 9396248, 365013, 24703301, 23065493, 1321585, - 149635, 51656090, 7159368}}, - }, - { - {{9987761, 30149673, 17507961, 9505530, 9731535, 31388918, 22356008, - 8312176, 22477218, 25151047}}, - {{18155857, 17049442, 19744715, 9006923, 15154154, 23015456, - 24256459, 28689437, 44560690, 9334108}}, - {{2986088, 28642539, 10776627, 30080588, 10620589, 26471229, - 45695018, 14253544, 44521715, 536905}}, - }, - { - {{4377737, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, - 10589625, 10838060, 18134008}}, - {{47766460, 867879, 9277171, 30335973, 52677291, 31567988, - 19295825, 17757482, 6378259, 699185}}, - {{7895007, 4057113, 60027092, 20476675, 49222032, 33231305, 66392824, - 15693154, 62063800, 20180469}}, - }, - { - {{59371282, 27685029, 52542544, 26147512, 11385653, 13201616, - 31730678, 22591592, 63190227, 23885106}}, - {{10188286, 17783598, 59772502, 13427542, 22223443, 14896287, - 30743455, 7116568, 45322357, 5427592}}, - {{696102, 13206899, 27047647, 22922350, 15285304, 23701253, - 10798489, 28975712, 19236242, 12477404}}, - }, - { - {{55879425, 11243795, 50054594, 25513566, 66320635, 25386464, - 63211194, 11180503, 43939348, 7733643}}, - {{17800790, 19518253, 40108434, 21787760, 23887826, 3149671, - 23466177, 23016261, 10322026, 15313801}}, - {{26246234, 11968874, 32263343, 28085704, 6830754, 20231401, - 51314159, 33452449, 42659621, 10890803}}, - }, - { - {{35743198, 10271362, 54448239, 27287163, 16690206, 20491888, - 52126651, 16484930, 25180797, 28219548}}, - {{66522290, 10376443, 34522450, 22268075, 19801892, 10997610, - 2276632, 9482883, 316878, 13820577}}, - {{57226037, 29044064, 64993357, 16457135, 56008783, 11674995, - 30756178, 26039378, 30696929, 29841583}}, - }, - { - {{32988917, 23951020, 12499365, 7910787, 56491607, 21622917, - 59766047, 23569034, 34759346, 7392472}}, - {{58253184, 15927860, 9866406, 29905021, 64711949, 16898650, - 36699387, 24419436, 25112946, 30627788}}, - {{64604801, 33117465, 25621773, 27875660, 15085041, 28074555, - 42223985, 20028237, 5537437, 19640113}}, - }, - }, - { - { - {{55883280, 2320284, 57524584, 10149186, 33664201, 5808647, - 52232613, 31824764, 31234589, 6090599}}, - {{57475529, 116425, 26083934, 2897444, 60744427, 30866345, 609720, - 15878753, 60138459, 24519663}}, - {{39351007, 247743, 51914090, 24551880, 23288160, 23542496, - 43239268, 6503645, 20650474, 1804084}}, - }, - { - {{39519059, 15456423, 8972517, 8469608, 15640622, 4439847, 3121995, - 23224719, 27842615, 33352104}}, - {{51801891, 2839643, 22530074, 10026331, 4602058, 5048462, 28248656, - 5031932, 55733782, 12714368}}, - {{20807691, 26283607, 29286140, 11421711, 39232341, 19686201, - 45881388, 1035545, 47375635, 12796919}}, - }, - { - {{12076880, 19253146, 58323862, 21705509, 42096072, 16400683, - 49517369, 20654993, 3480664, 18371617}}, - {{34747315, 5457596, 28548107, 7833186, 7303070, 21600887, - 42745799, 17632556, 33734809, 2771024}}, - {{45719598, 421931, 26597266, 6860826, 22486084, 26817260, - 49971378, 29344205, 42556581, 15673396}}, - }, - { - {{46924223, 2338215, 19788685, 23933476, 63107598, 24813538, - 46837679, 4733253, 3727144, 20619984}}, - {{6120100, 814863, 55314462, 32931715, 6812204, 17806661, 2019593, - 7975683, 31123697, 22595451}}, - {{30069250, 22119100, 30434653, 2958439, 18399564, 32578143, - 12296868, 9204260, 50676426, 9648164}}, - }, - { - {{32705413, 32003455, 30705657, 7451065, 55303258, 9631812, 3305266, - 5248604, 41100532, 22176930}}, - {{17219846, 2375039, 35537917, 27978816, 47649184, 9219902, 294711, - 15298639, 2662509, 17257359}}, - {{65935918, 25995736, 62742093, 29266687, 45762450, 25120105, - 32087528, 32331655, 32247247, 19164571}}, - }, - { - {{14312609, 1221556, 17395390, 24854289, 62163122, 24869796, - 38911119, 23916614, 51081240, 20175586}}, - {{65680039, 23875441, 57873182, 6549686, 59725795, 33085767, 23046501, - 9803137, 17597934, 2346211}}, - {{18510781, 15337574, 26171504, 981392, 44867312, 7827555, - 43617730, 22231079, 3059832, 21771562}}, - }, - { - {{10141598, 6082907, 17829293, 31606789, 9830091, 13613136, - 41552228, 28009845, 33606651, 3592095}}, - {{33114149, 17665080, 40583177, 20211034, 33076704, 8716171, - 1151462, 1521897, 66126199, 26716628}}, - {{34169699, 29298616, 23947180, 33230254, 34035889, 21248794, - 50471177, 3891703, 26353178, 693168}}, - }, - { - {{30374239, 1595580, 50224825, 13186930, 4600344, 406904, 9585294, - 33153764, 31375463, 14369965}}, - {{52738210, 25781902, 1510300, 6434173, 48324075, 27291703, - 32732229, 20445593, 17901440, 16011505}}, - {{18171223, 21619806, 54608461, 15197121, 56070717, 18324396, - 47936623, 17508055, 8764034, 12309598}}, - }, - }, - { - { - {{5975889, 28311244, 47649501, 23872684, 55567586, 14015781, - 43443107, 1228318, 17544096, 22960650}}, - {{5811932, 31839139, 3442886, 31285122, 48741515, 25194890, - 49064820, 18144304, 61543482, 12348899}}, - {{35709185, 11407554, 25755363, 6891399, 63851926, 14872273, - 42259511, 8141294, 56476330, 32968952}}, - }, - { - {{54433560, 694025, 62032719, 13300343, 14015258, 19103038, - 57410191, 22225381, 30944592, 1130208}}, - {{8247747, 26843490, 40546482, 25845122, 52706924, 18905521, - 4652151, 2488540, 23550156, 33283200}}, - {{17294297, 29765994, 7026747, 15626851, 22990044, 113481, 2267737, - 27646286, 66700045, 33416712}}, - }, - { - {{16091066, 17300506, 18599251, 7340678, 2137637, 32332775, - 63744702, 14550935, 3260525, 26388161}}, - {{62198760, 20221544, 18550886, 10864893, 50649539, 26262835, - 44079994, 20349526, 54360141, 2701325}}, - {{58534169, 16099414, 4629974, 17213908, 46322650, 27548999, - 57090500, 9276970, 11329923, 1862132}}, - }, - { - {{14763057, 17650824, 36190593, 3689866, 3511892, 10313526, - 45157776, 12219230, 58070901, 32614131}}, - {{8894987, 30108338, 6150752, 3013931, 301220, 15693451, 35127648, - 30644714, 51670695, 11595569}}, - {{15214943, 3537601, 40870142, 19495559, 4418656, 18323671, - 13947275, 10730794, 53619402, 29190761}}, - }, - { - {{64570558, 7682792, 32759013, 263109, 37124133, 25598979, - 44776739, 23365796, 977107, 699994}}, - {{54642373, 4195083, 57897332, 550903, 51543527, 12917919, - 19118110, 33114591, 36574330, 19216518}}, - {{31788442, 19046775, 4799988, 7372237, 8808585, 18806489, 9408236, - 23502657, 12493931, 28145115}}, - }, - { - {{41428258, 5260743, 47873055, 27269961, 63412921, 16566086, - 27218280, 2607121, 29375955, 6024730}}, - {{842132, 30759739, 62345482, 24831616, 26332017, 21148791, - 11831879, 6985184, 57168503, 2854095}}, - {{62261602, 25585100, 2516241, 27706719, 9695690, 26333246, 16512644, - 960770, 12121869, 16648078}}, - }, - { - {{51890212, 14667095, 53772635, 2013716, 30598287, 33090295, - 35603941, 25672367, 20237805, 2838411}}, - {{47820798, 4453151, 15298546, 17376044, 22115042, 17581828, - 12544293, 20083975, 1068880, 21054527}}, - {{57549981, 17035596, 33238497, 13506958, 30505848, 32439836, - 58621956, 30924378, 12521377, 4845654}}, - }, - { - {{38910324, 10744107, 64150484, 10199663, 7759311, 20465832, - 3409347, 32681032, 60626557, 20668561}}, - {{43547042, 6230155, 46726851, 10655313, 43068279, 21933259, - 10477733, 32314216, 63995636, 13974497}}, - {{12966261, 15550616, 35069916, 31939085, 21025979, 32924988, - 5642324, 7188737, 18895762, 12629579}}, - }, - }, - { - { - {{14741879, 18607545, 22177207, 21833195, 1279740, 8058600, - 11758140, 789443, 32195181, 3895677}}, - {{10758205, 15755439, 62598914, 9243697, 62229442, 6879878, 64904289, - 29988312, 58126794, 4429646}}, - {{64654951, 15725972, 46672522, 23143759, 61304955, 22514211, - 59972993, 21911536, 18047435, 18272689}}, - }, - { - {{41935844, 22247266, 29759955, 11776784, 44846481, 17733976, - 10993113, 20703595, 49488162, 24145963}}, - {{21987233, 700364, 42603816, 14972007, 59334599, 27836036, - 32155025, 2581431, 37149879, 8773374}}, - {{41540495, 454462, 53896929, 16126714, 25240068, 8594567, - 20656846, 12017935, 59234475, 19634276}}, - }, - { - {{6028163, 6263078, 36097058, 22252721, 66289944, 2461771, - 35267690, 28086389, 65387075, 30777706}}, - {{54829870, 16624276, 987579, 27631834, 32908202, 1248608, 7719845, - 29387734, 28408819, 6816612}}, - {{56750770, 25316602, 19549650, 21385210, 22082622, 16147817, - 20613181, 13982702, 56769294, 5067942}}, - }, - { - {{36602878, 29732664, 12074680, 13582412, 47230892, 2443950, - 47389578, 12746131, 5331210, 23448488}}, - {{30528792, 3601899, 65151774, 4619784, 39747042, 18118043, - 24180792, 20984038, 27679907, 31905504}}, - {{9402385, 19597367, 32834042, 10838634, 40528714, 20317236, - 26653273, 24868867, 22611443, 20839026}}, - }, - { - {{22190590, 1118029, 22736441, 15130463, 36648172, 27563110, - 19189624, 28905490, 4854858, 6622139}}, - {{58798126, 30600981, 58846284, 30166382, 56707132, 33282502, - 13424425, 29987205, 26404408, 13001963}}, - {{35867026, 18138731, 64114613, 8939345, 11562230, 20713762, - 41044498, 21932711, 51703708, 11020692}}, - }, - { - {{1866042, 25604943, 59210214, 23253421, 12483314, 13477547, - 3175636, 21130269, 28761761, 1406734}}, - {{66660290, 31776765, 13018550, 3194501, 57528444, 22392694, - 24760584, 29207344, 25577410, 20175752}}, - {{42818486, 4759344, 66418211, 31701615, 2066746, 10693769, - 37513074, 9884935, 57739938, 4745409}}, - }, - { - {{57967561, 6049713, 47577803, 29213020, 35848065, 9944275, - 51646856, 22242579, 10931923, 21622501}}, - {{50547351, 14112679, 59096219, 4817317, 59068400, 22139825, - 44255434, 10856640, 46638094, 13434653}}, - {{22759470, 23480998, 50342599, 31683009, 13637441, 23386341, - 1765143, 20900106, 28445306, 28189722}}, - }, - { - {{29875063, 12493613, 2795536, 29768102, 1710619, 15181182, - 56913147, 24765756, 9074233, 1167180}}, - {{40903181, 11014232, 57266213, 30918946, 40200743, 7532293, - 48391976, 24018933, 3843902, 9367684}}, - {{56139269, 27150720, 9591133, 9582310, 11349256, 108879, 16235123, - 8601684, 66969667, 4242894}}, - }, - }, - { - { - {{22092954, 20363309, 65066070, 21585919, 32186752, 22037044, - 60534522, 2470659, 39691498, 16625500}}, - {{56051142, 3042015, 13770083, 24296510, 584235, 33009577, 59338006, - 2602724, 39757248, 14247412}}, - {{6314156, 23289540, 34336361, 15957556, 56951134, 168749, - 58490057, 14290060, 27108877, 32373552}}, - }, - { - {{58522267, 26383465, 13241781, 10960156, 34117849, 19759835, - 33547975, 22495543, 39960412, 981873}}, - {{22833421, 9293594, 34459416, 19935764, 57971897, 14756818, - 44180005, 19583651, 56629059, 17356469}}, - {{59340277, 3326785, 38997067, 10783823, 19178761, 14905060, - 22680049, 13906969, 51175174, 3797898}}, - }, - { - {{21721337, 29341686, 54902740, 9310181, 63226625, 19901321, - 23740223, 30845200, 20491982, 25512280}}, - {{9209251, 18419377, 53852306, 27386633, 66377847, 15289672, - 25947805, 15286587, 30997318, 26851369}}, - {{7392013, 16618386, 23946583, 25514540, 53843699, 32020573, - 52911418, 31232855, 17649997, 33304352}}, - }, - { - {{57807776, 19360604, 30609525, 30504889, 41933794, 32270679, - 51867297, 24028707, 64875610, 7662145}}, - {{49550191, 1763593, 33994528, 15908609, 37067994, 21380136, - 7335079, 25082233, 63934189, 3440182}}, - {{47219164, 27577423, 42997570, 23865561, 10799742, 16982475, - 40449, 29122597, 4862399, 1133}}, - }, - { - {{34252636, 25680474, 61686474, 14860949, 50789833, 7956141, - 7258061, 311861, 36513873, 26175010}}, - {{63335436, 31988495, 28985339, 7499440, 24445838, 9325937, 29727763, - 16527196, 18278453, 15405622}}, - {{62726958, 8508651, 47210498, 29880007, 61124410, 15149969, - 53795266, 843522, 45233802, 13626196}}, - }, - { - {{2281448, 20067377, 56193445, 30944521, 1879357, 16164207, - 56324982, 3953791, 13340839, 15928663}}, - {{31727126, 26374577, 48671360, 25270779, 2875792, 17164102, - 41838969, 26539605, 43656557, 5964752}}, - {{4100401, 27594980, 49929526, 6017713, 48403027, 12227140, - 40424029, 11344143, 2538215, 25983677}}, - }, - { - {{57675240, 6123112, 11159803, 31397824, 30016279, 14966241, - 46633881, 1485420, 66479608, 17595569}}, - {{40304287, 4260918, 11851389, 9658551, 35091757, 16367491, - 46903439, 20363143, 11659921, 22439314}}, - {{26180377, 10015009, 36264640, 24973138, 5418196, 9480663, 2231568, - 23384352, 33100371, 32248261}}, - }, - { - {{15121094, 28352561, 56718958, 15427820, 39598927, 17561924, - 21670946, 4486675, 61177054, 19088051}}, - {{16166467, 24070699, 56004733, 6023907, 35182066, 32189508, - 2340059, 17299464, 56373093, 23514607}}, - {{28042865, 29997343, 54982337, 12259705, 63391366, 26608532, - 6766452, 24864833, 18036435, 5803270}}, - }, - }, - { - { - {{66291264, 6763911, 11803561, 1585585, 10958447, 30883267, 23855390, - 4598332, 60949433, 19436993}}, - {{36077558, 19298237, 17332028, 31170912, 31312681, 27587249, - 696308, 50292, 47013125, 11763583}}, - {{66514282, 31040148, 34874710, 12643979, 12650761, 14811489, 665117, - 20940800, 47335652, 22840869}}, - }, - { - {{30464590, 22291560, 62981387, 20819953, 19835326, 26448819, - 42712688, 2075772, 50088707, 992470}}, - {{18357166, 26559999, 7766381, 16342475, 37783946, 411173, 14578841, - 8080033, 55534529, 22952821}}, - {{19598397, 10334610, 12555054, 2555664, 18821899, 23214652, - 21873262, 16014234, 26224780, 16452269}}, - }, - { - {{36884939, 5145195, 5944548, 16385966, 3976735, 2009897, 55731060, - 25936245, 46575034, 3698649}}, - {{14187449, 3448569, 56472628, 22743496, 44444983, 30120835, - 7268409, 22663988, 27394300, 12015369}}, - {{19695742, 16087646, 28032085, 12999827, 6817792, 11427614, - 20244189, 32241655, 53849736, 30151970}}, - }, - { - {{30860084, 12735208, 65220619, 28854697, 50133957, 2256939, - 58942851, 12298311, 58558340, 23160969}}, - {{61389038, 22309106, 65198214, 15569034, 26642876, 25966672, - 61319509, 18435777, 62132699, 12651792}}, - {{64260450, 9953420, 11531313, 28271553, 26895122, 20857343, - 53990043, 17036529, 9768697, 31021214}}, - }, - { - {{42389405, 1894650, 66821166, 28850346, 15348718, 25397902, - 32767512, 12765450, 4940095, 10678226}}, - {{18860224, 15980149, 48121624, 31991861, 40875851, 22482575, - 59264981, 13944023, 42736516, 16582018}}, - {{51604604, 4970267, 37215820, 4175592, 46115652, 31354675, - 55404809, 15444559, 56105103, 7989036}}, - }, - { - {{31490433, 5568061, 64696061, 2182382, 34772017, 4531685, - 35030595, 6200205, 47422751, 18754260}}, - {{49800177, 17674491, 35586086, 33551600, 34221481, 16375548, - 8680158, 17182719, 28550067, 26697300}}, - {{38981977, 27866340, 16837844, 31733974, 60258182, 12700015, - 37068883, 4364037, 1155602, 5988841}}, - }, - { - {{21890435, 20281525, 54484852, 12154348, 59276991, 15300495, - 23148983, 29083951, 24618406, 8283181}}, - {{33972757, 23041680, 9975415, 6841041, 35549071, 16356535, - 3070187, 26528504, 1466168, 10740210}}, - {{65599446, 18066246, 53605478, 22898515, 32799043, 909394, - 53169961, 27774712, 34944214, 18227391}}, - }, - { - {{3960804, 19286629, 39082773, 17636380, 47704005, 13146867, - 15567327, 951507, 63848543, 32980496}}, - {{24740822, 5052253, 37014733, 8961360, 25877428, 6165135, - 42740684, 14397371, 59728495, 27410326}}, - {{38220480, 3510802, 39005586, 32395953, 55870735, 22922977, - 51667400, 19101303, 65483377, 27059617}}, - }, - }, - { - { - {{793280, 24323954, 8836301, 27318725, 39747955, 31184838, 33152842, - 28669181, 57202663, 32932579}}, - {{5666214, 525582, 20782575, 25516013, 42570364, 14657739, 16099374, - 1468826, 60937436, 18367850}}, - {{62249590, 29775088, 64191105, 26806412, 7778749, 11688288, - 36704511, 23683193, 65549940, 23690785}}, - }, - { - {{10896313, 25834728, 824274, 472601, 47648556, 3009586, 25248958, - 14783338, 36527388, 17796587}}, - {{10566929, 12612572, 35164652, 11118702, 54475488, 12362878, - 21752402, 8822496, 24003793, 14264025}}, - {{27713843, 26198459, 56100623, 9227529, 27050101, 2504721, - 23886875, 20436907, 13958494, 27821979}}, - }, - { - {{43627235, 4867225, 39861736, 3900520, 29838369, 25342141, - 35219464, 23512650, 7340520, 18144364}}, - {{4646495, 25543308, 44342840, 22021777, 23184552, 8566613, - 31366726, 32173371, 52042079, 23179239}}, - {{49838347, 12723031, 50115803, 14878793, 21619651, 27356856, - 27584816, 3093888, 58265170, 3849920}}, - }, - { - {{58043933, 2103171, 25561640, 18428694, 61869039, 9582957, - 32477045, 24536477, 5002293, 18004173}}, - {{55051311, 22376525, 21115584, 20189277, 8808711, 21523724, - 16489529, 13378448, 41263148, 12741425}}, - {{61162478, 10645102, 36197278, 15390283, 63821882, 26435754, - 24306471, 15852464, 28834118, 25908360}}, - }, - { - {{49773116, 24447374, 42577584, 9434952, 58636780, 32971069, - 54018092, 455840, 20461858, 5491305}}, - {{13669229, 17458950, 54626889, 23351392, 52539093, 21661233, - 42112877, 11293806, 38520660, 24132599}}, - {{28497909, 6272777, 34085870, 14470569, 8906179, 32328802, - 18504673, 19389266, 29867744, 24758489}}, - }, - { - {{50901822, 13517195, 39309234, 19856633, 24009063, 27180541, - 60741263, 20379039, 22853428, 29542421}}, - {{24191359, 16712145, 53177067, 15217830, 14542237, 1646131, - 18603514, 22516545, 12876622, 31441985}}, - {{17902668, 4518229, 66697162, 30725184, 26878216, 5258055, 54248111, - 608396, 16031844, 3723494}}, - }, - { - {{38476072, 12763727, 46662418, 7577503, 33001348, 20536687, - 17558841, 25681542, 23896953, 29240187}}, - {{47103464, 21542479, 31520463, 605201, 2543521, 5991821, 64163800, - 7229063, 57189218, 24727572}}, - {{28816026, 298879, 38943848, 17633493, 19000927, 31888542, - 54428030, 30605106, 49057085, 31471516}}, - }, - { - {{16000882, 33209536, 3493091, 22107234, 37604268, 20394642, - 12577739, 16041268, 47393624, 7847706}}, - {{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, - 34252933, 27035413, 57088296, 3852847}}, - {{55678375, 15697595, 45987307, 29133784, 5386313, 15063598, - 16514493, 17622322, 29330898, 18478208}}, - }, - }, - { - { - {{41609129, 29175637, 51885955, 26653220, 16615730, 2051784, - 3303702, 15490, 39560068, 12314390}}, - {{15683501, 27551389, 18109119, 23573784, 15337967, 27556609, - 50391428, 15921865, 16103996, 29823217}}, - {{43939021, 22773182, 13588191, 31925625, 63310306, 32479502, - 47835256, 5402698, 37293151, 23713330}}, - }, - { - {{23190676, 2384583, 34394524, 3462153, 37205209, 32025299, - 55842007, 8911516, 41903005, 2739712}}, - {{21374101, 30000182, 33584214, 9874410, 15377179, 11831242, - 33578960, 6134906, 4931255, 11987849}}, - {{67101132, 30575573, 50885377, 7277596, 105524, 33232381, 35628324, - 13861387, 37032554, 10117929}}, - }, - { - {{37607694, 22809559, 40945095, 13051538, 41483300, 5089642, - 60783361, 6704078, 12890019, 15728940}}, - {{45136504, 21783052, 66157804, 29135591, 14704839, 2695116, 903376, - 23126293, 12885166, 8311031}}, - {{49592363, 5352193, 10384213, 19742774, 7506450, 13453191, - 26423267, 4384730, 1888765, 28119028}}, - }, - { - {{41291507, 30447119, 53614264, 30371925, 30896458, 19632703, - 34857219, 20846562, 47644429, 30214188}}, - {{43500868, 30888657, 66582772, 4651135, 5765089, 4618330, 6092245, - 14845197, 17151279, 23700316}}, - {{42278406, 20820711, 51942885, 10367249, 37577956, 33289075, - 22825804, 26467153, 50242379, 16176524}}, - }, - { - {{43525589, 6564960, 20063689, 3798228, 62368686, 7359224, 2006182, - 23191006, 38362610, 23356922}}, - {{56482264, 29068029, 53788301, 28429114, 3432135, 27161203, - 23632036, 31613822, 32808309, 1099883}}, - {{15030958, 5768825, 39657628, 30667132, 60681485, 18193060, - 51830967, 26745081, 2051440, 18328567}}, - }, - { - {{63746541, 26315059, 7517889, 9824992, 23555850, 295369, 5148398, - 19400244, 44422509, 16633659}}, - {{4577067, 16802144, 13249840, 18250104, 19958762, 19017158, - 18559669, 22794883, 8402477, 23690159}}, - {{38702534, 32502850, 40318708, 32646733, 49896449, 22523642, - 9453450, 18574360, 17983009, 9967138}}, - }, - { - {{41346370, 6524721, 26585488, 9969270, 24709298, 1220360, 65430874, - 7806336, 17507396, 3651560}}, - {{56688388, 29436320, 14584638, 15971087, 51340543, 8861009, - 26556809, 27979875, 48555541, 22197296}}, - {{2839082, 14284142, 4029895, 3472686, 14402957, 12689363, 40466743, - 8459446, 61503401, 25932490}}, - }, - { - {{62269556, 30018987, 9744960, 2871048, 25113978, 3187018, 41998051, - 32705365, 17258083, 25576693}}, - {{18164541, 22959256, 49953981, 32012014, 19237077, 23809137, - 23357532, 18337424, 26908269, 12150756}}, - {{36843994, 25906566, 5112248, 26517760, 65609056, 26580174, 43167, - 28016731, 34806789, 16215818}}, - }, - }, - { - { - {{60209940, 9824393, 54804085, 29153342, 35711722, 27277596, - 32574488, 12532905, 59605792, 24879084}}, - {{39765323, 17038963, 39957339, 22831480, 946345, 16291093, - 254968, 7168080, 21676107, 31611404}}, - {{21260942, 25129680, 50276977, 21633609, 43430902, 3968120, - 63456915, 27338965, 63552672, 25641356}}, - }, - { - {{16544735, 13250366, 50304436, 15546241, 62525861, 12757257, - 64646556, 24874095, 48201831, 23891632}}, - {{64693606, 17976703, 18312302, 4964443, 51836334, 20900867, - 26820650, 16690659, 25459437, 28989823}}, - {{41964155, 11425019, 28423002, 22533875, 60963942, 17728207, - 9142794, 31162830, 60676445, 31909614}}, - }, - { - {{44004212, 6253475, 16964147, 29785560, 41994891, 21257994, - 39651638, 17209773, 6335691, 7249989}}, - {{36775618, 13979674, 7503222, 21186118, 55152142, 28932738, - 36836594, 2682241, 25993170, 21075909}}, - {{4364628, 5930691, 32304656, 23509878, 59054082, 15091130, - 22857016, 22955477, 31820367, 15075278}}, - }, - { - {{31879134, 24635739, 17258760, 90626, 59067028, 28636722, 24162787, - 23903546, 49138625, 12833044}}, - {{19073683, 14851414, 42705695, 21694263, 7625277, 11091125, - 47489674, 2074448, 57694925, 14905376}}, - {{24483648, 21618865, 64589997, 22007013, 65555733, 15355505, - 41826784, 9253128, 27628530, 25998952}}, - }, - { - {{17597607, 8340603, 19355617, 552187, 26198470, 30377849, 4593323, - 24396850, 52997988, 15297015}}, - {{510886, 14337390, 35323607, 16638631, 6328095, 2713355, 46891447, - 21690211, 8683220, 2921426}}, - {{18606791, 11874196, 27155355, 28272950, 43077121, 6265445, - 41930624, 32275507, 4674689, 13890525}}, - }, - { - {{13609624, 13069022, 39736503, 20498523, 24360585, 9592974, - 14977157, 9835105, 4389687, 288396}}, - {{9922506, 33035038, 13613106, 5883594, 48350519, 33120168, 54804801, - 8317627, 23388070, 16052080}}, - {{12719997, 11937594, 35138804, 28525742, 26900119, 8561328, - 46953177, 21921452, 52354592, 22741539}}, - }, - { - {{15961858, 14150409, 26716931, 32888600, 44314535, 13603568, - 11829573, 7467844, 38286736, 929274}}, - {{11038231, 21972036, 39798381, 26237869, 56610336, 17246600, - 43629330, 24182562, 45715720, 2465073}}, - {{20017144, 29231206, 27915241, 1529148, 12396362, 15675764, - 13817261, 23896366, 2463390, 28932292}}, - }, - { - {{50749986, 20890520, 55043680, 4996453, 65852442, 1073571, - 9583558, 12851107, 4003896, 12673717}}, - {{65377275, 18398561, 63845933, 16143081, 19294135, 13385325, - 14741514, 24450706, 7903885, 2348101}}, - {{24536016, 17039225, 12715591, 29692277, 1511292, 10047386, - 63266518, 26425272, 38731325, 10048126}}, - }, - }, - { - { - {{54486638, 27349611, 30718824, 2591312, 56491836, 12192839, - 18873298, 26257342, 34811107, 15221631}}, - {{40630742, 22450567, 11546243, 31701949, 9180879, 7656409, - 45764914, 2095754, 29769758, 6593415}}, - {{35114656, 30646970, 4176911, 3264766, 12538965, 32686321, 26312344, - 27435754, 30958053, 8292160}}, - }, - { - {{31429803, 19595316, 29173531, 15632448, 12174511, 30794338, - 32808830, 3977186, 26143136, 30405556}}, - {{22648882, 1402143, 44308880, 13746058, 7936347, 365344, 58440231, - 31879998, 63350620, 31249806}}, - {{51616947, 8012312, 64594134, 20851969, 43143017, 23300402, - 65496150, 32018862, 50444388, 8194477}}, - }, - { - {{27338066, 26047012, 59694639, 10140404, 48082437, 26964542, - 27277190, 8855376, 28572286, 3005164}}, - {{26287105, 4821776, 25476601, 29408529, 63344350, 17765447, - 49100281, 1182478, 41014043, 20474836}}, - {{59937691, 3178079, 23970071, 6201893, 49913287, 29065239, - 45232588, 19571804, 32208682, 32356184}}, - }, - { - {{50451143, 2817642, 56822502, 14811297, 6024667, 13349505, - 39793360, 23056589, 39436278, 22014573}}, - {{15941010, 24148500, 45741813, 8062054, 31876073, 33315803, - 51830470, 32110002, 15397330, 29424239}}, - {{8934485, 20068965, 43822466, 20131190, 34662773, 14047985, - 31170398, 32113411, 39603297, 15087183}}, - }, - { - {{48751602, 31397940, 24524912, 16876564, 15520426, 27193656, - 51606457, 11461895, 16788528, 27685490}}, - {{65161459, 16013772, 21750665, 3714552, 49707082, 17498998, - 63338576, 23231111, 31322513, 21938797}}, - {{21426636, 27904214, 53460576, 28206894, 38296674, 28633461, - 48833472, 18933017, 13040861, 21441484}}, - }, - { - {{11293895, 12478086, 39972463, 15083749, 37801443, 14748871, - 14555558, 20137329, 1613710, 4896935}}, - {{41213962, 15323293, 58619073, 25496531, 25967125, 20128972, - 2825959, 28657387, 43137087, 22287016}}, - {{51184079, 28324551, 49665331, 6410663, 3622847, 10243618, - 20615400, 12405433, 43355834, 25118015}}, - }, - { - {{60017550, 12556207, 46917512, 9025186, 50036385, 4333800, - 4378436, 2432030, 23097949, 32988414}}, - {{4565804, 17528778, 20084411, 25711615, 1724998, 189254, 24767264, - 10103221, 48596551, 2424777}}, - {{366633, 21577626, 8173089, 26664313, 30788633, 5745705, 59940186, - 1344108, 63466311, 12412658}}, - }, - { - {{43107073, 7690285, 14929416, 33386175, 34898028, 20141445, - 24162696, 18227928, 63967362, 11179384}}, - {{18289503, 18829478, 8056944, 16430056, 45379140, 7842513, - 61107423, 32067534, 48424218, 22110928}}, - {{476239, 6601091, 60956074, 23831056, 17503544, 28690532, 27672958, - 13403813, 11052904, 5219329}}, - }, - }, - { - { - {{20678527, 25178694, 34436965, 8849122, 62099106, 14574751, - 31186971, 29580702, 9014761, 24975376}}, - {{53464795, 23204192, 51146355, 5075807, 65594203, 22019831, - 34006363, 9160279, 8473550, 30297594}}, - {{24900749, 14435722, 17209120, 18261891, 44516588, 9878982, - 59419555, 17218610, 42540382, 11788947}}, - }, - { - {{63990690, 22159237, 53306774, 14797440, 9652448, 26708528, - 47071426, 10410732, 42540394, 32095740}}, - {{51449703, 16736705, 44641714, 10215877, 58011687, 7563910, - 11871841, 21049238, 48595538, 8464117}}, - {{43708233, 8348506, 52522913, 32692717, 63158658, 27181012, - 14325288, 8628612, 33313881, 25183915}}, - }, - { - {{46921872, 28586496, 22367355, 5271547, 66011747, 28765593, - 42303196, 23317577, 58168128, 27736162}}, - {{60160060, 31759219, 34483180, 17533252, 32635413, 26180187, - 15989196, 20716244, 28358191, 29300528}}, - {{43547083, 30755372, 34757181, 31892468, 57961144, 10429266, - 50471180, 4072015, 61757200, 5596588}}, - }, - { - {{38872266, 30164383, 12312895, 6213178, 3117142, 16078565, - 29266239, 2557221, 1768301, 15373193}}, - {{59865506, 30307471, 62515396, 26001078, 66980936, 32642186, 66017961, - 29049440, 42448372, 3442909}}, - {{36898293, 5124042, 14181784, 8197961, 18964734, 21615339, - 22597930, 7176455, 48523386, 13365929}}, - }, - { - {{59231455, 32054473, 8324672, 4690079, 6261860, 890446, 24538107, - 24984246, 57419264, 30522764}}, - {{25008885, 22782833, 62803832, 23916421, 16265035, 15721635, - 683793, 21730648, 15723478, 18390951}}, - {{57448220, 12374378, 40101865, 26528283, 59384749, 21239917, - 11879681, 5400171, 519526, 32318556}}, - }, - { - {{22258397, 17222199, 59239046, 14613015, 44588609, 30603508, - 46754982, 7315966, 16648397, 7605640}}, - {{59027556, 25089834, 58885552, 9719709, 19259459, 18206220, - 23994941, 28272877, 57640015, 4763277}}, - {{45409620, 9220968, 51378240, 1084136, 41632757, 30702041, - 31088446, 25789909, 55752334, 728111}}, - }, - { - {{26047201, 21802961, 60208540, 17032633, 24092067, 9158119, - 62835319, 20998873, 37743427, 28056159}}, - {{17510331, 33231575, 5854288, 8403524, 17133918, 30441820, 38997856, - 12327944, 10750447, 10014012}}, - {{56796096, 3936951, 9156313, 24656749, 16498691, 32559785, - 39627812, 32887699, 3424690, 7540221}}, - }, - { - {{30322361, 26590322, 11361004, 29411115, 7433303, 4989748, 60037442, - 17237212, 57864598, 15258045}}, - {{13054543, 30774935, 19155473, 469045, 54626067, 4566041, 5631406, - 2711395, 1062915, 28418087}}, - {{47868616, 22299832, 37599834, 26054466, 61273100, 13005410, - 61042375, 12194496, 32960380, 1459310}}, - }, - }, - { - { - {{19852015, 7027924, 23669353, 10020366, 8586503, 26896525, 394196, - 27452547, 18638002, 22379495}}, - {{31395515, 15098109, 26581030, 8030562, 50580950, 28547297, - 9012485, 25970078, 60465776, 28111795}}, - {{57916680, 31207054, 65111764, 4529533, 25766844, 607986, 67095642, - 9677542, 34813975, 27098423}}, - }, - { - {{64664349, 33404494, 29348901, 8186665, 1873760, 12489863, 36174285, - 25714739, 59256019, 25416002}}, - {{51872508, 18120922, 7766469, 746860, 26346930, 23332670, - 39775412, 10754587, 57677388, 5203575}}, - {{31834314, 14135496, 66338857, 5159117, 20917671, 16786336, - 59640890, 26216907, 31809242, 7347066}}, - }, - { - {{57502122, 21680191, 20414458, 13033986, 13716524, 21862551, - 19797969, 21343177, 15192875, 31466942}}, - {{54445282, 31372712, 1168161, 29749623, 26747876, 19416341, - 10609329, 12694420, 33473243, 20172328}}, - {{33184999, 11180355, 15832085, 22169002, 65475192, 225883, - 15089336, 22530529, 60973201, 14480052}}, - }, - { - {{31308717, 27934434, 31030839, 31657333, 15674546, 26971549, - 5496207, 13685227, 27595050, 8737275}}, - {{46790012, 18404192, 10933842, 17376410, 8335351, 26008410, - 36100512, 20943827, 26498113, 66511}}, - {{22644435, 24792703, 50437087, 4884561, 64003250, 19995065, - 30540765, 29267685, 53781076, 26039336}}, - }, - { - {{39091017, 9834844, 18617207, 30873120, 63706907, 20246925, - 8205539, 13585437, 49981399, 15115438}}, - {{23711543, 32881517, 31206560, 25191721, 6164646, 23844445, - 33572981, 32128335, 8236920, 16492939}}, - {{43198286, 20038905, 40809380, 29050590, 25005589, 25867162, - 19574901, 10071562, 6708380, 27332008}}, - }, - { - {{2101372, 28624378, 19702730, 2367575, 51681697, 1047674, 5301017, - 9328700, 29955601, 21876122}}, - {{3096359, 9271816, 45488000, 18032587, 52260867, 25961494, - 41216721, 20918836, 57191288, 6216607}}, - {{34493015, 338662, 41913253, 2510421, 37895298, 19734218, - 24822829, 27407865, 40341383, 7525078}}, - }, - { - {{44042215, 19568808, 16133486, 25658254, 63719298, 778787, - 66198528, 30771936, 47722230, 11994100}}, - {{21691500, 19929806, 66467532, 19187410, 3285880, 30070836, - 42044197, 9718257, 59631427, 13381417}}, - {{18445390, 29352196, 14979845, 11622458, 65381754, 29971451, - 23111647, 27179185, 28535281, 15779576}}, - }, - { - {{30098034, 3089662, 57874477, 16662134, 45801924, 11308410, - 53040410, 12021729, 9955285, 17251076}}, - {{9734894, 18977602, 59635230, 24415696, 2060391, 11313496, - 48682835, 9924398, 20194861, 13380996}}, - {{40730762, 25589224, 44941042, 15789296, 49053522, 27385639, - 65123949, 15707770, 26342023, 10146099}}, - }, - }, - { - { - {{41091971, 33334488, 21339190, 33513044, 19745255, 30675732, - 37471583, 2227039, 21612326, 33008704}}, - {{54031477, 1184227, 23562814, 27583990, 46757619, 27205717, - 25764460, 12243797, 46252298, 11649657}}, - {{57077370, 11262625, 27384172, 2271902, 26947504, 17556661, 39943, - 6114064, 33514190, 2333242}}, - }, - { - {{45675257, 21132610, 8119781, 7219913, 45278342, 24538297, - 60429113, 20883793, 24350577, 20104431}}, - {{62992557, 22282898, 43222677, 4843614, 37020525, 690622, - 35572776, 23147595, 8317859, 12352766}}, - {{18200138, 19078521, 34021104, 30857812, 43406342, 24451920, - 43556767, 31266881, 20712162, 6719373}}, - }, - { - {{26656189, 6075253, 59250308, 1886071, 38764821, 4262325, 11117530, - 29791222, 26224234, 30256974}}, - {{49939907, 18700334, 63713187, 17184554, 47154818, 14050419, - 21728352, 9493610, 18620611, 17125804}}, - {{53785524, 13325348, 11432106, 5964811, 18609221, 6062965, - 61839393, 23828875, 36407290, 17074774}}, - }, - { - {{43248326, 22321272, 26961356, 1640861, 34695752, 16816491, - 12248508, 28313793, 13735341, 1934062}}, - {{25089769, 6742589, 17081145, 20148166, 21909292, 17486451, - 51972569, 29789085, 45830866, 5473615}}, - {{31883658, 25593331, 1083431, 21982029, 22828470, 13290673, - 59983779, 12469655, 29111212, 28103418}}, - }, - { - {{24244947, 18504025, 40845887, 2791539, 52111265, 16666677, - 24367466, 6388839, 56813277, 452382}}, - {{41468082, 30136590, 5217915, 16224624, 19987036, 29472163, - 42872612, 27639183, 15766061, 8407814}}, - {{46701865, 13990230, 15495425, 16395525, 5377168, 15166495, - 58191841, 29165478, 59040954, 2276717}}, - }, - { - {{30157899, 12924066, 49396814, 9245752, 19895028, 3368142, - 43281277, 5096218, 22740376, 26251015}}, - {{2041139, 19298082, 7783686, 13876377, 41161879, 20201972, - 24051123, 13742383, 51471265, 13295221}}, - {{33338218, 25048699, 12532112, 7977527, 9106186, 31839181, - 49388668, 28941459, 62657506, 18884987}}, - }, - { - {{47063583, 5454096, 52762316, 6447145, 28862071, 1883651, - 64639598, 29412551, 7770568, 9620597}}, - {{23208049, 7979712, 33071466, 8149229, 1758231, 22719437, 30945527, - 31860109, 33606523, 18786461}}, - {{1439939, 17283952, 66028874, 32760649, 4625401, 10647766, 62065063, - 1220117, 30494170, 22113633}}, - }, - { - {{62071265, 20526136, 64138304, 30492664, 15640973, 26852766, - 40369837, 926049, 65424525, 20220784}}, - {{13908495, 30005160, 30919927, 27280607, 45587000, 7989038, - 9021034, 9078865, 3353509, 4033511}}, - {{37445433, 18440821, 32259990, 33209950, 24295848, 20642309, - 23161162, 8839127, 27485041, 7356032}}, - }, - }, - { - { - {{9661008, 705443, 11980065, 28184278, 65480320, 14661172, 60762722, - 2625014, 28431036, 16782598}}, - {{43269631, 25243016, 41163352, 7480957, 49427195, 25200248, - 44562891, 14150564, 15970762, 4099461}}, - {{29262576, 16756590, 26350592, 24760869, 8529670, 22346382, - 13617292, 23617289, 11465738, 8317062}}, - }, - { - {{41615764, 26591503, 32500199, 24135381, 44070139, 31252209, - 14898636, 3848455, 20969334, 28396916}}, - {{46724414, 19206718, 48772458, 13884721, 34069410, 2842113, - 45498038, 29904543, 11177094, 14989547}}, - {{42612143, 21838415, 16959895, 2278463, 12066309, 10137771, - 13515641, 2581286, 38621356, 9930239}}, - }, - { - {{49357223, 31456605, 16544299, 20545132, 51194056, 18605350, - 18345766, 20150679, 16291480, 28240394}}, - {{33879670, 2553287, 32678213, 9875984, 8534129, 6889387, 57432090, - 6957616, 4368891, 9788741}}, - {{16660737, 7281060, 56278106, 12911819, 20108584, 25452756, - 45386327, 24941283, 16250551, 22443329}}, - }, - { - {{47343357, 2390525, 50557833, 14161979, 1905286, 6414907, 4689584, - 10604807, 36918461, 4782746}}, - {{65754325, 14736940, 59741422, 20261545, 7710541, 19398842, - 57127292, 4383044, 22546403, 437323}}, - {{31665558, 21373968, 50922033, 1491338, 48740239, 3294681, - 27343084, 2786261, 36475274, 19457415}}, - }, - { - {{52641566, 32870716, 33734756, 7448551, 19294360, 14334329, - 47418233, 2355318, 47824193, 27440058}}, - {{15121312, 17758270, 6377019, 27523071, 56310752, 20596586, - 18952176, 15496498, 37728731, 11754227}}, - {{64471568, 20071356, 8488726, 19250536, 12728760, 31931939, - 7141595, 11724556, 22761615, 23420291}}, - }, - { - {{16918416, 11729663, 49025285, 3022986, 36093132, 20214772, - 38367678, 21327038, 32851221, 11717399}}, - {{11166615, 7338049, 60386341, 4531519, 37640192, 26252376, - 31474878, 3483633, 65915689, 29523600}}, - {{66923210, 9921304, 31456609, 20017994, 55095045, 13348922, - 33142652, 6546660, 47123585, 29606055}}, - }, - { - {{34648249, 11266711, 55911757, 25655328, 31703693, 3855903, - 58571733, 20721383, 36336829, 18068118}}, - {{49102387, 12709067, 3991746, 27075244, 45617340, 23004006, - 35973516, 17504552, 10928916, 3011958}}, - {{60151107, 17960094, 31696058, 334240, 29576716, 14796075, - 36277808, 20749251, 18008030, 10258577}}, - }, - { - {{44660220, 15655568, 7018479, 29144429, 36794597, 32352840, - 65255398, 1367119, 25127874, 6671743}}, - {{29701166, 19180498, 56230743, 9279287, 67091296, 13127209, - 21382910, 11042292, 25838796, 4642684}}, - {{46678630, 14955536, 42982517, 8124618, 61739576, 27563961, - 30468146, 19653792, 18423288, 4177476}}, - }, - }, -}; - static uint8_t negative(signed char b) { uint32_t x = b; x >>= 31; // 1: yes; 0: no @@ -3698,73 +2047,6 @@ static void slide(signed char *r, const uint8_t *a) { } } -static const ge_precomp Bi[8] = { - { - {{25967493, 19198397, 29566455, 3660896, 54414519, 4014786, 27544626, - 21800161, 61029707, 2047604}}, - {{54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, - 5043384, 19500929, 18085054}}, - {{58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, - 11864899, 42594502, 29115885}}, - }, - { - {{15636272, 23865875, 24204772, 25642034, 616976, 16869170, 27787599, - 18782243, 28944399, 32004408}}, - {{16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, - 21778470, 7689661, 11199574}}, - {{30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, - 10017326, 49359771, 23634074}}, - }, - { - {{10861363, 11473154, 27284546, 1981175, 37044515, 12577860, 32867885, - 14515107, 51670560, 10819379}}, - {{4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, - 12483687, 54440373, 5581305}}, - {{19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, - 13850243, 43430843, 17738489}}, - }, - { - {{5153727, 9909285, 1723747, 30776558, 30523604, 5516873, 19480852, - 5230134, 43156425, 18378665}}, - {{36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, - 16520125, 30598449, 7715701}}, - {{28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, - 1370707, 29794553, 32145132}}, - }, - { - {{44589871, 26862249, 14201701, 24808930, 43598457, 8844725, 18474211, - 32192982, 54046167, 13821876}}, - {{60653668, 25714560, 3374701, 28813570, 40010246, 22982724, 31655027, - 26342105, 18853321, 19333481}}, - {{4566811, 20590564, 38133974, 21313742, 59506191, 30723862, 58594505, - 23123294, 2207752, 30344648}}, - }, - { - {{41954014, 29368610, 29681143, 7868801, 60254203, 24130566, 54671499, - 32891431, 35997400, 17421995}}, - {{25576264, 30851218, 7349803, 21739588, 16472781, 9300885, 3844789, - 15725684, 171356, 6466918}}, - {{23103977, 13316479, 9739013, 17404951, 817874, 18515490, 8965338, - 19466374, 36393951, 16193876}}, - }, - { - {{33587053, 3180712, 64714734, 14003686, 50205390, 17283591, 17238397, - 4729455, 49034351, 9256799}}, - {{41926547, 29380300, 32336397, 5036987, 45872047, 11360616, 22616405, - 9761698, 47281666, 630304}}, - {{53388152, 2639452, 42871404, 26147950, 9494426, 27780403, 60554312, - 17593437, 64659607, 19263131}}, - }, - { - {{63957664, 28508356, 9282713, 6866145, 35201802, 32691408, 48168288, - 15033783, 25105118, 25659556}}, - {{42782475, 15950225, 35307649, 18961608, 55446126, 28463506, - 1573891, 30928545, 2198789, 17749813}}, - {{64009494, 10324966, 64867251, 7453182, 61661885, 30818928, 53296841, - 17317989, 34647629, 21263748}}, - }, -}; - // r = a * A + b * B // where a = a[0]+256*a[1]+...+256^31 a[31]. // and b = b[0]+256*b[1]+...+256^31 b[31]. @@ -3848,7 +2130,7 @@ static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a, // s[0]+256*s[1]+...+256^31*s[31] = s mod l // where l = 2^252 + 27742317777372353535851937790883648493. // Overwrites s in place. -void x25519_sc_reduce(uint8_t *s) { +void x25519_sc_reduce(uint8_t s[64]) { int64_t s0 = 2097151 & load_3(s); int64_t s1 = 2097151 & (load_4(s + 2) >> 5); int64_t s2 = 2097151 & (load_3(s + 5) >> 2); @@ -4676,8 +2958,8 @@ void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) { ED25519_keypair_from_seed(out_public_key, out_private_key, seed); } -int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, - const uint8_t private_key[64]) { +int ED25519_sign(uint8_t out_sig[64], const uint8_t *message, + size_t message_len, const uint8_t private_key[64]) { uint8_t az[SHA512_DIGEST_LENGTH]; SHA512(private_key, 32, az); @@ -4728,8 +3010,31 @@ int ED25519_verify(const uint8_t *message, size_t message_len, OPENSSL_memcpy(pkcopy, public_key, 32); uint8_t rcopy[32]; OPENSSL_memcpy(rcopy, signature, 32); - uint8_t scopy[32]; - OPENSSL_memcpy(scopy, signature + 32, 32); + union { + uint64_t u64[4]; + uint8_t u8[32]; + } scopy; + OPENSSL_memcpy(&scopy.u8[0], signature + 32, 32); + + // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in + // the range [0, order) in order to prevent signature malleability. + + // kOrder is the order of Curve25519 in little-endian form. + static const uint64_t kOrder[4] = { + UINT64_C(0x5812631a5cf5d3ed), + UINT64_C(0x14def9dea2f79cd6), + 0, + UINT64_C(0x1000000000000000), + }; + for (size_t i = 3;; i--) { + if (scopy.u64[i] > kOrder[i]) { + return 0; + } else if (scopy.u64[i] < kOrder[i]) { + break; + } else if (i == 0) { + return 0; + } + } SHA512_CTX hash_ctx; SHA512_Init(&hash_ctx); @@ -4742,7 +3047,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, x25519_sc_reduce(h); ge_p2 R; - ge_double_scalarmult_vartime(&R, h, &A, scopy); + ge_double_scalarmult_vartime(&R, h, &A, scopy.u8); uint8_t rcheck[32]; x25519_ge_tobytes(rcheck, &R); @@ -4769,154 +3074,6 @@ void ED25519_keypair_from_seed(uint8_t out_public_key[32], } -#if defined(BORINGSSL_X25519_X86_64) - -static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32], - const uint8_t point[32]) { - x25519_x86_64(out, scalar, point); -} - -#else - -// Replace (f,g) with (g,f) if b == 1; -// replace (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -static void fe_cswap(fe *f, fe *g, unsigned int b) { - b = 0-b; - unsigned i; - for (i = 0; i < 10; i++) { - uint32_t x = f->v[i] ^ g->v[i]; - x &= b; - f->v[i] ^= x; - g->v[i] ^= x; - } -} - -// NOTE: based on fiat-crypto fe_mul, edited for in2=121666, 0, 0.. -static void fe_mul_121666_impl(uint32_t out[10], const uint32_t in1[10]) { - assert_fe_loose(in1); - { const uint32_t x20 = in1[9]; - { const uint32_t x21 = in1[8]; - { const uint32_t x19 = in1[7]; - { const uint32_t x17 = in1[6]; - { const uint32_t x15 = in1[5]; - { const uint32_t x13 = in1[4]; - { const uint32_t x11 = in1[3]; - { const uint32_t x9 = in1[2]; - { const uint32_t x7 = in1[1]; - { const uint32_t x5 = in1[0]; - { const uint32_t x38 = 0; - { const uint32_t x39 = 0; - { const uint32_t x37 = 0; - { const uint32_t x35 = 0; - { const uint32_t x33 = 0; - { const uint32_t x31 = 0; - { const uint32_t x29 = 0; - { const uint32_t x27 = 0; - { const uint32_t x25 = 0; - { const uint32_t x23 = 121666; - { uint64_t x40 = ((uint64_t)x23 * x5); - { uint64_t x41 = (((uint64_t)x23 * x7) + ((uint64_t)x25 * x5)); - { uint64_t x42 = ((((uint64_t)(0x2 * x25) * x7) + ((uint64_t)x23 * x9)) + ((uint64_t)x27 * x5)); - { uint64_t x43 = (((((uint64_t)x25 * x9) + ((uint64_t)x27 * x7)) + ((uint64_t)x23 * x11)) + ((uint64_t)x29 * x5)); - { uint64_t x44 = (((((uint64_t)x27 * x9) + (0x2 * (((uint64_t)x25 * x11) + ((uint64_t)x29 * x7)))) + ((uint64_t)x23 * x13)) + ((uint64_t)x31 * x5)); - { uint64_t x45 = (((((((uint64_t)x27 * x11) + ((uint64_t)x29 * x9)) + ((uint64_t)x25 * x13)) + ((uint64_t)x31 * x7)) + ((uint64_t)x23 * x15)) + ((uint64_t)x33 * x5)); - { uint64_t x46 = (((((0x2 * ((((uint64_t)x29 * x11) + ((uint64_t)x25 * x15)) + ((uint64_t)x33 * x7))) + ((uint64_t)x27 * x13)) + ((uint64_t)x31 * x9)) + ((uint64_t)x23 * x17)) + ((uint64_t)x35 * x5)); - { uint64_t x47 = (((((((((uint64_t)x29 * x13) + ((uint64_t)x31 * x11)) + ((uint64_t)x27 * x15)) + ((uint64_t)x33 * x9)) + ((uint64_t)x25 * x17)) + ((uint64_t)x35 * x7)) + ((uint64_t)x23 * x19)) + ((uint64_t)x37 * x5)); - { uint64_t x48 = (((((((uint64_t)x31 * x13) + (0x2 * (((((uint64_t)x29 * x15) + ((uint64_t)x33 * x11)) + ((uint64_t)x25 * x19)) + ((uint64_t)x37 * x7)))) + ((uint64_t)x27 * x17)) + ((uint64_t)x35 * x9)) + ((uint64_t)x23 * x21)) + ((uint64_t)x39 * x5)); - { uint64_t x49 = (((((((((((uint64_t)x31 * x15) + ((uint64_t)x33 * x13)) + ((uint64_t)x29 * x17)) + ((uint64_t)x35 * x11)) + ((uint64_t)x27 * x19)) + ((uint64_t)x37 * x9)) + ((uint64_t)x25 * x21)) + ((uint64_t)x39 * x7)) + ((uint64_t)x23 * x20)) + ((uint64_t)x38 * x5)); - { uint64_t x50 = (((((0x2 * ((((((uint64_t)x33 * x15) + ((uint64_t)x29 * x19)) + ((uint64_t)x37 * x11)) + ((uint64_t)x25 * x20)) + ((uint64_t)x38 * x7))) + ((uint64_t)x31 * x17)) + ((uint64_t)x35 * x13)) + ((uint64_t)x27 * x21)) + ((uint64_t)x39 * x9)); - { uint64_t x51 = (((((((((uint64_t)x33 * x17) + ((uint64_t)x35 * x15)) + ((uint64_t)x31 * x19)) + ((uint64_t)x37 * x13)) + ((uint64_t)x29 * x21)) + ((uint64_t)x39 * x11)) + ((uint64_t)x27 * x20)) + ((uint64_t)x38 * x9)); - { uint64_t x52 = (((((uint64_t)x35 * x17) + (0x2 * (((((uint64_t)x33 * x19) + ((uint64_t)x37 * x15)) + ((uint64_t)x29 * x20)) + ((uint64_t)x38 * x11)))) + ((uint64_t)x31 * x21)) + ((uint64_t)x39 * x13)); - { uint64_t x53 = (((((((uint64_t)x35 * x19) + ((uint64_t)x37 * x17)) + ((uint64_t)x33 * x21)) + ((uint64_t)x39 * x15)) + ((uint64_t)x31 * x20)) + ((uint64_t)x38 * x13)); - { uint64_t x54 = (((0x2 * ((((uint64_t)x37 * x19) + ((uint64_t)x33 * x20)) + ((uint64_t)x38 * x15))) + ((uint64_t)x35 * x21)) + ((uint64_t)x39 * x17)); - { uint64_t x55 = (((((uint64_t)x37 * x21) + ((uint64_t)x39 * x19)) + ((uint64_t)x35 * x20)) + ((uint64_t)x38 * x17)); - { uint64_t x56 = (((uint64_t)x39 * x21) + (0x2 * (((uint64_t)x37 * x20) + ((uint64_t)x38 * x19)))); - { uint64_t x57 = (((uint64_t)x39 * x20) + ((uint64_t)x38 * x21)); - { uint64_t x58 = ((uint64_t)(0x2 * x38) * x20); - { uint64_t x59 = (x48 + (x58 << 0x4)); - { uint64_t x60 = (x59 + (x58 << 0x1)); - { uint64_t x61 = (x60 + x58); - { uint64_t x62 = (x47 + (x57 << 0x4)); - { uint64_t x63 = (x62 + (x57 << 0x1)); - { uint64_t x64 = (x63 + x57); - { uint64_t x65 = (x46 + (x56 << 0x4)); - { uint64_t x66 = (x65 + (x56 << 0x1)); - { uint64_t x67 = (x66 + x56); - { uint64_t x68 = (x45 + (x55 << 0x4)); - { uint64_t x69 = (x68 + (x55 << 0x1)); - { uint64_t x70 = (x69 + x55); - { uint64_t x71 = (x44 + (x54 << 0x4)); - { uint64_t x72 = (x71 + (x54 << 0x1)); - { uint64_t x73 = (x72 + x54); - { uint64_t x74 = (x43 + (x53 << 0x4)); - { uint64_t x75 = (x74 + (x53 << 0x1)); - { uint64_t x76 = (x75 + x53); - { uint64_t x77 = (x42 + (x52 << 0x4)); - { uint64_t x78 = (x77 + (x52 << 0x1)); - { uint64_t x79 = (x78 + x52); - { uint64_t x80 = (x41 + (x51 << 0x4)); - { uint64_t x81 = (x80 + (x51 << 0x1)); - { uint64_t x82 = (x81 + x51); - { uint64_t x83 = (x40 + (x50 << 0x4)); - { uint64_t x84 = (x83 + (x50 << 0x1)); - { uint64_t x85 = (x84 + x50); - { uint64_t x86 = (x85 >> 0x1a); - { uint32_t x87 = ((uint32_t)x85 & 0x3ffffff); - { uint64_t x88 = (x86 + x82); - { uint64_t x89 = (x88 >> 0x19); - { uint32_t x90 = ((uint32_t)x88 & 0x1ffffff); - { uint64_t x91 = (x89 + x79); - { uint64_t x92 = (x91 >> 0x1a); - { uint32_t x93 = ((uint32_t)x91 & 0x3ffffff); - { uint64_t x94 = (x92 + x76); - { uint64_t x95 = (x94 >> 0x19); - { uint32_t x96 = ((uint32_t)x94 & 0x1ffffff); - { uint64_t x97 = (x95 + x73); - { uint64_t x98 = (x97 >> 0x1a); - { uint32_t x99 = ((uint32_t)x97 & 0x3ffffff); - { uint64_t x100 = (x98 + x70); - { uint64_t x101 = (x100 >> 0x19); - { uint32_t x102 = ((uint32_t)x100 & 0x1ffffff); - { uint64_t x103 = (x101 + x67); - { uint64_t x104 = (x103 >> 0x1a); - { uint32_t x105 = ((uint32_t)x103 & 0x3ffffff); - { uint64_t x106 = (x104 + x64); - { uint64_t x107 = (x106 >> 0x19); - { uint32_t x108 = ((uint32_t)x106 & 0x1ffffff); - { uint64_t x109 = (x107 + x61); - { uint64_t x110 = (x109 >> 0x1a); - { uint32_t x111 = ((uint32_t)x109 & 0x3ffffff); - { uint64_t x112 = (x110 + x49); - { uint64_t x113 = (x112 >> 0x19); - { uint32_t x114 = ((uint32_t)x112 & 0x1ffffff); - { uint64_t x115 = (x87 + (0x13 * x113)); - { uint32_t x116 = (uint32_t) (x115 >> 0x1a); - { uint32_t x117 = ((uint32_t)x115 & 0x3ffffff); - { uint32_t x118 = (x116 + x90); - { uint32_t x119 = (x118 >> 0x19); - { uint32_t x120 = (x118 & 0x1ffffff); - out[0] = x117; - out[1] = x120; - out[2] = (x119 + x93); - out[3] = x96; - out[4] = x99; - out[5] = x102; - out[6] = x105; - out[7] = x108; - out[8] = x111; - out[9] = x114; - }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} - assert_fe(out); -} - -static void fe_mul121666(fe *h, const fe_loose *f) { - assert_fe_loose(f->v); - fe_mul_121666_impl(h->v, f->v); - assert_fe(h->v); -} - static void x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32]) { @@ -4928,6 +3085,24 @@ static void x25519_scalar_mult_generic(uint8_t out[32], e[0] &= 248; e[31] &= 127; e[31] |= 64; + + // The following implementation was transcribed to Coq and proven to + // correspond to unary scalar multiplication in affine coordinates given that + // x1 != 0 is the x coordinate of some point on the curve. It was also checked + // in Coq that doing a ladderstep with x1 = x3 = 0 gives z2' = z3' = 0, and z2 + // = z3 = 0 gives z2' = z3' = 0. The statement was quantified over the + // underlying field, so it applies to Curve25519 itself and the quadratic + // twist of Curve25519. It was not proven in Coq that prime-field arithmetic + // correctly simulates extension-field arithmetic on prime-field values. + // The decoding of the byte array representation of e was not considered. + // Specification of Montgomery curves in affine coordinates: + // + // Proof that these form a group that is isomorphic to a Weierstrass curve: + // + // Coq transcription and correctness proof of the loop (where scalarbits=255): + // + // + // preconditions: 0 <= e < 2^255 (not necessarily e < order), fe_invert(0) = 0 fe_frombytes(&x1, point); fe_1(&x2); fe_0(&z2); @@ -4937,11 +3112,22 @@ static void x25519_scalar_mult_generic(uint8_t out[32], unsigned swap = 0; int pos; for (pos = 254; pos >= 0; --pos) { + // loop invariant as of right before the test, for the case where x1 != 0: + // pos >= -1; if z2 = 0 then x2 is nonzero; if z3 = 0 then x3 is nonzero + // let r := e >> (pos+1) in the following equalities of projective points: + // to_xz (r*P) === if swap then (x3, z3) else (x2, z2) + // to_xz ((r+1)*P) === if swap then (x2, z2) else (x3, z3) + // x1 is the nonzero x coordinate of the nonzero point (r*P-(r+1)*P) unsigned b = 1 & (e[pos / 8] >> (pos & 7)); swap ^= b; fe_cswap(&x2, &x3, swap); fe_cswap(&z2, &z3, swap); swap = b; + // Coq transcription of ladderstep formula (called from transcribed loop): + // + // + // x1 != 0 + // x1 = 0 fe_sub(&tmp0l, &x3, &z3); fe_sub(&tmp1l, &x2, &z2); fe_add(&x2l, &x2, &z2); @@ -4961,6 +3147,7 @@ static void x25519_scalar_mult_generic(uint8_t out[32], fe_mul_ttt(&z3, &x1, &z2); fe_mul_tll(&z2, &tmp1l, &tmp0l); } + // here pos=-1, so r=e, so to_xz (e*P) === if swap then (x3, z3) else (x2, z2) fe_cswap(&x2, &x3, swap); fe_cswap(&z2, &z3, swap); @@ -4981,9 +3168,6 @@ static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32], x25519_scalar_mult_generic(out, scalar, point); } -#endif // BORINGSSL_X25519_X86_64 - - void X25519_keypair(uint8_t out_public_value[32], uint8_t out_private_key[32]) { RAND_bytes(out_private_key, 32); @@ -5015,20 +3199,6 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0; } -#if defined(BORINGSSL_X25519_X86_64) - -// When |BORINGSSL_X25519_X86_64| is set, base point multiplication is done with -// the Montgomery ladder because it's faster. Otherwise it's done using the -// Ed25519 tables. - -void X25519_public_from_private(uint8_t out_public_value[32], - const uint8_t private_key[32]) { - static const uint8_t kMongomeryBasePoint[32] = {9}; - x25519_scalar_mult(out_public_value, private_key, kMongomeryBasePoint); -} - -#else - void X25519_public_from_private(uint8_t out_public_value[32], const uint8_t private_key[32]) { #if defined(BORINGSSL_X25519_NEON) @@ -5058,5 +3228,3 @@ void X25519_public_from_private(uint8_t out_public_value[32], fe_mul_tlt(&zminusy_inv, &zplusy, &zminusy_inv); fe_tobytes(out_public_value, &zminusy_inv); } - -#endif // BORINGSSL_X25519_X86_64 diff --git a/Sources/BoringSSL/third_party/fiat/curve25519_tables.h b/Sources/BoringSSL/third_party/fiat/curve25519_tables.h new file mode 100644 index 000000000..c293e95dc --- /dev/null +++ b/Sources/BoringSSL/third_party/fiat/curve25519_tables.h @@ -0,0 +1,7880 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// This file is generated from +// ./make_curve25519_tables.py > curve25519_tables.h + + +static const fe d = {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 929955233495203, 466365720129213, 1662059464998953, 2033849074728123, + 1442794654840575 +#else + 56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712, + 48412415, 21499315 +#endif +}}; + +static const fe sqrtm1 = {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, + 765476049583133 +#else + 34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654, + 31548777, 326685, 11406482 +#endif +}}; + +static const fe d2 = {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, + 633789495995903 +#else + 45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047, + 27058993, 29715967, 9444199 +#endif +}}; + +#if defined(OPENSSL_SMALL) + +// This block of code replaces the standard base-point table with a much smaller +// one. The standard table is 30,720 bytes while this one is just 960. +// +// This table contains 15 pairs of group elements, (x, y), where each field +// element is serialised with |fe_tobytes|. If |i| is the index of the group +// element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀ +// is the most significant bit). The value of the group element is then: +// (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator. +static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = { + 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, + 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e, + 0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4, + 0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62, + 0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba, + 0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd, + 0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03, 0xa2, 0xfb, 0xcc, 0x61, + 0x67, 0x06, 0x70, 0x1a, 0xc4, 0x78, 0x3a, 0xff, 0x32, 0x62, 0xdd, 0x2c, + 0xab, 0x50, 0x19, 0x3b, 0xf2, 0x9b, 0x7d, 0xb8, 0xfd, 0x4f, 0x29, 0x9c, + 0xa7, 0x91, 0xba, 0x0e, 0x46, 0x5e, 0x51, 0xfe, 0x1d, 0xbf, 0xe5, 0xe5, + 0x9b, 0x95, 0x0d, 0x67, 0xf8, 0xd1, 0xb5, 0x5a, 0xa1, 0x93, 0x2c, 0xc3, + 0xde, 0x0e, 0x97, 0x85, 0x2d, 0x7f, 0xea, 0xab, 0x3e, 0x47, 0x30, 0x18, + 0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, + 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, + 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c, 0x6b, 0xa6, 0xf5, 0x4b, + 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, + 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, + 0xe6, 0x99, 0x2c, 0x5f, 0x9a, 0x96, 0x0c, 0x68, 0x29, 0xfd, 0xe2, 0xfb, + 0xe6, 0xbc, 0xec, 0x31, 0x08, 0xec, 0xe6, 0xb0, 0x53, 0x60, 0xc3, 0x8c, + 0xbe, 0xc1, 0xb3, 0x8a, 0x8f, 0xe4, 0x88, 0x2b, 0x55, 0xe5, 0x64, 0x6e, + 0x9b, 0xd0, 0xaf, 0x7b, 0x64, 0x2a, 0x35, 0x25, 0x10, 0x52, 0xc5, 0x9e, + 0x58, 0x11, 0x39, 0x36, 0x45, 0x51, 0xb8, 0x39, 0x93, 0xfc, 0x9d, 0x6a, + 0xbe, 0x58, 0xcb, 0xa4, 0x0f, 0x51, 0x3c, 0x38, 0x05, 0xca, 0xab, 0x43, + 0x63, 0x0e, 0xf3, 0x8b, 0x41, 0xa6, 0xf8, 0x9b, 0x53, 0x70, 0x80, 0x53, + 0x86, 0x5e, 0x8f, 0xe3, 0xc3, 0x0d, 0x18, 0xc8, 0x4b, 0x34, 0x1f, 0xd8, + 0x1d, 0xbc, 0xf2, 0x6d, 0x34, 0x3a, 0xbe, 0xdf, 0xd9, 0xf6, 0xf3, 0x89, + 0xa1, 0xe1, 0x94, 0x9f, 0x5d, 0x4c, 0x5d, 0xe9, 0xa1, 0x49, 0x92, 0xef, + 0x0e, 0x53, 0x81, 0x89, 0x58, 0x87, 0xa6, 0x37, 0xf1, 0xdd, 0x62, 0x60, + 0x63, 0x5a, 0x9d, 0x1b, 0x8c, 0xc6, 0x7d, 0x52, 0xea, 0x70, 0x09, 0x6a, + 0xe1, 0x32, 0xf3, 0x73, 0x21, 0x1f, 0x07, 0x7b, 0x7c, 0x9b, 0x49, 0xd8, + 0xc0, 0xf3, 0x25, 0x72, 0x6f, 0x9d, 0xed, 0x31, 0x67, 0x36, 0x36, 0x54, + 0x40, 0x92, 0x71, 0xe6, 0x11, 0x28, 0x11, 0xad, 0x93, 0x32, 0x85, 0x7b, + 0x3e, 0xb7, 0x3b, 0x49, 0x13, 0x1c, 0x07, 0xb0, 0x2e, 0x93, 0xaa, 0xfd, + 0xfd, 0x28, 0x47, 0x3d, 0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, + 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, + 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b, + 0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, + 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, + 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61, 0x38, 0x68, 0xb0, 0x07, + 0xa3, 0xfc, 0xcc, 0x85, 0x10, 0x7f, 0x4c, 0x65, 0x65, 0xb3, 0xfa, 0xfa, + 0xa5, 0x53, 0x6f, 0xdb, 0x74, 0x4c, 0x56, 0x46, 0x03, 0xe2, 0xd5, 0x7a, + 0x29, 0x1c, 0xc6, 0x02, 0xbc, 0x59, 0xf2, 0x04, 0x75, 0x63, 0xc0, 0x84, + 0x2f, 0x60, 0x1c, 0x67, 0x76, 0xfd, 0x63, 0x86, 0xf3, 0xfa, 0xbf, 0xdc, + 0xd2, 0x2d, 0x90, 0x91, 0xbd, 0x33, 0xa9, 0xe5, 0x66, 0x0c, 0xda, 0x42, + 0x27, 0xca, 0xf4, 0x66, 0xc2, 0xec, 0x92, 0x14, 0x57, 0x06, 0x63, 0xd0, + 0x4d, 0x15, 0x06, 0xeb, 0x69, 0x58, 0x4f, 0x77, 0xc5, 0x8b, 0xc7, 0xf0, + 0x8e, 0xed, 0x64, 0xa0, 0xb3, 0x3c, 0x66, 0x71, 0xc6, 0x2d, 0xda, 0x0a, + 0x0d, 0xfe, 0x70, 0x27, 0x64, 0xf8, 0x27, 0xfa, 0xf6, 0x5f, 0x30, 0xa5, + 0x0d, 0x6c, 0xda, 0xf2, 0x62, 0x5e, 0x78, 0x47, 0xd3, 0x66, 0x00, 0x1c, + 0xfd, 0x56, 0x1f, 0x5d, 0x3f, 0x6f, 0xf4, 0x4c, 0xd8, 0xfd, 0x0e, 0x27, + 0xc9, 0x5c, 0x2b, 0xbc, 0xc0, 0xa4, 0xe7, 0x23, 0x29, 0x02, 0x9f, 0x31, + 0xd6, 0xe9, 0xd7, 0x96, 0xf4, 0xe0, 0x5e, 0x0b, 0x0e, 0x13, 0xee, 0x3c, + 0x09, 0xed, 0xf2, 0x3d, 0x76, 0x91, 0xc3, 0xa4, 0x97, 0xae, 0xd4, 0x87, + 0xd0, 0x5d, 0xf6, 0x18, 0x47, 0x1f, 0x1d, 0x67, 0xf2, 0xcf, 0x63, 0xa0, + 0x91, 0x27, 0xf8, 0x93, 0x45, 0x75, 0x23, 0x3f, 0xd1, 0xf1, 0xad, 0x23, + 0xdd, 0x64, 0x93, 0x96, 0x41, 0x70, 0x7f, 0xf7, 0xf5, 0xa9, 0x89, 0xa2, + 0x34, 0xb0, 0x8d, 0x1b, 0xae, 0x19, 0x15, 0x49, 0x58, 0x23, 0x6d, 0x87, + 0x15, 0x4f, 0x81, 0x76, 0xfb, 0x23, 0xb5, 0xea, 0xcf, 0xac, 0x54, 0x8d, + 0x4e, 0x42, 0x2f, 0xeb, 0x0f, 0x63, 0xdb, 0x68, 0x37, 0xa8, 0xcf, 0x8b, + 0xab, 0xf5, 0xa4, 0x6e, 0x96, 0x2a, 0xb2, 0xd6, 0xbe, 0x9e, 0xbd, 0x0d, + 0xb4, 0x42, 0xa9, 0xcf, 0x01, 0x83, 0x8a, 0x17, 0x47, 0x76, 0xc4, 0xc6, + 0x83, 0x04, 0x95, 0x0b, 0xfc, 0x11, 0xc9, 0x62, 0xb8, 0x0c, 0x76, 0x84, + 0xd9, 0xb9, 0x37, 0xfa, 0xfc, 0x7c, 0xc2, 0x6d, 0x58, 0x3e, 0xb3, 0x04, + 0xbb, 0x8c, 0x8f, 0x48, 0xbc, 0x91, 0x27, 0xcc, 0xf9, 0xb7, 0x22, 0x19, + 0x83, 0x2e, 0x09, 0xb5, 0x72, 0xd9, 0x54, 0x1c, 0x4d, 0xa1, 0xea, 0x0b, + 0xf1, 0xc6, 0x08, 0x72, 0x46, 0x87, 0x7a, 0x6e, 0x80, 0x56, 0x0a, 0x8a, + 0xc0, 0xdd, 0x11, 0x6b, 0xd6, 0xdd, 0x47, 0xdf, 0x10, 0xd9, 0xd8, 0xea, + 0x7c, 0xb0, 0x8f, 0x03, 0x00, 0x2e, 0xc1, 0x8f, 0x44, 0xa8, 0xd3, 0x30, + 0x06, 0x89, 0xa2, 0xf9, 0x34, 0xad, 0xdc, 0x03, 0x85, 0xed, 0x51, 0xa7, + 0x82, 0x9c, 0xe7, 0x5d, 0x52, 0x93, 0x0c, 0x32, 0x9a, 0x5b, 0xe1, 0xaa, + 0xca, 0xb8, 0x02, 0x6d, 0x3a, 0xd4, 0xb1, 0x3a, 0xf0, 0x5f, 0xbe, 0xb5, + 0x0d, 0x10, 0x6b, 0x38, 0x32, 0xac, 0x76, 0x80, 0xbd, 0xca, 0x94, 0x71, + 0x7a, 0xf2, 0xc9, 0x35, 0x2a, 0xde, 0x9f, 0x42, 0x49, 0x18, 0x01, 0xab, + 0xbc, 0xef, 0x7c, 0x64, 0x3f, 0x58, 0x3d, 0x92, 0x59, 0xdb, 0x13, 0xdb, + 0x58, 0x6e, 0x0a, 0xe0, 0xb7, 0x91, 0x4a, 0x08, 0x20, 0xd6, 0x2e, 0x3c, + 0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25, +}; + +#else + +// k25519Precomp[i][j] = (j+1)*256^i*B +static const ge_precomp k25519Precomp[32][8] = { + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1288382639258501, 245678601348599, 269427782077623, + 1462984067271730, 137412439391563 +#else + 25967493, 19198397, 29566455, 3660896, 54414519, 4014786, + 27544626, 21800161, 61029707, 2047604 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 62697248952638, 204681361388450, 631292143396476, + 338455783676468, 1213667448819585 +#else + 54563134, 934261, 64385954, 3049989, 66381436, 9406985, + 12720692, 5043384, 19500929, 18085054 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 301289933810280, 1259582250014073, 1422107436869536, + 796239922652654, 1953934009299142 +#else + 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, + 29287918, 11864899, 42594502, 29115885 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1380971894829527, 790832306631236, 2067202295274102, + 1995808275510000, 1566530869037010 +#else + 54292951, 20578084, 45527620, 11784319, 41753206, 30803714, + 55390960, 29739860, 66750418, 23343128 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 463307831301544, 432984605774163, 1610641361907204, + 750899048855000, 1894842303421586 +#else + 45405608, 6903824, 27185491, 6451973, 37531140, 24000426, + 51492312, 11189267, 40279186, 28235350 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 748439484463711, 1033211726465151, 1396005112841647, + 1611506220286469, 1972177495910992 +#else + 26966623, 11152617, 32442495, 15396054, 14353839, 20802097, + 63980037, 24013313, 51636816, 29387734 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1601611775252272, 1720807796594148, 1132070835939856, + 1260455018889551, 2147779492816911 +#else + 15636272, 23865875, 24204772, 25642034, 616976, 16869170, + 27787599, 18782243, 28944399, 32004408 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 316559037616741, 2177824224946892, 1459442586438991, + 1461528397712656, 751590696113597 +#else + 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, + 16354576, 21778470, 7689661, 11199574 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1850748884277385, 1200145853858453, 1068094770532492, + 672251375690438, 1586055907191707 +#else + 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, + 7512774, 10017326, 49359771, 23634074 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 934282339813791, 1846903124198670, 1172395437954843, + 1007037127761661, 1830588347719256 +#else + 50071967, 13921891, 10945806, 27521001, 27105051, 17470053, + 38182653, 15006022, 3284568, 27277892 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1694390458783935, 1735906047636159, 705069562067493, + 648033061693059, 696214010414170 +#else + 23599295, 25248385, 55915199, 25867015, 13236773, 10506355, + 7464579, 9656445, 13059162, 10374397 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1121406372216585, 192876649532226, 190294192191717, + 1994165897297032, 2245000007398739 +#else + 7798537, 16710257, 3033922, 2874086, 28997861, 2835604, + 32406664, 29715387, 66467155, 33453106 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 769950342298419, 132954430919746, 844085933195555, + 974092374476333, 726076285546016 +#else + 10861363, 11473154, 27284546, 1981175, 37044515, 12577860, + 32867885, 14515107, 51670560, 10819379 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 425251763115706, 608463272472562, 442562545713235, + 837766094556764, 374555092627893 +#else + 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, + 41455196, 12483687, 54440373, 5581305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1086255230780037, 274979815921559, 1960002765731872, + 929474102396301, 1190409889297339 +#else + 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, + 28542349, 13850243, 43430843, 17738489 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1388594989461809, 316767091099457, 394298842192982, + 1230079486801005, 1440737038838979 +#else + 51736881, 20691677, 32573249, 4720197, 40672342, 5875510, + 47920237, 18329612, 57289923, 21468654 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 7380825640100, 146210432690483, 304903576448906, + 1198869323871120, 997689833219095 +#else + 58559652, 109982, 15149363, 2178705, 22900618, 4543417, 3044240, + 17864545, 1762327, 14866737 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1181317918772081, 114573476638901, 262805072233344, + 265712217171332, 294181933805782 +#else + 48909169, 17603008, 56635573, 1707277, 49922944, 3916100, + 38872452, 3959420, 27914454, 4383652 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665000864555967, 2065379846933859, 370231110385876, + 350988370788628, 1233371373142985 +#else + 5153727, 9909285, 1723747, 30776558, 30523604, 5516873, + 19480852, 5230134, 43156425, 18378665 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2019367628972465, 676711900706637, 110710997811333, + 1108646842542025, 517791959672113 +#else + 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, + 20654025, 16520125, 30598449, 7715701 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 965130719900578, 247011430587952, 526356006571389, + 91986625355052, 2157223321444601 +#else + 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, + 35708204, 1370707, 29794553, 32145132 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2068619540119183, 1966274918058806, 957728544705549, + 729906502578991, 159834893065166 +#else + 14499471, 30824833, 33917750, 29299779, 28494861, 14271267, + 30290735, 10876454, 33954766, 2381725 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2073601412052185, 31021124762708, 264500969797082, + 248034690651703, 1030252227928288 +#else + 59913433, 30899068, 52378708, 462250, 39384538, 3941371, + 60872247, 3696004, 34808032, 15351954 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 551790716293402, 1989538725166328, 801169423371717, + 2052451893578887, 678432056995012 +#else + 27431194, 8222322, 16448760, 29646437, 48401861, 11938354, + 34147463, 30583916, 29551812, 10109425 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1368953770187805, 790347636712921, 437508475667162, + 2142576377050580, 1932081720066286 +#else + 53451805, 20399000, 35825113, 11777097, 21447386, 6519384, + 64730580, 31926875, 10092782, 28790261 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 953638594433374, 1092333936795051, 1419774766716690, + 805677984380077, 859228993502513 +#else + 27939166, 14210322, 4677035, 16277044, 44144402, 21156292, + 34600109, 12005537, 49298737, 12803509 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1200766035879111, 20142053207432, 1465634435977050, + 1645256912097844, 295121984874596 +#else + 17228999, 17892808, 65875336, 300139, 65883994, 21839654, + 30364212, 24516238, 18016356, 4397660 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1735718747031557, 1248237894295956, 1204753118328107, + 976066523550493, 65943769534592 +#else + 56150021, 25864224, 4776340, 18600194, 27850027, 17952220, + 40489757, 14544524, 49631360, 982638 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1060098822528990, 1586825862073490, 212301317240126, + 1975302711403555, 666724059764335 +#else + 29253598, 15796703, 64244882, 23645547, 10057022, 3163536, + 7332899, 29434304, 46061167, 9934962 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1091990273418756, 1572899409348578, 80968014455247, + 306009358661350, 1520450739132526 +#else + 5793284, 16271923, 42977250, 23438027, 29188559, 1206517, + 52360934, 4559894, 36984942, 22656481 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1480517209436112, 1511153322193952, 1244343858991172, + 304788150493241, 369136856496443 +#else + 39464912, 22061425, 16282656, 22517939, 28414020, 18542168, + 24191033, 4541697, 53770555, 5500567 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2151330273626164, 762045184746182, 1688074332551515, + 823046109005759, 907602769079491 +#else + 12650548, 32057319, 9052870, 11355358, 49428827, 25154267, + 49678271, 12264342, 10874051, 13524335 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2047386910586836, 168470092900250, 1552838872594810, + 340951180073789, 360819374702533 +#else + 25556948, 30508442, 714650, 2510400, 23394682, 23139102, + 33119037, 5080568, 44580805, 5376627 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1982622644432056, 2014393600336956, 128909208804214, + 1617792623929191, 105294281913815 +#else + 41020600, 29543379, 50095164, 30016803, 60382070, 1920896, + 44787559, 24106988, 4535767, 1569007 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 980234343912898, 1712256739246056, 588935272190264, + 204298813091998, 841798321043288 +#else + 64853442, 14606629, 45416424, 25514613, 28430648, 8775819, + 36614302, 3044289, 31848280, 12543772 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 197561292938973, 454817274782871, 1963754960082318, + 2113372252160468, 971377527342673 +#else + 45080285, 2943892, 35251351, 6777305, 13784462, 29262229, + 39731668, 31491700, 7718481, 14474653 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 164699448829328, 3127451757672, 1199504971548753, + 1766155447043652, 1899238924683527 +#else + 2385296, 2454213, 44477544, 46602, 62670929, 17874016, 656964, + 26317767, 24316167, 28300865 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 732262946680281, 1674412764227063, 2182456405662809, + 1350894754474250, 558458873295247 +#else + 13741529, 10911568, 33875447, 24950694, 46931033, 32521134, + 33040650, 20129900, 46379407, 8321685 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2103305098582922, 1960809151316468, 715134605001343, + 1454892949167181, 40827143824949 +#else + 21060490, 31341688, 15712756, 29218333, 1639039, 10656336, + 23845965, 21679594, 57124405, 608371 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1239289043050212, 1744654158124578, 758702410031698, + 1796762995074688, 1603056663766 +#else + 53436132, 18466845, 56219170, 25997372, 61071954, 11305546, + 1123968, 26773855, 27229398, 23887 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2232056027107988, 987343914584615, 2115594492994461, + 1819598072792159, 1119305654014850 +#else + 43864724, 33260226, 55364135, 14712570, 37643165, 31524814, + 12797023, 27114124, 65475458, 16678953 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 320153677847348, 939613871605645, 641883205761567, + 1930009789398224, 329165806634126 +#else + 37608244, 4770661, 51054477, 14001337, 7830047, 9564805, + 65600720, 28759386, 49939598, 4904952 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 980930490474130, 1242488692177893, 1251446316964684, + 1086618677993530, 1961430968465772 +#else + 24059538, 14617003, 19037157, 18514524, 19766092, 18648003, + 5169210, 16191880, 2128236, 29227599 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 276821765317453, 1536835591188030, 1305212741412361, + 61473904210175, 2051377036983058 +#else + 50127693, 4124965, 58568254, 22900634, 30336521, 19449185, + 37302527, 916032, 60226322, 30567899 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 833449923882501, 1750270368490475, 1123347002068295, + 185477424765687, 278090826653186 +#else + 44477957, 12419371, 59974635, 26081060, 50629959, 16739174, + 285431, 2763829, 15736322, 4143876 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 794524995833413, 1849907304548286, 53348672473145, + 1272368559505217, 1147304168324779 +#else + 2379333, 11839345, 62998462, 27565766, 11274297, 794957, 212801, + 18959769, 23527083, 17096164 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1504846112759364, 1203096289004681, 562139421471418, + 274333017451844, 1284344053775441 +#else + 33431108, 22423954, 49269897, 17927531, 8909498, 8376530, + 34483524, 4087880, 51919953, 19138217 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 483048732424432, 2116063063343382, 30120189902313, + 292451576741007, 1156379271702225 +#else + 1767664, 7197987, 53903638, 31531796, 54017513, 448825, 5799055, + 4357868, 62334673, 17231393 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 928372153029038, 2147692869914564, 1455665844462196, + 1986737809425946, 185207050258089 +#else + 6721966, 13833823, 43585476, 32003117, 26354292, 21691111, + 23365146, 29604700, 7390889, 2759800 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 137732961814206, 706670923917341, 1387038086865771, + 1965643813686352, 1384777115696347 +#else + 4409022, 2052381, 23373853, 10530217, 7676779, 20668478, + 21302352, 29290375, 1244379, 20634787 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 481144981981577, 2053319313589856, 2065402289827512, + 617954271490316, 1106602634668125 +#else + 62687625, 7169618, 4982368, 30596842, 30256824, 30776892, + 14086412, 9208236, 15886429, 16489664 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 696298019648792, 893299659040895, 1148636718636009, + 26734077349617, 2203955659340681 +#else + 1996056, 10375649, 14346367, 13311202, 60234729, 17116020, + 53415665, 398368, 36502409, 32841498 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 657390353372855, 998499966885562, 991893336905797, + 810470207106761, 343139804608786 +#else + 41801399, 9795879, 64331450, 14878808, 33577029, 14780362, + 13348553, 12076947, 36272402, 5113181 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 791736669492960, 934767652997115, 824656780392914, + 1759463253018643, 361530362383518 +#else + 49338080, 11797795, 31950843, 13929123, 41220562, 12288343, + 36767763, 26218045, 13847710, 5387222 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022541353055597, 2094700262587466, 1551008075025686, + 242785517418164, 695985404963562 +#else + 48526701, 30138214, 17824842, 31213466, 22744342, 23111821, + 8763060, 3617786, 47508202, 10370990 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1287487199965223, 2215311941380308, 1552928390931986, + 1664859529680196, 1125004975265243 +#else + 20246567, 19185054, 22358228, 33010720, 18507282, 23140436, + 14554436, 24808340, 32232923, 16763880 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 677434665154918, 989582503122485, 1817429540898386, + 1052904935475344, 1143826298169798 +#else + 9648486, 10094563, 26416693, 14745928, 36734546, 27081810, + 11094160, 15689506, 3140038, 17044340 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 367266328308408, 318431188922404, 695629353755355, + 634085657580832, 24581612564426 +#else + 50948792, 5472694, 31895588, 4744994, 8823515, 10365685, + 39884064, 9448612, 38334410, 366294 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 773360688841258, 1815381330538070, 363773437667376, + 539629987070205, 783280434248437 +#else + 19153450, 11523972, 56012374, 27051289, 42461232, 5420646, + 28344573, 8041113, 719605, 11671788 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 180820816194166, 168937968377394, 748416242794470, + 1227281252254508, 1567587861004268 +#else + 8678006, 2694440, 60300850, 2517371, 4964326, 11152271, + 51675948, 18287915, 27000812, 23358879 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 478775558583645, 2062896624554807, 699391259285399, + 358099408427873, 1277310261461761 +#else + 51950941, 7134311, 8639287, 30739555, 59873175, 10421741, + 564065, 5336097, 6750977, 19033406 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1984740906540026, 1079164179400229, 1056021349262661, + 1659958556483663, 1088529069025527 +#else + 11836410, 29574944, 26297893, 16080799, 23455045, 15735944, + 1695823, 24735310, 8169719, 16220347 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 580736401511151, 1842931091388998, 1177201471228238, + 2075460256527244, 1301133425678027 +#else + 48993007, 8653646, 17578566, 27461813, 59083086, 17541668, + 55964556, 30926767, 61118155, 19388398 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1515728832059182, 1575261009617579, 1510246567196186, + 191078022609704, 116661716289141 +#else + 43800366, 22586119, 15213227, 23473218, 36255258, 22504427, + 27884328, 2847284, 2655861, 1738395 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1295295738269652, 1714742313707026, 545583042462581, + 2034411676262552, 1513248090013606 +#else + 39571412, 19301410, 41772562, 25551651, 57738101, 8129820, + 21651608, 30315096, 48021414, 22549153 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 230710545179830, 30821514358353, 760704303452229, + 390668103790604, 573437871383156 +#else + 1533110, 3437855, 23735889, 459276, 29970501, 11335377, + 26030092, 5821408, 10478196, 8544890 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1169380107545646, 263167233745614, 2022901299054448, + 819900753251120, 2023898464874585 +#else + 32173102, 17425121, 24896206, 3921497, 22579056, 30143578, + 19270448, 12217473, 17789017, 30158437 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2102254323485823, 1570832666216754, 34696906544624, + 1993213739807337, 70638552271463 +#else + 36555903, 31326030, 51530034, 23407230, 13243888, 517024, + 15479401, 29701199, 30460519, 1052596 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 894132856735058, 548675863558441, 845349339503395, + 1942269668326667, 1615682209874691 +#else + 55493970, 13323617, 32618793, 8175907, 51878691, 12596686, + 27491595, 28942073, 3179267, 24075541 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1287670217537834, 1222355136884920, 1846481788678694, + 1150426571265110, 1613523400722047 +#else + 31947050, 19187781, 62468280, 18214510, 51982886, 27514722, + 52352086, 17142691, 19072639, 24043372 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 793388516527298, 1315457083650035, 1972286999342417, + 1901825953052455, 338269477222410 +#else + 11685058, 11822410, 3158003, 19601838, 33402193, 29389366, + 5977895, 28339415, 473098, 5040608 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 550201530671806, 778605267108140, 2063911101902983, + 115500557286349, 2041641272971022 +#else + 46817982, 8198641, 39698732, 11602122, 1290375, 30754672, + 28326861, 1721092, 47550222, 30422825 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 717255318455100, 519313764361315, 2080406977303708, + 541981206705521, 774328150311600 +#else + 7881532, 10687937, 7578723, 7738378, 48157852, 31000479, + 21820785, 8076149, 39240368, 11538388 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 261715221532238, 1795354330069993, 1496878026850283, + 499739720521052, 389031152673770 +#else + 47173198, 3899860, 18283497, 26752864, 51380203, 22305220, + 8754524, 7446702, 61432810, 5797015 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1997217696294013, 1717306351628065, 1684313917746180, + 1644426076011410, 1857378133465451 +#else + 55813245, 29760862, 51326753, 25589858, 12708868, 25098233, + 2014098, 24503858, 64739691, 27677090 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1475434724792648, 76931896285979, 1116729029771667, + 2002544139318042, 725547833803938 +#else + 44636488, 21985690, 39426843, 1146374, 18956691, 16640559, + 1192730, 29840233, 15123618, 10811505 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022306639183567, 726296063571875, 315345054448644, + 1058733329149221, 1448201136060677 +#else + 14352079, 30134717, 48166819, 10822654, 32750596, 4699007, + 67038501, 15776355, 38222085, 21579878 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1710065158525665, 1895094923036397, 123988286168546, + 1145519900776355, 1607510767693874 +#else + 38867681, 25481956, 62129901, 28239114, 29416930, 1847569, + 46454691, 17069576, 4714546, 23953777 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 561605375422540, 1071733543815037, 131496498800990, + 1946868434569999, 828138133964203 +#else + 15200332, 8368572, 19679101, 15970074, 35236190, 1959450, + 24611599, 29010600, 55362987, 12340219 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1548495173745801, 442310529226540, 998072547000384, + 553054358385281, 644824326376171 +#else + 12876937, 23074376, 33134380, 6590940, 60801088, 14872439, + 9613953, 8241152, 15370987, 9608631 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1445526537029440, 2225519789662536, 914628859347385, + 1064754194555068, 1660295614401091 +#else + 62965568, 21540023, 8446280, 33162829, 4407737, 13629032, + 59383996, 15866073, 38898243, 24740332 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1199690223111956, 24028135822341, 66638289244341, + 57626156285975, 565093967979607 +#else + 26660628, 17876777, 8393733, 358047, 59707573, 992987, 43204631, + 858696, 20571223, 8420556 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 876926774220824, 554618976488214, 1012056309841565, + 839961821554611, 1414499340307677 +#else + 14620696, 13067227, 51661590, 8264466, 14106269, 15080814, + 33531827, 12516406, 45534429, 21077682 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 703047626104145, 1266841406201770, 165556500219173, + 486991595001879, 1011325891650656 +#else + 236881, 10476226, 57258, 18877408, 6472997, 2466984, 17258519, + 7256740, 8791136, 15069930 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1622861044480487, 1156394801573634, 1869132565415504, + 327103985777730, 2095342781472284 +#else + 1276391, 24182514, 22949634, 17231625, 43615824, 27852245, + 14711874, 4874229, 36445724, 31223040 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 334886927423922, 489511099221528, 129160865966726, + 1720809113143481, 619700195649254 +#else + 5855666, 4990204, 53397016, 7294283, 59304582, 1924646, + 65685689, 25642053, 34039526, 9234252 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1646545795166119, 1758370782583567, 714746174550637, + 1472693650165135, 898994790308209 +#else + 20590503, 24535444, 31529743, 26201766, 64402029, 10650547, + 31559055, 21944845, 18979185, 13396066 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 333403773039279, 295772542452938, 1693106465353610, + 912330357530760, 471235657950362 +#else + 24474287, 4968103, 22267082, 4407354, 24063882, 25229252, + 48291976, 13594781, 33514650, 7021958 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1811196219982022, 1068969825533602, 289602974833439, + 1988956043611592, 863562343398367 +#else + 55541958, 26988926, 45743778, 15928891, 40950559, 4315420, + 41160136, 29637754, 45628383, 12868081 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 906282429780072, 2108672665779781, 432396390473936, + 150625823801893, 1708930497638539 +#else + 38473832, 13504660, 19988037, 31421671, 21078224, 6443208, + 45662757, 2244499, 54653067, 25465048 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 925664675702328, 21416848568684, 1831436641861340, + 601157008940113, 371818055044496 +#else + 36513336, 13793478, 61256044, 319135, 41385692, 27290532, + 33086545, 8957937, 51875216, 5540520 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1479786007267725, 1738881859066675, 68646196476567, + 2146507056100328, 1247662817535471 +#else + 55478669, 22050529, 58989363, 25911358, 2620055, 1022908, + 43398120, 31985447, 50980335, 18591624 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 52035296774456, 939969390708103, 312023458773250, + 59873523517659, 1231345905848899 +#else + 23152952, 775386, 27395463, 14006635, 57407746, 4649511, + 1689819, 892185, 55595587, 18348483 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 643355106415761, 290186807495774, 2013561737429023, + 319648069511546, 393736678496162 +#else + 9770129, 9586738, 26496094, 4324120, 1556511, 30004408, + 27453818, 4763127, 47929250, 5867133 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 129358342392716, 1932811617704777, 1176749390799681, + 398040349861790, 1170779668090425 +#else + 34343820, 1927589, 31726409, 28801137, 23962433, 17534932, + 27846558, 5931263, 37359161, 17445976 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2051980782668029, 121859921510665, 2048329875753063, + 1235229850149665, 519062146124755 +#else + 27461885, 30576896, 22380809, 1815854, 44075111, 30522493, + 7283489, 18406359, 47582163, 7734628 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1608170971973096, 415809060360428, 1350468408164766, + 2038620059057678, 1026904485989112 +#else + 59098600, 23963614, 55988460, 6196037, 29344158, 20123547, + 7585294, 30377806, 18549496, 15302069 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1837656083115103, 1510134048812070, 906263674192061, + 1821064197805734, 565375124676301 +#else + 34450527, 27383209, 59436070, 22502750, 6258877, 13504381, + 10458790, 27135971, 58236621, 8424745 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 578027192365650, 2034800251375322, 2128954087207123, + 478816193810521, 2196171989962750 +#else + 24687186, 8613276, 36441818, 30320886, 1863891, 31723888, + 19206233, 7134917, 55824382, 32725512 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1633188840273139, 852787172373708, 1548762607215796, + 1266275218902681, 1107218203325133 +#else + 11334899, 24336410, 8025292, 12707519, 17523892, 23078361, + 10243737, 18868971, 62042829, 16498836 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 462189358480054, 1784816734159228, 1611334301651368, + 1303938263943540, 707589560319424 +#else + 8911542, 6887158, 57524604, 26595841, 11145640, 24010752, + 17303924, 19430194, 6536640, 10543906 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1038829280972848, 38176604650029, 753193246598573, + 1136076426528122, 595709990562434 +#else + 38162480, 15479762, 49642029, 568875, 65611181, 11223453, + 64439674, 16928857, 39873154, 8876770 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1408451820859834, 2194984964010833, 2198361797561729, + 1061962440055713, 1645147963442934 +#else + 41365946, 20987567, 51458897, 32707824, 34082177, 32758143, + 33627041, 15824473, 66504438, 24514614 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 4701053362120, 1647641066302348, 1047553002242085, + 1923635013395977, 206970314902065 +#else + 10330056, 70051, 7957388, 24551765, 9764901, 15609756, 27698697, + 28664395, 1657393, 3084098 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1750479161778571, 1362553355169293, 1891721260220598, + 966109370862782, 1024913988299801 +#else + 10477963, 26084172, 12119565, 20303627, 29016246, 28188843, + 31280318, 14396151, 36875289, 15272408 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 212699049131723, 1117950018299775, 1873945661751056, + 1403802921984058, 130896082652698 +#else + 54820555, 3169462, 28813183, 16658753, 25116432, 27923966, + 41934906, 20918293, 42094106, 1950503 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 636808533673210, 1262201711667560, 390951380330599, + 1663420692697294, 561951321757406 +#else + 40928506, 9489186, 11053416, 18808271, 36055143, 5825629, + 58724558, 24786899, 15341278, 8373727 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 520731594438141, 1446301499955692, 273753264629267, + 1565101517999256, 1019411827004672 +#else + 28685821, 7759505, 52730348, 21551571, 35137043, 4079241, + 298136, 23321830, 64230656, 15190419 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 926527492029409, 1191853477411379, 734233225181171, + 184038887541270, 1790426146325343 +#else + 34175969, 13806335, 52771379, 17760000, 43104243, 10940927, + 8669718, 2742393, 41075551, 26679428 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1464651961852572, 1483737295721717, 1519450561335517, + 1161429831763785, 405914998179977 +#else + 65528476, 21825014, 41129205, 22109408, 49696989, 22641577, + 9291593, 17306653, 54954121, 6048604 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 996126634382301, 796204125879525, 127517800546509, + 344155944689303, 615279846169038 +#else + 36803549, 14843443, 1539301, 11864366, 20201677, 1900163, + 13934231, 5128323, 11213262, 9168384 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 738724080975276, 2188666632415296, 1961313708559162, + 1506545807547587, 1151301638969740 +#else + 40828332, 11007846, 19408960, 32613674, 48515898, 29225851, + 62020803, 22449281, 20470156, 17155731 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 622917337413835, 1218989177089035, 1284857712846592, + 970502061709359, 351025208117090 +#else + 43972811, 9282191, 14855179, 18164354, 59746048, 19145871, + 44324911, 14461607, 14042978, 5230683 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2067814584765580, 1677855129927492, 2086109782475197, + 235286517313238, 1416314046739645 +#else + 29969548, 30812838, 50396996, 25001989, 9175485, 31085458, + 21556950, 3506042, 61174973, 21104723 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 586844262630358, 307444381952195, 458399356043426, + 602068024507062, 1028548203415243 +#else + 63964118, 8744660, 19704003, 4581278, 46678178, 6830682, + 45824694, 8971512, 38569675, 15326562 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 678489922928203, 2016657584724032, 90977383049628, + 1026831907234582, 615271492942522 +#else + 47644235, 10110287, 49846336, 30050539, 43608476, 1355668, + 51585814, 15300987, 46594746, 9168259 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 301225714012278, 1094837270268560, 1202288391010439, + 644352775178361, 1647055902137983 +#else + 61755510, 4488612, 43305616, 16314346, 7780487, 17915493, + 38160505, 9601604, 33087103, 24543045 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1210746697896478, 1416608304244708, 686487477217856, + 1245131191434135, 1051238336855737 +#else + 47665694, 18041531, 46311396, 21109108, 37284416, 10229460, + 39664535, 18553900, 61111993, 15664671 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1135604073198207, 1683322080485474, 769147804376683, + 2086688130589414, 900445683120379 +#else + 23294591, 16921819, 44458082, 25083453, 27844203, 11461195, + 13099750, 31094076, 18151675, 13417686 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1971518477615628, 401909519527336, 448627091057375, + 1409486868273821, 1214789035034363 +#else + 42385932, 29377914, 35958184, 5988918, 40250079, 6685064, + 1661597, 21002991, 15271675, 18101767 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1364039144731711, 1897497433586190, 2203097701135459, + 145461396811251, 1349844460790699 +#else + 11433023, 20325767, 8239630, 28274915, 65123427, 32828713, + 48410099, 2167543, 60187563, 20114249 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1045230323257973, 818206601145807, 630513189076103, + 1672046528998132, 807204017562437 +#else + 35672693, 15575145, 30436815, 12192228, 44645511, 9395378, + 57191156, 24915434, 12215109, 12028277 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 439961968385997, 386362664488986, 1382706320807688, + 309894000125359, 2207801346498567 +#else + 14098381, 6555944, 23007258, 5757252, 51681032, 20603929, + 30123439, 4617780, 50208775, 32898803 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1229004686397588, 920643968530863, 123975893911178, + 681423993215777, 1400559197080973 +#else + 63082644, 18313596, 11893167, 13718664, 52299402, 1847384, + 51288865, 10154008, 23973261, 20869958 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2003766096898049, 170074059235165, 1141124258967971, + 1485419893480973, 1573762821028725 +#else + 40577025, 29858441, 65199965, 2534300, 35238307, 17004076, + 18341389, 22134481, 32013173, 23450893 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 729905708611432, 1270323270673202, 123353058984288, + 426460209632942, 2195574535456672 +#else + 41629544, 10876442, 55337778, 18929291, 54739296, 1838103, + 21911214, 6354752, 4425632, 32716610 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1271140255321235, 2044363183174497, 52125387634689, + 1445120246694705, 942541986339084 +#else + 56675475, 18941465, 22229857, 30463385, 53917697, 776728, + 49693489, 21533969, 4725004, 14044970 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1761608437466135, 583360847526804, 1586706389685493, + 2157056599579261, 1170692369685772 +#else + 19268631, 26250011, 1555348, 8692754, 45634805, 23643767, + 6347389, 32142648, 47586572, 17444675 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 871476219910823, 1878769545097794, 2241832391238412, + 548957640601001, 690047440233174 +#else + 42244775, 12986007, 56209986, 27995847, 55796492, 33405905, + 19541417, 8180106, 9282262, 10282508 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 297194732135507, 1366347803776820, 1301185512245601, + 561849853336294, 1533554921345731 +#else + 40903763, 4428546, 58447668, 20360168, 4098401, 19389175, + 15522534, 8372215, 5542595, 22851749 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 999628998628371, 1132836708493400, 2084741674517453, + 469343353015612, 678782988708035 +#else + 56546323, 14895632, 26814552, 16880582, 49628109, 31065071, + 64326972, 6993760, 49014979, 10114654 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2189427607417022, 699801937082607, 412764402319267, + 1478091893643349, 2244675696854460 +#else + 47001790, 32625013, 31422703, 10427861, 59998115, 6150668, + 38017109, 22025285, 25953724, 33448274 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1712292055966563, 204413590624874, 1405738637332841, + 408981300829763, 861082219276721 +#else + 62874467, 25515139, 57989738, 3045999, 2101609, 20947138, + 19390019, 6094296, 63793585, 12831124 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 508561155940631, 966928475686665, 2236717801150132, + 424543858577297, 2089272956986143 +#else + 51110167, 7578151, 5310217, 14408357, 33560244, 33329692, + 31575953, 6326196, 7381791, 31132593 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 221245220129925, 1156020201681217, 491145634799213, + 542422431960839, 828100817819207 +#else + 46206085, 3296810, 24736065, 17226043, 18374253, 7318640, + 6295303, 8082724, 51746375, 12339663 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 153756971240384, 1299874139923977, 393099165260502, + 1058234455773022, 996989038681183 +#else + 27724736, 2291157, 6088201, 19369634, 1792726, 5857634, + 13848414, 15768922, 25091167, 14856294 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 559086812798481, 573177704212711, 1629737083816402, + 1399819713462595, 1646954378266038 +#else + 48242193, 8331042, 24373479, 8541013, 66406866, 24284974, + 12927299, 20858939, 44926390, 24541532 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1887963056288059, 228507035730124, 1468368348640282, + 930557653420194, 613513962454686 +#else + 55685435, 28132841, 11632844, 3405020, 30536730, 21880393, + 39848098, 13866389, 30146206, 9142070 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1224529808187553, 1577022856702685, 2206946542980843, + 625883007765001, 279930793512158 +#else + 3924129, 18246916, 53291741, 23499471, 12291819, 32886066, + 39406089, 9326383, 58871006, 4171293 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1076287717051609, 1114455570543035, 187297059715481, + 250446884292121, 1885187512550540 +#else + 51186905, 16037936, 6713787, 16606682, 45496729, 2790943, + 26396185, 3731949, 345228, 28091483 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 902497362940219, 76749815795675, 1657927525633846, + 1420238379745202, 1340321636548352 +#else + 45781307, 13448258, 25284571, 1143661, 20614966, 24705045, + 2031538, 21163201, 50855680, 19972348 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1129576631190784, 1281994010027327, 996844254743018, + 257876363489249, 1150850742055018 +#else + 31016192, 16832003, 26371391, 19103199, 62081514, 14854136, + 17477601, 3842657, 28012650, 17149012 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 628740660038789, 1943038498527841, 467786347793886, + 1093341428303375, 235413859513003 +#else + 62033029, 9368965, 58546785, 28953529, 51858910, 6970559, + 57918991, 16292056, 58241707, 3507939 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 237425418909360, 469614029179605, 1512389769174935, + 1241726368345357, 441602891065214 +#else + 29439664, 3537914, 23333589, 6997794, 49553303, 22536363, + 51899661, 18503164, 57943934, 6580395 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1736417953058555, 726531315520508, 1833335034432527, + 1629442561574747, 624418919286085 +#else + 54923003, 25874643, 16438268, 10826160, 58412047, 27318820, + 17860443, 24280586, 65013061, 9304566 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1960754663920689, 497040957888962, 1909832851283095, + 1271432136996826, 2219780368020940 +#else + 20714545, 29217521, 29088194, 7406487, 11426967, 28458727, + 14792666, 18945815, 5289420, 33077305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1537037379417136, 1358865369268262, 2130838645654099, + 828733687040705, 1999987652890901 +#else + 50443312, 22903641, 60948518, 20248671, 9192019, 31751970, + 17271489, 12349094, 26939669, 29802138 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 629042105241814, 1098854999137608, 887281544569320, + 1423102019874777, 7911258951561 +#else + 54218966, 9373457, 31595848, 16374215, 21471720, 13221525, + 39825369, 21205872, 63410057, 117886 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1811562332665373, 1501882019007673, 2213763501088999, + 359573079719636, 36370565049116 +#else + 22263325, 26994382, 3984569, 22379786, 51994855, 32987646, + 28311252, 5358056, 43789084, 541963 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 218907117361280, 1209298913016966, 1944312619096112, + 1130690631451061, 1342327389191701 +#else + 16259200, 3261970, 2309254, 18019958, 50223152, 28972515, + 24134069, 16848603, 53771797, 20002236 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1369976867854704, 1396479602419169, 1765656654398856, + 2203659200586299, 998327836117241 +#else + 9378160, 20414246, 44262881, 20809167, 28198280, 26310334, + 64709179, 32837080, 690425, 14876244 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2230701885562825, 1348173180338974, 2172856128624598, + 1426538746123771, 444193481326151 +#else + 24977353, 33240048, 58884894, 20089345, 28432342, 32378079, + 54040059, 21257083, 44727879, 6618998 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 784210426627951, 918204562375674, 1284546780452985, + 1324534636134684, 1872449409642708 +#else + 65570671, 11685645, 12944378, 13682314, 42719353, 19141238, + 8044828, 19737104, 32239828, 27901670 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 319638829540294, 596282656808406, 2037902696412608, + 1557219121643918, 341938082688094 +#else + 48505798, 4762989, 66182614, 8885303, 38696384, 30367116, + 9781646, 23204373, 32779358, 5095274 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1901860206695915, 2004489122065736, 1625847061568236, + 973529743399879, 2075287685312905 +#else + 34100715, 28339925, 34843976, 29869215, 9460460, 24227009, + 42507207, 14506723, 21639561, 30924196 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1371853944110545, 1042332820512553, 1949855697918254, + 1791195775521505, 37487364849293 +#else + 50707921, 20442216, 25239337, 15531969, 3987758, 29055114, + 65819361, 26690896, 17874573, 558605 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 687200189577855, 1082536651125675, 644224940871546, + 340923196057951, 343581346747396 +#else + 53508735, 10240080, 9171883, 16131053, 46239610, 9599699, + 33499487, 5080151, 2085892, 5119761 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2082717129583892, 27829425539422, 145655066671970, + 1690527209845512, 1865260509673478 +#else + 44903700, 31034903, 50727262, 414690, 42089314, 2170429, + 30634760, 25190818, 35108870, 27794547 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1059729620568824, 2163709103470266, 1440302280256872, + 1769143160546397, 869830310425069 +#else + 60263160, 15791201, 8550074, 32241778, 29928808, 21462176, + 27534429, 26362287, 44757485, 12961481 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1609516219779025, 777277757338817, 2101121130363987, + 550762194946473, 1905542338659364 +#else + 42616785, 23983660, 10368193, 11582341, 43711571, 31309144, + 16533929, 8206996, 36914212, 28394793 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2024821921041576, 426948675450149, 595133284085473, + 471860860885970, 600321679413000 +#else + 55987368, 30172197, 2307365, 6362031, 66973409, 8868176, + 50273234, 7031274, 7589640, 8945490 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 598474602406721, 1468128276358244, 1191923149557635, + 1501376424093216, 1281662691293476 +#else + 34956097, 8917966, 6661220, 21876816, 65916803, 17761038, + 7251488, 22372252, 24099108, 19098262 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1721138489890707, 1264336102277790, 433064545421287, + 1359988423149466, 1561871293409447 +#else + 5019539, 25646962, 4244126, 18840076, 40175591, 6453164, + 47990682, 20265406, 60876967, 23273695 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 719520245587143, 393380711632345, 132350400863381, + 1543271270810729, 1819543295798660 +#else + 10853575, 10721687, 26480089, 5861829, 44113045, 1972174, + 65242217, 22996533, 63745412, 27113307 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 396397949784152, 1811354474471839, 1362679985304303, + 2117033964846756, 498041172552279 +#else + 50106456, 5906789, 221599, 26991285, 7828207, 20305514, + 24362660, 31546264, 53242455, 7421391 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1812471844975748, 1856491995543149, 126579494584102, + 1036244859282620, 1975108050082550 +#else + 8139908, 27007935, 32257645, 27663886, 30375718, 1886181, + 45933756, 15441251, 28826358, 29431403 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 650623932407995, 1137551288410575, 2125223403615539, + 1725658013221271, 2134892965117796 +#else + 6267067, 9695052, 7709135, 16950835, 34239795, 31668296, + 14795159, 25714308, 13746020, 31812384 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 522584000310195, 1241762481390450, 1743702789495384, + 2227404127826575, 1686746002148897 +#else + 28584883, 7787108, 60375922, 18503702, 22846040, 25983196, + 63926927, 33190907, 4771361, 25134474 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 427904865186312, 1703211129693455, 1585368107547509, + 1436984488744336, 761188534613978 +#else + 24949256, 6376279, 39642383, 25379823, 48462709, 23623825, + 33543568, 21412737, 3569626, 11342593 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 318101947455002, 248138407995851, 1481904195303927, + 309278454311197, 1258516760217879 +#else + 26514970, 4740088, 27912651, 3697550, 19331575, 22082093, + 6809885, 4608608, 7325975, 18753361 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1275068538599310, 513726919533379, 349926553492294, + 688428871968420, 1702400196000666 +#else + 55490446, 19000001, 42787651, 7655127, 65739590, 5214311, + 39708324, 10258389, 49462170, 25367739 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1061864036265233, 961611260325381, 321859632700838, + 1045600629959517, 1985130202504038 +#else + 11431185, 15823007, 26570245, 14329124, 18029990, 4796082, + 35662685, 15580663, 9280358, 29580745 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1558816436882417, 1962896332636523, 1337709822062152, + 1501413830776938, 294436165831932 +#else + 66948081, 23228174, 44253547, 29249434, 46247496, 19933429, + 34297962, 22372809, 51563772, 4387440 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 818359826554971, 1862173000996177, 626821592884859, + 573655738872376, 1749691246745455 +#else + 46309467, 12194511, 3937617, 27748540, 39954043, 9340369, + 42594872, 8548136, 20617071, 26072431 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1988022651432119, 1082111498586040, 1834020786104821, + 1454826876423687, 692929915223122 +#else + 66170039, 29623845, 58394552, 16124717, 24603125, 27329039, + 53333511, 21678609, 24345682, 10325460 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2146513703733331, 584788900394667, 464965657279958, + 2183973639356127, 238371159456790 +#else + 47253587, 31985546, 44906155, 8714033, 14007766, 6928528, + 16318175, 32543743, 4766742, 3552007 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1129007025494441, 2197883144413266, 265142755578169, + 971864464758890, 1983715884903702 +#else + 45357481, 16823515, 1351762, 32751011, 63099193, 3950934, + 3217514, 14481909, 10988822, 29559670 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1291366624493075, 381456718189114, 1711482489312444, + 1815233647702022, 892279782992467 +#else + 15564307, 19242862, 3101242, 5684148, 30446780, 25503076, + 12677126, 27049089, 58813011, 13296004 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 444548969917454, 1452286453853356, 2113731441506810, + 645188273895859, 810317625309512 +#else + 57666574, 6624295, 36809900, 21640754, 62437882, 31497052, + 31521203, 9614054, 37108040, 12074673 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2242724082797924, 1373354730327868, 1006520110883049, + 2147330369940688, 1151816104883620 +#else + 4771172, 33419193, 14290748, 20464580, 27992297, 14998318, + 65694928, 31997715, 29832612, 17163397 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1745720200383796, 1911723143175317, 2056329390702074, + 355227174309849, 879232794371100 +#else + 7064884, 26013258, 47946901, 28486894, 48217594, 30641695, + 25825241, 5293297, 39986204, 13101589 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 163723479936298, 115424889803150, 1156016391581227, + 1894942220753364, 1970549419986329 +#else + 64810282, 2439669, 59642254, 1719964, 39841323, 17225986, + 32512468, 28236839, 36752793, 29363474 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 681981452362484, 267208874112496, 1374683991933094, + 638600984916117, 646178654558546 +#else + 37102324, 10162315, 33928688, 3981722, 50626726, 20484387, + 14413973, 9515896, 19568978, 9628812 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 13378654854251, 106237307029567, 1944412051589651, + 1841976767925457, 230702819835573 +#else + 33053803, 199357, 15894591, 1583059, 27380243, 28973997, + 49269969, 27447592, 60817077, 3437739 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 260683893467075, 854060306077237, 913639551980112, + 4704576840123, 280254810808712 +#else + 48129987, 3884492, 19469877, 12726490, 15913552, 13614290, + 44147131, 70103, 7463304, 4176122 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 715374893080287, 1173334812210491, 1806524662079626, + 1894596008000979, 398905715033393 +#else + 39984863, 10659916, 11482427, 17484051, 12771466, 26919315, + 34389459, 28231680, 24216881, 5944158 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 500026409727661, 1596431288195371, 1420380351989370, + 985211561521489, 392444930785633 +#else + 8894125, 7450974, 64444715, 23788679, 39028346, 21165316, + 19345745, 14680796, 11632993, 5847885 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2096421546958141, 1922523000950363, 789831022876840, + 427295144688779, 320923973161730 +#else + 26942781, 31239115, 9129563, 28647825, 26024104, 11769399, + 55590027, 6367193, 57381634, 4782139 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1927770723575450, 1485792977512719, 1850996108474547, + 551696031508956, 2126047405475647 +#else + 19916442, 28726022, 44198159, 22140040, 25606323, 27581991, + 33253852, 8220911, 6358847, 31680575 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2112099158080148, 742570803909715, 6484558077432, + 1951119898618916, 93090382703416 +#else + 801428, 31472730, 16569427, 11065167, 29875704, 96627, 7908388, + 29073952, 53570360, 1387154 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 383905201636970, 859946997631870, 855623867637644, + 1017125780577795, 794250831877809 +#else + 19646058, 5720633, 55692158, 12814208, 11607948, 12749789, + 14147075, 15156355, 45242033, 11835259 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 77571826285752, 999304298101753, 487841111777762, + 1038031143212339, 339066367948762 +#else + 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, + 26121523, 15467869, 40548314, 5052482 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 674994775520533, 266035846330789, 826951213393478, + 1405007746162285, 1781791018620876 +#else + 64091413, 10058205, 1980837, 3964243, 22160966, 12322533, + 60677741, 20936246, 12228556, 26550755 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1001412661522686, 348196197067298, 1666614366723946, + 888424995032760, 580747687801357 +#else + 32944382, 14922211, 44263970, 5188527, 21913450, 24834489, + 4001464, 13238564, 60994061, 8653814 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1939560076207777, 1409892634407635, 552574736069277, + 383854338280405, 190706709864139 +#else + 22865569, 28901697, 27603667, 21009037, 14348957, 8234005, + 24808405, 5719875, 28483275, 2841751 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2177087163428741, 1439255351721944, 1208070840382793, + 2230616362004769, 1396886392021913 +#else + 50687877, 32441126, 66781144, 21446575, 21886281, 18001658, + 65220897, 33238773, 19932057, 20815229 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 676962063230039, 1880275537148808, 2046721011602706, + 888463247083003, 1318301552024067 +#else + 55452759, 10087520, 58243976, 28018288, 47830290, 30498519, + 3999227, 13239134, 62331395, 19644223 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1466980508178206, 617045217998949, 652303580573628, + 757303753529064, 207583137376902 +#else + 1382174, 21859713, 17266789, 9194690, 53784508, 9720080, + 20403944, 11284705, 53095046, 3093229 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1511056752906902, 105403126891277, 493434892772846, + 1091943425335976, 1802717338077427 +#else + 16650902, 22516500, 66044685, 1570628, 58779118, 7352752, + 66806440, 16271224, 43059443, 26862581 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1853982405405128, 1878664056251147, 1528011020803992, + 1019626468153565, 1128438412189035 +#else + 45197768, 27626490, 62497547, 27994275, 35364760, 22769138, + 24123613, 15193618, 45456747, 16815042 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1963939888391106, 293456433791664, 697897559513649, + 985882796904380, 796244541237972 +#else + 57172930, 29264984, 41829040, 4372841, 2087473, 10399484, + 31870908, 14690798, 17361620, 11864968 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 416770998629779, 389655552427054, 1314476859406756, + 1749382513022778, 1161905598739491 +#else + 55801235, 6210371, 13206574, 5806320, 38091172, 19587231, + 54777658, 26067830, 41530403, 17313742 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1428358296490651, 1027115282420478, 304840698058337, + 441410174026628, 1819358356278573 +#else + 14668443, 21284197, 26039038, 15305210, 25515617, 4542480, + 10453892, 6577524, 9145645, 27110552 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 204943430200135, 1554861433819175, 216426658514651, + 264149070665950, 2047097371738319 +#else + 5974855, 3053895, 57675815, 23169240, 35243739, 3225008, + 59136222, 3936127, 61456591, 30504127 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1934415182909034, 1393285083565062, 516409331772960, + 1157690734993892, 121039666594268 +#else + 30625386, 28825032, 41552902, 20761565, 46624288, 7695098, + 17097188, 17250936, 39109084, 1803631 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 662035583584445, 286736105093098, 1131773000510616, + 818494214211439, 472943792054479 +#else + 63555773, 9865098, 61880298, 4272700, 61435032, 16864731, + 14911343, 12196514, 45703375, 7047411 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665784778135882, 1893179629898606, 808313193813106, + 276797254706413, 1563426179676396 +#else + 20093258, 9920966, 55970670, 28210574, 13161586, 12044805, + 34252013, 4124600, 34765036, 23296865 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 945205108984232, 526277562959295, 1324180513733566, + 1666970227868664, 153547609289173 +#else + 46320040, 14084653, 53577151, 7842146, 19119038, 19731827, + 4752376, 24839792, 45429205, 2288037 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2031433403516252, 203996615228162, 170487168837083, + 981513604791390, 843573964916831 +#else + 40289628, 30270716, 29965058, 3039786, 52635099, 2540456, + 29457502, 14625692, 42289247, 12570231 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1476570093962618, 838514669399805, 1857930577281364, + 2017007352225784, 317085545220047 +#else + 66045306, 22002608, 16920317, 12494842, 1278292, 27685323, + 45948920, 30055751, 55134159, 4724942 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1461557121912842, 1600674043318359, 2157134900399597, + 1670641601940616, 127765583803283 +#else + 17960970, 21778898, 62967895, 23851901, 58232301, 32143814, + 54201480, 24894499, 37532563, 1903855 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1293543509393474, 2143624609202546, 1058361566797508, + 214097127393994, 946888515472729 +#else + 23134274, 19275300, 56426866, 31942495, 20684484, 15770816, + 54119114, 3190295, 26955097, 14109738 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 357067959932916, 1290876214345711, 521245575443703, + 1494975468601005, 800942377643885 +#else + 15308788, 5320727, 36995055, 19235554, 22902007, 7767164, + 29425325, 22276870, 31960941, 11934971 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 566116659100033, 820247422481740, 994464017954148, + 327157611686365, 92591318111744 +#else + 39713153, 8435795, 4109644, 12222639, 42480996, 14818668, + 20638173, 4875028, 10491392, 1379718 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 617256647603209, 1652107761099439, 1857213046645471, + 1085597175214970, 817432759830522 +#else + 53949449, 9197840, 3875503, 24618324, 65725151, 27674630, + 33518458, 16176658, 21432314, 12180697 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 771808161440705, 1323510426395069, 680497615846440, + 851580615547985, 1320806384849017 +#else + 55321537, 11500837, 13787581, 19721842, 44678184, 10140204, + 1465425, 12689540, 56807545, 19681548 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1219260086131915, 647169006596815, 79601124759706, + 2161724213426748, 404861897060198 +#else + 5414091, 18168391, 46101199, 9643569, 12834970, 1186149, + 64485948, 32212200, 26128230, 6032912 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1327968293887866, 1335500852943256, 1401587164534264, + 558137311952440, 1551360549268902 +#else + 40771450, 19788269, 32496024, 19900513, 17847800, 20885276, + 3604024, 8316894, 41233830, 23117073 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 417621685193956, 1429953819744454, 396157358457099, + 1940470778873255, 214000046234152 +#else + 3296484, 6223048, 24680646, 21307972, 44056843, 5903204, + 58246567, 28915267, 12376616, 3188849 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1268047918491973, 2172375426948536, 1533916099229249, + 1761293575457130, 1590622667026765 +#else + 29190469, 18895386, 27549112, 32370916, 3520065, 22857131, + 32049514, 26245319, 50999629, 23702124 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1627072914981959, 2211603081280073, 1912369601616504, + 1191770436221309, 2187309757525860 +#else + 52364359, 24245275, 735817, 32955454, 46701176, 28496527, + 25246077, 17758763, 18640740, 32593455 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1149147819689533, 378692712667677, 828475842424202, + 2218619146419342, 70688125792186 +#else + 60180029, 17123636, 10361373, 5642961, 4910474, 12345252, + 35470478, 33060001, 10530746, 1053335 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1299739417079761, 1438616663452759, 1536729078504412, + 2053896748919838, 1008421032591246 +#else + 37842897, 19367626, 53570647, 21437058, 47651804, 22899047, + 35646494, 30605446, 24018830, 15026644 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2040723824657366, 399555637875075, 632543375452995, + 872649937008051, 1235394727030233 +#else + 44516310, 30409154, 64819587, 5953842, 53668675, 9425630, + 25310643, 13003497, 64794073, 18408815 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2211311599327900, 2139787259888175, 938706616835350, + 12609661139114, 2081897930719789 +#else + 39688860, 32951110, 59064879, 31885314, 41016598, 13987818, + 39811242, 187898, 43942445, 31022696 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1324994503390450, 336982330582631, 1183998925654177, + 1091654665913274, 48727673971319 +#else + 45364466, 19743956, 1844839, 5021428, 56674465, 17642958, + 9716666, 16266922, 62038647, 726098 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1845522914617879, 1222198248335542, 150841072760134, + 1927029069940982, 1189913404498011 +#else + 29370903, 27500434, 7334070, 18212173, 9385286, 2247707, + 53446902, 28714970, 30007387, 17731091 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1079559557592645, 2215338383666441, 1903569501302605, + 49033973033940, 305703433934152 +#else + 66172485, 16086690, 23751945, 33011114, 65941325, 28365395, + 9137108, 730663, 9835848, 4555336 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 94653405416909, 1386121349852999, 1062130477891762, + 36553947479274, 833669648948846 +#else + 43732429, 1410445, 44855111, 20654817, 30867634, 15826977, + 17693930, 544696, 55123566, 12422645 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1432015813136298, 440364795295369, 1395647062821501, + 1976874522764578, 934452372723352 +#else + 31117226, 21338698, 53606025, 6561946, 57231997, 20796761, + 61990178, 29457725, 29120152, 13924425 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1296625309219774, 2068273464883862, 1858621048097805, + 1492281814208508, 2235868981918946 +#else + 49707966, 19321222, 19675798, 30819676, 56101901, 27695611, + 57724924, 22236731, 7240930, 33317044 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1490330266465570, 1858795661361448, 1436241134969763, + 294573218899647, 1208140011028933 +#else + 35747106, 22207651, 52101416, 27698213, 44655523, 21401660, + 1222335, 4389483, 3293637, 18002689 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1282462923712748, 741885683986255, 2027754642827561, + 518989529541027, 1826610009555945 +#else + 50424044, 19110186, 11038543, 11054958, 53307689, 30215898, + 42789283, 7733546, 12796905, 27218610 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1525827120027511, 723686461809551, 1597702369236987, + 244802101764964, 1502833890372311 +#else + 58349431, 22736595, 41689999, 10783768, 36493307, 23807620, + 38855524, 3647835, 3222231, 22393970 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 113622036244513, 1233740067745854, 674109952278496, + 2114345180342965, 166764512856263 +#else + 18606113, 1693100, 41660478, 18384159, 4112352, 10045021, + 23603893, 31506198, 59558087, 2484984 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2041668749310338, 2184405322203901, 1633400637611036, + 2110682505536899, 2048144390084644 +#else + 9255298, 30423235, 54952701, 32550175, 13098012, 24339566, + 16377219, 31451620, 47306788, 30519729 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 503058759232932, 760293024620937, 2027152777219493, + 666858468148475, 1539184379870952 +#else + 44379556, 7496159, 61366665, 11329248, 19991973, 30206930, + 35390715, 9936965, 37011176, 22935634 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1916168475367211, 915626432541343, 883217071712575, + 363427871374304, 1976029821251593 +#else + 21878571, 28553135, 4338335, 13643897, 64071999, 13160959, + 19708896, 5415497, 59748361, 29445138 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 678039535434506, 570587290189340, 1605302676614120, + 2147762562875701, 1706063797091704 +#else + 27736842, 10103576, 12500508, 8502413, 63695848, 23920873, + 10436917, 32004156, 43449720, 25422331 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1439489648586438, 2194580753290951, 832380563557396, + 561521973970522, 584497280718389 +#else + 19492550, 21450067, 37426887, 32701801, 63900692, 12403436, + 30066266, 8367329, 13243957, 8709688 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 187989455492609, 681223515948275, 1933493571072456, + 1872921007304880, 488162364135671 +#else + 12015105, 2801261, 28198131, 10151021, 24818120, 28811299, + 55914672, 27908697, 5150967, 7274186 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1413466089534451, 410844090765630, 1397263346404072, + 408227143123410, 1594561803147811 +#else + 2831347, 21062286, 1478974, 6122054, 23825128, 20820846, + 31097298, 6083058, 31021603, 23760822 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2102170800973153, 719462588665004, 1479649438510153, + 1097529543970028, 1302363283777685 +#else + 64578913, 31324785, 445612, 10720828, 53259337, 22048494, + 43601132, 16354464, 15067285, 19406725 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 942065717847195, 1069313679352961, 2007341951411051, + 70973416446291, 1419433790163706 +#else + 7840923, 14037873, 33744001, 15934015, 66380651, 29911725, + 21403987, 1057586, 47729402, 21151211 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1146565545556377, 1661971299445212, 406681704748893, + 564452436406089, 1109109865829139 +#else + 915865, 17085158, 15608284, 24765302, 42751837, 6060029, + 49737545, 8410996, 59888403, 16527024 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2214421081775077, 1165671861210569, 1890453018796184, + 3556249878661, 442116172656317 +#else + 32922597, 32997445, 20336073, 17369864, 10903704, 28169945, + 16957573, 52992, 23834301, 6588044 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 753830546620811, 1666955059895019, 1530775289309243, + 1119987029104146, 2164156153857580 +#else + 32752011, 11232950, 3381995, 24839566, 22652987, 22810329, + 17159698, 16689107, 46794284, 32248439 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 615171919212796, 1523849404854568, 854560460547503, + 2067097370290715, 1765325848586042 +#else + 62419196, 9166775, 41398568, 22707125, 11576751, 12733943, + 7924251, 30802151, 1976122, 26305405 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1094538949313667, 1796592198908825, 870221004284388, + 2025558921863561, 1699010892802384 +#else + 21251203, 16309901, 64125849, 26771309, 30810596, 12967303, + 156041, 30183180, 12331344, 25317235 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1951351290725195, 1916457206844795, 198025184438026, + 1909076887557595, 1938542290318919 +#else + 8651595, 29077400, 51023227, 28557437, 13002506, 2950805, + 29054427, 28447462, 10008135, 28886531 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1014323197538413, 869150639940606, 1756009942696599, + 1334952557375672, 1544945379082874 +#else + 31486061, 15114593, 52847614, 12951353, 14369431, 26166587, + 16347320, 19892343, 8684154, 23021480 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 764055910920305, 1603590757375439, 146805246592357, + 1843313433854297, 954279890114939 +#else + 19443825, 11385320, 24468943, 23895364, 43189605, 2187568, + 40845657, 27467510, 31316347, 14219878 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 80113526615750, 764536758732259, 1055139345100233, + 469252651759390, 617897512431515 +#else + 38514374, 1193784, 32245219, 11392485, 31092169, 15722801, + 27146014, 6992409, 29126555, 9207390 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 74497112547268, 740094153192149, 1745254631717581, + 727713886503130, 1283034364416928 +#else + 32382916, 1110093, 18477781, 11028262, 39697101, 26006320, + 62128346, 10843781, 59151264, 19118701 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 525892105991110, 1723776830270342, 1476444848991936, + 573789489857760, 133864092632978 +#else + 2814918, 7836403, 27519878, 25686276, 46214848, 22000742, + 45614304, 8550129, 28346258, 1994730 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 542611720192581, 1986812262899321, 1162535242465837, + 481498966143464, 544600533583622 +#else + 47530565, 8085544, 53108345, 29605809, 2785837, 17323125, + 47591912, 7174893, 22628102, 8115180 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 64123227344372, 1239927720647794, 1360722983445904, + 222610813654661, 62429487187991 +#else + 36703732, 955510, 55975026, 18476362, 34661776, 20276352, + 41457285, 3317159, 57165847, 930271 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1793193323953132, 91096687857833, 70945970938921, + 2158587638946380, 1537042406482111 +#else + 51805164, 26720662, 28856489, 1357446, 23421993, 1057177, + 24091212, 32165462, 44343487, 22903716 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1895854577604609, 1394895708949416, 1728548428495944, + 1140864900240149, 563645333603061 +#else + 44357633, 28250434, 54201256, 20785565, 51297352, 25757378, + 52269845, 17000211, 65241845, 8398969 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 141358280486863, 91435889572504, 1087208572552643, + 1829599652522921, 1193307020643647 +#else + 35139535, 2106402, 62372504, 1362500, 12813763, 16200670, + 22981545, 27263159, 18009407, 17781660 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1611230858525381, 950720175540785, 499589887488610, + 2001656988495019, 88977313255908 +#else + 49887941, 24009210, 39324209, 14166834, 29815394, 7444469, + 29551787, 29827013, 19288548, 1325865 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1189080501479658, 2184348804772597, 1040818725742319, + 2018318290311834, 1712060030915354 +#else + 15100138, 17718680, 43184885, 32549333, 40658671, 15509407, + 12376730, 30075286, 33166106, 25511682 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 873966876953756, 1090638350350440, 1708559325189137, + 672344594801910, 1320437969700239 +#else + 20909212, 13023121, 57899112, 16251777, 61330449, 25459517, + 12412150, 10018715, 2213263, 19676059 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1508590048271766, 1131769479776094, 101550868699323, + 428297785557897, 561791648661744 +#else + 32529814, 22479743, 30361438, 16864679, 57972923, 1513225, + 22922121, 6382134, 61341936, 8371347 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 756417570499462, 237882279232602, 2136263418594016, + 1701968045454886, 703713185137472 +#else + 9923462, 11271500, 12616794, 3544722, 37110496, 31832805, + 12891686, 25361300, 40665920, 10486143 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1781187809325462, 1697624151492346, 1381393690939988, + 175194132284669, 1483054666415238 +#else + 44511638, 26541766, 8587002, 25296571, 4084308, 20584370, + 361725, 2610596, 43187334, 22099236 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2175517777364616, 708781536456029, 955668231122942, + 1967557500069555, 2021208005604118 +#else + 5408392, 32417741, 62139741, 10561667, 24145918, 14240566, + 31319731, 29318891, 19985174, 30118346 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1115135966606887, 224217372950782, 915967306279222, + 593866251291540, 561747094208006 +#else + 53114407, 16616820, 14549246, 3341099, 32155958, 13648976, + 49531796, 8849296, 65030, 8370684 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1443163092879439, 391875531646162, 2180847134654632, + 464538543018753, 1594098196837178 +#else + 58787919, 21504805, 31204562, 5839400, 46481576, 32497154, + 47665921, 6922163, 12743482, 23753914 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 850858855888869, 319436476624586, 327807784938441, + 740785849558761, 17128415486016 +#else + 64747493, 12678784, 28815050, 4759974, 43215817, 4884716, + 23783145, 11038569, 18800704, 255233 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2132756334090067, 536247820155645, 48907151276867, + 608473197600695, 1261689545022784 +#else + 61839187, 31780545, 13957885, 7990715, 23132995, 728773, + 13393847, 9066957, 19258688, 18800639 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1525176236978354, 974205476721062, 293436255662638, + 148269621098039, 137961998433963 +#else + 64172210, 22726896, 56676774, 14516792, 63468078, 4372540, + 35173943, 2209389, 65584811, 2055793 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1121075518299410, 2071745529082111, 1265567917414828, + 1648196578317805, 496232102750820 +#else + 580882, 16705327, 5468415, 30871414, 36182444, 18858431, + 59905517, 24560042, 37087844, 7394434 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 122321229299801, 1022922077493685, 2001275453369484, + 2017441881607947, 993205880778002 +#else + 23838809, 1822728, 51370421, 15242726, 8318092, 29821328, + 45436683, 30062226, 62287122, 14799920 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 654925550560074, 1168810995576858, 575655959430926, + 905758704861388, 496774564663534 +#else + 13345610, 9759151, 3371034, 17416641, 16353038, 8577942, + 31129804, 13496856, 58052846, 7402517 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1954109525779738, 2117022646152485, 338102630417180, + 1194140505732026, 107881734943492 +#else + 2286874, 29118501, 47066405, 31546095, 53412636, 5038121, + 11006906, 17794080, 8205060, 1607563 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1714785840001267, 2036500018681589, 1876380234251966, + 2056717182974196, 1645855254384642 +#else + 14414067, 25552300, 3331829, 30346215, 22249150, 27960244, + 18364660, 30647474, 30019586, 24525154 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 106431476499341, 62482972120563, 1513446655109411, + 807258751769522, 538491469114 +#else + 39420813, 1585952, 56333811, 931068, 37988643, 22552112, + 52698034, 12029092, 9944378, 8024 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2002850762893643, 1243624520538135, 1486040410574605, + 2184752338181213, 378495998083531 +#else + 4368715, 29844802, 29874199, 18531449, 46878477, 22143727, + 50994269, 32555346, 58966475, 5640029 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 922510868424903, 1089502620807680, 402544072617374, + 1131446598479839, 1290278588136533 +#else + 10299591, 13746483, 11661824, 16234854, 7630238, 5998374, + 9809887, 16859868, 15219797, 19226649 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1867998812076769, 715425053580701, 39968586461416, + 2173068014586163, 653822651801304 +#else + 27425505, 27835351, 3055005, 10660664, 23458024, 595578, + 51710259, 32381236, 48766680, 9742716 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 162892278589453, 182585796682149, 75093073137630, + 497037941226502, 133871727117371 +#else + 6744077, 2427284, 26042789, 2720740, 66260958, 1118973, + 32324614, 7406442, 12420155, 1994844 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1914596576579670, 1608999621851578, 1987629837704609, + 1519655314857977, 1819193753409464 +#else + 14012502, 28529712, 48724410, 23975962, 40623521, 29617992, + 54075385, 22644628, 24319928, 27108099 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1949315551096831, 1069003344994464, 1939165033499916, + 1548227205730856, 1933767655861407 +#else + 16412671, 29047065, 10772640, 15929391, 50040076, 28895810, + 10555944, 23070383, 37006495, 28815383 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1730519386931635, 1393284965610134, 1597143735726030, + 416032382447158, 1429665248828629 +#else + 22397363, 25786748, 57815702, 20761563, 17166286, 23799296, + 39775798, 6199365, 21880021, 21303672 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 360275475604565, 547835731063078, 215360904187529, + 596646739879007, 332709650425085 +#else + 62825557, 5368522, 35991846, 8163388, 36785801, 3209127, + 16557151, 8890729, 8840445, 4957760 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 47602113726801, 1522314509708010, 437706261372925, + 814035330438027, 335930650933545 +#else + 51661137, 709326, 60189418, 22684253, 37330941, 6522331, + 45388683, 12130071, 52312361, 5005756 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1291597595523886, 1058020588994081, 402837842324045, + 1363323695882781, 2105763393033193 +#else + 64994094, 19246303, 23019041, 15765735, 41839181, 6002751, + 10183197, 20315106, 50713577, 31378319 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 109521982566564, 1715257748585139, 1112231216891516, + 2046641005101484, 134249157157013 +#else + 48083108, 1632004, 13466291, 25559332, 43468412, 16573536, + 35094956, 30497327, 22208661, 2000468 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2156991030936798, 2227544497153325, 1869050094431622, + 754875860479115, 1754242344267058 +#else + 3065054, 32141671, 41510189, 33192999, 49425798, 27851016, + 58944651, 11248526, 63417650, 26140247 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1846089562873800, 98894784984326, 1412430299204844, + 171351226625762, 1100604760929008 +#else + 10379208, 27508878, 8877318, 1473647, 37817580, 21046851, + 16690914, 2553332, 63976176, 16400288 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 84172382130492, 499710970700046, 425749630620778, + 1762872794206857, 612842602127960 +#else + 15716668, 1254266, 48636174, 7446273, 58659946, 6344163, + 45011593, 26268851, 26894936, 9132066 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 868309334532756, 1703010512741873, 1952690008738057, + 4325269926064, 2071083554962116 +#else + 24158868, 12938817, 11085297, 25376834, 39045385, 29097348, + 36532400, 64451, 60291780, 30861549 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 523094549451158, 401938899487815, 1407690589076010, + 2022387426254453, 158660516411257 +#else + 13488534, 7794716, 22236231, 5989356, 25426474, 20976224, + 2350709, 30135921, 62420857, 2364225 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 612867287630009, 448212612103814, 571629077419196, + 1466796750919376, 1728478129663858 +#else + 16335033, 9132434, 25640582, 6678888, 1725628, 8517937, + 55301840, 21856974, 15445874, 25756331 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1723848973783452, 2208822520534681, 1718748322776940, + 1974268454121942, 1194212502258141 +#else + 29004188, 25687351, 28661401, 32914020, 54314860, 25611345, + 31863254, 29418892, 66830813, 17795152 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1254114807944608, 977770684047110, 2010756238954993, + 1783628927194099, 1525962994408256 +#else + 60986784, 18687766, 38493958, 14569918, 56250865, 29962602, + 10343411, 26578142, 37280576, 22738620 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 232464058235826, 1948628555342434, 1835348780427694, + 1031609499437291, 64472106918373 +#else + 27081650, 3463984, 14099042, 29036828, 1616302, 27348828, + 29542635, 15372179, 17293797, 960709 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 767338676040683, 754089548318405, 1523192045639075, + 435746025122062, 512692508440385 +#else + 20263915, 11434237, 61343429, 11236809, 13505955, 22697330, + 50997518, 6493121, 47724353, 7639713 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1255955808701983, 1700487367990941, 1166401238800299, + 1175121994891534, 1190934801395380 +#else + 64278047, 18715199, 25403037, 25339236, 58791851, 17380732, + 18006286, 17510682, 29994676, 17746311 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 349144008168292, 1337012557669162, 1475912332999108, + 1321618454900458, 47611291904320 +#else + 9769828, 5202651, 42951466, 19923039, 39057860, 21992807, + 42495722, 19693649, 35924288, 709463 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 877519947135419, 2172838026132651, 272304391224129, + 1655143327559984, 886229406429814 +#else + 12286395, 13076066, 45333675, 32377809, 42105665, 4057651, + 35090736, 24663557, 16102006, 13205847 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 375806028254706, 214463229793940, 572906353144089, + 572168269875638, 697556386112979 +#else + 13733362, 5599946, 10557076, 3195751, 61550873, 8536969, + 41568694, 8525971, 10151379, 10394400 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1168827102357844, 823864273033637, 2071538752104697, + 788062026895924, 599578340743362 +#else + 4024660, 17416881, 22436261, 12276534, 58009849, 30868332, + 19698228, 11743039, 33806530, 8934413 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1948116082078088, 2054898304487796, 2204939184983900, + 210526805152138, 786593586607626 +#else + 51229064, 29029191, 58528116, 30620370, 14634844, 32856154, + 57659786, 3137093, 55571978, 11721157 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1915320147894736, 156481169009469, 655050471180417, + 592917090415421, 2165897438660879 +#else + 17555920, 28540494, 8268605, 2331751, 44370049, 9761012, + 9319229, 8835153, 57903375, 32274386 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1726336468579724, 1119932070398949, 1929199510967666, + 33918788322959, 1836837863503150 +#else + 66647436, 25724417, 20614117, 16688288, 59594098, 28747312, + 22300303, 505429, 6108462, 27371017 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 829996854845988, 217061778005138, 1686565909803640, + 1346948817219846, 1723823550730181 +#else + 62038564, 12367916, 36445330, 3234472, 32617080, 25131790, + 29880582, 20071101, 40210373, 25686972 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 384301494966394, 687038900403062, 2211195391021739, + 254684538421383, 1245698430589680 +#else + 35133562, 5726538, 26934134, 10237677, 63935147, 32949378, + 24199303, 3795095, 7592688, 18562353 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1247567493562688, 1978182094455847, 183871474792955, + 806570235643435, 288461518067916 +#else + 21594432, 18590204, 17466407, 29477210, 32537083, 2739898, + 6407723, 12018833, 38852812, 4298411 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1449077384734201, 38285445457996, 2136537659177832, + 2146493000841573, 725161151123125 +#else + 46458361, 21592935, 39872588, 570497, 3767144, 31836892, + 13891941, 31985238, 13717173, 10805743 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1201928866368855, 800415690605445, 1703146756828343, + 997278587541744, 1858284414104014 +#else + 52432215, 17910135, 15287173, 11927123, 24177847, 25378864, + 66312432, 14860608, 40169934, 27690595 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 356468809648877, 782373916933152, 1718002439402870, + 1392222252219254, 663171266061951 +#else + 12962541, 5311799, 57048096, 11658279, 18855286, 25600231, + 13286262, 20745728, 62727807, 9882021 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 759628738230460, 1012693474275852, 353780233086498, + 246080061387552, 2030378857679162 +#else + 18512060, 11319350, 46985740, 15090308, 18818594, 5271736, + 44380960, 3666878, 43141434, 30255002 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2040672435071076, 888593182036908, 1298443657189359, + 1804780278521327, 354070726137060 +#else + 60319844, 30408388, 16192428, 13241070, 15898607, 19348318, + 57023983, 26893321, 64705764, 5276064 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1894938527423184, 1463213041477277, 474410505497651, + 247294963033299, 877975941029128 +#else + 30169808, 28236784, 26306205, 21803573, 27814963, 7069267, + 7152851, 3684982, 1449224, 13082861 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 207937160991127, 12966911039119, 820997788283092, + 1010440472205286, 1701372890140810 +#else + 10342807, 3098505, 2119311, 193222, 25702612, 12233820, + 23697382, 15056736, 46092426, 25352431 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 218882774543183, 533427444716285, 1233243976733245, + 435054256891319, 1509568989549904 +#else + 33958735, 3261607, 22745853, 7948688, 19370557, 18376767, + 40936887, 6482813, 56808784, 22494330 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1888838535711826, 1052177758340622, 1213553803324135, + 169182009127332, 463374268115872 +#else + 32869458, 28145887, 25609742, 15678670, 56421095, 18083360, + 26112420, 2521008, 44444576, 6904814 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 299137589460312, 1594371588983567, 868058494039073, + 257771590636681, 1805012993142921 +#else + 29506904, 4457497, 3377935, 23757988, 36598817, 12935079, + 1561737, 3841096, 38105225, 26896789 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1806842755664364, 2098896946025095, 1356630998422878, + 1458279806348064, 347755825962072 +#else + 10340844, 26924055, 48452231, 31276001, 12621150, 20215377, + 30878496, 21730062, 41524312, 5181965 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1402334161391744, 1560083671046299, 1008585416617747, + 1147797150908892, 1420416683642459 +#else + 25940096, 20896407, 17324187, 23247058, 58437395, 15029093, + 24396252, 17103510, 64786011, 21165857 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665506704253369, 273770475169863, 799236974202630, + 848328990077558, 1811448782807931 +#else + 45343161, 9916822, 65808455, 4079497, 66080518, 11909558, + 1782390, 12641087, 20603771, 26992690 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1468412523962641, 771866649897997, 1931766110147832, + 799561180078482, 524837559150077 +#else + 48226577, 21881051, 24849421, 11501709, 13161720, 28785558, + 1925522, 11914390, 4662781, 7820689 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2223212657821850, 630416247363666, 2144451165500328, + 816911130947791, 1024351058410032 +#else + 12241050, 33128450, 8132690, 9393934, 32846760, 31954812, + 29749455, 12172924, 16136752, 15264020 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1266603897524861, 156378408858100, 1275649024228779, + 447738405888420, 253186462063095 +#else + 56758909, 18873868, 58896884, 2330219, 49446315, 19008651, + 10658212, 6671822, 19012087, 3772772 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022215964509735, 136144366993649, 1800716593296582, + 1193970603800203, 871675847064218 +#else + 3753511, 30133366, 10617073, 2028709, 14841030, 26832768, + 28718731, 17791548, 20527770, 12988982 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1862751661970328, 851596246739884, 1519315554814041, + 1542798466547449, 1417975335901520 +#else + 52286360, 27757162, 63400876, 12689772, 66209881, 22639565, + 42925817, 22989488, 3299664, 21129479 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1228168094547481, 334133883362894, 587567568420081, + 433612590281181, 603390400373205 +#else + 50331161, 18301130, 57466446, 4978982, 3308785, 8755439, + 6943197, 6461331, 41525717, 8991217 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 121893973206505, 1843345804916664, 1703118377384911, + 497810164760654, 101150811654673 +#else + 49882601, 1816361, 65435576, 27467992, 31783887, 25378441, + 34160718, 7417949, 36866577, 1507264 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 458346255946468, 290909935619344, 1452768413850679, + 550922875254215, 1537286854336538 +#else + 29692644, 6829891, 56610064, 4334895, 20945975, 21647936, + 38221255, 8209390, 14606362, 22907359 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 584322311184395, 380661238802118, 114839394528060, + 655082270500073, 2111856026034852 +#else + 63627275, 8707080, 32188102, 5672294, 22096700, 1711240, + 34088169, 9761486, 4170404, 31469107 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 996965581008991, 2148998626477022, 1012273164934654, + 1073876063914522, 1688031788934939 +#else + 55521375, 14855944, 62981086, 32022574, 40459774, 15084045, + 22186522, 16002000, 52832027, 25153633 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 923487018849600, 2085106799623355, 528082801620136, + 1606206360876188, 735907091712524 +#else + 62297408, 13761028, 35404987, 31070512, 63796392, 7869046, + 59995292, 23934339, 13240844, 10965870 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1697697887804317, 1335343703828273, 831288615207040, + 949416685250051, 288760277392022 +#else + 59366301, 25297669, 52340529, 19898171, 43876480, 12387165, + 4498947, 14147411, 29514390, 4302863 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1419122478109648, 1325574567803701, 602393874111094, + 2107893372601700, 1314159682671307 +#else + 53695440, 21146572, 20757301, 19752600, 14785142, 8976368, + 62047588, 31410058, 17846987, 19582505 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2201150872731804, 2180241023425241, 97663456423163, + 1633405770247824, 848945042443986 +#else + 64864412, 32799703, 62511833, 32488122, 60861691, 1455298, + 45461136, 24339642, 61886162, 12650266 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1173339555550611, 818605084277583, 47521504364289, + 924108720564965, 735423405754506 +#else + 57202067, 17484121, 21134159, 12198166, 40044289, 708125, + 387813, 13770293, 47974538, 10958662 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 830104860549448, 1886653193241086, 1600929509383773, + 1475051275443631, 286679780900937 +#else + 22470984, 12369526, 23446014, 28113323, 45588061, 23855708, + 55336367, 21979976, 42025033, 4271861 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1577111294832995, 1030899169768747, 144900916293530, + 1964672592979567, 568390100955250 +#else + 41939299, 23500789, 47199531, 15361594, 61124506, 2159191, + 75375, 29275903, 34582642, 8469672 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 278388655910247, 487143369099838, 927762205508727, + 181017540174210, 1616886700741287 +#else + 15854951, 4148314, 58214974, 7259001, 11666551, 13824734, + 36577666, 2697371, 24154791, 24093489 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1191033906638969, 940823957346562, 1606870843663445, + 861684761499847, 658674867251089 +#else + 15446137, 17747788, 29759746, 14019369, 30811221, 23944241, + 35526855, 12840103, 24913809, 9815020 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1875032594195546, 1427106132796197, 724736390962158, + 901860512044740, 635268497268760 +#else + 62399578, 27940162, 35267365, 21265538, 52665326, 10799413, + 58005188, 13438768, 18735128, 9466238 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 622869792298357, 1903919278950367, 1922588621661629, + 1520574711600434, 1087100760174640 +#else + 11933045, 9281483, 5081055, 28370608, 64480701, 28648802, + 59381042, 22658328, 44380208, 16199063 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 25465949416618, 1693639527318811, 1526153382657203, + 125943137857169, 145276964043999 +#else + 14576810, 379472, 40322331, 25237195, 37682355, 22741457, + 67006097, 1876698, 30801119, 2164795 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 214739857969358, 920212862967915, 1939901550972269, + 1211862791775221, 85097515720120 +#else + 15995086, 3199873, 13672555, 13712240, 47730029, 28906785, + 54027253, 18058162, 53616056, 1268051 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2006245852772938, 734762734836159, 254642929763427, + 1406213292755966, 239303749517686 +#else + 56818250, 29895392, 63822271, 10948817, 23037027, 3794475, + 63638526, 20954210, 50053494, 3565903 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1619678837192149, 1919424032779215, 1357391272956794, + 1525634040073113, 1310226789796241 +#else + 29210069, 24135095, 61189071, 28601646, 10834810, 20226706, + 50596761, 22733718, 39946641, 19523900 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1040763709762123, 1704449869235352, 605263070456329, + 1998838089036355, 1312142911487502 +#else + 53946955, 15508587, 16663704, 25398282, 38758921, 9019122, + 37925443, 29785008, 2244110, 19552453 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1996723311435669, 1844342766567060, 985455700466044, + 1165924681400960, 311508689870129 +#else + 61955989, 29753495, 57802388, 27482848, 16243068, 14684434, + 41435776, 17373631, 13491505, 4641841 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 43173156290518, 2202883069785309, 1137787467085917, + 1733636061944606, 1394992037553852 +#else + 10813398, 643330, 47920349, 32825515, 30292061, 16954354, + 27548446, 25833190, 14476988, 20787001 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 670078326344559, 555655025059356, 471959386282438, + 2141455487356409, 849015953823125 +#else + 10292079, 9984945, 6481436, 8279905, 59857350, 7032742, + 27282937, 31910173, 39196053, 12651323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2197214573372804, 794254097241315, 1030190060513737, + 267632515541902, 2040478049202624 +#else + 35923332, 32741048, 22271203, 11835308, 10201545, 15351028, + 17099662, 3988035, 21721536, 30405492 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1812516004670529, 1609256702920783, 1706897079364493, + 258549904773295, 996051247540686 +#else + 10202177, 27008593, 35735631, 23979793, 34958221, 25434748, + 54202543, 3852693, 13216206, 14842320 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1540374301420584, 1764656898914615, 1810104162020396, + 923808779163088, 664390074196579 +#else + 51293224, 22953365, 60569911, 26295436, 60124204, 26972653, + 35608016, 13765823, 39674467, 9900183 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1323460699404750, 1262690757880991, 871777133477900, + 1060078894988977, 1712236889662886 +#else + 14465486, 19721101, 34974879, 18815558, 39665676, 12990491, + 33046193, 15796406, 60056998, 25514317 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1696163952057966, 1391710137550823, 608793846867416, + 1034391509472039, 1780770894075012 +#else + 30924398, 25274812, 6359015, 20738097, 16508376, 9071735, + 41620263, 15413634, 9524356, 26535554 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1367603834210841, 2131988646583224, 890353773628144, + 1908908219165595, 270836895252891 +#else + 12274201, 20378885, 32627640, 31769106, 6736624, 13267305, + 5237659, 28444949, 15663515, 4035784 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 597536315471731, 40375058742586, 1942256403956049, + 1185484645495932, 312666282024145 +#else + 64157555, 8903984, 17349946, 601635, 50676049, 28941875, + 53376124, 17665097, 44850385, 4659090 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1919411405316294, 1234508526402192, 1066863051997083, + 1008444703737597, 1348810787701552 +#else + 50192582, 28601458, 36715152, 18395610, 20774811, 15897498, + 5736189, 15026997, 64930608, 20098846 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2102881477513865, 1570274565945361, 1573617900503708, + 18662635732583, 2232324307922098 +#else + 58249865, 31335375, 28571665, 23398914, 66634396, 23448733, + 63307367, 278094, 23440562, 33264224 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1853931367696942, 8107973870707, 350214504129299, + 775206934582587, 1752317649166792 +#else + 10226222, 27625730, 15139955, 120818, 52241171, 5218602, + 32937275, 11551483, 50536904, 26111567 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1417148368003523, 721357181628282, 505725498207811, + 373232277872983, 261634707184480 +#else + 17932739, 21117156, 43069306, 10749059, 11316803, 7535897, + 22503767, 5561594, 63462240, 3898660 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2186733281493267, 2250694917008620, 1014829812957440, + 479998161452389, 83566193876474 +#else + 7749907, 32584865, 50769132, 33537967, 42090752, 15122142, + 65535333, 7152529, 21831162, 1245233 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1268116367301224, 560157088142809, 802626839600444, + 2210189936605713, 1129993785579988 +#else + 26958440, 18896406, 4314585, 8346991, 61431100, 11960071, + 34519569, 32934396, 36706772, 16838219 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 615183387352312, 917611676109240, 878893615973325, + 978940963313282, 938686890583575 +#else + 54942968, 9166946, 33491384, 13673479, 29787085, 13096535, + 6280834, 14587357, 44770839, 13987524 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 522024729211672, 1045059315315808, 1892245413707790, + 1907891107684253, 2059998109500714 +#else + 42758936, 7778774, 21116000, 15572597, 62275598, 28196653, + 62807965, 28429792, 59639082, 30696363 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1799679152208884, 912132775900387, 25967768040979, + 432130448590461, 274568990261996 +#else + 9681908, 26817309, 35157219, 13591837, 60225043, 386949, + 31622781, 6439245, 52527852, 4091396 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 98698809797682, 2144627600856209, 1907959298569602, + 811491302610148, 1262481774981493 +#else + 58682418, 1470726, 38999185, 31957441, 3978626, 28430809, + 47486180, 12092162, 29077877, 18812444 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1791451399743152, 1713538728337276, 118349997257490, + 1882306388849954, 158235232210248 +#else + 5269168, 26694706, 53878652, 25533716, 25932562, 1763552, + 61502754, 28048550, 47091016, 2357888 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1217809823321928, 2173947284933160, 1986927836272325, + 1388114931125539, 12686131160169 +#else + 32264008, 18146780, 61721128, 32394338, 65017541, 29607531, + 23104803, 20684524, 5727337, 189038 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1650875518872272, 1136263858253897, 1732115601395988, + 734312880662190, 1252904681142109 +#else + 14609104, 24599962, 61108297, 16931650, 52531476, 25810533, + 40363694, 10942114, 41219933, 18669734 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 372986456113865, 525430915458171, 2116279931702135, + 501422713587815, 1907002872974925 +#else + 20513481, 5557931, 51504251, 7829530, 26413943, 31535028, + 45729895, 7471780, 13913677, 28416557 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 803147181835288, 868941437997146, 316299302989663, + 943495589630550, 571224287904572 +#else + 41534488, 11967825, 29233242, 12948236, 60354399, 4713226, + 58167894, 14059179, 12878652, 8511905 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 227742695588364, 1776969298667369, 628602552821802, + 457210915378118, 2041906378111140 +#else + 41452044, 3393630, 64153449, 26478905, 64858154, 9366907, + 36885446, 6812973, 5568676, 30426776 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 815000523470260, 913085688728307, 1052060118271173, + 1345536665214223, 541623413135555 +#else + 11630004, 12144454, 2116339, 13606037, 27378885, 15676917, + 49700111, 20050058, 52713667, 8070817 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1580216071604333, 1877997504342444, 857147161260913, + 703522726778478, 2182763974211603 +#else + 27117677, 23547054, 35826092, 27984343, 1127281, 12772488, + 37262958, 10483305, 55556115, 32525717 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1870080310923419, 71988220958492, 1783225432016732, + 615915287105016, 1035570475990230 +#else + 10637467, 27866368, 5674780, 1072708, 40765276, 26572129, + 65424888, 9177852, 39615702, 15431202 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 730987750830150, 857613889540280, 1083813157271766, + 1002817255970169, 1719228484436074 +#else + 20525126, 10892566, 54366392, 12779442, 37615830, 16150074, + 38868345, 14943141, 52052074, 25618500 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 377616581647602, 1581980403078513, 804044118130621, + 2034382823044191, 643844048472185 +#else + 37084402, 5626925, 66557297, 23573344, 753597, 11981191, + 25244767, 30314666, 63752313, 9594023 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 176957326463017, 1573744060478586, 528642225008045, + 1816109618372371, 1515140189765006 +#else + 43356201, 2636869, 61944954, 23450613, 585133, 7877383, + 11345683, 27062142, 13352334, 22577348 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1888911448245718, 1387110895611080, 1924503794066429, + 1731539523700949, 2230378382645454 +#else + 65177046, 28146973, 3304648, 20669563, 17015805, 28677341, + 37325013, 25801949, 53893326, 33235227 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 443392177002051, 233793396845137, 2199506622312416, + 1011858706515937, 974676837063129 +#else + 20239939, 6607058, 6203985, 3483793, 48721888, 32775202, + 46385121, 15077869, 44358105, 14523816 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1846351103143623, 1949984838808427, 671247021915253, + 1946756846184401, 1929296930380217 +#else + 27406023, 27512775, 27423595, 29057038, 4996213, 10002360, + 38266833, 29008937, 36936121, 28748764 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 849646212452002, 1410198775302919, 73767886183695, + 1641663456615812, 762256272452411 +#else + 11374242, 12660715, 17861383, 21013599, 10935567, 1099227, + 53222788, 24462691, 39381819, 11358503 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 692017667358279, 723305578826727, 1638042139863265, + 748219305990306, 334589200523901 +#else + 54378055, 10311866, 1510375, 10778093, 64989409, 24408729, + 32676002, 11149336, 40985213, 4985767 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 22893968530686, 2235758574399251, 1661465835630252, + 925707319443452, 1203475116966621 +#else + 48012542, 341146, 60911379, 33315398, 15756972, 24757770, + 66125820, 13794113, 47694557, 17933176 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 801299035785166, 1733292596726131, 1664508947088596, + 467749120991922, 1647498584535623 +#else + 6490062, 11940286, 25495923, 25828072, 8668372, 24803116, + 3367602, 6970005, 65417799, 24549641 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 903105258014366, 427141894933047, 561187017169777, + 1884330244401954, 1914145708422219 +#else + 1656478, 13457317, 15370807, 6364910, 13605745, 8362338, + 47934242, 28078708, 50312267, 28522993 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1344191060517578, 1960935031767890, 1518838929955259, + 1781502350597190, 1564784025565682 +#else + 44835530, 20030007, 67044178, 29220208, 48503227, 22632463, + 46537798, 26546453, 67009010, 23317098 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 673723351748086, 1979969272514923, 1175287312495508, + 1187589090978666, 1881897672213940 +#else + 17747446, 10039260, 19368299, 29503841, 46478228, 17513145, + 31992682, 17696456, 37848500, 28042460 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1917185587363432, 1098342571752737, 5935801044414, + 2000527662351839, 1538640296181569 +#else + 31932008, 28568291, 47496481, 16366579, 22023614, 88450, + 11371999, 29810185, 4882241, 22927527 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2495540013192, 678856913479236, 224998292422872, + 219635787698590, 1972465269000940 +#else + 29796488, 37186, 19818052, 10115756, 55279832, 3352735, + 18551198, 3272828, 61917932, 29392022 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 271413961212179, 1353052061471651, 344711291283483, + 2014925838520662, 2006221033113941 +#else + 12501267, 4044383, 58495907, 20162046, 34678811, 5136598, + 47878486, 30024734, 330069, 29895023 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 194583029968109, 514316781467765, 829677956235672, + 1676415686873082, 810104584395840 +#else + 6384877, 2899513, 17807477, 7663917, 64749976, 12363164, + 25366522, 24980540, 66837568, 12071498 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1980510813313589, 1948645276483975, 152063780665900, + 129968026417582, 256984195613935 +#else + 58743349, 29511910, 25133447, 29037077, 60897836, 2265926, + 34339246, 1936674, 61949167, 3829362 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1860190562533102, 1936576191345085, 461100292705964, + 1811043097042830, 957486749306835 +#else + 28425966, 27718999, 66531773, 28857233, 52891308, 6870929, + 7921550, 26986645, 26333139, 14267664 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 796664815624365, 1543160838872951, 1500897791837765, + 1667315977988401, 599303877030711 +#else + 56041645, 11871230, 27385719, 22994888, 62522949, 22365119, + 10004785, 24844944, 45347639, 8930323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1151480509533204, 2136010406720455, 738796060240027, + 319298003765044, 1150614464349587 +#else + 45911060, 17158396, 25654215, 31829035, 12282011, 11008919, + 1541940, 4757911, 40617363, 17145491 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1731069268103150, 735642447616087, 1364750481334268, + 417232839982871, 927108269127661 +#else + 13537262, 25794942, 46504023, 10961926, 61186044, 20336366, + 53952279, 6217253, 51165165, 13814989 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1017222050227968, 1987716148359, 2234319589635701, + 621282683093392, 2132553131763026 +#else + 49686272, 15157789, 18705543, 29619, 24409717, 33293956, + 27361680, 9257833, 65152338, 31777517 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1567828528453324, 1017807205202360, 565295260895298, + 829541698429100, 307243822276582 +#else + 42063564, 23362465, 15366584, 15166509, 54003778, 8423555, + 37937324, 12361134, 48422886, 4578289 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 249079270936248, 1501514259790706, 947909724204848, + 944551802437487, 552658763982480 +#else + 24579768, 3711570, 1342322, 22374306, 40103728, 14124955, + 44564335, 14074918, 21964432, 8235257 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2089966982947227, 1854140343916181, 2151980759220007, + 2139781292261749, 158070445864917 +#else + 60580251, 31142934, 9442965, 27628844, 12025639, 32067012, + 64127349, 31885225, 13006805, 2355433 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1338766321464554, 1906702607371284, 1519569445519894, + 115384726262267, 1393058953390992 +#else + 50803946, 19949172, 60476436, 28412082, 16974358, 22643349, + 27202043, 1719366, 1141648, 20758196 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1364621558265400, 1512388234908357, 1926731583198686, + 2041482526432505, 920401122333774 +#else + 54244920, 20334445, 58790597, 22536340, 60298718, 28710537, + 13475065, 30420460, 32674894, 13715045 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1884844597333588, 601480070269079, 620203503079537, + 1079527400117915, 1202076693132015 +#else + 11423316, 28086373, 32344215, 8962751, 24989809, 9241752, + 53843611, 16086211, 38367983, 17912338 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 840922919763324, 727955812569642, 1303406629750194, + 522898432152867, 294161410441865 +#else + 65699196, 12530727, 60740138, 10847386, 19531186, 19422272, + 55399715, 7791793, 39862921, 4383346 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 353760790835310, 1598361541848743, 1122905698202299, + 1922533590158905, 419107700666580 +#else + 38137966, 5271446, 65842855, 23817442, 54653627, 16732598, + 62246457, 28647982, 27193556, 6245191 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 359856369838236, 180914355488683, 861726472646627, + 218807937262986, 575626773232501 +#else + 51914908, 5362277, 65324971, 2695833, 4960227, 12840725, + 23061898, 3260492, 22510453, 8577507 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 755467689082474, 909202735047934, 730078068932500, + 936309075711518, 2007798262842972 +#else + 54476394, 11257345, 34415870, 13548176, 66387860, 10879010, + 31168030, 13952092, 37537372, 29918525 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1609384177904073, 362745185608627, 1335318541768201, + 800965770436248, 547877979267412 +#else + 3877321, 23981693, 32416691, 5405324, 56104457, 19897796, + 3759768, 11935320, 5611860, 8164018 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 984339177776787, 815727786505884, 1645154585713747, + 1659074964378553, 1686601651984156 +#else + 50833043, 14667796, 15906460, 12155291, 44997715, 24514713, + 32003001, 24722143, 5773084, 25132323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1697863093781930, 599794399429786, 1104556219769607, + 830560774794755, 12812858601017 +#else + 43320746, 25300131, 1950874, 8937633, 18686727, 16459170, + 66203139, 12376319, 31632953, 190926 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1168737550514982, 897832437380552, 463140296333799, + 302564600022547, 2008360505135501 +#else + 42515238, 17415546, 58684872, 13378745, 14162407, 6901328, + 58820115, 4508563, 41767309, 29926903 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1856930662813910, 678090852002597, 1920179140755167, + 1259527833759868, 55540971895511 +#else + 8884438, 27670423, 6023973, 10104341, 60227295, 28612898, + 18722940, 18768427, 65436375, 827624 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1158643631044921, 476554103621892, 178447851439725, + 1305025542653569, 103433927680625 +#else + 34388281, 17265135, 34605316, 7101209, 13354605, 2659080, + 65308289, 19446395, 42230385, 1541285 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2176793111709008, 1576725716350391, 2009350167273523, + 2012390194631546, 2125297410909580 +#else + 2901328, 32436745, 3880375, 23495044, 49487923, 29941650, + 45306746, 29986950, 20456844, 31669399 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 825403285195098, 2144208587560784, 1925552004644643, + 1915177840006985, 1015952128947864 +#else + 27019610, 12299467, 53450576, 31951197, 54247203, 28692960, + 47568713, 28538373, 29439640, 15138866 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1807108316634472, 1534392066433717, 347342975407218, + 1153820745616376, 7375003497471 +#else + 21536104, 26928012, 34661045, 22864223, 44700786, 5175813, + 61688824, 17193268, 7779327, 109896 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 983061001799725, 431211889901241, 2201903782961093, + 817393911064341, 2214616493042167 +#else + 30279725, 14648750, 59063993, 6425557, 13639621, 32810923, + 28698389, 12180118, 23177719, 33000357 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 228567918409756, 865093958780220, 358083886450556, + 159617889659320, 1360637926292598 +#else + 26572828, 3405927, 35407164, 12890904, 47843196, 5335865, + 60615096, 2378491, 4439158, 20275085 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 234147501399755, 2229469128637390, 2175289352258889, + 1397401514549353, 1885288963089922 +#else + 44392139, 3489069, 57883598, 33221678, 18875721, 32414337, + 14819433, 20822905, 49391106, 28092994 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1111762412951562, 252849572507389, 1048714233823341, + 146111095601446, 1237505378776770 +#else + 62052362, 16566550, 15953661, 3767752, 56672365, 15627059, + 66287910, 2177224, 8550082, 18440267 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1113790697840279, 1051167139966244, 1045930658550944, + 2011366241542643, 1686166824620755 +#else + 48635543, 16596774, 66727204, 15663610, 22860960, 15585581, + 39264755, 29971692, 43848403, 25125843 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1054097349305049, 1872495070333352, 182121071220717, + 1064378906787311, 100273572924182 +#else + 34628313, 15707274, 58902952, 27902350, 29464557, 2713815, + 44383727, 15860481, 45206294, 1494192 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1306410853171605, 1627717417672447, 50983221088417, + 1109249951172250, 870201789081392 +#else + 47546773, 19467038, 41524991, 24254879, 13127841, 759709, + 21923482, 16529112, 8742704, 12967017 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 104233794644221, 1548919791188248, 2224541913267306, + 2054909377116478, 1043803389015153 +#else + 38643965, 1553204, 32536856, 23080703, 42417258, 33148257, + 58194238, 30620535, 37205105, 15553882 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 216762189468802, 707284285441622, 190678557969733, + 973969342604308, 1403009538434867 +#else + 21877890, 3230008, 9881174, 10539357, 62311749, 2841331, + 11543572, 14513274, 19375923, 20906471 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1279024291038477, 344776835218310, 273722096017199, + 1834200436811442, 634517197663804 +#else + 8832269, 19058947, 13253510, 5137575, 5037871, 4078777, + 24880818, 27331716, 2862652, 9455043 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 343805853118335, 1302216857414201, 566872543223541, + 2051138939539004, 321428858384280 +#else + 29306751, 5123106, 20245049, 19404543, 9592565, 8447059, + 65031740, 30564351, 15511448, 4789663 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 470067171324852, 1618629234173951, 2000092177515639, + 7307679772789, 1117521120249968 +#else + 46429108, 7004546, 8824831, 24119455, 63063159, 29803695, + 61354101, 108892, 23513200, 16652362 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 278151578291475, 1810282338562947, 1771599529530998, + 1383659409671631, 685373414471841 +#else + 33852691, 4144781, 62632835, 26975308, 10770038, 26398890, + 60458447, 20618131, 48789665, 10212859 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 577009397403102, 1791440261786291, 2177643735971638, + 174546149911960, 1412505077782326 +#else + 2756062, 8598110, 7383731, 26694540, 22312758, 32449420, + 21179800, 2600940, 57120566, 21047965 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 893719721537457, 1201282458018197, 1522349501711173, + 58011597740583, 1130406465887139 +#else + 42463153, 13317461, 36659605, 17900503, 21365573, 22684775, + 11344423, 864440, 64609187, 16844368 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 412607348255453, 1280455764199780, 2233277987330768, + 14180080401665, 331584698417165 +#else + 40676061, 6148328, 49924452, 19080277, 18782928, 33278435, + 44547329, 211299, 2719757, 4940997 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 262483770854550, 990511055108216, 526885552771698, + 571664396646158, 354086190278723 +#else + 65784982, 3911312, 60160120, 14759764, 37081714, 7851206, + 21690126, 8518463, 26699843, 5276295 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1820352417585487, 24495617171480, 1547899057533253, + 10041836186225, 480457105094042 +#else + 53958991, 27125364, 9396248, 365013, 24703301, 23065493, + 1321585, 149635, 51656090, 7159368 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2023310314989233, 637905337525881, 2106474638900687, + 557820711084072, 1687858215057826 +#else + 9987761, 30149673, 17507961, 9505530, 9731535, 31388918, + 22356008, 8312176, 22477218, 25151047 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1144168702609745, 604444390410187, 1544541121756138, + 1925315550126027, 626401428894002 +#else + 18155857, 17049442, 19744715, 9006923, 15154154, 23015456, + 24256459, 28689437, 44560690, 9334108 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1922168257351784, 2018674099908659, 1776454117494445, + 956539191509034, 36031129147635 +#else + 2986088, 28642539, 10776627, 30080588, 10620589, 26471229, + 45695018, 14253544, 44521715, 536905 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 544644538748041, 1039872944430374, 876750409130610, + 710657711326551, 1216952687484972 +#else + 4377737, 8115836, 24567078, 15495314, 11625074, 13064599, + 7390551, 10589625, 10838060, 18134008 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 58242421545916, 2035812695641843, 2118491866122923, + 1191684463816273, 46921517454099 +#else + 47766460, 867879, 9277171, 30335973, 52677291, 31567988, + 19295825, 17757482, 6378259, 699185 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 272268252444639, 1374166457774292, 2230115177009552, + 1053149803909880, 1354288411641016 +#else + 7895007, 4057113, 60027092, 20476675, 49222032, 33231305, + 66392824, 15693154, 62063800, 20180469 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1857910905368338, 1754729879288912, 885945464109877, + 1516096106802166, 1602902393369811 +#else + 59371282, 27685029, 52542544, 26147512, 11385653, 13201616, + 31730678, 22591592, 63190227, 23885106 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1193437069800958, 901107149704790, 999672920611411, + 477584824802207, 364239578697845 +#else + 10188286, 17783598, 59772502, 13427542, 22223443, 14896287, + 30743455, 7116568, 45322357, 5427592 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 886299989548838, 1538292895758047, 1590564179491896, + 1944527126709657, 837344427345298 +#else + 696102, 13206899, 27047647, 22922350, 15285304, 23701253, + 10798489, 28975712, 19236242, 12477404 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 754558365378305, 1712186480903618, 1703656826337531, + 750310918489786, 518996040250900 +#else + 55879425, 11243795, 50054594, 25513566, 66320635, 25386464, + 63211194, 11180503, 43939348, 7733643 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1309847803895382, 1462151862813074, 211370866671570, + 1544595152703681, 1027691798954090 +#else + 17800790, 19518253, 40108434, 21787760, 23887826, 3149671, + 23466177, 23016261, 10322026, 15313801 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 803217563745370, 1884799722343599, 1357706345069218, + 2244955901722095, 730869460037413 +#else + 26246234, 11968874, 32263343, 28085704, 6830754, 20231401, + 51314159, 33452449, 42659621, 10890803 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 689299471295966, 1831210565161071, 1375187341585438, + 1106284977546171, 1893781834054269 +#else + 35743198, 10271362, 54448239, 27287163, 16690206, 20491888, + 52126651, 16484930, 25180797, 28219548 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 696351368613042, 1494385251239250, 738037133616932, + 636385507851544, 927483222611406 +#else + 66522290, 10376443, 34522450, 22268075, 19801892, 10997610, + 2276632, 9482883, 316878, 13820577 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1949114198209333, 1104419699537997, 783495707664463, + 1747473107602770, 2002634765788641 +#else + 57226037, 29044064, 64993357, 16457135, 56008783, 11674995, + 30756178, 26039378, 30696929, 29841583 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1607325776830197, 530883941415333, 1451089452727895, + 1581691157083423, 496100432831154 +#else + 32988917, 23951020, 12499365, 7910787, 56491607, 21622917, + 59766047, 23569034, 34759346, 7392472 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1068900648804224, 2006891997072550, 1134049269345549, + 1638760646180091, 2055396084625778 +#else + 58253184, 15927860, 9866406, 29905021, 64711949, 16898650, + 36699387, 24419436, 25112946, 30627788 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2222475519314561, 1870703901472013, 1884051508440561, + 1344072275216753, 1318025677799069 +#else + 64604801, 33117465, 25621773, 27875660, 15085041, 28074555, + 42223985, 20028237, 5537437, 19640113 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 155711679280656, 681100400509288, 389811735211209, + 2135723811340709, 408733211204125 +#else + 55883280, 2320284, 57524584, 10149186, 33664201, 5808647, + 52232613, 31824764, 31234589, 6090599 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 7813206966729, 194444201427550, 2071405409526507, + 1065605076176312, 1645486789731291 +#else + 57475529, 116425, 26083934, 2897444, 60744427, 30866345, 609720, + 15878753, 60138459, 24519663 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 16625790644959, 1647648827778410, 1579910185572704, + 436452271048548, 121070048451050 +#else + 39351007, 247743, 51914090, 24551880, 23288160, 23542496, + 43239268, 6503645, 20650474, 1804084 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1037263028552531, 568385780377829, 297953104144430, + 1558584511931211, 2238221839292471 +#else + 39519059, 15456423, 8972517, 8469608, 15640622, 4439847, + 3121995, 23224719, 27842615, 33352104 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 190565267697443, 672855706028058, 338796554369226, + 337687268493904, 853246848691734 +#else + 51801891, 2839643, 22530074, 10026331, 4602058, 5048462, + 28248656, 5031932, 55733782, 12714368 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1763863028400139, 766498079432444, 1321118624818005, + 69494294452268, 858786744165651 +#else + 20807691, 26283607, 29286140, 11421711, 39232341, 19686201, + 45881388, 1035545, 47375635, 12796919 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1292056768563024, 1456632109855638, 1100631247050184, + 1386133165675321, 1232898350193752 +#else + 12076880, 19253146, 58323862, 21705509, 42096072, 16400683, + 49517369, 20654993, 3480664, 18371617 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 366253102478259, 525676242508811, 1449610995265438, + 1183300845322183, 185960306491545 +#else + 34747315, 5457596, 28548107, 7833186, 7303070, 21600887, + 42745799, 17632556, 33734809, 2771024 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 28315355815982, 460422265558930, 1799675876678724, + 1969256312504498, 1051823843138725 +#else + 45719598, 421931, 26597266, 6860826, 22486084, 26817260, + 49971378, 29344205, 42556581, 15673396 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 156914999361983, 1606148405719949, 1665208410108430, + 317643278692271, 1383783705665320 +#else + 46924223, 2338215, 19788685, 23933476, 63107598, 24813538, + 46837679, 4733253, 3727144, 20619984 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 54684536365732, 2210010038536222, 1194984798155308, + 535239027773705, 1516355079301361 +#else + 6120100, 814863, 55314462, 32931715, 6812204, 17806661, 2019593, + 7975683, 31123697, 22595451 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1484387703771650, 198537510937949, 2186282186359116, + 617687444857508, 647477376402122 +#else + 30069250, 22119100, 30434653, 2958439, 18399564, 32578143, + 12296868, 9204260, 50676426, 9648164 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2147715541830533, 500032538445817, 646380016884826, + 352227855331122, 1488268620408052 +#else + 32705413, 32003455, 30705657, 7451065, 55303258, 9631812, + 3305266, 5248604, 41100532, 22176930 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 159386186465542, 1877626593362941, 618737197060512, + 1026674284330807, 1158121760792685 +#else + 17219846, 2375039, 35537917, 27978816, 47649184, 9219902, + 294711, 15298639, 2662509, 17257359 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1744544377739822, 1964054180355661, 1685781755873170, + 2169740670377448, 1286112621104591 +#else + 65935918, 25995736, 62742093, 29266687, 45762450, 25120105, + 32087528, 32331655, 32247247, 19164571 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 81977249784993, 1667943117713086, 1668983819634866, + 1605016835177615, 1353960708075544 +#else + 14312609, 1221556, 17395390, 24854289, 62163122, 24869796, + 38911119, 23916614, 51081240, 20175586 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1602253788689063, 439542044889886, 2220348297664483, + 657877410752869, 157451572512238 +#else + 65680039, 23875441, 57873182, 6549686, 59725795, 33085767, + 23046501, 9803137, 17597934, 2346211 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1029287186166717, 65860128430192, 525298368814832, + 1491902500801986, 1461064796385400 +#else + 18510781, 15337574, 26171504, 981392, 44867312, 7827555, + 43617730, 22231079, 3059832, 21771562 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 408216988729246, 2121095722306989, 913562102267595, + 1879708920318308, 241061448436731 +#else + 10141598, 6082907, 17829293, 31606789, 9830091, 13613136, + 41552228, 28009845, 33606651, 3592095 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1185483484383269, 1356339572588553, 584932367316448, + 102132779946470, 1792922621116791 +#else + 33114149, 17665080, 40583177, 20211034, 33076704, 8716171, + 1151462, 1521897, 66126199, 26716628 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1966196870701923, 2230044620318636, 1425982460745905, + 261167817826569, 46517743394330 +#else + 34169699, 29298616, 23947180, 33230254, 34035889, 21248794, + 50471177, 3891703, 26353178, 693168 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 107077591595359, 884959942172345, 27306869797400, + 2224911448949390, 964352058245223 +#else + 30374239, 1595580, 50224825, 13186930, 4600344, 406904, 9585294, + 33153764, 31375463, 14369965 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1730194207717538, 431790042319772, 1831515233279467, + 1372080552768581, 1074513929381760 +#else + 52738210, 25781902, 1510300, 6434173, 48324075, 27291703, + 32732229, 20445593, 17901440, 16011505 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1450880638731607, 1019861580989005, 1229729455116861, + 1174945729836143, 826083146840706 +#else + 18171223, 21619806, 54608461, 15197121, 56070717, 18324396, + 47936623, 17508055, 8764034, 12309598 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1899935429242705, 1602068751520477, 940583196550370, + 82431069053859, 1540863155745696 +#else + 5975889, 28311244, 47649501, 23872684, 55567586, 14015781, + 43443107, 1228318, 17544096, 22960650 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2136688454840028, 2099509000964294, 1690800495246475, + 1217643678575476, 828720645084218 +#else + 5811932, 31839139, 3442886, 31285122, 48741515, 25194890, + 49064820, 18144304, 61543482, 12348899 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 765548025667841, 462473984016099, 998061409979798, + 546353034089527, 2212508972466858 +#else + 35709185, 11407554, 25755363, 6891399, 63851926, 14872273, + 42259511, 8141294, 56476330, 32968952 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 46575283771160, 892570971573071, 1281983193144090, + 1491520128287375, 75847005908304 +#else + 54433560, 694025, 62032719, 13300343, 14015258, 19103038, + 57410191, 22225381, 30944592, 1130208 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1801436127943107, 1734436817907890, 1268728090345068, + 167003097070711, 2233597765834956 +#else + 8247747, 26843490, 40546482, 25845122, 52706924, 18905521, + 4652151, 2488540, 23550156, 33283200 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1997562060465113, 1048700225534011, 7615603985628, + 1855310849546841, 2242557647635213 +#else + 17294297, 29765994, 7026747, 15626851, 22990044, 113481, + 2267737, 27646286, 66700045, 33416712 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1161017320376250, 492624580169043, 2169815802355237, + 976496781732542, 1770879511019629 +#else + 16091066, 17300506, 18599251, 7340678, 2137637, 32332775, + 63744702, 14550935, 3260525, 26388161 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1357044908364776, 729130645262438, 1762469072918979, + 1365633616878458, 181282906404941 +#else + 62198760, 20221544, 18550886, 10864893, 50649539, 26262835, + 44079994, 20349526, 54360141, 2701325 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1080413443139865, 1155205815510486, 1848782073549786, + 622566975152580, 124965574467971 +#else + 58534169, 16099414, 4629974, 17213908, 46322650, 27548999, + 57090500, 9276970, 11329923, 1862132 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1184526762066993, 247622751762817, 692129017206356, + 820018689412496, 2188697339828085 +#else + 14763057, 17650824, 36190593, 3689866, 3511892, 10313526, + 45157776, 12219230, 58070901, 32614131 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2020536369003019, 202261491735136, 1053169669150884, + 2056531979272544, 778165514694311 +#else + 8894987, 30108338, 6150752, 3013931, 301220, 15693451, 35127648, + 30644714, 51670695, 11595569 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 237404399610207, 1308324858405118, 1229680749538400, + 720131409105291, 1958958863624906 +#else + 15214943, 3537601, 40870142, 19495559, 4418656, 18323671, + 13947275, 10730794, 53619402, 29190761 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 515583508038846, 17656978857189, 1717918437373989, + 1568052070792483, 46975803123923 +#else + 64570558, 7682792, 32759013, 263109, 37124133, 25598979, + 44776739, 23365796, 977107, 699994 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 281527309158085, 36970532401524, 866906920877543, + 2222282602952734, 1289598729589882 +#else + 54642373, 4195083, 57897332, 550903, 51543527, 12917919, + 19118110, 33114591, 36574330, 19216518 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1278207464902042, 494742455008756, 1262082121427081, + 1577236621659884, 1888786707293291 +#else + 31788442, 19046775, 4799988, 7372237, 8808585, 18806489, + 9408236, 23502657, 12493931, 28145115 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 353042527954210, 1830056151907359, 1111731275799225, + 174960955838824, 404312815582675 +#else + 41428258, 5260743, 47873055, 27269961, 63412921, 16566086, + 27218280, 2607121, 29375955, 6024730 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2064251142068628, 1666421603389706, 1419271365315441, + 468767774902855, 191535130366583 +#else + 842132, 30759739, 62345482, 24831616, 26332017, 21148791, + 11831879, 6985184, 57168503, 2854095 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1716987058588002, 1859366439773457, 1767194234188234, + 64476199777924, 1117233614485261 +#else + 62261602, 25585100, 2516241, 27706719, 9695690, 26333246, + 16512644, 960770, 12121869, 16648078 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 984292135520292, 135138246951259, 2220652137473167, + 1722843421165029, 190482558012909 +#else + 51890212, 14667095, 53772635, 2013716, 30598287, 33090295, + 35603941, 25672367, 20237805, 2838411 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 298845952651262, 1166086588952562, 1179896526238434, + 1347812759398693, 1412945390096208 +#else + 47820798, 4453151, 15298546, 17376044, 22115042, 17581828, + 12544293, 20083975, 1068880, 21054527 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1143239552672925, 906436640714209, 2177000572812152, + 2075299936108548, 325186347798433 +#else + 57549981, 17035596, 33238497, 13506958, 30505848, 32439836, + 58621956, 30924378, 12521377, 4845654 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 721024854374772, 684487861263316, 1373438744094159, + 2193186935276995, 1387043709851261 +#else + 38910324, 10744107, 64150484, 10199663, 7759311, 20465832, + 3409347, 32681032, 60626557, 20668561 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 418098668140962, 715065997721283, 1471916138376055, + 2168570337288357, 937812682637044 +#else + 43547042, 6230155, 46726851, 10655313, 43068279, 21933259, + 10477733, 32314216, 63995636, 13974497 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1043584187226485, 2143395746619356, 2209558562919611, + 482427979307092, 847556718384018 +#else + 12966261, 15550616, 35069916, 31939085, 21025979, 32924988, + 5642324, 7188737, 18895762, 12629579 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1248731221520759, 1465200936117687, 540803492710140, + 52978634680892, 261434490176109 +#else + 14741879, 18607545, 22177207, 21833195, 1279740, 8058600, + 11758140, 789443, 32195181, 3895677 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1057329623869501, 620334067429122, 461700859268034, + 2012481616501857, 297268569108938 +#else + 10758205, 15755439, 62598914, 9243697, 62229442, 6879878, + 64904289, 29988312, 58126794, 4429646 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1055352180870759, 1553151421852298, 1510903185371259, + 1470458349428097, 1226259419062731 +#else + 64654951, 15725972, 46672522, 23143759, 61304955, 22514211, + 59972993, 21911536, 18047435, 18272689 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1492988790301668, 790326625573331, 1190107028409745, + 1389394752159193, 1620408196604194 +#else + 41935844, 22247266, 29759955, 11776784, 44846481, 17733976, + 10993113, 20703595, 49488162, 24145963 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 47000654413729, 1004754424173864, 1868044813557703, + 173236934059409, 588771199737015 +#else + 21987233, 700364, 42603816, 14972007, 59334599, 27836036, + 32155025, 2581431, 37149879, 8773374 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 30498470091663, 1082245510489825, 576771653181956, + 806509986132686, 1317634017056939 +#else + 41540495, 454462, 53896929, 16126714, 25240068, 8594567, + 20656846, 12017935, 59234475, 19634276 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 420308055751555, 1493354863316002, 165206721528088, + 1884845694919786, 2065456951573059 +#else + 6028163, 6263078, 36097058, 22252721, 66289944, 2461771, + 35267690, 28086389, 65387075, 30777706 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1115636332012334, 1854340990964155, 83792697369514, + 1972177451994021, 457455116057587 +#else + 54829870, 16624276, 987579, 27631834, 32908202, 1248608, + 7719845, 29387734, 28408819, 6816612 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1698968457310898, 1435137169051090, 1083661677032510, + 938363267483709, 340103887207182 +#else + 56750770, 25316602, 19549650, 21385210, 22082622, 16147817, + 20613181, 13982702, 56769294, 5067942 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1995325341336574, 911500251774648, 164010755403692, + 855378419194762, 1573601397528842 +#else + 36602878, 29732664, 12074680, 13582412, 47230892, 2443950, + 47389578, 12746131, 5331210, 23448488 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 241719380661528, 310028521317150, 1215881323380194, + 1408214976493624, 2141142156467363 +#else + 30528792, 3601899, 65151774, 4619784, 39747042, 18118043, + 24180792, 20984038, 27679907, 31905504 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1315157046163473, 727368447885818, 1363466668108618, + 1668921439990361, 1398483384337907 +#else + 9402385, 19597367, 32834042, 10838634, 40528714, 20317236, + 26653273, 24868867, 22611443, 20839026 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 75029678299646, 1015388206460473, 1849729037055212, + 1939814616452984, 444404230394954 +#else + 22190590, 1118029, 22736441, 15130463, 36648172, 27563110, + 19189624, 28905490, 4854858, 6622139 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2053597130993710, 2024431685856332, 2233550957004860, + 2012407275509545, 872546993104440 +#else + 58798126, 30600981, 58846284, 30166382, 56707132, 33282502, + 13424425, 29987205, 26404408, 13001963 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1217269667678610, 599909351968693, 1390077048548598, + 1471879360694802, 739586172317596 +#else + 35867026, 18138731, 64114613, 8939345, 11562230, 20713762, + 41044498, 21932711, 51703708, 11020692 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1718318639380794, 1560510726633958, 904462881159922, + 1418028351780052, 94404349451937 +#else + 1866042, 25604943, 59210214, 23253421, 12483314, 13477547, + 3175636, 21130269, 28761761, 1406734 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2132502667405250, 214379346175414, 1502748313768060, + 1960071701057800, 1353971822643138 +#else + 66660290, 31776765, 13018550, 3194501, 57528444, 22392694, + 24760584, 29207344, 25577410, 20175752 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 319394212043702, 2127459436033571, 717646691535162, + 663366796076914, 318459064945314 +#else + 42818486, 4759344, 66418211, 31701615, 2066746, 10693769, + 37513074, 9884935, 57739938, 4745409 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 405989424923593, 1960452633787083, 667349034401665, + 1492674260767112, 1451061489880787 +#else + 57967561, 6049713, 47577803, 29213020, 35848065, 9944275, + 51646856, 22242579, 10931923, 21622501 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 947085906234007, 323284730494107, 1485778563977200, + 728576821512394, 901584347702286 +#else + 50547351, 14112679, 59096219, 4817317, 59068400, 22139825, + 44255434, 10856640, 46638094, 13434653 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1575783124125742, 2126210792434375, 1569430791264065, + 1402582372904727, 1891780248341114 +#else + 22759470, 23480998, 50342599, 31683009, 13637441, 23386341, + 1765143, 20900106, 28445306, 28189722 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 838432205560695, 1997703511451664, 1018791879907867, + 1662001808174331, 78328132957753 +#else + 29875063, 12493613, 2795536, 29768102, 1710619, 15181182, + 56913147, 24765756, 9074233, 1167180 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 739152638255629, 2074935399403557, 505483666745895, + 1611883356514088, 628654635394878 +#else + 40903181, 11014232, 57266213, 30918946, 40200743, 7532293, + 48391976, 24018933, 3843902, 9367684 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1822054032121349, 643057948186973, 7306757352712, + 577249257962099, 284735863382083 +#else + 56139269, 27150720, 9591133, 9582310, 11349256, 108879, + 16235123, 8601684, 66969667, 4242894 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1366558556363930, 1448606567552086, 1478881020944768, + 165803179355898, 1115718458123498 +#else + 22092954, 20363309, 65066070, 21585919, 32186752, 22037044, + 60534522, 2470659, 39691498, 16625500 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 204146226972102, 1630511199034723, 2215235214174763, + 174665910283542, 956127674017216 +#else + 56051142, 3042015, 13770083, 24296510, 584235, 33009577, + 59338006, 2602724, 39757248, 14247412 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1562934578796716, 1070893489712745, 11324610642270, + 958989751581897, 2172552325473805 +#else + 6314156, 23289540, 34336361, 15957556, 56951134, 168749, + 58490057, 14290060, 27108877, 32373552 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1770564423056027, 735523631664565, 1326060113795289, + 1509650369341127, 65892421582684 +#else + 58522267, 26383465, 13241781, 10960156, 34117849, 19759835, + 33547975, 22495543, 39960412, 981873 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 623682558650637, 1337866509471512, 990313350206649, + 1314236615762469, 1164772974270275 +#else + 22833421, 9293594, 34459416, 19935764, 57971897, 14756818, + 44180005, 19583651, 56629059, 17356469 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 223256821462517, 723690150104139, 1000261663630601, + 933280913953265, 254872671543046 +#else + 59340277, 3326785, 38997067, 10783823, 19178761, 14905060, + 22680049, 13906969, 51175174, 3797898 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1969087237026041, 624795725447124, 1335555107635969, + 2069986355593023, 1712100149341902 +#else + 21721337, 29341686, 54902740, 9310181, 63226625, 19901321, + 23740223, 30845200, 20491982, 25512280 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1236103475266979, 1837885883267218, 1026072585230455, + 1025865513954973, 1801964901432134 +#else + 9209251, 18419377, 53852306, 27386633, 66377847, 15289672, + 25947805, 15286587, 30997318, 26851369 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1115241013365517, 1712251818829143, 2148864332502771, + 2096001471438138, 2235017246626125 +#else + 7392013, 16618386, 23946583, 25514540, 53843699, 32020573, + 52911418, 31232855, 17649997, 33304352 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1299268198601632, 2047148477845621, 2165648650132450, + 1612539282026145, 514197911628890 +#else + 57807776, 19360604, 30609525, 30504889, 41933794, 32270679, + 51867297, 24028707, 64875610, 7662145 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 118352772338543, 1067608711804704, 1434796676193498, + 1683240170548391, 230866769907437 +#else + 49550191, 1763593, 33994528, 15908609, 37067994, 21380136, + 7335079, 25082233, 63934189, 3440182 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1850689576796636, 1601590730430274, 1139674615958142, + 1954384401440257, 76039205311 +#else + 47219164, 27577423, 42997570, 23865561, 10799742, 16982475, + 40449, 29122597, 4862399, 1133 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1723387471374172, 997301467038410, 533927635123657, + 20928644693965, 1756575222802513 +#else + 34252636, 25680474, 61686474, 14860949, 50789833, 7956141, + 7258061, 311861, 36513873, 26175010 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2146711623855116, 503278928021499, 625853062251406, + 1109121378393107, 1033853809911861 +#else + 63335436, 31988495, 28985339, 7499440, 24445838, 9325937, + 29727763, 16527196, 18278453, 15405622 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 571005965509422, 2005213373292546, 1016697270349626, + 56607856974274, 914438579435146 +#else + 62726958, 8508651, 47210498, 29880007, 61124410, 15149969, + 53795266, 843522, 45233802, 13626196 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1346698876211176, 2076651707527589, 1084761571110205, + 265334478828406, 1068954492309671 +#else + 2281448, 20067377, 56193445, 30944521, 1879357, 16164207, + 56324982, 3953791, 13340839, 15928663 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1769967932677654, 1695893319756416, 1151863389675920, + 1781042784397689, 400287774418285 +#else + 31727126, 26374577, 48671360, 25270779, 2875792, 17164102, + 41838969, 26539605, 43656557, 5964752 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1851867764003121, 403841933237558, 820549523771987, + 761292590207581, 1743735048551143 +#else + 4100401, 27594980, 49929526, 6017713, 48403027, 12227140, + 40424029, 11344143, 2538215, 25983677 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 410915148140008, 2107072311871739, 1004367461876503, + 99684895396761, 1180818713503224 +#else + 57675240, 6123112, 11159803, 31397824, 30016279, 14966241, + 46633881, 1485420, 66479608, 17595569 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 285945406881439, 648174397347453, 1098403762631981, + 1366547441102991, 1505876883139217 +#else + 40304287, 4260918, 11851389, 9658551, 35091757, 16367491, + 46903439, 20363143, 11659921, 22439314 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 672095903120153, 1675918957959872, 636236529315028, + 1569297300327696, 2164144194785875 +#else + 26180377, 10015009, 36264640, 24973138, 5418196, 9480663, + 2231568, 23384352, 33100371, 32248261 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1902708175321798, 1035343530915438, 1178560808893263, + 301095684058146, 1280977479761118 +#else + 15121094, 28352561, 56718958, 15427820, 39598927, 17561924, + 21670946, 4486675, 61177054, 19088051 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1615357281742403, 404257611616381, 2160201349780978, + 1160947379188955, 1578038619549541 +#else + 16166467, 24070699, 56004733, 6023907, 35182066, 32189508, + 2340059, 17299464, 56373093, 23514607 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2013087639791217, 822734930507457, 1785668418619014, + 1668650702946164, 389450875221715 +#else + 28042865, 29997343, 54982337, 12259705, 63391366, 26608532, + 6766452, 24864833, 18036435, 5803270 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 453918449698368, 106406819929001, 2072540975937135, + 308588860670238, 1304394580755385 +#else + 66291264, 6763911, 11803561, 1585585, 10958447, 30883267, + 23855390, 4598332, 60949433, 19436993 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1295082798350326, 2091844511495996, 1851348972587817, + 3375039684596, 789440738712837 +#else + 36077558, 19298237, 17332028, 31170912, 31312681, 27587249, + 696308, 50292, 47013125, 11763583 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2083069137186154, 848523102004566, 993982213589257, + 1405313299916317, 1532824818698468 +#else + 66514282, 31040148, 34874710, 12643979, 12650761, 14811489, + 665117, 20940800, 47335652, 22840869 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1495961298852430, 1397203457344779, 1774950217066942, + 139302743555696, 66603584342787 +#else + 30464590, 22291560, 62981387, 20819953, 19835326, 26448819, + 42712688, 2075772, 50088707, 992470 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1782411379088302, 1096724939964781, 27593390721418, + 542241850291353, 1540337798439873 +#else + 18357166, 26559999, 7766381, 16342475, 37783946, 411173, + 14578841, 8080033, 55534529, 22952821 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 693543956581437, 171507720360750, 1557908942697227, + 1074697073443438, 1104093109037196 +#else + 19598397, 10334610, 12555054, 2555664, 18821899, 23214652, + 21873262, 16014234, 26224780, 16452269 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 345288228393419, 1099643569747172, 134881908403743, + 1740551994106740, 248212179299770 +#else + 36884939, 5145195, 5944548, 16385966, 3976735, 2009897, + 55731060, 25936245, 46575034, 3698649 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 231429562203065, 1526290236421172, 2021375064026423, + 1520954495658041, 806337791525116 +#else + 14187449, 3448569, 56472628, 22743496, 44444983, 30120835, + 7268409, 22663988, 27394300, 12015369 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1079623667189886, 872403650198613, 766894200588288, + 2163700860774109, 2023464507911816 +#else + 19695742, 16087646, 28032085, 12999827, 6817792, 11427614, + 20244189, 32241655, 53849736, 30151970 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 854645372543796, 1936406001954827, 151460662541253, + 825325739271555, 1554306377287556 +#else + 30860084, 12735208, 65220619, 28854697, 50133957, 2256939, + 58942851, 12298311, 58558340, 23160969 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1497138821904622, 1044820250515590, 1742593886423484, + 1237204112746837, 849047450816987 +#else + 61389038, 22309106, 65198214, 15569034, 26642876, 25966672, + 61319509, 18435777, 62132699, 12651792 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 667962773375330, 1897271816877105, 1399712621683474, + 1143302161683099, 2081798441209593 +#else + 64260450, 9953420, 11531313, 28271553, 26895122, 20857343, + 53990043, 17036529, 9768697, 31021214 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 127147851567005, 1936114012888110, 1704424366552046, + 856674880716312, 716603621335359 +#else + 42389405, 1894650, 66821166, 28850346, 15348718, 25397902, + 32767512, 12765450, 4940095, 10678226 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1072409664800960, 2146937497077528, 1508780108920651, + 935767602384853, 1112800433544068 +#else + 18860224, 15980149, 48121624, 31991861, 40875851, 22482575, + 59264981, 13944023, 42736516, 16582018 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 333549023751292, 280219272863308, 2104176666454852, + 1036466864875785, 536135186520207 +#else + 51604604, 4970267, 37215820, 4175592, 46115652, 31354675, + 55404809, 15444559, 56105103, 7989036 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 373666279883137, 146457241530109, 304116267127857, + 416088749147715, 1258577131183391 +#else + 31490433, 5568061, 64696061, 2182382, 34772017, 4531685, + 35030595, 6200205, 47422751, 18754260 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1186115062588401, 2251609796968486, 1098944457878953, + 1153112761201374, 1791625503417267 +#else + 49800177, 17674491, 35586086, 33551600, 34221481, 16375548, + 8680158, 17182719, 28550067, 26697300 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1870078460219737, 2129630962183380, 852283639691142, + 292865602592851, 401904317342226 +#else + 38981977, 27866340, 16837844, 31733974, 60258182, 12700015, + 37068883, 4364037, 1155602, 5988841 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1361070124828035, 815664541425524, 1026798897364671, + 1951790935390647, 555874891834790 +#else + 21890435, 20281525, 54484852, 12154348, 59276991, 15300495, + 23148983, 29083951, 24618406, 8283181 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1546301003424277, 459094500062839, 1097668518375311, + 1780297770129643, 720763293687608 +#else + 33972757, 23041680, 9975415, 6841041, 35549071, 16356535, + 3070187, 26528504, 1466168, 10740210 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1212405311403990, 1536693382542438, 61028431067459, + 1863929423417129, 1223219538638038 +#else + 65599446, 18066246, 53605478, 22898515, 32799043, 909394, + 53169961, 27774712, 34944214, 18227391 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1294303766540260, 1183557465955093, 882271357233093, + 63854569425375, 2213283684565087 +#else + 3960804, 19286629, 39082773, 17636380, 47704005, 13146867, + 15567327, 951507, 63848543, 32980496 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 339050984211414, 601386726509773, 413735232134068, + 966191255137228, 1839475899458159 +#else + 24740822, 5052253, 37014733, 8961360, 25877428, 6165135, + 42740684, 14397371, 59728495, 27410326 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 235605972169408, 2174055643032978, 1538335001838863, + 1281866796917192, 1815940222628465 +#else + 38220480, 3510802, 39005586, 32395953, 55870735, 22922977, + 51667400, 19101303, 65483377, 27059617 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1632352921721536, 1833328609514701, 2092779091951987, + 1923956201873226, 2210068022482919 +#else + 793280, 24323954, 8836301, 27318725, 39747955, 31184838, + 33152842, 28669181, 57202663, 32932579 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 35271216625062, 1712350667021807, 983664255668860, + 98571260373038, 1232645608559836 +#else + 5666214, 525582, 20782575, 25516013, 42570364, 14657739, + 16099374, 1468826, 60937436, 18367850 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1998172393429622, 1798947921427073, 784387737563581, + 1589352214827263, 1589861734168180 +#else + 62249590, 29775088, 64191105, 26806412, 7778749, 11688288, + 36704511, 23683193, 65549940, 23690785 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1733739258725305, 31715717059538, 201969945218860, + 992093044556990, 1194308773174556 +#else + 10896313, 25834728, 824274, 472601, 47648556, 3009586, 25248958, + 14783338, 36527388, 17796587 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 846415389605137, 746163495539180, 829658752826080, + 592067705956946, 957242537821393 +#else + 10566929, 12612572, 35164652, 11118702, 54475488, 12362878, + 21752402, 8822496, 24003793, 14264025 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1758148849754419, 619249044817679, 168089007997045, + 1371497636330523, 1867101418880350 +#else + 27713843, 26198459, 56100623, 9227529, 27050101, 2504721, + 23886875, 20436907, 13958494, 27821979 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 326633984209635, 261759506071016, 1700682323676193, + 1577907266349064, 1217647663383016 +#else + 43627235, 4867225, 39861736, 3900520, 29838369, 25342141, + 35219464, 23512650, 7340520, 18144364 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1714182387328607, 1477856482074168, 574895689942184, + 2159118410227270, 1555532449716575 +#else + 4646495, 25543308, 44342840, 22021777, 23184552, 8566613, + 31366726, 32173371, 52042079, 23179239 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 853828206885131, 998498946036955, 1835887550391235, + 207627336608048, 258363815956050 +#else + 49838347, 12723031, 50115803, 14878793, 21619651, 27356856, + 27584816, 3093888, 58265170, 3849920 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 141141474651677, 1236728744905256, 643101419899887, + 1646615130509173, 1208239602291765 +#else + 58043933, 2103171, 25561640, 18428694, 61869039, 9582957, + 32477045, 24536477, 5002293, 18004173 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1501663228068911, 1354879465566912, 1444432675498247, + 897812463852601, 855062598754348 +#else + 55051311, 22376525, 21115584, 20189277, 8808711, 21523724, + 16489529, 13378448, 41263148, 12741425 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 714380763546606, 1032824444965790, 1774073483745338, + 1063840874947367, 1738680636537158 +#else + 61162478, 10645102, 36197278, 15390283, 63821882, 26435754, + 24306471, 15852464, 28834118, 25908360 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1640635546696252, 633168953192112, 2212651044092396, + 30590958583852, 368515260889378 +#else + 49773116, 24447374, 42577584, 9434952, 58636780, 32971069, + 54018092, 455840, 20461858, 5491305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1171650314802029, 1567085444565577, 1453660792008405, + 757914533009261, 1619511342778196 +#else + 13669229, 17458950, 54626889, 23351392, 52539093, 21661233, + 42112877, 11293806, 38520660, 24132599 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 420958967093237, 971103481109486, 2169549185607107, + 1301191633558497, 1661514101014240 +#else + 28497909, 6272777, 34085870, 14470569, 8906179, 32328802, + 18504673, 19389266, 29867744, 24758489 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 907123651818302, 1332556122804146, 1824055253424487, + 1367614217442959, 1982558335973172 +#else + 50901822, 13517195, 39309234, 19856633, 24009063, 27180541, + 60741263, 20379039, 22853428, 29542421 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1121533090144639, 1021251337022187, 110469995947421, + 1511059774758394, 2110035908131662 +#else + 24191359, 16712145, 53177067, 15217830, 14542237, 1646131, + 18603514, 22516545, 12876622, 31441985 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 303213233384524, 2061932261128138, 352862124777736, + 40828818670255, 249879468482660 +#else + 17902668, 4518229, 66697162, 30725184, 26878216, 5258055, + 54248111, 608396, 16031844, 3723494 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 856559257852200, 508517664949010, 1378193767894916, + 1723459126947129, 1962275756614521 +#else + 38476072, 12763727, 46662418, 7577503, 33001348, 20536687, + 17558841, 25681542, 23896953, 29240187 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1445691340537320, 40614383122127, 402104303144865, + 485134269878232, 1659439323587426 +#else + 47103464, 21542479, 31520463, 605201, 2543521, 5991821, + 64163800, 7229063, 57189218, 24727572 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 20057458979482, 1183363722525800, 2140003847237215, + 2053873950687614, 2112017736174909 +#else + 28816026, 298879, 38943848, 17633493, 19000927, 31888542, + 54428030, 30605106, 49057085, 31471516 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2228654250927986, 1483591363415267, 1368661293910956, + 1076511285177291, 526650682059608 +#else + 16000882, 33209536, 3493091, 22107234, 37604268, 20394642, + 12577739, 16041268, 47393624, 7847706 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 709481497028540, 531682216165724, 316963769431931, + 1814315888453765, 258560242424104 +#else + 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, + 34252933, 27035413, 57088296, 3852847 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1053447823660455, 1955135194248683, 1010900954918985, + 1182614026976701, 1240051576966610 +#else + 55678375, 15697595, 45987307, 29133784, 5386313, 15063598, + 16514493, 17622322, 29330898, 18478208 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1957943897155497, 1788667368028035, 137692910029106, + 1039519607062, 826404763313028 +#else + 41609129, 29175637, 51885955, 26653220, 16615730, 2051784, + 3303702, 15490, 39560068, 12314390 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1848942433095597, 1582009882530495, 1849292741020143, + 1068498323302788, 2001402229799484 +#else + 15683501, 27551389, 18109119, 23573784, 15337967, 27556609, + 50391428, 15921865, 16103996, 29823217 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1528282417624269, 2142492439828191, 2179662545816034, + 362568973150328, 1591374675250271 +#else + 43939021, 22773182, 13588191, 31925625, 63310306, 32479502, + 47835256, 5402698, 37293151, 23713330 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 160026679434388, 232341189218716, 2149181472355545, + 598041771119831, 183859001910173 +#else + 23190676, 2384583, 34394524, 3462153, 37205209, 32025299, + 55842007, 8911516, 41903005, 2739712 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2013278155187349, 662660471354454, 793981225706267, + 411706605985744, 804490933124791 +#else + 21374101, 30000182, 33584214, 9874410, 15377179, 11831242, + 33578960, 6134906, 4931255, 11987849 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2051892037280204, 488391251096321, 2230187337030708, + 930221970662692, 679002758255210 +#else + 67101132, 30575573, 50885377, 7277596, 105524, 33232381, + 35628324, 13861387, 37032554, 10117929 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1530723630438670, 875873929577927, 341560134269988, + 449903119530753, 1055551308214179 +#else + 37607694, 22809559, 40945095, 13051538, 41483300, 5089642, + 60783361, 6704078, 12890019, 15728940 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1461835919309432, 1955256480136428, 180866187813063, + 1551979252664528, 557743861963950 +#else + 45136504, 21783052, 66157804, 29135591, 14704839, 2695116, + 903376, 23126293, 12885166, 8311031 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 359179641731115, 1324915145732949, 902828372691474, + 294254275669987, 1887036027752957 +#else + 49592363, 5352193, 10384213, 19742774, 7506450, 13453191, + 26423267, 4384730, 1888765, 28119028 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2043271609454323, 2038225437857464, 1317528426475850, + 1398989128982787, 2027639881006861 +#else + 41291507, 30447119, 53614264, 30371925, 30896458, 19632703, + 34857219, 20846562, 47644429, 30214188 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2072902725256516, 312132452743412, 309930885642209, + 996244312618453, 1590501300352303 +#else + 43500868, 30888657, 66582772, 4651135, 5765089, 4618330, + 6092245, 14845197, 17151279, 23700316 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1397254305160710, 695734355138021, 2233992044438756, + 1776180593969996, 1085588199351115 +#else + 42278406, 20820711, 51942885, 10367249, 37577956, 33289075, + 22825804, 26467153, 50242379, 16176524 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 440567051331029, 254894786356681, 493869224930222, + 1556322069683366, 1567456540319218 +#else + 43525589, 6564960, 20063689, 3798228, 62368686, 7359224, + 2006182, 23191006, 38362610, 23356922 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1950722461391320, 1907845598854797, 1822757481635527, + 2121567704750244, 73811931471221 +#else + 56482264, 29068029, 53788301, 28429114, 3432135, 27161203, + 23632036, 31613822, 32808309, 1099883 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 387139307395758, 2058036430315676, 1220915649965325, + 1794832055328951, 1230009312169328 +#else + 15030958, 5768825, 39657628, 30667132, 60681485, 18193060, + 51830967, 26745081, 2051440, 18328567 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1765973779329517, 659344059446977, 19821901606666, + 1301928341311214, 1116266004075885 +#else + 63746541, 26315059, 7517889, 9824992, 23555850, 295369, 5148398, + 19400244, 44422509, 16633659 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1127572801181483, 1224743760571696, 1276219889847274, + 1529738721702581, 1589819666871853 +#else + 4577067, 16802144, 13249840, 18250104, 19958762, 19017158, + 18559669, 22794883, 8402477, 23690159 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2181229378964934, 2190885205260020, 1511536077659137, + 1246504208580490, 668883326494241 +#else + 38702534, 32502850, 40318708, 32646733, 49896449, 22523642, + 9453450, 18574360, 17983009, 9967138 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 437866655573314, 669026411194768, 81896997980338, + 523874406393178, 245052060935236 +#else + 41346370, 6524721, 26585488, 9969270, 24709298, 1220360, + 65430874, 7806336, 17507396, 3651560 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1975438052228868, 1071801519999806, 594652299224319, + 1877697652668809, 1489635366987285 +#else + 56688388, 29436320, 14584638, 15971087, 51340543, 8861009, + 26556809, 27979875, 48555541, 22197296 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 958592545673770, 233048016518599, 851568750216589, + 567703851596087, 1740300006094761 +#else + 2839082, 14284142, 4029895, 3472686, 14402957, 12689363, + 40466743, 8459446, 61503401, 25932490 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2014540178270324, 192672779514432, 213877182641530, + 2194819933853411, 1716422829364835 +#else + 62269556, 30018987, 9744960, 2871048, 25113978, 3187018, + 41998051, 32705365, 17258083, 25576693 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1540769606609725, 2148289943846077, 1597804156127445, + 1230603716683868, 815423458809453 +#else + 18164541, 22959256, 49953981, 32012014, 19237077, 23809137, + 23357532, 18337424, 26908269, 12150756 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1738560251245018, 1779576754536888, 1783765347671392, + 1880170990446751, 1088225159617541 +#else + 36843994, 25906566, 5112248, 26517760, 65609056, 26580174, + 43167, 28016731, 34806789, 16215818 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 659303913929492, 1956447718227573, 1830568515922666, + 841069049744408, 1669607124206368 +#else + 60209940, 9824393, 54804085, 29153342, 35711722, 27277596, + 32574488, 12532905, 59605792, 24879084 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1143465490433355, 1532194726196059, 1093276745494697, + 481041706116088, 2121405433561163 +#else + 39765323, 17038963, 39957339, 22831480, 946345, 16291093, + 254968, 7168080, 21676107, 31611404 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1686424298744462, 1451806974487153, 266296068846582, + 1834686947542675, 1720762336132256 +#else + 21260942, 25129680, 50276977, 21633609, 43430902, 3968120, + 63456915, 27338965, 63552672, 25641356 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 889217026388959, 1043290623284660, 856125087551909, + 1669272323124636, 1603340330827879 +#else + 16544735, 13250366, 50304436, 15546241, 62525861, 12757257, + 64646556, 24874095, 48201831, 23891632 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1206396181488998, 333158148435054, 1402633492821422, + 1120091191722026, 1945474114550509 +#else + 64693606, 17976703, 18312302, 4964443, 51836334, 20900867, + 26820650, 16690659, 25459437, 28989823 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 766720088232571, 1512222781191002, 1189719893490790, + 2091302129467914, 2141418006894941 +#else + 41964155, 11425019, 28423002, 22533875, 60963942, 17728207, + 9142794, 31162830, 60676445, 31909614 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 419663647306612, 1998875112167987, 1426599870253707, + 1154928355379510, 486538532138187 +#else + 44004212, 6253475, 16964147, 29785560, 41994891, 21257994, + 39651638, 17209773, 6335691, 7249989 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 938160078005954, 1421776319053174, 1941643234741774, + 180002183320818, 1414380336750546 +#else + 36775618, 13979674, 7503222, 21186118, 55152142, 28932738, + 36836594, 2682241, 25993170, 21075909 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 398001940109652, 1577721237663248, 1012748649830402, + 1540516006905144, 1011684812884559 +#else + 4364628, 5930691, 32304656, 23509878, 59054082, 15091130, + 22857016, 22955477, 31820367, 15075278 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1653276489969630, 6081825167624, 1921777941170836, + 1604139841794531, 861211053640641 +#else + 31879134, 24635739, 17258760, 90626, 59067028, 28636722, + 24162787, 23903546, 49138625, 12833044 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 996661541407379, 1455877387952927, 744312806857277, + 139213896196746, 1000282908547789 +#else + 19073683, 14851414, 42705695, 21694263, 7625277, 11091125, + 47489674, 2074448, 57694925, 14905376 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1450817495603008, 1476865707053229, 1030490562252053, + 620966950353376, 1744760161539058 +#else + 24483648, 21618865, 64589997, 22007013, 65555733, 15355505, + 41826784, 9253128, 27628530, 25998952 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 559728410002599, 37056661641185, 2038622963352006, + 1637244893271723, 1026565352238948 +#else + 17597607, 8340603, 19355617, 552187, 26198470, 30377849, + 4593323, 24396850, 52997988, 15297015 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 962165956135846, 1116599660248791, 182090178006815, + 1455605467021751, 196053588803284 +#else + 510886, 14337390, 35323607, 16638631, 6328095, 2713355, + 46891447, 21690211, 8683220, 2921426 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 796863823080135, 1897365583584155, 420466939481601, + 2165972651724672, 932177357788289 +#else + 18606791, 11874196, 27155355, 28272950, 43077121, 6265445, + 41930624, 32275507, 4674689, 13890525 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 877047233620632, 1375632631944375, 643773611882121, + 660022738847877, 19353932331831 +#else + 13609624, 13069022, 39736503, 20498523, 24360585, 9592974, + 14977157, 9835105, 4389687, 288396 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2216943882299338, 394841323190322, 2222656898319671, + 558186553950529, 1077236877025190 +#else + 9922506, 33035038, 13613106, 5883594, 48350519, 33120168, + 54804801, 8317627, 23388070, 16052080 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 801118384953213, 1914330175515892, 574541023311511, + 1471123787903705, 1526158900256288 +#else + 12719997, 11937594, 35138804, 28525742, 26900119, 8561328, + 46953177, 21921452, 52354592, 22741539 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 949617889087234, 2207116611267331, 912920039141287, + 501158539198789, 62362560771472 +#else + 15961858, 14150409, 26716931, 32888600, 44314535, 13603568, + 11829573, 7467844, 38286736, 929274 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1474518386765335, 1760793622169197, 1157399790472736, + 1622864308058898, 165428294422792 +#else + 11038231, 21972036, 39798381, 26237869, 56610336, 17246600, + 43629330, 24182562, 45715720, 2465073 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1961673048027128, 102619413083113, 1051982726768458, + 1603657989805485, 1941613251499678 +#else + 20017144, 29231206, 27915241, 1529148, 12396362, 15675764, + 13817261, 23896366, 2463390, 28932292 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1401939116319266, 335306339903072, 72046196085786, + 862423201496006, 850518754531384 +#else + 50749986, 20890520, 55043680, 4996453, 65852442, 1073571, + 9583558, 12851107, 4003896, 12673717 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1234706593321979, 1083343891215917, 898273974314935, + 1640859118399498, 157578398571149 +#else + 65377275, 18398561, 63845933, 16143081, 19294135, 13385325, + 14741514, 24450706, 7903885, 2348101 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1143483057726416, 1992614991758919, 674268662140796, + 1773370048077526, 674318359920189 +#else + 24536016, 17039225, 12715591, 29692277, 1511292, 10047386, + 63266518, 26425272, 38731325, 10048126 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1835401379538542, 173900035308392, 818247630716732, + 1762100412152786, 1021506399448291 +#else + 54486638, 27349611, 30718824, 2591312, 56491836, 12192839, + 18873298, 26257342, 34811107, 15221631 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1506632088156630, 2127481795522179, 513812919490255, + 140643715928370, 442476620300318 +#else + 40630742, 22450567, 11546243, 31701949, 9180879, 7656409, + 45764914, 2095754, 29769758, 6593415 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2056683376856736, 219094741662735, 2193541883188309, + 1841182310235800, 556477468664293 +#else + 35114656, 30646970, 4176911, 3264766, 12538965, 32686321, + 26312344, 27435754, 30958053, 8292160 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1315019427910827, 1049075855992603, 2066573052986543, + 266904467185534, 2040482348591520 +#else + 31429803, 19595316, 29173531, 15632448, 12174511, 30794338, + 32808830, 3977186, 26143136, 30405556 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 94096246544434, 922482381166992, 24517828745563, + 2139430508542503, 2097139044231004 +#else + 22648882, 1402143, 44308880, 13746058, 7936347, 365344, + 58440231, 31879998, 63350620, 31249806 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 537697207950515, 1399352016347350, 1563663552106345, + 2148749520888918, 549922092988516 +#else + 51616947, 8012312, 64594134, 20851969, 43143017, 23300402, + 65496150, 32018862, 50444388, 8194477 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1747985413252434, 680511052635695, 1809559829982725, + 594274250930054, 201673170745982 +#else + 27338066, 26047012, 59694639, 10140404, 48082437, 26964542, + 27277190, 8855376, 28572286, 3005164 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 323583936109569, 1973572998577657, 1192219029966558, + 79354804385273, 1374043025560347 +#else + 26287105, 4821776, 25476601, 29408529, 63344350, 17765447, + 49100281, 1182478, 41014043, 20474836 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 213277331329947, 416202017849623, 1950535221091783, + 1313441578103244, 2171386783823658 +#else + 59937691, 3178079, 23970071, 6201893, 49913287, 29065239, + 45232588, 19571804, 32208682, 32356184 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 189088804229831, 993969372859110, 895870121536987, + 1547301535298256, 1477373024911350 +#else + 50451143, 2817642, 56822502, 14811297, 6024667, 13349505, + 39793360, 23056589, 39436278, 22014573 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1620578418245010, 541035331188469, 2235785724453865, + 2154865809088198, 1974627268751826 +#else + 15941010, 24148500, 45741813, 8062054, 31876073, 33315803, + 51830470, 32110002, 15397330, 29424239 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1346805451740245, 1350981335690626, 942744349501813, + 2155094562545502, 1012483751693409 +#else + 8934485, 20068965, 43822466, 20131190, 34662773, 14047985, + 31170398, 32113411, 39603297, 15087183 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2107080134091762, 1132567062788208, 1824935377687210, + 769194804343737, 1857941799971888 +#else + 48751602, 31397940, 24524912, 16876564, 15520426, 27193656, + 51606457, 11461895, 16788528, 27685490 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1074666112436467, 249279386739593, 1174337926625354, + 1559013532006480, 1472287775519121 +#else + 65161459, 16013772, 21750665, 3714552, 49707082, 17498998, + 63338576, 23231111, 31322513, 21938797 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1872620123779532, 1892932666768992, 1921559078394978, + 1270573311796160, 1438913646755037 +#else + 21426636, 27904214, 53460576, 28206894, 38296674, 28633461, + 48833472, 18933017, 13040861, 21441484 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 837390187648199, 1012253300223599, 989780015893987, + 1351393287739814, 328627746545550 +#else + 11293895, 12478086, 39972463, 15083749, 37801443, 14748871, + 14555558, 20137329, 1613710, 4896935 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1028328827183114, 1711043289969857, 1350832470374933, + 1923164689604327, 1495656368846911 +#else + 41213962, 15323293, 58619073, 25496531, 25967125, 20128972, + 2825959, 28657387, 43137087, 22287016 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1900828492104143, 430212361082163, 687437570852799, + 832514536673512, 1685641495940794 +#else + 51184079, 28324551, 49665331, 6410663, 3622847, 10243618, + 20615400, 12405433, 43355834, 25118015 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 842632847936398, 605670026766216, 290836444839585, + 163210774892356, 2213815011799645 +#else + 60017550, 12556207, 46917512, 9025186, 50036385, 4333800, + 4378436, 2432030, 23097949, 32988414 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1176336383453996, 1725477294339771, 12700622672454, + 678015708818208, 162724078519879 +#else + 4565804, 17528778, 20084411, 25711615, 1724998, 189254, + 24767264, 10103221, 48596551, 2424777 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1448049969043497, 1789411762943521, 385587766217753, + 90201620913498, 832999441066823 +#else + 366633, 21577626, 8173089, 26664313, 30788633, 5745705, + 59940186, 1344108, 63466311, 12412658 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 516086333293313, 2240508292484616, 1351669528166508, + 1223255565316488, 750235824427138 +#else + 43107073, 7690285, 14929416, 33386175, 34898028, 20141445, + 24162696, 18227928, 63967362, 11179384 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1263624896582495, 1102602401673328, 526302183714372, + 2152015839128799, 1483839308490010 +#else + 18289503, 18829478, 8056944, 16430056, 45379140, 7842513, + 61107423, 32067534, 48424218, 22110928 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 442991718646863, 1599275157036458, 1925389027579192, + 899514691371390, 350263251085160 +#else + 476239, 6601091, 60956074, 23831056, 17503544, 28690532, + 27672958, 13403813, 11052904, 5219329 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1689713572022143, 593854559254373, 978095044791970, + 1985127338729499, 1676069120347625 +#else + 20678527, 25178694, 34436965, 8849122, 62099106, 14574751, + 31186971, 29580702, 9014761, 24975376 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1557207018622683, 340631692799603, 1477725909476187, + 614735951619419, 2033237123746766 +#else + 53464795, 23204192, 51146355, 5075807, 65594203, 22019831, + 34006363, 9160279, 8473550, 30297594 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 968764929340557, 1225534776710944, 662967304013036, + 1155521416178595, 791142883466590 +#else + 24900749, 14435722, 17209120, 18261891, 44516588, 9878982, + 59419555, 17218610, 42540382, 11788947 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1487081286167458, 993039441814934, 1792378982844640, + 698652444999874, 2153908693179754 +#else + 63990690, 22159237, 53306774, 14797440, 9652448, 26708528, + 47071426, 10410732, 42540394, 32095740 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1123181311102823, 685575944875442, 507605465509927, + 1412590462117473, 568017325228626 +#else + 51449703, 16736705, 44641714, 10215877, 58011687, 7563910, + 11871841, 21049238, 48595538, 8464117 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 560258797465417, 2193971151466401, 1824086900849026, + 579056363542056, 1690063960036441 +#else + 43708233, 8348506, 52522913, 32692717, 63158658, 27181012, + 14325288, 8628612, 33313881, 25183915 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1918407319222416, 353767553059963, 1930426334528099, + 1564816146005724, 1861342381708096 +#else + 46921872, 28586496, 22367355, 5271547, 66011747, 28765593, + 42303196, 23317577, 58168128, 27736162 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2131325168777276, 1176636658428908, 1756922641512981, + 1390243617176012, 1966325177038383 +#else + 60160060, 31759219, 34483180, 17533252, 32635413, 26180187, + 15989196, 20716244, 28358191, 29300528 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2063958120364491, 2140267332393533, 699896251574968, + 273268351312140, 375580724713232 +#else + 43547083, 30755372, 34757181, 31892468, 57961144, 10429266, + 50471180, 4072015, 61757200, 5596588 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2024297515263178, 416959329722687, 1079014235017302, + 171612225573183, 1031677520051053 +#else + 38872266, 30164383, 12312895, 6213178, 3117142, 16078565, + 29266239, 2557221, 1768301, 15373193 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2033900009388450, 1744902869870788, 2190580087917640, + 1949474984254121, 231049754293748 +#else + 59865506, 30307471, 62515396, 26001078, 66980936, 32642186, + 66017961, 29049440, 42448372, 3442909 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 343868674606581, 550155864008088, 1450580864229630, + 481603765195050, 896972360018042 +#else + 36898293, 5124042, 14181784, 8197961, 18964734, 21615339, + 22597930, 7176455, 48523386, 13365929 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2151139328380127, 314745882084928, 59756825775204, + 1676664391494651, 2048348075599360 +#else + 59231455, 32054473, 8324672, 4690079, 6261860, 890446, 24538107, + 24984246, 57419264, 30522764 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1528930066340597, 1605003907059576, 1055061081337675, + 1458319101947665, 1234195845213142 +#else + 25008885, 22782833, 62803832, 23916421, 16265035, 15721635, + 683793, 21730648, 15723478, 18390951 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 830430507734812, 1780282976102377, 1425386760709037, + 362399353095425, 2168861579799910 +#else + 57448220, 12374378, 40101865, 26528283, 59384749, 21239917, + 11879681, 5400171, 519526, 32318556 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1155762232730333, 980662895504006, 2053766700883521, + 490966214077606, 510405877041357 +#else + 22258397, 17222199, 59239046, 14613015, 44588609, 30603508, + 46754982, 7315966, 16648397, 7605640 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1683750316716132, 652278688286128, 1221798761193539, + 1897360681476669, 319658166027343 +#else + 59027556, 25089834, 58885552, 9719709, 19259459, 18206220, + 23994941, 28272877, 57640015, 4763277 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 618808732869972, 72755186759744, 2060379135624181, + 1730731526741822, 48862757828238 +#else + 45409620, 9220968, 51378240, 1084136, 41632757, 30702041, + 31088446, 25789909, 55752334, 728111 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1463171970593505, 1143040711767452, 614590986558883, + 1409210575145591, 1882816996436803 +#else + 26047201, 21802961, 60208540, 17032633, 24092067, 9158119, + 62835319, 20998873, 37743427, 28056159 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2230133264691131, 563950955091024, 2042915975426398, + 827314356293472, 672028980152815 +#else + 17510331, 33231575, 5854288, 8403524, 17133918, 30441820, + 38997856, 12327944, 10750447, 10014012 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 264204366029760, 1654686424479449, 2185050199932931, + 2207056159091748, 506015669043634 +#else + 56796096, 3936951, 9156313, 24656749, 16498691, 32559785, + 39627812, 32887699, 3424690, 7540221 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1784446333136569, 1973746527984364, 334856327359575, + 1156769775884610, 1023950124675478 +#else + 30322361, 26590322, 11361004, 29411115, 7433303, 4989748, + 60037442, 17237212, 57864598, 15258045 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2065270940578383, 31477096270353, 306421879113491, + 181958643936686, 1907105536686083 +#else + 13054543, 30774935, 19155473, 469045, 54626067, 4566041, + 5631406, 2711395, 1062915, 28418087 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1496516440779464, 1748485652986458, 872778352227340, + 818358834654919, 97932669284220 +#else + 47868616, 22299832, 37599834, 26054466, 61273100, 13005410, + 61042375, 12194496, 32960380, 1459310 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 471636015770351, 672455402793577, 1804995246884103, + 1842309243470804, 1501862504981682 +#else + 19852015, 7027924, 23669353, 10020366, 8586503, 26896525, + 394196, 27452547, 18638002, 22379495 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1013216974933691, 538921919682598, 1915776722521558, + 1742822441583877, 1886550687916656 +#else + 31395515, 15098109, 26581030, 8030562, 50580950, 28547297, + 9012485, 25970078, 60465776, 28111795 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2094270000643336, 303971879192276, 40801275554748, + 649448917027930, 1818544418535447 +#else + 57916680, 31207054, 65111764, 4529533, 25766844, 607986, + 67095642, 9677542, 34813975, 27098423 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2241737709499165, 549397817447461, 838180519319392, + 1725686958520781, 1705639080897747 +#else + 64664349, 33404494, 29348901, 8186665, 1873760, 12489863, + 36174285, 25714739, 59256019, 25416002 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1216074541925116, 50120933933509, 1565829004133810, + 721728156134580, 349206064666188 +#else + 51872508, 18120922, 7766469, 746860, 26346930, 23332670, + 39775412, 10754587, 57677388, 5203575 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 948617110470858, 346222547451945, 1126511960599975, + 1759386906004538, 493053284802266 +#else + 31834314, 14135496, 66338857, 5159117, 20917671, 16786336, + 59640890, 26216907, 31809242, 7347066 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1454933046815146, 874696014266362, 1467170975468588, + 1432316382418897, 2111710746366763 +#else + 57502122, 21680191, 20414458, 13033986, 13716524, 21862551, + 19797969, 21343177, 15192875, 31466942 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2105387117364450, 1996463405126433, 1303008614294500, + 851908115948209, 1353742049788635 +#else + 54445282, 31372712, 1168161, 29749623, 26747876, 19416341, + 10609329, 12694420, 33473243, 20172328 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 750300956351719, 1487736556065813, 15158817002104, + 1511998221598392, 971739901354129 +#else + 33184999, 11180355, 15832085, 22169002, 65475192, 225883, + 15089336, 22530529, 60973201, 14480052 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1874648163531693, 2124487685930551, 1810030029384882, + 918400043048335, 586348627300650 +#else + 31308717, 27934434, 31030839, 31657333, 15674546, 26971549, + 5496207, 13685227, 27595050, 8737275 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1235084464747900, 1166111146432082, 1745394857881591, + 1405516473883040, 4463504151617 +#else + 46790012, 18404192, 10933842, 17376410, 8335351, 26008410, + 36100512, 20943827, 26498113, 66511 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1663810156463827, 327797390285791, 1341846161759410, + 1964121122800605, 1747470312055380 +#else + 22644435, 24792703, 50437087, 4884561, 64003250, 19995065, + 30540765, 29267685, 53781076, 26039336 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 660005247548233, 2071860029952887, 1358748199950107, + 911703252219107, 1014379923023831 +#else + 39091017, 9834844, 18617207, 30873120, 63706907, 20246925, + 8205539, 13585437, 49981399, 15115438 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2206641276178231, 1690587809721504, 1600173622825126, + 2156096097634421, 1106822408548216 +#else + 23711543, 32881517, 31206560, 25191721, 6164646, 23844445, + 33572981, 32128335, 8236920, 16492939 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1344788193552206, 1949552134239140, 1735915881729557, + 675891104100469, 1834220014427292 +#else + 43198286, 20038905, 40809380, 29050590, 25005589, 25867162, + 19574901, 10071562, 6708380, 27332008 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1920949492387964, 158885288387530, 70308263664033, + 626038464897817, 1468081726101009 +#else + 2101372, 28624378, 19702730, 2367575, 51681697, 1047674, + 5301017, 9328700, 29955601, 21876122 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 622221042073383, 1210146474039168, 1742246422343683, + 1403839361379025, 417189490895736 +#else + 3096359, 9271816, 45488000, 18032587, 52260867, 25961494, + 41216721, 20918836, 57191288, 6216607 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 22727256592983, 168471543384997, 1324340989803650, + 1839310709638189, 504999476432775 +#else + 34493015, 338662, 41913253, 2510421, 37895298, 19734218, + 24822829, 27407865, 40341383, 7525078 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1313240518756327, 1721896294296942, 52263574587266, + 2065069734239232, 804910473424630 +#else + 44042215, 19568808, 16133486, 25658254, 63719298, 778787, + 66198528, 30771936, 47722230, 11994100 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1337466662091884, 1287645354669772, 2018019646776184, + 652181229374245, 898011753211715 +#else + 21691500, 19929806, 66467532, 19187410, 3285880, 30070836, + 42044197, 9718257, 59631427, 13381417 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1969792547910734, 779969968247557, 2011350094423418, + 1823964252907487, 1058949448296945 +#else + 18445390, 29352196, 14979845, 11622458, 65381754, 29971451, + 23111647, 27179185, 28535281, 15779576 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 207343737062002, 1118176942430253, 758894594548164, + 806764629546266, 1157700123092949 +#else + 30098034, 3089662, 57874477, 16662134, 45801924, 11308410, + 53040410, 12021729, 9955285, 17251076 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1273565321399022, 1638509681964574, 759235866488935, + 666015124346707, 897983460943405 +#else + 9734894, 18977602, 59635230, 24415696, 2060391, 11313496, + 48682835, 9924398, 20194861, 13380996 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1717263794012298, 1059601762860786, 1837819172257618, + 1054130665797229, 680893204263559 +#else + 40730762, 25589224, 44941042, 15789296, 49053522, 27385639, + 65123949, 15707770, 26342023, 10146099 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2237039662793603, 2249022333361206, 2058613546633703, + 149454094845279, 2215176649164582 +#else + 41091971, 33334488, 21339190, 33513044, 19745255, 30675732, + 37471583, 2227039, 21612326, 33008704 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 79472182719605, 1851130257050174, 1825744808933107, + 821667333481068, 781795293511946 +#else + 54031477, 1184227, 23562814, 27583990, 46757619, 27205717, + 25764460, 12243797, 46252298, 11649657 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 755822026485370, 152464789723500, 1178207602290608, + 410307889503239, 156581253571278 +#else + 57077370, 11262625, 27384172, 2271902, 26947504, 17556661, + 39943, 6114064, 33514190, 2333242 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1418185496130297, 484520167728613, 1646737281442950, + 1401487684670265, 1349185550126961 +#else + 45675257, 21132610, 8119781, 7219913, 45278342, 24538297, + 60429113, 20883793, 24350577, 20104431 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1495380034400429, 325049476417173, 46346894893933, + 1553408840354856, 828980101835683 +#else + 62992557, 22282898, 43222677, 4843614, 37020525, 690622, + 35572776, 23147595, 8317859, 12352766 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1280337889310282, 2070832742866672, 1640940617225222, + 2098284908289951, 450929509534434 +#else + 18200138, 19078521, 34021104, 30857812, 43406342, 24451920, + 43556767, 31266881, 20712162, 6719373 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 407703353998781, 126572141483652, 286039827513621, + 1999255076709338, 2030511179441770 +#else + 26656189, 6075253, 59250308, 1886071, 38764821, 4262325, + 11117530, 29791222, 26224234, 30256974 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1254958221100483, 1153235960999843, 942907704968834, + 637105404087392, 1149293270147267 +#else + 49939907, 18700334, 63713187, 17184554, 47154818, 14050419, + 21728352, 9493610, 18620611, 17125804 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 894249020470196, 400291701616810, 406878712230981, + 1599128793487393, 1145868722604026 +#else + 53785524, 13325348, 11432106, 5964811, 18609221, 6062965, + 61839393, 23828875, 36407290, 17074774 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1497955250203334, 110116344653260, 1128535642171976, + 1900106496009660, 129792717460909 +#else + 43248326, 22321272, 26961356, 1640861, 34695752, 16816491, + 12248508, 28313793, 13735341, 1934062 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 452487513298665, 1352120549024569, 1173495883910956, + 1999111705922009, 367328130454226 +#else + 25089769, 6742589, 17081145, 20148166, 21909292, 17486451, + 51972569, 29789085, 45830866, 5473615 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1717539401269642, 1475188995688487, 891921989653942, + 836824441505699, 1885988485608364 +#else + 31883658, 25593331, 1083431, 21982029, 22828470, 13290673, + 59983779, 12469655, 29111212, 28103418 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1241784121422547, 187337051947583, 1118481812236193, + 428747751936362, 30358898927325 +#else + 24244947, 18504025, 40845887, 2791539, 52111265, 16666677, + 24367466, 6388839, 56813277, 452382 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022432361201842, 1088816090685051, 1977843398539868, + 1854834215890724, 564238862029357 +#else + 41468082, 30136590, 5217915, 16224624, 19987036, 29472163, + 42872612, 27639183, 15766061, 8407814 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 938868489100585, 1100285072929025, 1017806255688848, + 1957262154788833, 152787950560442 +#else + 46701865, 13990230, 15495425, 16395525, 5377168, 15166495, + 58191841, 29165478, 59040954, 2276717 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 867319417678923, 620471962942542, 226032203305716, + 342001443957629, 1761675818237336 +#else + 30157899, 12924066, 49396814, 9245752, 19895028, 3368142, + 43281277, 5096218, 22740376, 26251015 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1295072362439987, 931227904689414, 1355731432641687, + 922235735834035, 892227229410209 +#else + 2041139, 19298082, 7783686, 13876377, 41161879, 20201972, + 24051123, 13742383, 51471265, 13295221 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1680989767906154, 535362787031440, 2136691276706570, + 1942228485381244, 1267350086882274 +#else + 33338218, 25048699, 12532112, 7977527, 9106186, 31839181, + 49388668, 28941459, 62657506, 18884987 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 366018233770527, 432660629755596, 126409707644535, + 1973842949591662, 645627343442376 +#else + 47063583, 5454096, 52762316, 6447145, 28862071, 1883651, + 64639598, 29412551, 7770568, 9620597 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 535509430575217, 546885533737322, 1524675609547799, + 2138095752851703, 1260738089896827 +#else + 23208049, 7979712, 33071466, 8149229, 1758231, 22719437, + 30945527, 31860109, 33606523, 18786461 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1159906385590467, 2198530004321610, 714559485023225, + 81880727882151, 1484020820037082 +#else + 1439939, 17283952, 66028874, 32760649, 4625401, 10647766, + 62065063, 1220117, 30494170, 22113633 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1377485731340769, 2046328105512000, 1802058637158797, + 62146136768173, 1356993908853901 +#else + 62071265, 20526136, 64138304, 30492664, 15640973, 26852766, + 40369837, 926049, 65424525, 20220784 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2013612215646735, 1830770575920375, 536135310219832, + 609272325580394, 270684344495013 +#else + 13908495, 30005160, 30919927, 27280607, 45587000, 7989038, + 9021034, 9078865, 3353509, 4033511 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1237542585982777, 2228682050256790, 1385281931622824, + 593183794882890, 493654978552689 +#else + 37445433, 18440821, 32259990, 33209950, 24295848, 20642309, + 23161162, 8839127, 27485041, 7356032 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 47341488007760, 1891414891220257, 983894663308928, + 176161768286818, 1126261115179708 +#else + 9661008, 705443, 11980065, 28184278, 65480320, 14661172, + 60762722, 2625014, 28431036, 16782598 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1694030170963455, 502038567066200, 1691160065225467, + 949628319562187, 275110186693066 +#else + 43269631, 25243016, 41163352, 7480957, 49427195, 25200248, + 44562891, 14150564, 15970762, 4099461 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1124515748676336, 1661673816593408, 1499640319059718, + 1584929449166988, 558148594103306 +#else + 29262576, 16756590, 26350592, 24760869, 8529670, 22346382, + 13617292, 23617289, 11465738, 8317062 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1784525599998356, 1619698033617383, 2097300287550715, + 258265458103756, 1905684794832758 +#else + 41615764, 26591503, 32500199, 24135381, 44070139, 31252209, + 14898636, 3848455, 20969334, 28396916 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1288941072872766, 931787902039402, 190731008859042, + 2006859954667190, 1005931482221702 +#else + 46724414, 19206718, 48772458, 13884721, 34069410, 2842113, + 45498038, 29904543, 11177094, 14989547 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1465551264822703, 152905080555927, 680334307368453, + 173227184634745, 666407097159852 +#else + 42612143, 21838415, 16959895, 2278463, 12066309, 10137771, + 13515641, 2581286, 38621356, 9930239 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2111017076203943, 1378760485794347, 1248583954016456, + 1352289194864422, 1895180776543896 +#else + 49357223, 31456605, 16544299, 20545132, 51194056, 18605350, + 18345766, 20150679, 16291480, 28240394 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 171348223915638, 662766099800389, 462338943760497, + 466917763340314, 656911292869115 +#else + 33879670, 2553287, 32678213, 9875984, 8534129, 6889387, + 57432090, 6957616, 4368891, 9788741 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 488623681976577, 866497561541722, 1708105560937768, + 1673781214218839, 1506146329818807 +#else + 16660737, 7281060, 56278106, 12911819, 20108584, 25452756, + 45386327, 24941283, 16250551, 22443329 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 160425464456957, 950394373239689, 430497123340934, + 711676555398832, 320964687779005 +#else + 47343357, 2390525, 50557833, 14161979, 1905286, 6414907, + 4689584, 10604807, 36918461, 4782746 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 988979367990485, 1359729327576302, 1301834257246029, + 294141160829308, 29348272277475 +#else + 65754325, 14736940, 59741422, 20261545, 7710541, 19398842, + 57127292, 4383044, 22546403, 437323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1434382743317910, 100082049942065, 221102347892623, + 186982837860588, 1305765053501834 +#else + 31665558, 21373968, 50922033, 1491338, 48740239, 3294681, + 27343084, 2786261, 36475274, 19457415 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2205916462268190, 499863829790820, 961960554686616, + 158062762756985, 1841471168298305 +#else + 52641566, 32870716, 33734756, 7448551, 19294360, 14334329, + 47418233, 2355318, 47824193, 27440058 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1191737341426592, 1847042034978363, 1382213545049056, + 1039952395710448, 788812858896859 +#else + 15121312, 17758270, 6377019, 27523071, 56310752, 20596586, + 18952176, 15496498, 37728731, 11754227 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1346965964571152, 1291881610839830, 2142916164336056, + 786821641205979, 1571709146321039 +#else + 64471568, 20071356, 8488726, 19250536, 12728760, 31931939, + 7141595, 11724556, 22761615, 23420291 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 787164375951248, 202869205373189, 1356590421032140, + 1431233331032510, 786341368775957 +#else + 16918416, 11729663, 49025285, 3022986, 36093132, 20214772, + 38367678, 21327038, 32851221, 11717399 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 492448143532951, 304105152670757, 1761767168301056, + 233782684697790, 1981295323106089 +#else + 11166615, 7338049, 60386341, 4531519, 37640192, 26252376, + 31474878, 3483633, 65915689, 29523600 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665807507761866, 1343384868355425, 895831046139653, + 439338948736892, 1986828765695105 +#else + 66923210, 9921304, 31456609, 20017994, 55095045, 13348922, + 33142652, 6546660, 47123585, 29606055 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 756096210874553, 1721699973539149, 258765301727885, + 1390588532210645, 1212530909934781 +#else + 34648249, 11266711, 55911757, 25655328, 31703693, 3855903, + 58571733, 20721383, 36336829, 18068118 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 852891097972275, 1816988871354562, 1543772755726524, + 1174710635522444, 202129090724628 +#else + 49102387, 12709067, 3991746, 27075244, 45617340, 23004006, + 35973516, 17504552, 10928916, 3011958 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1205281565824323, 22430498399418, 992947814485516, + 1392458699738672, 688441466734558 +#else + 60151107, 17960094, 31696058, 334240, 29576716, 14796075, + 36277808, 20749251, 18008030, 10258577 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1050627428414972, 1955849529137135, 2171162376368357, + 91745868298214, 447733118757826 +#else + 44660220, 15655568, 7018479, 29144429, 36794597, 32352840, + 65255398, 1367119, 25127874, 6671743 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1287181461435438, 622722465530711, 880952150571872, + 741035693459198, 311565274989772 +#else + 29701166, 19180498, 56230743, 9279287, 67091296, 13127209, + 21382910, 11042292, 25838796, 4642684 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1003649078149734, 545233927396469, 1849786171789880, + 1318943684880434, 280345687170552 +#else + 46678630, 14955536, 42982517, 8124618, 61739576, 27563961, + 30468146, 19653792, 18423288, 4177476 +#endif + }}, + }, + }, +}; + +#endif // OPENSSL_SMALL + +// Bi[i] = (2*i+1)*B +static const ge_precomp Bi[8] = { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1288382639258501, 245678601348599, 269427782077623, + 1462984067271730, 137412439391563 +#else + 25967493, 19198397, 29566455, 3660896, 54414519, 4014786, 27544626, + 21800161, 61029707, 2047604 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 62697248952638, 204681361388450, 631292143396476, 338455783676468, + 1213667448819585 +#else + 54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, + 5043384, 19500929, 18085054 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 301289933810280, 1259582250014073, 1422107436869536, + 796239922652654, 1953934009299142 +#else + 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, + 11864899, 42594502, 29115885 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1601611775252272, 1720807796594148, 1132070835939856, + 1260455018889551, 2147779492816911 +#else + 15636272, 23865875, 24204772, 25642034, 616976, 16869170, 27787599, + 18782243, 28944399, 32004408 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 316559037616741, 2177824224946892, 1459442586438991, + 1461528397712656, 751590696113597 +#else + 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, + 21778470, 7689661, 11199574 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1850748884277385, 1200145853858453, 1068094770532492, + 672251375690438, 1586055907191707 +#else + 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, + 10017326, 49359771, 23634074 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 769950342298419, 132954430919746, 844085933195555, 974092374476333, + 726076285546016 +#else + 10861363, 11473154, 27284546, 1981175, 37044515, 12577860, 32867885, + 14515107, 51670560, 10819379 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 425251763115706, 608463272472562, 442562545713235, 837766094556764, + 374555092627893 +#else + 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, + 12483687, 54440373, 5581305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1086255230780037, 274979815921559, 1960002765731872, + 929474102396301, 1190409889297339 +#else + 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, + 13850243, 43430843, 17738489 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665000864555967, 2065379846933859, 370231110385876, 350988370788628, + 1233371373142985 +#else + 5153727, 9909285, 1723747, 30776558, 30523604, 5516873, 19480852, + 5230134, 43156425, 18378665 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2019367628972465, 676711900706637, 110710997811333, + 1108646842542025, 517791959672113 +#else + 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, + 16520125, 30598449, 7715701 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 965130719900578, 247011430587952, 526356006571389, 91986625355052, + 2157223321444601 +#else + 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, + 1370707, 29794553, 32145132 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1802695059465007, 1664899123557221, 593559490740857, + 2160434469266659, 927570450755031 +#else + 44589871, 26862249, 14201701, 24808930, 43598457, 8844725, 18474211, + 32192982, 54046167, 13821876 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1725674970513508, 1933645953859181, 1542344539275782, + 1767788773573747, 1297447965928905 +#else + 60653668, 25714560, 3374701, 28813570, 40010246, 22982724, 31655027, + 26342105, 18853321, 19333481 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1381809363726107, 1430341051343062, 2061843536018959, + 1551778050872521, 2036394857967624 +#else + 4566811, 20590564, 38133974, 21313742, 59506191, 30723862, 58594505, + 23123294, 2207752, 30344648 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1970894096313054, 528066325833207, 1619374932191227, + 2207306624415883, 1169170329061080 +#else + 41954014, 29368610, 29681143, 7868801, 60254203, 24130566, 54671499, + 32891431, 35997400, 17421995 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2070390218572616, 1458919061857835, 624171843017421, + 1055332792707765, 433987520732508 +#else + 25576264, 30851218, 7349803, 21739588, 16472781, 9300885, 3844789, + 15725684, 171356, 6466918 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 893653801273833, 1168026499324677, 1242553501121234, + 1306366254304474, 1086752658510815 +#else + 23103977, 13316479, 9739013, 17404951, 817874, 18515490, 8965338, + 19466374, 36393951, 16193876 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 213454002618221, 939771523987438, 1159882208056014, 317388369627517, + 621213314200687 +#else + 33587053, 3180712, 64714734, 14003686, 50205390, 17283591, 17238397, + 4729455, 49034351, 9256799 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1971678598905747, 338026507889165, 762398079972271, 655096486107477, + 42299032696322 +#else + 41926547, 29380300, 32336397, 5036987, 45872047, 11360616, 22616405, + 9761698, 47281666, 630304 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 177130678690680, 1754759263300204, 1864311296286618, + 1180675631479880, 1292726903152791 +#else + 53388152, 2639452, 42871404, 26147950, 9494426, 27780403, 60554312, + 17593437, 64659607, 19263131 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1913163449625248, 460779200291993, 2193883288642314, + 1008900146920800, 1721983679009502 +#else + 63957664, 28508356, 9282713, 6866145, 35201802, 32691408, 48168288, + 15033783, 25105118, 25659556 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1070401523076875, 1272492007800961, 1910153608563310, + 2075579521696771, 1191169788841221 +#else + 42782475, 15950225, 35307649, 18961608, 55446126, 28463506, 1573891, + 30928545, 2198789, 17749813 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 692896803108118, 500174642072499, 2068223309439677, + 1162190621851337, 1426986007309901 +#else + 64009494, 10324966, 64867251, 7453182, 61661885, 30818928, 53296841, + 17317989, 34647629, 21263748 +#endif + }}, + }, +}; diff --git a/Sources/BoringSSL/third_party/fiat/internal.h b/Sources/BoringSSL/third_party/fiat/internal.h index 10218e065..be3e265a5 100644 --- a/Sources/BoringSSL/third_party/fiat/internal.h +++ b/Sources/BoringSSL/third_party/fiat/internal.h @@ -27,14 +27,9 @@ extern "C" { #endif +#include -#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \ - !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM) -#define BORINGSSL_X25519_X86_64 - -void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32], - const uint8_t point[32]); -#endif +#include "../../crypto/internal.h" #if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_APPLE) @@ -45,6 +40,22 @@ void x25519_NEON(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32]); #endif +#if defined(BORINGSSL_HAS_UINT128) +#define BORINGSSL_CURVE25519_64BIT +#endif + +#if defined(BORINGSSL_CURVE25519_64BIT) +// fe means field element. Here the field is \Z/(2^255-19). An element t, +// entries t[0]...t[4], represents the integer t[0]+2^51 t[1]+2^102 t[2]+2^153 +// t[3]+2^204 t[4]. +// fe limbs are bounded by 1.125*2^51. +// Multiplication and carrying produce fe from fe_loose. +typedef struct fe { uint64_t v[5]; } fe; + +// fe_loose limbs are bounded by 3.375*2^51. +// Addition and subtraction produce fe_loose from (fe, fe). +typedef struct fe_loose { uint64_t v[5]; } fe_loose; +#else // fe means field element. Here the field is \Z/(2^255-19). An element t, // entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 // t[3]+2^102 t[4]+...+2^230 t[9]. @@ -55,18 +66,19 @@ typedef struct fe { uint32_t v[10]; } fe; // fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc. // Addition and subtraction produce fe_loose from (fe, fe). typedef struct fe_loose { uint32_t v[10]; } fe_loose; +#endif -/* ge means group element. - - * Here the group is the set of pairs (x,y) of field elements (see fe.h) - * satisfying -x^2 + y^2 = 1 + d x^2y^2 - * where d = -121665/121666. - * - * Representations: - * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z - * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT - * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T - * ge_precomp (Duif): (y+x,y-x,2dxy) */ +// ge means group element. +// +// Here the group is the set of pairs (x,y) of field elements (see fe.h) +// satisfying -x^2 + y^2 = 1 + d x^2y^2 +// where d = -121665/121666. +// +// Representations: +// ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z +// ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT +// ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T +// ge_precomp (Duif): (y+x,y-x,2dxy) typedef struct { fe X; @@ -101,7 +113,7 @@ typedef struct { fe_loose T2d; } ge_cached; -void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h); +void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h); int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s); void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p); void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); @@ -112,7 +124,7 @@ void x25519_ge_scalarmult_small_precomp( ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]); void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]); void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A); -void x25519_sc_reduce(uint8_t *s); +void x25519_sc_reduce(uint8_t s[64]); enum spake2_state_t { spake2_state_init = 0, diff --git a/Sources/BoringSSL/third_party/fiat/p256.c b/Sources/BoringSSL/third_party/fiat/p256.c new file mode 100644 index 000000000..82f36085e --- /dev/null +++ b/Sources/BoringSSL/third_party/fiat/p256.c @@ -0,0 +1,1824 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// The field arithmetic code is generated by Fiat +// (https://github.com/mit-plv/fiat-crypto), which is MIT licensed. +// +// An implementation of the NIST P-256 elliptic curve point multiplication. +// 256-bit Montgomery form, generated using fiat-crypto, for 64 and 32-bit. +// Field operations with inputs in [0,p) return outputs in [0,p). + +#include + +#include +#include +#include +#include + +#include + +#include "../../crypto/fipsmodule/delocate.h" +#include "../../crypto/fipsmodule/ec/internal.h" +#include "../../crypto/internal.h" + + +// MSVC does not implement uint128_t, and crashes with intrinsics +#if defined(BORINGSSL_HAS_UINT128) +#define BORINGSSL_NISTP256_64BIT 1 +#endif + +// "intrinsics" + +#if defined(BORINGSSL_NISTP256_64BIT) + +static uint64_t mulx_u64(uint64_t a, uint64_t b, uint64_t *high) { + uint128_t x = (uint128_t)a * b; + *high = (uint64_t) (x >> 64); + return (uint64_t) x; +} + +static uint64_t addcarryx_u64(uint8_t c, uint64_t a, uint64_t b, uint64_t *low) { + uint128_t x = (uint128_t)a + b + c; + *low = (uint64_t) x; + return (uint64_t) (x>>64); +} + +static uint64_t subborrow_u64(uint8_t c, uint64_t a, uint64_t b, uint64_t *low) { + uint128_t t = ((uint128_t) b + c); + uint128_t x = a-t; + *low = (uint64_t) x; + return (uint8_t) (x>>127); +} + +static uint64_t cmovznz_u64(uint64_t t, uint64_t z, uint64_t nz) { + t = -!!t; // all set if nonzero, 0 if 0 + return (t&nz) | ((~t)&z); +} + +#else + +static uint32_t mulx_u32(uint32_t a, uint32_t b, uint32_t *high) { + uint64_t x = (uint64_t)a * b; + *high = (uint32_t) (x >> 32); + return (uint32_t) x; +} + +static uint32_t addcarryx_u32(uint8_t c, uint32_t a, uint32_t b, uint32_t *low) { + uint64_t x = (uint64_t)a + b + c; + *low = (uint32_t) x; + return (uint32_t) (x>>32); +} + +static uint32_t subborrow_u32(uint8_t c, uint32_t a, uint32_t b, uint32_t *low) { + uint64_t t = ((uint64_t) b + c); + uint64_t x = a-t; + *low = (uint32_t) x; + return (uint8_t) (x>>63); +} + +static uint32_t cmovznz_u32(uint32_t t, uint32_t z, uint32_t nz) { + t = -!!t; // all set if nonzero, 0 if 0 + return (t&nz) | ((~t)&z); +} + +#endif + +// fiat-crypto generated code + +#if defined(BORINGSSL_NISTP256_64BIT) + +static void fe_add(uint64_t out[4], const uint64_t in1[4], const uint64_t in2[4]) { + { const uint64_t x8 = in1[3]; + { const uint64_t x9 = in1[2]; + { const uint64_t x7 = in1[1]; + { const uint64_t x5 = in1[0]; + { const uint64_t x14 = in2[3]; + { const uint64_t x15 = in2[2]; + { const uint64_t x13 = in2[1]; + { const uint64_t x11 = in2[0]; + { uint64_t x17; uint8_t x18 = addcarryx_u64(0x0, x5, x11, &x17); + { uint64_t x20; uint8_t x21 = addcarryx_u64(x18, x7, x13, &x20); + { uint64_t x23; uint8_t x24 = addcarryx_u64(x21, x9, x15, &x23); + { uint64_t x26; uint8_t x27 = addcarryx_u64(x24, x8, x14, &x26); + { uint64_t x29; uint8_t x30 = subborrow_u64(0x0, x17, 0xffffffffffffffffL, &x29); + { uint64_t x32; uint8_t x33 = subborrow_u64(x30, x20, 0xffffffff, &x32); + { uint64_t x35; uint8_t x36 = subborrow_u64(x33, x23, 0x0, &x35); + { uint64_t x38; uint8_t x39 = subborrow_u64(x36, x26, 0xffffffff00000001L, &x38); + { uint64_t _1; uint8_t x42 = subborrow_u64(x39, x27, 0x0, &_1); + { uint64_t x43 = cmovznz_u64(x42, x38, x26); + { uint64_t x44 = cmovznz_u64(x42, x35, x23); + { uint64_t x45 = cmovznz_u64(x42, x32, x20); + { uint64_t x46 = cmovznz_u64(x42, x29, x17); + out[0] = x46; + out[1] = x45; + out[2] = x44; + out[3] = x43; + }}}}}}}}}}}}}}}}}}}}} +} + +// fe_op sets out = -in +static void fe_opp(uint64_t out[4], const uint64_t in1[4]) { + const uint64_t x5 = in1[3]; + const uint64_t x6 = in1[2]; + const uint64_t x4 = in1[1]; + const uint64_t x2 = in1[0]; + uint64_t x8; uint8_t x9 = subborrow_u64(0x0, 0x0, x2, &x8); + uint64_t x11; uint8_t x12 = subborrow_u64(x9, 0x0, x4, &x11); + uint64_t x14; uint8_t x15 = subborrow_u64(x12, 0x0, x6, &x14); + uint64_t x17; uint8_t x18 = subborrow_u64(x15, 0x0, x5, &x17); + uint64_t x19 = (uint64_t)cmovznz_u64(x18, 0x0, 0xffffffffffffffffL); + uint64_t x20 = (x19 & 0xffffffffffffffffL); + uint64_t x22; uint8_t x23 = addcarryx_u64(0x0, x8, x20, &x22); + uint64_t x24 = (x19 & 0xffffffff); + uint64_t x26; uint8_t x27 = addcarryx_u64(x23, x11, x24, &x26); + uint64_t x29; uint8_t x30 = addcarryx_u64(x27, x14, 0x0, &x29); + uint64_t x31 = (x19 & 0xffffffff00000001L); + uint64_t x33; addcarryx_u64(x30, x17, x31, &x33); + out[0] = x22; + out[1] = x26; + out[2] = x29; + out[3] = x33; +} + +static void fe_mul(uint64_t out[4], const uint64_t in1[4], const uint64_t in2[4]) { + const uint64_t x8 = in1[3]; + const uint64_t x9 = in1[2]; + const uint64_t x7 = in1[1]; + const uint64_t x5 = in1[0]; + const uint64_t x14 = in2[3]; + const uint64_t x15 = in2[2]; + const uint64_t x13 = in2[1]; + const uint64_t x11 = in2[0]; + uint64_t x18; uint64_t x17 = mulx_u64(x5, x11, &x18); + uint64_t x21; uint64_t x20 = mulx_u64(x5, x13, &x21); + uint64_t x24; uint64_t x23 = mulx_u64(x5, x15, &x24); + uint64_t x27; uint64_t x26 = mulx_u64(x5, x14, &x27); + uint64_t x29; uint8_t x30 = addcarryx_u64(0x0, x18, x20, &x29); + uint64_t x32; uint8_t x33 = addcarryx_u64(x30, x21, x23, &x32); + uint64_t x35; uint8_t x36 = addcarryx_u64(x33, x24, x26, &x35); + uint64_t x38; addcarryx_u64(0x0, x36, x27, &x38); + uint64_t x42; uint64_t x41 = mulx_u64(x17, 0xffffffffffffffffL, &x42); + uint64_t x45; uint64_t x44 = mulx_u64(x17, 0xffffffff, &x45); + uint64_t x48; uint64_t x47 = mulx_u64(x17, 0xffffffff00000001L, &x48); + uint64_t x50; uint8_t x51 = addcarryx_u64(0x0, x42, x44, &x50); + uint64_t x53; uint8_t x54 = addcarryx_u64(x51, x45, 0x0, &x53); + uint64_t x56; uint8_t x57 = addcarryx_u64(x54, 0x0, x47, &x56); + uint64_t x59; addcarryx_u64(0x0, x57, x48, &x59); + uint64_t _2; uint8_t x63 = addcarryx_u64(0x0, x17, x41, &_2); + uint64_t x65; uint8_t x66 = addcarryx_u64(x63, x29, x50, &x65); + uint64_t x68; uint8_t x69 = addcarryx_u64(x66, x32, x53, &x68); + uint64_t x71; uint8_t x72 = addcarryx_u64(x69, x35, x56, &x71); + uint64_t x74; uint8_t x75 = addcarryx_u64(x72, x38, x59, &x74); + uint64_t x78; uint64_t x77 = mulx_u64(x7, x11, &x78); + uint64_t x81; uint64_t x80 = mulx_u64(x7, x13, &x81); + uint64_t x84; uint64_t x83 = mulx_u64(x7, x15, &x84); + uint64_t x87; uint64_t x86 = mulx_u64(x7, x14, &x87); + uint64_t x89; uint8_t x90 = addcarryx_u64(0x0, x78, x80, &x89); + uint64_t x92; uint8_t x93 = addcarryx_u64(x90, x81, x83, &x92); + uint64_t x95; uint8_t x96 = addcarryx_u64(x93, x84, x86, &x95); + uint64_t x98; addcarryx_u64(0x0, x96, x87, &x98); + uint64_t x101; uint8_t x102 = addcarryx_u64(0x0, x65, x77, &x101); + uint64_t x104; uint8_t x105 = addcarryx_u64(x102, x68, x89, &x104); + uint64_t x107; uint8_t x108 = addcarryx_u64(x105, x71, x92, &x107); + uint64_t x110; uint8_t x111 = addcarryx_u64(x108, x74, x95, &x110); + uint64_t x113; uint8_t x114 = addcarryx_u64(x111, x75, x98, &x113); + uint64_t x117; uint64_t x116 = mulx_u64(x101, 0xffffffffffffffffL, &x117); + uint64_t x120; uint64_t x119 = mulx_u64(x101, 0xffffffff, &x120); + uint64_t x123; uint64_t x122 = mulx_u64(x101, 0xffffffff00000001L, &x123); + uint64_t x125; uint8_t x126 = addcarryx_u64(0x0, x117, x119, &x125); + uint64_t x128; uint8_t x129 = addcarryx_u64(x126, x120, 0x0, &x128); + uint64_t x131; uint8_t x132 = addcarryx_u64(x129, 0x0, x122, &x131); + uint64_t x134; addcarryx_u64(0x0, x132, x123, &x134); + uint64_t _3; uint8_t x138 = addcarryx_u64(0x0, x101, x116, &_3); + uint64_t x140; uint8_t x141 = addcarryx_u64(x138, x104, x125, &x140); + uint64_t x143; uint8_t x144 = addcarryx_u64(x141, x107, x128, &x143); + uint64_t x146; uint8_t x147 = addcarryx_u64(x144, x110, x131, &x146); + uint64_t x149; uint8_t x150 = addcarryx_u64(x147, x113, x134, &x149); + uint8_t x151 = (x150 + x114); + uint64_t x154; uint64_t x153 = mulx_u64(x9, x11, &x154); + uint64_t x157; uint64_t x156 = mulx_u64(x9, x13, &x157); + uint64_t x160; uint64_t x159 = mulx_u64(x9, x15, &x160); + uint64_t x163; uint64_t x162 = mulx_u64(x9, x14, &x163); + uint64_t x165; uint8_t x166 = addcarryx_u64(0x0, x154, x156, &x165); + uint64_t x168; uint8_t x169 = addcarryx_u64(x166, x157, x159, &x168); + uint64_t x171; uint8_t x172 = addcarryx_u64(x169, x160, x162, &x171); + uint64_t x174; addcarryx_u64(0x0, x172, x163, &x174); + uint64_t x177; uint8_t x178 = addcarryx_u64(0x0, x140, x153, &x177); + uint64_t x180; uint8_t x181 = addcarryx_u64(x178, x143, x165, &x180); + uint64_t x183; uint8_t x184 = addcarryx_u64(x181, x146, x168, &x183); + uint64_t x186; uint8_t x187 = addcarryx_u64(x184, x149, x171, &x186); + uint64_t x189; uint8_t x190 = addcarryx_u64(x187, x151, x174, &x189); + uint64_t x193; uint64_t x192 = mulx_u64(x177, 0xffffffffffffffffL, &x193); + uint64_t x196; uint64_t x195 = mulx_u64(x177, 0xffffffff, &x196); + uint64_t x199; uint64_t x198 = mulx_u64(x177, 0xffffffff00000001L, &x199); + uint64_t x201; uint8_t x202 = addcarryx_u64(0x0, x193, x195, &x201); + uint64_t x204; uint8_t x205 = addcarryx_u64(x202, x196, 0x0, &x204); + uint64_t x207; uint8_t x208 = addcarryx_u64(x205, 0x0, x198, &x207); + uint64_t x210; addcarryx_u64(0x0, x208, x199, &x210); + uint64_t _4; uint8_t x214 = addcarryx_u64(0x0, x177, x192, &_4); + uint64_t x216; uint8_t x217 = addcarryx_u64(x214, x180, x201, &x216); + uint64_t x219; uint8_t x220 = addcarryx_u64(x217, x183, x204, &x219); + uint64_t x222; uint8_t x223 = addcarryx_u64(x220, x186, x207, &x222); + uint64_t x225; uint8_t x226 = addcarryx_u64(x223, x189, x210, &x225); + uint8_t x227 = (x226 + x190); + uint64_t x230; uint64_t x229 = mulx_u64(x8, x11, &x230); + uint64_t x233; uint64_t x232 = mulx_u64(x8, x13, &x233); + uint64_t x236; uint64_t x235 = mulx_u64(x8, x15, &x236); + uint64_t x239; uint64_t x238 = mulx_u64(x8, x14, &x239); + uint64_t x241; uint8_t x242 = addcarryx_u64(0x0, x230, x232, &x241); + uint64_t x244; uint8_t x245 = addcarryx_u64(x242, x233, x235, &x244); + uint64_t x247; uint8_t x248 = addcarryx_u64(x245, x236, x238, &x247); + uint64_t x250; addcarryx_u64(0x0, x248, x239, &x250); + uint64_t x253; uint8_t x254 = addcarryx_u64(0x0, x216, x229, &x253); + uint64_t x256; uint8_t x257 = addcarryx_u64(x254, x219, x241, &x256); + uint64_t x259; uint8_t x260 = addcarryx_u64(x257, x222, x244, &x259); + uint64_t x262; uint8_t x263 = addcarryx_u64(x260, x225, x247, &x262); + uint64_t x265; uint8_t x266 = addcarryx_u64(x263, x227, x250, &x265); + uint64_t x269; uint64_t x268 = mulx_u64(x253, 0xffffffffffffffffL, &x269); + uint64_t x272; uint64_t x271 = mulx_u64(x253, 0xffffffff, &x272); + uint64_t x275; uint64_t x274 = mulx_u64(x253, 0xffffffff00000001L, &x275); + uint64_t x277; uint8_t x278 = addcarryx_u64(0x0, x269, x271, &x277); + uint64_t x280; uint8_t x281 = addcarryx_u64(x278, x272, 0x0, &x280); + uint64_t x283; uint8_t x284 = addcarryx_u64(x281, 0x0, x274, &x283); + uint64_t x286; addcarryx_u64(0x0, x284, x275, &x286); + uint64_t _5; uint8_t x290 = addcarryx_u64(0x0, x253, x268, &_5); + uint64_t x292; uint8_t x293 = addcarryx_u64(x290, x256, x277, &x292); + uint64_t x295; uint8_t x296 = addcarryx_u64(x293, x259, x280, &x295); + uint64_t x298; uint8_t x299 = addcarryx_u64(x296, x262, x283, &x298); + uint64_t x301; uint8_t x302 = addcarryx_u64(x299, x265, x286, &x301); + uint8_t x303 = (x302 + x266); + uint64_t x305; uint8_t x306 = subborrow_u64(0x0, x292, 0xffffffffffffffffL, &x305); + uint64_t x308; uint8_t x309 = subborrow_u64(x306, x295, 0xffffffff, &x308); + uint64_t x311; uint8_t x312 = subborrow_u64(x309, x298, 0x0, &x311); + uint64_t x314; uint8_t x315 = subborrow_u64(x312, x301, 0xffffffff00000001L, &x314); + uint64_t _6; uint8_t x318 = subborrow_u64(x315, x303, 0x0, &_6); + uint64_t x319 = cmovznz_u64(x318, x314, x301); + uint64_t x320 = cmovznz_u64(x318, x311, x298); + uint64_t x321 = cmovznz_u64(x318, x308, x295); + uint64_t x322 = cmovznz_u64(x318, x305, x292); + out[0] = x322; + out[1] = x321; + out[2] = x320; + out[3] = x319; +} + +static void fe_sub(uint64_t out[4], const uint64_t in1[4], const uint64_t in2[4]) { + const uint64_t x8 = in1[3]; + const uint64_t x9 = in1[2]; + const uint64_t x7 = in1[1]; + const uint64_t x5 = in1[0]; + const uint64_t x14 = in2[3]; + const uint64_t x15 = in2[2]; + const uint64_t x13 = in2[1]; + const uint64_t x11 = in2[0]; + uint64_t x17; uint8_t x18 = subborrow_u64(0x0, x5, x11, &x17); + uint64_t x20; uint8_t x21 = subborrow_u64(x18, x7, x13, &x20); + uint64_t x23; uint8_t x24 = subborrow_u64(x21, x9, x15, &x23); + uint64_t x26; uint8_t x27 = subborrow_u64(x24, x8, x14, &x26); + uint64_t x28 = (uint64_t)cmovznz_u64(x27, 0x0, 0xffffffffffffffffL); + uint64_t x29 = (x28 & 0xffffffffffffffffL); + uint64_t x31; uint8_t x32 = addcarryx_u64(0x0, x17, x29, &x31); + uint64_t x33 = (x28 & 0xffffffff); + uint64_t x35; uint8_t x36 = addcarryx_u64(x32, x20, x33, &x35); + uint64_t x38; uint8_t x39 = addcarryx_u64(x36, x23, 0x0, &x38); + uint64_t x40 = (x28 & 0xffffffff00000001L); + uint64_t x42; addcarryx_u64(x39, x26, x40, &x42); + out[0] = x31; + out[1] = x35; + out[2] = x38; + out[3] = x42; +} + +#else // 64BIT, else 32BIT + +static void fe_add(uint32_t out[8], const uint32_t in1[8], const uint32_t in2[8]) { + const uint32_t x16 = in1[7]; + const uint32_t x17 = in1[6]; + const uint32_t x15 = in1[5]; + const uint32_t x13 = in1[4]; + const uint32_t x11 = in1[3]; + const uint32_t x9 = in1[2]; + const uint32_t x7 = in1[1]; + const uint32_t x5 = in1[0]; + const uint32_t x30 = in2[7]; + const uint32_t x31 = in2[6]; + const uint32_t x29 = in2[5]; + const uint32_t x27 = in2[4]; + const uint32_t x25 = in2[3]; + const uint32_t x23 = in2[2]; + const uint32_t x21 = in2[1]; + const uint32_t x19 = in2[0]; + uint32_t x33; uint8_t x34 = addcarryx_u32(0x0, x5, x19, &x33); + uint32_t x36; uint8_t x37 = addcarryx_u32(x34, x7, x21, &x36); + uint32_t x39; uint8_t x40 = addcarryx_u32(x37, x9, x23, &x39); + uint32_t x42; uint8_t x43 = addcarryx_u32(x40, x11, x25, &x42); + uint32_t x45; uint8_t x46 = addcarryx_u32(x43, x13, x27, &x45); + uint32_t x48; uint8_t x49 = addcarryx_u32(x46, x15, x29, &x48); + uint32_t x51; uint8_t x52 = addcarryx_u32(x49, x17, x31, &x51); + uint32_t x54; uint8_t x55 = addcarryx_u32(x52, x16, x30, &x54); + uint32_t x57; uint8_t x58 = subborrow_u32(0x0, x33, 0xffffffff, &x57); + uint32_t x60; uint8_t x61 = subborrow_u32(x58, x36, 0xffffffff, &x60); + uint32_t x63; uint8_t x64 = subborrow_u32(x61, x39, 0xffffffff, &x63); + uint32_t x66; uint8_t x67 = subborrow_u32(x64, x42, 0x0, &x66); + uint32_t x69; uint8_t x70 = subborrow_u32(x67, x45, 0x0, &x69); + uint32_t x72; uint8_t x73 = subborrow_u32(x70, x48, 0x0, &x72); + uint32_t x75; uint8_t x76 = subborrow_u32(x73, x51, 0x1, &x75); + uint32_t x78; uint8_t x79 = subborrow_u32(x76, x54, 0xffffffff, &x78); + uint32_t _; uint8_t x82 = subborrow_u32(x79, x55, 0x0, &_); + uint32_t x83 = cmovznz_u32(x82, x78, x54); + uint32_t x84 = cmovznz_u32(x82, x75, x51); + uint32_t x85 = cmovznz_u32(x82, x72, x48); + uint32_t x86 = cmovznz_u32(x82, x69, x45); + uint32_t x87 = cmovznz_u32(x82, x66, x42); + uint32_t x88 = cmovznz_u32(x82, x63, x39); + uint32_t x89 = cmovznz_u32(x82, x60, x36); + uint32_t x90 = cmovznz_u32(x82, x57, x33); + out[0] = x90; + out[1] = x89; + out[2] = x88; + out[3] = x87; + out[4] = x86; + out[5] = x85; + out[6] = x84; + out[7] = x83; +} + +static void fe_mul(uint32_t out[8], const uint32_t in1[8], const uint32_t in2[8]) { + const uint32_t x16 = in1[7]; + const uint32_t x17 = in1[6]; + const uint32_t x15 = in1[5]; + const uint32_t x13 = in1[4]; + const uint32_t x11 = in1[3]; + const uint32_t x9 = in1[2]; + const uint32_t x7 = in1[1]; + const uint32_t x5 = in1[0]; + const uint32_t x30 = in2[7]; + const uint32_t x31 = in2[6]; + const uint32_t x29 = in2[5]; + const uint32_t x27 = in2[4]; + const uint32_t x25 = in2[3]; + const uint32_t x23 = in2[2]; + const uint32_t x21 = in2[1]; + const uint32_t x19 = in2[0]; + uint32_t x34; uint32_t x33 = mulx_u32(x5, x19, &x34); + uint32_t x37; uint32_t x36 = mulx_u32(x5, x21, &x37); + uint32_t x40; uint32_t x39 = mulx_u32(x5, x23, &x40); + uint32_t x43; uint32_t x42 = mulx_u32(x5, x25, &x43); + uint32_t x46; uint32_t x45 = mulx_u32(x5, x27, &x46); + uint32_t x49; uint32_t x48 = mulx_u32(x5, x29, &x49); + uint32_t x52; uint32_t x51 = mulx_u32(x5, x31, &x52); + uint32_t x55; uint32_t x54 = mulx_u32(x5, x30, &x55); + uint32_t x57; uint8_t x58 = addcarryx_u32(0x0, x34, x36, &x57); + uint32_t x60; uint8_t x61 = addcarryx_u32(x58, x37, x39, &x60); + uint32_t x63; uint8_t x64 = addcarryx_u32(x61, x40, x42, &x63); + uint32_t x66; uint8_t x67 = addcarryx_u32(x64, x43, x45, &x66); + uint32_t x69; uint8_t x70 = addcarryx_u32(x67, x46, x48, &x69); + uint32_t x72; uint8_t x73 = addcarryx_u32(x70, x49, x51, &x72); + uint32_t x75; uint8_t x76 = addcarryx_u32(x73, x52, x54, &x75); + uint32_t x78; addcarryx_u32(0x0, x76, x55, &x78); + uint32_t x82; uint32_t x81 = mulx_u32(x33, 0xffffffff, &x82); + uint32_t x85; uint32_t x84 = mulx_u32(x33, 0xffffffff, &x85); + uint32_t x88; uint32_t x87 = mulx_u32(x33, 0xffffffff, &x88); + uint32_t x91; uint32_t x90 = mulx_u32(x33, 0xffffffff, &x91); + uint32_t x93; uint8_t x94 = addcarryx_u32(0x0, x82, x84, &x93); + uint32_t x96; uint8_t x97 = addcarryx_u32(x94, x85, x87, &x96); + uint32_t x99; uint8_t x100 = addcarryx_u32(x97, x88, 0x0, &x99); + uint8_t x101 = (0x0 + 0x0); + uint32_t _1; uint8_t x104 = addcarryx_u32(0x0, x33, x81, &_1); + uint32_t x106; uint8_t x107 = addcarryx_u32(x104, x57, x93, &x106); + uint32_t x109; uint8_t x110 = addcarryx_u32(x107, x60, x96, &x109); + uint32_t x112; uint8_t x113 = addcarryx_u32(x110, x63, x99, &x112); + uint32_t x115; uint8_t x116 = addcarryx_u32(x113, x66, x100, &x115); + uint32_t x118; uint8_t x119 = addcarryx_u32(x116, x69, x101, &x118); + uint32_t x121; uint8_t x122 = addcarryx_u32(x119, x72, x33, &x121); + uint32_t x124; uint8_t x125 = addcarryx_u32(x122, x75, x90, &x124); + uint32_t x127; uint8_t x128 = addcarryx_u32(x125, x78, x91, &x127); + uint8_t x129 = (x128 + 0x0); + uint32_t x132; uint32_t x131 = mulx_u32(x7, x19, &x132); + uint32_t x135; uint32_t x134 = mulx_u32(x7, x21, &x135); + uint32_t x138; uint32_t x137 = mulx_u32(x7, x23, &x138); + uint32_t x141; uint32_t x140 = mulx_u32(x7, x25, &x141); + uint32_t x144; uint32_t x143 = mulx_u32(x7, x27, &x144); + uint32_t x147; uint32_t x146 = mulx_u32(x7, x29, &x147); + uint32_t x150; uint32_t x149 = mulx_u32(x7, x31, &x150); + uint32_t x153; uint32_t x152 = mulx_u32(x7, x30, &x153); + uint32_t x155; uint8_t x156 = addcarryx_u32(0x0, x132, x134, &x155); + uint32_t x158; uint8_t x159 = addcarryx_u32(x156, x135, x137, &x158); + uint32_t x161; uint8_t x162 = addcarryx_u32(x159, x138, x140, &x161); + uint32_t x164; uint8_t x165 = addcarryx_u32(x162, x141, x143, &x164); + uint32_t x167; uint8_t x168 = addcarryx_u32(x165, x144, x146, &x167); + uint32_t x170; uint8_t x171 = addcarryx_u32(x168, x147, x149, &x170); + uint32_t x173; uint8_t x174 = addcarryx_u32(x171, x150, x152, &x173); + uint32_t x176; addcarryx_u32(0x0, x174, x153, &x176); + uint32_t x179; uint8_t x180 = addcarryx_u32(0x0, x106, x131, &x179); + uint32_t x182; uint8_t x183 = addcarryx_u32(x180, x109, x155, &x182); + uint32_t x185; uint8_t x186 = addcarryx_u32(x183, x112, x158, &x185); + uint32_t x188; uint8_t x189 = addcarryx_u32(x186, x115, x161, &x188); + uint32_t x191; uint8_t x192 = addcarryx_u32(x189, x118, x164, &x191); + uint32_t x194; uint8_t x195 = addcarryx_u32(x192, x121, x167, &x194); + uint32_t x197; uint8_t x198 = addcarryx_u32(x195, x124, x170, &x197); + uint32_t x200; uint8_t x201 = addcarryx_u32(x198, x127, x173, &x200); + uint32_t x203; uint8_t x204 = addcarryx_u32(x201, x129, x176, &x203); + uint32_t x207; uint32_t x206 = mulx_u32(x179, 0xffffffff, &x207); + uint32_t x210; uint32_t x209 = mulx_u32(x179, 0xffffffff, &x210); + uint32_t x213; uint32_t x212 = mulx_u32(x179, 0xffffffff, &x213); + uint32_t x216; uint32_t x215 = mulx_u32(x179, 0xffffffff, &x216); + uint32_t x218; uint8_t x219 = addcarryx_u32(0x0, x207, x209, &x218); + uint32_t x221; uint8_t x222 = addcarryx_u32(x219, x210, x212, &x221); + uint32_t x224; uint8_t x225 = addcarryx_u32(x222, x213, 0x0, &x224); + uint8_t x226 = (0x0 + 0x0); + uint32_t _2; uint8_t x229 = addcarryx_u32(0x0, x179, x206, &_2); + uint32_t x231; uint8_t x232 = addcarryx_u32(x229, x182, x218, &x231); + uint32_t x234; uint8_t x235 = addcarryx_u32(x232, x185, x221, &x234); + uint32_t x237; uint8_t x238 = addcarryx_u32(x235, x188, x224, &x237); + uint32_t x240; uint8_t x241 = addcarryx_u32(x238, x191, x225, &x240); + uint32_t x243; uint8_t x244 = addcarryx_u32(x241, x194, x226, &x243); + uint32_t x246; uint8_t x247 = addcarryx_u32(x244, x197, x179, &x246); + uint32_t x249; uint8_t x250 = addcarryx_u32(x247, x200, x215, &x249); + uint32_t x252; uint8_t x253 = addcarryx_u32(x250, x203, x216, &x252); + uint8_t x254 = (x253 + x204); + uint32_t x257; uint32_t x256 = mulx_u32(x9, x19, &x257); + uint32_t x260; uint32_t x259 = mulx_u32(x9, x21, &x260); + uint32_t x263; uint32_t x262 = mulx_u32(x9, x23, &x263); + uint32_t x266; uint32_t x265 = mulx_u32(x9, x25, &x266); + uint32_t x269; uint32_t x268 = mulx_u32(x9, x27, &x269); + uint32_t x272; uint32_t x271 = mulx_u32(x9, x29, &x272); + uint32_t x275; uint32_t x274 = mulx_u32(x9, x31, &x275); + uint32_t x278; uint32_t x277 = mulx_u32(x9, x30, &x278); + uint32_t x280; uint8_t x281 = addcarryx_u32(0x0, x257, x259, &x280); + uint32_t x283; uint8_t x284 = addcarryx_u32(x281, x260, x262, &x283); + uint32_t x286; uint8_t x287 = addcarryx_u32(x284, x263, x265, &x286); + uint32_t x289; uint8_t x290 = addcarryx_u32(x287, x266, x268, &x289); + uint32_t x292; uint8_t x293 = addcarryx_u32(x290, x269, x271, &x292); + uint32_t x295; uint8_t x296 = addcarryx_u32(x293, x272, x274, &x295); + uint32_t x298; uint8_t x299 = addcarryx_u32(x296, x275, x277, &x298); + uint32_t x301; addcarryx_u32(0x0, x299, x278, &x301); + uint32_t x304; uint8_t x305 = addcarryx_u32(0x0, x231, x256, &x304); + uint32_t x307; uint8_t x308 = addcarryx_u32(x305, x234, x280, &x307); + uint32_t x310; uint8_t x311 = addcarryx_u32(x308, x237, x283, &x310); + uint32_t x313; uint8_t x314 = addcarryx_u32(x311, x240, x286, &x313); + uint32_t x316; uint8_t x317 = addcarryx_u32(x314, x243, x289, &x316); + uint32_t x319; uint8_t x320 = addcarryx_u32(x317, x246, x292, &x319); + uint32_t x322; uint8_t x323 = addcarryx_u32(x320, x249, x295, &x322); + uint32_t x325; uint8_t x326 = addcarryx_u32(x323, x252, x298, &x325); + uint32_t x328; uint8_t x329 = addcarryx_u32(x326, x254, x301, &x328); + uint32_t x332; uint32_t x331 = mulx_u32(x304, 0xffffffff, &x332); + uint32_t x335; uint32_t x334 = mulx_u32(x304, 0xffffffff, &x335); + uint32_t x338; uint32_t x337 = mulx_u32(x304, 0xffffffff, &x338); + uint32_t x341; uint32_t x340 = mulx_u32(x304, 0xffffffff, &x341); + uint32_t x343; uint8_t x344 = addcarryx_u32(0x0, x332, x334, &x343); + uint32_t x346; uint8_t x347 = addcarryx_u32(x344, x335, x337, &x346); + uint32_t x349; uint8_t x350 = addcarryx_u32(x347, x338, 0x0, &x349); + uint8_t x351 = (0x0 + 0x0); + uint32_t _3; uint8_t x354 = addcarryx_u32(0x0, x304, x331, &_3); + uint32_t x356; uint8_t x357 = addcarryx_u32(x354, x307, x343, &x356); + uint32_t x359; uint8_t x360 = addcarryx_u32(x357, x310, x346, &x359); + uint32_t x362; uint8_t x363 = addcarryx_u32(x360, x313, x349, &x362); + uint32_t x365; uint8_t x366 = addcarryx_u32(x363, x316, x350, &x365); + uint32_t x368; uint8_t x369 = addcarryx_u32(x366, x319, x351, &x368); + uint32_t x371; uint8_t x372 = addcarryx_u32(x369, x322, x304, &x371); + uint32_t x374; uint8_t x375 = addcarryx_u32(x372, x325, x340, &x374); + uint32_t x377; uint8_t x378 = addcarryx_u32(x375, x328, x341, &x377); + uint8_t x379 = (x378 + x329); + uint32_t x382; uint32_t x381 = mulx_u32(x11, x19, &x382); + uint32_t x385; uint32_t x384 = mulx_u32(x11, x21, &x385); + uint32_t x388; uint32_t x387 = mulx_u32(x11, x23, &x388); + uint32_t x391; uint32_t x390 = mulx_u32(x11, x25, &x391); + uint32_t x394; uint32_t x393 = mulx_u32(x11, x27, &x394); + uint32_t x397; uint32_t x396 = mulx_u32(x11, x29, &x397); + uint32_t x400; uint32_t x399 = mulx_u32(x11, x31, &x400); + uint32_t x403; uint32_t x402 = mulx_u32(x11, x30, &x403); + uint32_t x405; uint8_t x406 = addcarryx_u32(0x0, x382, x384, &x405); + uint32_t x408; uint8_t x409 = addcarryx_u32(x406, x385, x387, &x408); + uint32_t x411; uint8_t x412 = addcarryx_u32(x409, x388, x390, &x411); + uint32_t x414; uint8_t x415 = addcarryx_u32(x412, x391, x393, &x414); + uint32_t x417; uint8_t x418 = addcarryx_u32(x415, x394, x396, &x417); + uint32_t x420; uint8_t x421 = addcarryx_u32(x418, x397, x399, &x420); + uint32_t x423; uint8_t x424 = addcarryx_u32(x421, x400, x402, &x423); + uint32_t x426; addcarryx_u32(0x0, x424, x403, &x426); + uint32_t x429; uint8_t x430 = addcarryx_u32(0x0, x356, x381, &x429); + uint32_t x432; uint8_t x433 = addcarryx_u32(x430, x359, x405, &x432); + uint32_t x435; uint8_t x436 = addcarryx_u32(x433, x362, x408, &x435); + uint32_t x438; uint8_t x439 = addcarryx_u32(x436, x365, x411, &x438); + uint32_t x441; uint8_t x442 = addcarryx_u32(x439, x368, x414, &x441); + uint32_t x444; uint8_t x445 = addcarryx_u32(x442, x371, x417, &x444); + uint32_t x447; uint8_t x448 = addcarryx_u32(x445, x374, x420, &x447); + uint32_t x450; uint8_t x451 = addcarryx_u32(x448, x377, x423, &x450); + uint32_t x453; uint8_t x454 = addcarryx_u32(x451, x379, x426, &x453); + uint32_t x457; uint32_t x456 = mulx_u32(x429, 0xffffffff, &x457); + uint32_t x460; uint32_t x459 = mulx_u32(x429, 0xffffffff, &x460); + uint32_t x463; uint32_t x462 = mulx_u32(x429, 0xffffffff, &x463); + uint32_t x466; uint32_t x465 = mulx_u32(x429, 0xffffffff, &x466); + uint32_t x468; uint8_t x469 = addcarryx_u32(0x0, x457, x459, &x468); + uint32_t x471; uint8_t x472 = addcarryx_u32(x469, x460, x462, &x471); + uint32_t x474; uint8_t x475 = addcarryx_u32(x472, x463, 0x0, &x474); + uint8_t x476 = (0x0 + 0x0); + uint32_t _4; uint8_t x479 = addcarryx_u32(0x0, x429, x456, &_4); + uint32_t x481; uint8_t x482 = addcarryx_u32(x479, x432, x468, &x481); + uint32_t x484; uint8_t x485 = addcarryx_u32(x482, x435, x471, &x484); + uint32_t x487; uint8_t x488 = addcarryx_u32(x485, x438, x474, &x487); + uint32_t x490; uint8_t x491 = addcarryx_u32(x488, x441, x475, &x490); + uint32_t x493; uint8_t x494 = addcarryx_u32(x491, x444, x476, &x493); + uint32_t x496; uint8_t x497 = addcarryx_u32(x494, x447, x429, &x496); + uint32_t x499; uint8_t x500 = addcarryx_u32(x497, x450, x465, &x499); + uint32_t x502; uint8_t x503 = addcarryx_u32(x500, x453, x466, &x502); + uint8_t x504 = (x503 + x454); + uint32_t x507; uint32_t x506 = mulx_u32(x13, x19, &x507); + uint32_t x510; uint32_t x509 = mulx_u32(x13, x21, &x510); + uint32_t x513; uint32_t x512 = mulx_u32(x13, x23, &x513); + uint32_t x516; uint32_t x515 = mulx_u32(x13, x25, &x516); + uint32_t x519; uint32_t x518 = mulx_u32(x13, x27, &x519); + uint32_t x522; uint32_t x521 = mulx_u32(x13, x29, &x522); + uint32_t x525; uint32_t x524 = mulx_u32(x13, x31, &x525); + uint32_t x528; uint32_t x527 = mulx_u32(x13, x30, &x528); + uint32_t x530; uint8_t x531 = addcarryx_u32(0x0, x507, x509, &x530); + uint32_t x533; uint8_t x534 = addcarryx_u32(x531, x510, x512, &x533); + uint32_t x536; uint8_t x537 = addcarryx_u32(x534, x513, x515, &x536); + uint32_t x539; uint8_t x540 = addcarryx_u32(x537, x516, x518, &x539); + uint32_t x542; uint8_t x543 = addcarryx_u32(x540, x519, x521, &x542); + uint32_t x545; uint8_t x546 = addcarryx_u32(x543, x522, x524, &x545); + uint32_t x548; uint8_t x549 = addcarryx_u32(x546, x525, x527, &x548); + uint32_t x551; addcarryx_u32(0x0, x549, x528, &x551); + uint32_t x554; uint8_t x555 = addcarryx_u32(0x0, x481, x506, &x554); + uint32_t x557; uint8_t x558 = addcarryx_u32(x555, x484, x530, &x557); + uint32_t x560; uint8_t x561 = addcarryx_u32(x558, x487, x533, &x560); + uint32_t x563; uint8_t x564 = addcarryx_u32(x561, x490, x536, &x563); + uint32_t x566; uint8_t x567 = addcarryx_u32(x564, x493, x539, &x566); + uint32_t x569; uint8_t x570 = addcarryx_u32(x567, x496, x542, &x569); + uint32_t x572; uint8_t x573 = addcarryx_u32(x570, x499, x545, &x572); + uint32_t x575; uint8_t x576 = addcarryx_u32(x573, x502, x548, &x575); + uint32_t x578; uint8_t x579 = addcarryx_u32(x576, x504, x551, &x578); + uint32_t x582; uint32_t x581 = mulx_u32(x554, 0xffffffff, &x582); + uint32_t x585; uint32_t x584 = mulx_u32(x554, 0xffffffff, &x585); + uint32_t x588; uint32_t x587 = mulx_u32(x554, 0xffffffff, &x588); + uint32_t x591; uint32_t x590 = mulx_u32(x554, 0xffffffff, &x591); + uint32_t x593; uint8_t x594 = addcarryx_u32(0x0, x582, x584, &x593); + uint32_t x596; uint8_t x597 = addcarryx_u32(x594, x585, x587, &x596); + uint32_t x599; uint8_t x600 = addcarryx_u32(x597, x588, 0x0, &x599); + uint8_t x601 = (0x0 + 0x0); + uint32_t _5; uint8_t x604 = addcarryx_u32(0x0, x554, x581, &_5); + uint32_t x606; uint8_t x607 = addcarryx_u32(x604, x557, x593, &x606); + uint32_t x609; uint8_t x610 = addcarryx_u32(x607, x560, x596, &x609); + uint32_t x612; uint8_t x613 = addcarryx_u32(x610, x563, x599, &x612); + uint32_t x615; uint8_t x616 = addcarryx_u32(x613, x566, x600, &x615); + uint32_t x618; uint8_t x619 = addcarryx_u32(x616, x569, x601, &x618); + uint32_t x621; uint8_t x622 = addcarryx_u32(x619, x572, x554, &x621); + uint32_t x624; uint8_t x625 = addcarryx_u32(x622, x575, x590, &x624); + uint32_t x627; uint8_t x628 = addcarryx_u32(x625, x578, x591, &x627); + uint8_t x629 = (x628 + x579); + uint32_t x632; uint32_t x631 = mulx_u32(x15, x19, &x632); + uint32_t x635; uint32_t x634 = mulx_u32(x15, x21, &x635); + uint32_t x638; uint32_t x637 = mulx_u32(x15, x23, &x638); + uint32_t x641; uint32_t x640 = mulx_u32(x15, x25, &x641); + uint32_t x644; uint32_t x643 = mulx_u32(x15, x27, &x644); + uint32_t x647; uint32_t x646 = mulx_u32(x15, x29, &x647); + uint32_t x650; uint32_t x649 = mulx_u32(x15, x31, &x650); + uint32_t x653; uint32_t x652 = mulx_u32(x15, x30, &x653); + uint32_t x655; uint8_t x656 = addcarryx_u32(0x0, x632, x634, &x655); + uint32_t x658; uint8_t x659 = addcarryx_u32(x656, x635, x637, &x658); + uint32_t x661; uint8_t x662 = addcarryx_u32(x659, x638, x640, &x661); + uint32_t x664; uint8_t x665 = addcarryx_u32(x662, x641, x643, &x664); + uint32_t x667; uint8_t x668 = addcarryx_u32(x665, x644, x646, &x667); + uint32_t x670; uint8_t x671 = addcarryx_u32(x668, x647, x649, &x670); + uint32_t x673; uint8_t x674 = addcarryx_u32(x671, x650, x652, &x673); + uint32_t x676; addcarryx_u32(0x0, x674, x653, &x676); + uint32_t x679; uint8_t x680 = addcarryx_u32(0x0, x606, x631, &x679); + uint32_t x682; uint8_t x683 = addcarryx_u32(x680, x609, x655, &x682); + uint32_t x685; uint8_t x686 = addcarryx_u32(x683, x612, x658, &x685); + uint32_t x688; uint8_t x689 = addcarryx_u32(x686, x615, x661, &x688); + uint32_t x691; uint8_t x692 = addcarryx_u32(x689, x618, x664, &x691); + uint32_t x694; uint8_t x695 = addcarryx_u32(x692, x621, x667, &x694); + uint32_t x697; uint8_t x698 = addcarryx_u32(x695, x624, x670, &x697); + uint32_t x700; uint8_t x701 = addcarryx_u32(x698, x627, x673, &x700); + uint32_t x703; uint8_t x704 = addcarryx_u32(x701, x629, x676, &x703); + uint32_t x707; uint32_t x706 = mulx_u32(x679, 0xffffffff, &x707); + uint32_t x710; uint32_t x709 = mulx_u32(x679, 0xffffffff, &x710); + uint32_t x713; uint32_t x712 = mulx_u32(x679, 0xffffffff, &x713); + uint32_t x716; uint32_t x715 = mulx_u32(x679, 0xffffffff, &x716); + uint32_t x718; uint8_t x719 = addcarryx_u32(0x0, x707, x709, &x718); + uint32_t x721; uint8_t x722 = addcarryx_u32(x719, x710, x712, &x721); + uint32_t x724; uint8_t x725 = addcarryx_u32(x722, x713, 0x0, &x724); + uint8_t x726 = (0x0 + 0x0); + uint32_t _6; uint8_t x729 = addcarryx_u32(0x0, x679, x706, &_6); + uint32_t x731; uint8_t x732 = addcarryx_u32(x729, x682, x718, &x731); + uint32_t x734; uint8_t x735 = addcarryx_u32(x732, x685, x721, &x734); + uint32_t x737; uint8_t x738 = addcarryx_u32(x735, x688, x724, &x737); + uint32_t x740; uint8_t x741 = addcarryx_u32(x738, x691, x725, &x740); + uint32_t x743; uint8_t x744 = addcarryx_u32(x741, x694, x726, &x743); + uint32_t x746; uint8_t x747 = addcarryx_u32(x744, x697, x679, &x746); + uint32_t x749; uint8_t x750 = addcarryx_u32(x747, x700, x715, &x749); + uint32_t x752; uint8_t x753 = addcarryx_u32(x750, x703, x716, &x752); + uint8_t x754 = (x753 + x704); + uint32_t x757; uint32_t x756 = mulx_u32(x17, x19, &x757); + uint32_t x760; uint32_t x759 = mulx_u32(x17, x21, &x760); + uint32_t x763; uint32_t x762 = mulx_u32(x17, x23, &x763); + uint32_t x766; uint32_t x765 = mulx_u32(x17, x25, &x766); + uint32_t x769; uint32_t x768 = mulx_u32(x17, x27, &x769); + uint32_t x772; uint32_t x771 = mulx_u32(x17, x29, &x772); + uint32_t x775; uint32_t x774 = mulx_u32(x17, x31, &x775); + uint32_t x778; uint32_t x777 = mulx_u32(x17, x30, &x778); + uint32_t x780; uint8_t x781 = addcarryx_u32(0x0, x757, x759, &x780); + uint32_t x783; uint8_t x784 = addcarryx_u32(x781, x760, x762, &x783); + uint32_t x786; uint8_t x787 = addcarryx_u32(x784, x763, x765, &x786); + uint32_t x789; uint8_t x790 = addcarryx_u32(x787, x766, x768, &x789); + uint32_t x792; uint8_t x793 = addcarryx_u32(x790, x769, x771, &x792); + uint32_t x795; uint8_t x796 = addcarryx_u32(x793, x772, x774, &x795); + uint32_t x798; uint8_t x799 = addcarryx_u32(x796, x775, x777, &x798); + uint32_t x801; addcarryx_u32(0x0, x799, x778, &x801); + uint32_t x804; uint8_t x805 = addcarryx_u32(0x0, x731, x756, &x804); + uint32_t x807; uint8_t x808 = addcarryx_u32(x805, x734, x780, &x807); + uint32_t x810; uint8_t x811 = addcarryx_u32(x808, x737, x783, &x810); + uint32_t x813; uint8_t x814 = addcarryx_u32(x811, x740, x786, &x813); + uint32_t x816; uint8_t x817 = addcarryx_u32(x814, x743, x789, &x816); + uint32_t x819; uint8_t x820 = addcarryx_u32(x817, x746, x792, &x819); + uint32_t x822; uint8_t x823 = addcarryx_u32(x820, x749, x795, &x822); + uint32_t x825; uint8_t x826 = addcarryx_u32(x823, x752, x798, &x825); + uint32_t x828; uint8_t x829 = addcarryx_u32(x826, x754, x801, &x828); + uint32_t x832; uint32_t x831 = mulx_u32(x804, 0xffffffff, &x832); + uint32_t x835; uint32_t x834 = mulx_u32(x804, 0xffffffff, &x835); + uint32_t x838; uint32_t x837 = mulx_u32(x804, 0xffffffff, &x838); + uint32_t x841; uint32_t x840 = mulx_u32(x804, 0xffffffff, &x841); + uint32_t x843; uint8_t x844 = addcarryx_u32(0x0, x832, x834, &x843); + uint32_t x846; uint8_t x847 = addcarryx_u32(x844, x835, x837, &x846); + uint32_t x849; uint8_t x850 = addcarryx_u32(x847, x838, 0x0, &x849); + uint8_t x851 = (0x0 + 0x0); + uint32_t _7; uint8_t x854 = addcarryx_u32(0x0, x804, x831, &_7); + uint32_t x856; uint8_t x857 = addcarryx_u32(x854, x807, x843, &x856); + uint32_t x859; uint8_t x860 = addcarryx_u32(x857, x810, x846, &x859); + uint32_t x862; uint8_t x863 = addcarryx_u32(x860, x813, x849, &x862); + uint32_t x865; uint8_t x866 = addcarryx_u32(x863, x816, x850, &x865); + uint32_t x868; uint8_t x869 = addcarryx_u32(x866, x819, x851, &x868); + uint32_t x871; uint8_t x872 = addcarryx_u32(x869, x822, x804, &x871); + uint32_t x874; uint8_t x875 = addcarryx_u32(x872, x825, x840, &x874); + uint32_t x877; uint8_t x878 = addcarryx_u32(x875, x828, x841, &x877); + uint8_t x879 = (x878 + x829); + uint32_t x882; uint32_t x881 = mulx_u32(x16, x19, &x882); + uint32_t x885; uint32_t x884 = mulx_u32(x16, x21, &x885); + uint32_t x888; uint32_t x887 = mulx_u32(x16, x23, &x888); + uint32_t x891; uint32_t x890 = mulx_u32(x16, x25, &x891); + uint32_t x894; uint32_t x893 = mulx_u32(x16, x27, &x894); + uint32_t x897; uint32_t x896 = mulx_u32(x16, x29, &x897); + uint32_t x900; uint32_t x899 = mulx_u32(x16, x31, &x900); + uint32_t x903; uint32_t x902 = mulx_u32(x16, x30, &x903); + uint32_t x905; uint8_t x906 = addcarryx_u32(0x0, x882, x884, &x905); + uint32_t x908; uint8_t x909 = addcarryx_u32(x906, x885, x887, &x908); + uint32_t x911; uint8_t x912 = addcarryx_u32(x909, x888, x890, &x911); + uint32_t x914; uint8_t x915 = addcarryx_u32(x912, x891, x893, &x914); + uint32_t x917; uint8_t x918 = addcarryx_u32(x915, x894, x896, &x917); + uint32_t x920; uint8_t x921 = addcarryx_u32(x918, x897, x899, &x920); + uint32_t x923; uint8_t x924 = addcarryx_u32(x921, x900, x902, &x923); + uint32_t x926; addcarryx_u32(0x0, x924, x903, &x926); + uint32_t x929; uint8_t x930 = addcarryx_u32(0x0, x856, x881, &x929); + uint32_t x932; uint8_t x933 = addcarryx_u32(x930, x859, x905, &x932); + uint32_t x935; uint8_t x936 = addcarryx_u32(x933, x862, x908, &x935); + uint32_t x938; uint8_t x939 = addcarryx_u32(x936, x865, x911, &x938); + uint32_t x941; uint8_t x942 = addcarryx_u32(x939, x868, x914, &x941); + uint32_t x944; uint8_t x945 = addcarryx_u32(x942, x871, x917, &x944); + uint32_t x947; uint8_t x948 = addcarryx_u32(x945, x874, x920, &x947); + uint32_t x950; uint8_t x951 = addcarryx_u32(x948, x877, x923, &x950); + uint32_t x953; uint8_t x954 = addcarryx_u32(x951, x879, x926, &x953); + uint32_t x957; uint32_t x956 = mulx_u32(x929, 0xffffffff, &x957); + uint32_t x960; uint32_t x959 = mulx_u32(x929, 0xffffffff, &x960); + uint32_t x963; uint32_t x962 = mulx_u32(x929, 0xffffffff, &x963); + uint32_t x966; uint32_t x965 = mulx_u32(x929, 0xffffffff, &x966); + uint32_t x968; uint8_t x969 = addcarryx_u32(0x0, x957, x959, &x968); + uint32_t x971; uint8_t x972 = addcarryx_u32(x969, x960, x962, &x971); + uint32_t x974; uint8_t x975 = addcarryx_u32(x972, x963, 0x0, &x974); + uint8_t x976 = (0x0 + 0x0); + uint32_t _8; uint8_t x979 = addcarryx_u32(0x0, x929, x956, &_8); + uint32_t x981; uint8_t x982 = addcarryx_u32(x979, x932, x968, &x981); + uint32_t x984; uint8_t x985 = addcarryx_u32(x982, x935, x971, &x984); + uint32_t x987; uint8_t x988 = addcarryx_u32(x985, x938, x974, &x987); + uint32_t x990; uint8_t x991 = addcarryx_u32(x988, x941, x975, &x990); + uint32_t x993; uint8_t x994 = addcarryx_u32(x991, x944, x976, &x993); + uint32_t x996; uint8_t x997 = addcarryx_u32(x994, x947, x929, &x996); + uint32_t x999; uint8_t x1000 = addcarryx_u32(x997, x950, x965, &x999); + uint32_t x1002; uint8_t x1003 = addcarryx_u32(x1000, x953, x966, &x1002); + uint8_t x1004 = (x1003 + x954); + uint32_t x1006; uint8_t x1007 = subborrow_u32(0x0, x981, 0xffffffff, &x1006); + uint32_t x1009; uint8_t x1010 = subborrow_u32(x1007, x984, 0xffffffff, &x1009); + uint32_t x1012; uint8_t x1013 = subborrow_u32(x1010, x987, 0xffffffff, &x1012); + uint32_t x1015; uint8_t x1016 = subborrow_u32(x1013, x990, 0x0, &x1015); + uint32_t x1018; uint8_t x1019 = subborrow_u32(x1016, x993, 0x0, &x1018); + uint32_t x1021; uint8_t x1022 = subborrow_u32(x1019, x996, 0x0, &x1021); + uint32_t x1024; uint8_t x1025 = subborrow_u32(x1022, x999, 0x1, &x1024); + uint32_t x1027; uint8_t x1028 = subborrow_u32(x1025, x1002, 0xffffffff, &x1027); + uint32_t _9; uint8_t x1031 = subborrow_u32(x1028, x1004, 0x0, &_9); + uint32_t x1032 = cmovznz_u32(x1031, x1027, x1002); + uint32_t x1033 = cmovznz_u32(x1031, x1024, x999); + uint32_t x1034 = cmovznz_u32(x1031, x1021, x996); + uint32_t x1035 = cmovznz_u32(x1031, x1018, x993); + uint32_t x1036 = cmovznz_u32(x1031, x1015, x990); + uint32_t x1037 = cmovznz_u32(x1031, x1012, x987); + uint32_t x1038 = cmovznz_u32(x1031, x1009, x984); + uint32_t x1039 = cmovznz_u32(x1031, x1006, x981); + out[0] = x1039; + out[1] = x1038; + out[2] = x1037; + out[3] = x1036; + out[4] = x1035; + out[5] = x1034; + out[6] = x1033; + out[7] = x1032; +} + +// NOTE: the following functions are generated from fiat-crypto, from the same +// template as their 64-bit counterparts above, but the correctness proof of +// the template was not composed with the correctness proof of the +// specialization pipeline. This is because Coq unexplainedly loops on trying +// to synthesize opp and sub using the normal pipeline. + +static void fe_sub(uint32_t out[8], const uint32_t in1[8], const uint32_t in2[8]) { + const uint32_t x14 = in1[7]; + const uint32_t x15 = in1[6]; + const uint32_t x13 = in1[5]; + const uint32_t x11 = in1[4]; + const uint32_t x9 = in1[3]; + const uint32_t x7 = in1[2]; + const uint32_t x5 = in1[1]; + const uint32_t x3 = in1[0]; + const uint32_t x28 = in2[7]; + const uint32_t x29 = in2[6]; + const uint32_t x27 = in2[5]; + const uint32_t x25 = in2[4]; + const uint32_t x23 = in2[3]; + const uint32_t x21 = in2[2]; + const uint32_t x19 = in2[1]; + const uint32_t x17 = in2[0]; + uint32_t x31; uint8_t x32 = subborrow_u32(0x0, x3, x17, &x31); + uint32_t x34; uint8_t x35 = subborrow_u32(x32, x5, x19, &x34); + uint32_t x37; uint8_t x38 = subborrow_u32(x35, x7, x21, &x37); + uint32_t x40; uint8_t x41 = subborrow_u32(x38, x9, x23, &x40); + uint32_t x43; uint8_t x44 = subborrow_u32(x41, x11, x25, &x43); + uint32_t x46; uint8_t x47 = subborrow_u32(x44, x13, x27, &x46); + uint32_t x49; uint8_t x50 = subborrow_u32(x47, x15, x29, &x49); + uint32_t x52; uint8_t x53 = subborrow_u32(x50, x14, x28, &x52); + uint32_t x54 = cmovznz_u32(x53, 0x0, 0xffffffff); + uint32_t x56; uint8_t x57 = addcarryx_u32(0x0, x31, (x54 & 0xffffffff), &x56); + uint32_t x59; uint8_t x60 = addcarryx_u32(x57, x34, (x54 & 0xffffffff), &x59); + uint32_t x62; uint8_t x63 = addcarryx_u32(x60, x37, (x54 & 0xffffffff), &x62); + uint32_t x65; uint8_t x66 = addcarryx_u32(x63, x40, 0x0, &x65); + uint32_t x68; uint8_t x69 = addcarryx_u32(x66, x43, 0x0, &x68); + uint32_t x71; uint8_t x72 = addcarryx_u32(x69, x46, 0x0, &x71); + uint32_t x74; uint8_t x75 = addcarryx_u32(x72, x49, ((uint8_t)x54 & 0x1), &x74); + uint32_t x77; addcarryx_u32(x75, x52, (x54 & 0xffffffff), &x77); + out[0] = x56; + out[1] = x59; + out[2] = x62; + out[3] = x65; + out[4] = x68; + out[5] = x71; + out[6] = x74; + out[7] = x77; +} + +// fe_op sets out = -in +static void fe_opp(uint32_t out[8], const uint32_t in1[8]) { + const uint32_t x12 = in1[7]; + const uint32_t x13 = in1[6]; + const uint32_t x11 = in1[5]; + const uint32_t x9 = in1[4]; + const uint32_t x7 = in1[3]; + const uint32_t x5 = in1[2]; + const uint32_t x3 = in1[1]; + const uint32_t x1 = in1[0]; + uint32_t x15; uint8_t x16 = subborrow_u32(0x0, 0x0, x1, &x15); + uint32_t x18; uint8_t x19 = subborrow_u32(x16, 0x0, x3, &x18); + uint32_t x21; uint8_t x22 = subborrow_u32(x19, 0x0, x5, &x21); + uint32_t x24; uint8_t x25 = subborrow_u32(x22, 0x0, x7, &x24); + uint32_t x27; uint8_t x28 = subborrow_u32(x25, 0x0, x9, &x27); + uint32_t x30; uint8_t x31 = subborrow_u32(x28, 0x0, x11, &x30); + uint32_t x33; uint8_t x34 = subborrow_u32(x31, 0x0, x13, &x33); + uint32_t x36; uint8_t x37 = subborrow_u32(x34, 0x0, x12, &x36); + uint32_t x38 = cmovznz_u32(x37, 0x0, 0xffffffff); + uint32_t x40; uint8_t x41 = addcarryx_u32(0x0, x15, (x38 & 0xffffffff), &x40); + uint32_t x43; uint8_t x44 = addcarryx_u32(x41, x18, (x38 & 0xffffffff), &x43); + uint32_t x46; uint8_t x47 = addcarryx_u32(x44, x21, (x38 & 0xffffffff), &x46); + uint32_t x49; uint8_t x50 = addcarryx_u32(x47, x24, 0x0, &x49); + uint32_t x52; uint8_t x53 = addcarryx_u32(x50, x27, 0x0, &x52); + uint32_t x55; uint8_t x56 = addcarryx_u32(x53, x30, 0x0, &x55); + uint32_t x58; uint8_t x59 = addcarryx_u32(x56, x33, ((uint8_t)x38 & 0x1), &x58); + uint32_t x61; addcarryx_u32(x59, x36, (x38 & 0xffffffff), &x61); + out[0] = x40; + out[1] = x43; + out[2] = x46; + out[3] = x49; + out[4] = x52; + out[5] = x55; + out[6] = x58; + out[7] = x61; +} + +#endif + +// utility functions, handwritten + +#define NBYTES 32 + +#if defined(BORINGSSL_NISTP256_64BIT) + +#define NLIMBS 4 +typedef uint64_t limb_t; +#define cmovznz_limb cmovznz_u64 +typedef uint64_t fe[NLIMBS]; +#else // 64BIT; else 32BIT + +#define NLIMBS 8 +typedef uint32_t limb_t; +#define cmovznz_limb cmovznz_u32 +typedef uint32_t fe[NLIMBS]; + +#endif // 64BIT + +static limb_t fe_nz(const limb_t in1[NLIMBS]) { + limb_t ret = 0; + for (int i = 0; i < NLIMBS; i++) { + ret |= in1[i]; + } + return ret; +} + +static void fe_copy(limb_t out[NLIMBS], const limb_t in1[NLIMBS]) { + for (int i = 0; i < NLIMBS; i++) { + out[i] = in1[i]; + } +} + +static void fe_cmovznz(limb_t out[NLIMBS], limb_t t, const limb_t z[NLIMBS], + const limb_t nz[NLIMBS]) { + for (int i = 0; i < NLIMBS; i++) { + out[i] = cmovznz_limb(t, z[i], nz[i]); + } +} + +static void fe_sqr(fe out, const fe in) { + fe_mul(out, in, in); +} + +static void fe_tobytes(uint8_t out[NBYTES], const fe in) { + for (int i = 0; i> (8*(i%sizeof(in[0])))); + } +} + +static void fe_frombytes(fe out, const uint8_t in[NBYTES]) { + for (int i = 0; i +// As a sanity check, a proof that these points form a commutative group: +// + +// point_double calculates 2*(x_in, y_in, z_in) +// +// The method is taken from: +// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b +// +// Coq transcription and correctness proof: +// +// +// +// Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. +// while x_out == y_in is not (maybe this works, but it's not tested). +static void point_double(fe x_out, fe y_out, fe z_out, + const fe x_in, const fe y_in, const fe z_in) { + fe delta, gamma, beta, ftmp, ftmp2, tmptmp, alpha, fourbeta; + // delta = z^2 + fe_sqr(delta, z_in); + // gamma = y^2 + fe_sqr(gamma, y_in); + // beta = x*gamma + fe_mul(beta, x_in, gamma); + + // alpha = 3*(x-delta)*(x+delta) + fe_sub(ftmp, x_in, delta); + fe_add(ftmp2, x_in, delta); + + fe_add(tmptmp, ftmp2, ftmp2); + fe_add(ftmp2, ftmp2, tmptmp); + fe_mul(alpha, ftmp, ftmp2); + + // x' = alpha^2 - 8*beta + fe_sqr(x_out, alpha); + fe_add(fourbeta, beta, beta); + fe_add(fourbeta, fourbeta, fourbeta); + fe_add(tmptmp, fourbeta, fourbeta); + fe_sub(x_out, x_out, tmptmp); + + // z' = (y + z)^2 - gamma - delta + fe_add(delta, gamma, delta); + fe_add(ftmp, y_in, z_in); + fe_sqr(z_out, ftmp); + fe_sub(z_out, z_out, delta); + + // y' = alpha*(4*beta - x') - 8*gamma^2 + fe_sub(y_out, fourbeta, x_out); + fe_add(gamma, gamma, gamma); + fe_sqr(gamma, gamma); + fe_mul(y_out, alpha, y_out); + fe_add(gamma, gamma, gamma); + fe_sub(y_out, y_out, gamma); +} + +// point_add calcuates (x1, y1, z1) + (x2, y2, z2) +// +// The method is taken from: +// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, +// adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). +// +// Coq transcription and correctness proof: +// +// +// +// This function includes a branch for checking whether the two input points +// are equal, (while not equal to the point at infinity). This case never +// happens during single point multiplication, so there is no timing leak for +// ECDH or ECDSA signing. +static void point_add(fe x3, fe y3, fe z3, const fe x1, + const fe y1, const fe z1, const int mixed, + const fe x2, const fe y2, const fe z2) { + fe x_out, y_out, z_out; + limb_t z1nz = fe_nz(z1); + limb_t z2nz = fe_nz(z2); + + // z1z1 = z1z1 = z1**2 + fe z1z1; fe_sqr(z1z1, z1); + + fe u1, s1, two_z1z2; + if (!mixed) { + // z2z2 = z2**2 + fe z2z2; fe_sqr(z2z2, z2); + + // u1 = x1*z2z2 + fe_mul(u1, x1, z2z2); + + // two_z1z2 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 + fe_add(two_z1z2, z1, z2); + fe_sqr(two_z1z2, two_z1z2); + fe_sub(two_z1z2, two_z1z2, z1z1); + fe_sub(two_z1z2, two_z1z2, z2z2); + + // s1 = y1 * z2**3 + fe_mul(s1, z2, z2z2); + fe_mul(s1, s1, y1); + } else { + // We'll assume z2 = 1 (special case z2 = 0 is handled later). + + // u1 = x1*z2z2 + fe_copy(u1, x1); + // two_z1z2 = 2z1z2 + fe_add(two_z1z2, z1, z1); + // s1 = y1 * z2**3 + fe_copy(s1, y1); + } + + // u2 = x2*z1z1 + fe u2; fe_mul(u2, x2, z1z1); + + // h = u2 - u1 + fe h; fe_sub(h, u2, u1); + + limb_t xneq = fe_nz(h); + + // z_out = two_z1z2 * h + fe_mul(z_out, h, two_z1z2); + + // z1z1z1 = z1 * z1z1 + fe z1z1z1; fe_mul(z1z1z1, z1, z1z1); + + // s2 = y2 * z1**3 + fe s2; fe_mul(s2, y2, z1z1z1); + + // r = (s2 - s1)*2 + fe r; + fe_sub(r, s2, s1); + fe_add(r, r, r); + + limb_t yneq = fe_nz(r); + + if (!xneq && !yneq && z1nz && z2nz) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + // I = (2h)**2 + fe i; + fe_add(i, h, h); + fe_sqr(i, i); + + // J = h * I + fe j; fe_mul(j, h, i); + + // V = U1 * I + fe v; fe_mul(v, u1, i); + + // x_out = r**2 - J - 2V + fe_sqr(x_out, r); + fe_sub(x_out, x_out, j); + fe_sub(x_out, x_out, v); + fe_sub(x_out, x_out, v); + + // y_out = r(V-x_out) - 2 * s1 * J + fe_sub(y_out, v, x_out); + fe_mul(y_out, y_out, r); + fe s1j; + fe_mul(s1j, s1, j); + fe_sub(y_out, y_out, s1j); + fe_sub(y_out, y_out, s1j); + + fe_cmovznz(x_out, z1nz, x2, x_out); + fe_cmovznz(x3, z2nz, x1, x_out); + fe_cmovznz(y_out, z1nz, y2, y_out); + fe_cmovznz(y3, z2nz, y1, y_out); + fe_cmovznz(z_out, z1nz, z2, z_out); + fe_cmovznz(z3, z2nz, z1, z_out); +} + +// Base point pre computation +// -------------------------- +// +// Two different sorts of precomputed tables are used in the following code. +// Each contain various points on the curve, where each point is three field +// elements (x, y, z). +// +// For the base point table, z is usually 1 (0 for the point at infinity). +// This table has 2 * 16 elements, starting with the following: +// index | bits | point +// ------+---------+------------------------------ +// 0 | 0 0 0 0 | 0G +// 1 | 0 0 0 1 | 1G +// 2 | 0 0 1 0 | 2^64G +// 3 | 0 0 1 1 | (2^64 + 1)G +// 4 | 0 1 0 0 | 2^128G +// 5 | 0 1 0 1 | (2^128 + 1)G +// 6 | 0 1 1 0 | (2^128 + 2^64)G +// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G +// 8 | 1 0 0 0 | 2^192G +// 9 | 1 0 0 1 | (2^192 + 1)G +// 10 | 1 0 1 0 | (2^192 + 2^64)G +// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G +// 12 | 1 1 0 0 | (2^192 + 2^128)G +// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G +// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G +// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G +// followed by a copy of this with each element multiplied by 2^32. +// +// The reason for this is so that we can clock bits into four different +// locations when doing simple scalar multiplies against the base point, +// and then another four locations using the second 16 elements. +// +// Tables for other points have table[i] = iG for i in 0 .. 16. + +// g_pre_comp is the table of precomputed base points +#if defined(BORINGSSL_NISTP256_64BIT) +static const fe g_pre_comp[2][16][3] = { + {{{0x0, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x0, 0x0}}, + {{0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, + 0x18905f76a53755c6}, + {0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, + 0x8571ff1825885d85}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x4f922fc516a0d2bb, 0xd5cc16c1a623499, 0x9241cf3a57c62c8b, + 0x2f5e6961fd1b667f}, + {0x5c15c70bf5a01797, 0x3d20b44d60956192, 0x4911b37071fdb52, + 0xf648f9168d6f0f7b}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x9e566847e137bbbc, 0xe434469e8a6a0bec, 0xb1c4276179d73463, + 0x5abe0285133d0015}, + {0x92aa837cc04c7dab, 0x573d9f4c43260c07, 0xc93156278e6cc37, + 0x94bb725b6b6f7383}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x62a8c244bfe20925, 0x91c19ac38fdce867, 0x5a96a5d5dd387063, + 0x61d587d421d324f6}, + {0xe87673a2a37173ea, 0x2384800853778b65, 0x10f8441e05bab43e, + 0xfa11fe124621efbe}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x1c891f2b2cb19ffd, 0x1ba8d5bb1923c23, 0xb6d03d678ac5ca8e, + 0x586eb04c1f13bedc}, + {0xc35c6e527e8ed09, 0x1e81a33c1819ede2, 0x278fd6c056c652fa, + 0x19d5ac0870864f11}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x62577734d2b533d5, 0x673b8af6a1bdddc0, 0x577e7c9aa79ec293, + 0xbb6de651c3b266b1}, + {0xe7e9303ab65259b3, 0xd6a0afd3d03a7480, 0xc5ac83d19b3cfc27, + 0x60b4619a5d18b99b}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xbd6a38e11ae5aa1c, 0xb8b7652b49e73658, 0xb130014ee5f87ed, + 0x9d0f27b2aeebffcd}, + {0xca9246317a730a55, 0x9c955b2fddbbc83a, 0x7c1dfe0ac019a71, + 0x244a566d356ec48d}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x56f8410ef4f8b16a, 0x97241afec47b266a, 0xa406b8e6d9c87c1, + 0x803f3e02cd42ab1b}, + {0x7f0309a804dbec69, 0xa83b85f73bbad05f, 0xc6097273ad8e197f, + 0xc097440e5067adc1}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x846a56f2c379ab34, 0xa8ee068b841df8d1, 0x20314459176c68ef, + 0xf1af32d5915f1f30}, + {0x99c375315d75bd50, 0x837cffbaf72f67bc, 0x613a41848d7723f, + 0x23d0f130e2d41c8b}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xed93e225d5be5a2b, 0x6fe799835934f3c6, 0x4314092622626ffc, + 0x50bbb4d97990216a}, + {0x378191c6e57ec63e, 0x65422c40181dcdb2, 0x41a8099b0236e0f6, + 0x2b10011801fe49c3}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xfc68b5c59b391593, 0xc385f5a2598270fc, 0x7144f3aad19adcbb, + 0xdd55899983fbae0c}, + {0x93b88b8e74b82ff4, 0xd2e03c4071e734c9, 0x9a7a9eaf43c0322a, + 0xe6e4c551149d6041}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x5fe14bfe80ec21fe, 0xf6ce116ac255be82, 0x98bc5a072f4a5d67, + 0xfad27148db7e63af}, + {0x90c0b6ac29ab05b3, 0x37a9a83c4e251ae6, 0xa7dc875c2aade7d, + 0x77387de39f0e1a84}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x1e9ecc49a56c0dd7, 0xa5cffcd846086c74, 0x8f7a1408f505aece, + 0xb37b85c0bef0c47e}, + {0x3596b6e4cc0e6a8f, 0xfd6d4bbf6b388f23, 0xaba453fac39cef4e, + 0x9c135ac8f9f628d5}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xa1c729495c8f8be, 0x2961c4803bf362bf, 0x9e418403df63d4ac, + 0xc109f9cb91ece900}, + {0xc2d095d058945705, 0xb9083d96ddeb85c0, 0x84692b8d7a40449b, + 0x9bc3344f2eee1ee1}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xd5ae35642913074, 0x55491b2748a542b1, 0x469ca665b310732a, + 0x29591d525f1a4cc1}, + {0xe76f5b6bb84f983f, 0xbe7eef419f5f84e1, 0x1200d49680baa189, + 0x6376551f18ef332c}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}}, + {{{0x0, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x0, 0x0}}, + {{0x202886024147519a, 0xd0981eac26b372f0, 0xa9d4a7caa785ebc8, + 0xd953c50ddbdf58e9}, + {0x9d6361ccfd590f8f, 0x72e9626b44e6c917, 0x7fd9611022eb64cf, + 0x863ebb7e9eb288f3}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x4fe7ee31b0e63d34, 0xf4600572a9e54fab, 0xc0493334d5e7b5a4, + 0x8589fb9206d54831}, + {0xaa70f5cc6583553a, 0x879094ae25649e5, 0xcc90450710044652, + 0xebb0696d02541c4f}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xabbaa0c03b89da99, 0xa6f2d79eb8284022, 0x27847862b81c05e8, + 0x337a4b5905e54d63}, + {0x3c67500d21f7794a, 0x207005b77d6d7f61, 0xa5a378104cfd6e8, + 0xd65e0d5f4c2fbd6}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xd433e50f6d3549cf, 0x6f33696ffacd665e, 0x695bfdacce11fcb4, + 0x810ee252af7c9860}, + {0x65450fe17159bb2c, 0xf7dfbebe758b357b, 0x2b057e74d69fea72, + 0xd485717a92731745}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xce1f69bbe83f7669, 0x9f8ae8272877d6b, 0x9548ae543244278d, + 0x207755dee3c2c19c}, + {0x87bd61d96fef1945, 0x18813cefb12d28c3, 0x9fbcd1d672df64aa, + 0x48dc5ee57154b00d}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xef0f469ef49a3154, 0x3e85a5956e2b2e9a, 0x45aaec1eaa924a9c, + 0xaa12dfc8a09e4719}, + {0x26f272274df69f1d, 0xe0e4c82ca2ff5e73, 0xb9d8ce73b7a9dd44, + 0x6c036e73e48ca901}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xe1e421e1a47153f0, 0xb86c3b79920418c9, 0x93bdce87705d7672, + 0xf25ae793cab79a77}, + {0x1f3194a36d869d0c, 0x9d55c8824986c264, 0x49fb5ea3096e945e, + 0x39b8e65313db0a3e}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xe3417bc035d0b34a, 0x440b386b8327c0a7, 0x8fb7262dac0362d1, + 0x2c41114ce0cdf943}, + {0x2ba5cef1ad95a0b1, 0xc09b37a867d54362, 0x26d6cdd201e486c9, + 0x20477abf42ff9297}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xf121b41bc0a67d2, 0x62d4760a444d248a, 0xe044f1d659b4737, + 0x8fde365250bb4a8}, + {0xaceec3da848bf287, 0xc2a62182d3369d6e, 0x3582dfdc92449482, + 0x2f7e2fd2565d6cd7}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xa0122b5178a876b, 0x51ff96ff085104b4, 0x50b31ab14f29f76, + 0x84abb28b5f87d4e6}, + {0xd5ed439f8270790a, 0x2d6cb59d85e3f46b, 0x75f55c1b6c1e2212, + 0xe5436f6717655640}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xc2965ecc9aeb596d, 0x1ea03e7023c92b4, 0x4704b4b62e013961, + 0xca8fd3f905ea367}, + {0x92523a42551b2b61, 0x1eb7a89c390fcd06, 0xe7f1d2be0392a63e, + 0x96dca2644ddb0c33}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x231c210e15339848, 0xe87a28e870778c8d, 0x9d1de6616956e170, + 0x4ac3c9382bb09c0b}, + {0x19be05516998987d, 0x8b2376c4ae09f4d6, 0x1de0b7651a3f933d, + 0x380d94c7e39705f4}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x3685954b8c31c31d, 0x68533d005bf21a0c, 0xbd7626e75c79ec9, + 0xca17754742c69d54}, + {0xcc6edafff6d2dbb2, 0xfd0d8cbd174a9d18, 0x875e8793aa4578e8, + 0xa976a7139cab2ce6}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0xce37ab11b43ea1db, 0xa7ff1a95259d292, 0x851b02218f84f186, + 0xa7222beadefaad13}, + {0xa2ac78ec2b0a9144, 0x5a024051f2fa59c5, 0x91d1eca56147ce38, + 0xbe94d523bc2ac690}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}, + {{0x2d8daefd79ec1a0f, 0x3bbcd6fdceb39c97, 0xf5575ffc58f61a95, + 0xdbd986c4adf7b420}, + {0x81aa881415f39eb7, 0x6ee2fcf5b98d976c, 0x5465475dcf2f717d, + 0x8e24d3c46860bbd0}, + {0x1, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffe}}}}; +#else +static const fe g_pre_comp[2][16][3] = { + {{{0x0,0x0, 0x0,0x0, 0x0,0x0, 0x0,0x0}, + {0x0,0x0, 0x0,0x0, 0x0,0x0, 0x0,0x0}, + {0x0,0x0, 0x0,0x0, 0x0,0x0, 0x0,0x0}}, + {{0x18a9143c,0x79e730d4, 0x5fedb601,0x75ba95fc, 0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76}, + {0xce95560a,0xddf25357, 0xba19e45c,0x8b4ab8e4, 0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x16a0d2bb,0x4f922fc5, 0x1a623499,0xd5cc16c, 0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961}, + {0xf5a01797,0x5c15c70b, 0x60956192,0x3d20b44d, 0x71fdb52,0x4911b37, + 0x8d6f0f7b,0xf648f916}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xe137bbbc,0x9e566847, 0x8a6a0bec,0xe434469e, 0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285}, + {0xc04c7dab,0x92aa837c, 0x43260c07,0x573d9f4c, 0x78e6cc37,0xc931562, + 0x6b6f7383,0x94bb725b}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xbfe20925,0x62a8c244, 0x8fdce867,0x91c19ac3, 0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4}, + {0xa37173ea,0xe87673a2, 0x53778b65,0x23848008, 0x5bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x2cb19ffd,0x1c891f2b, 0xb1923c23,0x1ba8d5b, 0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c}, + {0x27e8ed09,0xc35c6e5, 0x1819ede2,0x1e81a33c, 0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xd2b533d5,0x62577734, 0xa1bdddc0,0x673b8af6, 0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651}, + {0xb65259b3,0xe7e9303a, 0xd03a7480,0xd6a0afd3, 0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x1ae5aa1c,0xbd6a38e1, 0x49e73658,0xb8b7652b, 0xee5f87ed,0xb130014, + 0xaeebffcd,0x9d0f27b2}, + {0x7a730a55,0xca924631, 0xddbbc83a,0x9c955b2f, 0xac019a71,0x7c1dfe0, + 0x356ec48d,0x244a566d}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xf4f8b16a,0x56f8410e, 0xc47b266a,0x97241afe, 0x6d9c87c1,0xa406b8e, + 0xcd42ab1b,0x803f3e02}, + {0x4dbec69,0x7f0309a8, 0x3bbad05f,0xa83b85f7, 0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xc379ab34,0x846a56f2, 0x841df8d1,0xa8ee068b, 0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5}, + {0x5d75bd50,0x99c37531, 0xf72f67bc,0x837cffba, 0x48d7723f,0x613a418, + 0xe2d41c8b,0x23d0f130}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xd5be5a2b,0xed93e225, 0x5934f3c6,0x6fe79983, 0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9}, + {0xe57ec63e,0x378191c6, 0x181dcdb2,0x65422c40, 0x236e0f6,0x41a8099b, + 0x1fe49c3,0x2b100118}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x9b391593,0xfc68b5c5, 0x598270fc,0xc385f5a2, 0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999}, + {0x74b82ff4,0x93b88b8e, 0x71e734c9,0xd2e03c40, 0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x80ec21fe,0x5fe14bfe, 0xc255be82,0xf6ce116a, 0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148}, + {0x29ab05b3,0x90c0b6ac, 0x4e251ae6,0x37a9a83c, 0xc2aade7d,0xa7dc875, + 0x9f0e1a84,0x77387de3}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xa56c0dd7,0x1e9ecc49, 0x46086c74,0xa5cffcd8, 0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0}, + {0xcc0e6a8f,0x3596b6e4, 0x6b388f23,0xfd6d4bbf, 0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x95c8f8be,0xa1c7294, 0x3bf362bf,0x2961c480, 0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb}, + {0x58945705,0xc2d095d0, 0xddeb85c0,0xb9083d96, 0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x42913074,0xd5ae356, 0x48a542b1,0x55491b27, 0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52}, + {0xb84f983f,0xe76f5b6b, 0x9f5f84e1,0xbe7eef41, 0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}}, + {{{0x0,0x0, 0x0,0x0, 0x0,0x0, 0x0,0x0}, + {0x0,0x0, 0x0,0x0, 0x0,0x0, 0x0,0x0}, + {0x0,0x0, 0x0,0x0, 0x0,0x0, 0x0,0x0}}, + {{0x4147519a,0x20288602, 0x26b372f0,0xd0981eac, 0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d}, + {0xfd590f8f,0x9d6361cc, 0x44e6c917,0x72e9626b, 0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xb0e63d34,0x4fe7ee31, 0xa9e54fab,0xf4600572, 0xd5e7b5a4,0xc0493334, + 0x6d54831,0x8589fb92}, + {0x6583553a,0xaa70f5cc, 0xe25649e5,0x879094a, 0x10044652,0xcc904507, + 0x2541c4f,0xebb0696d}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x3b89da99,0xabbaa0c0, 0xb8284022,0xa6f2d79e, 0xb81c05e8,0x27847862, + 0x5e54d63,0x337a4b59}, + {0x21f7794a,0x3c67500d, 0x7d6d7f61,0x207005b7, 0x4cfd6e8,0xa5a3781, + 0xf4c2fbd6,0xd65e0d5}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x6d3549cf,0xd433e50f, 0xfacd665e,0x6f33696f, 0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252}, + {0x7159bb2c,0x65450fe1, 0x758b357b,0xf7dfbebe, 0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xe83f7669,0xce1f69bb, 0x72877d6b,0x9f8ae82, 0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de}, + {0x6fef1945,0x87bd61d9, 0xb12d28c3,0x18813cef, 0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xf49a3154,0xef0f469e, 0x6e2b2e9a,0x3e85a595, 0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8}, + {0x4df69f1d,0x26f27227, 0xa2ff5e73,0xe0e4c82c, 0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xa47153f0,0xe1e421e1, 0x920418c9,0xb86c3b79, 0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793}, + {0x6d869d0c,0x1f3194a3, 0x4986c264,0x9d55c882, 0x96e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x35d0b34a,0xe3417bc0, 0x8327c0a7,0x440b386b, 0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c}, + {0xad95a0b1,0x2ba5cef1, 0x67d54362,0xc09b37a8, 0x1e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xbc0a67d2,0xf121b41, 0x444d248a,0x62d4760a, 0x659b4737,0xe044f1d, + 0x250bb4a8,0x8fde365}, + {0x848bf287,0xaceec3da, 0xd3369d6e,0xc2a62182, 0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x178a876b,0xa0122b5, 0x85104b4,0x51ff96ff, 0x14f29f76,0x50b31ab, + 0x5f87d4e6,0x84abb28b}, + {0x8270790a,0xd5ed439f, 0x85e3f46b,0x2d6cb59d, 0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x9aeb596d,0xc2965ecc, 0x23c92b4,0x1ea03e7, 0x2e013961,0x4704b4b6, + 0x905ea367,0xca8fd3f}, + {0x551b2b61,0x92523a42, 0x390fcd06,0x1eb7a89c, 0x392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x15339848,0x231c210e, 0x70778c8d,0xe87a28e8, 0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938}, + {0x6998987d,0x19be0551, 0xae09f4d6,0x8b2376c4, 0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x8c31c31d,0x3685954b, 0x5bf21a0c,0x68533d00, 0x75c79ec9,0xbd7626e, + 0x42c69d54,0xca177547}, + {0xf6d2dbb2,0xcc6edaff, 0x174a9d18,0xfd0d8cbd, 0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0xb43ea1db,0xce37ab11, 0x5259d292,0xa7ff1a9, 0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea}, + {0x2b0a9144,0xa2ac78ec, 0xf2fa59c5,0x5a024051, 0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}, + {{0x79ec1a0f,0x2d8daefd, 0xceb39c97,0x3bbcd6fd, 0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4}, + {0x15f39eb7,0x81aa8814, 0xb98d976c,0x6ee2fcf5, 0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4}, + {0x1,0x0, 0x0,0xffffffff, 0xffffffff,0xffffffff, 0xfffffffe,0x0}}}}; +#endif + +// select_point selects the |idx|th point from a precomputation table and +// copies it to out. +static void select_point(const limb_t idx, size_t size, + const fe pre_comp[/*size*/][3], + fe out[3]) { + OPENSSL_memset(out, 0, sizeof(fe) * 3); + for (size_t i = 0; i < size; i++) { + limb_t mismatch = i ^ idx; + fe_cmovznz(out[0], mismatch, pre_comp[i][0], out[0]); + fe_cmovznz(out[1], mismatch, pre_comp[i][1], out[1]); + fe_cmovznz(out[2], mismatch, pre_comp[i][2], out[2]); + } +} + +// get_bit returns the |i|th bit in |in| +static char get_bit(const uint8_t *in, int i) { + if (i < 0 || i >= 256) { + return 0; + } + return (in[i >> 3] >> (i & 7)) & 1; +} + +// Interleaved point multiplication using precomputed point multiples: The +// small point multiples 0*P, 1*P, ..., 17*P are in p_pre_comp, the scalar +// in p_scalar, if non-NULL. If g_scalar is non-NULL, we also add this multiple +// of the generator, using certain (large) precomputed multiples in g_pre_comp. +// Output point (X, Y, Z) is stored in x_out, y_out, z_out. +static void batch_mul(fe x_out, fe y_out, fe z_out, + const uint8_t *p_scalar, const uint8_t *g_scalar, + const fe p_pre_comp[17][3]) { + // set nq to the point at infinity + fe nq[3] = {{0},{0},{0}}, ftmp, tmp[3]; + uint64_t bits; + uint8_t sign, digit; + + // Loop over both scalars msb-to-lsb, interleaving additions of multiples + // of the generator (two in each of the last 32 rounds) and additions of p + // (every 5th round). + + int skip = 1; // save two point operations in the first round + size_t i = p_scalar != NULL ? 255 : 31; + for (;;) { + // double + if (!skip) { + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + } + + // add multiples of the generator + if (g_scalar != NULL && i <= 31) { + // first, look 32 bits upwards + bits = get_bit(g_scalar, i + 224) << 3; + bits |= get_bit(g_scalar, i + 160) << 2; + bits |= get_bit(g_scalar, i + 96) << 1; + bits |= get_bit(g_scalar, i + 32); + // select the point to add, in constant time + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + fe_copy(nq[0], tmp[0]); + fe_copy(nq[1], tmp[1]); + fe_copy(nq[2], tmp[2]); + skip = 0; + } + + // second, look at the current position + bits = get_bit(g_scalar, i + 192) << 3; + bits |= get_bit(g_scalar, i + 128) << 2; + bits |= get_bit(g_scalar, i + 64) << 1; + bits |= get_bit(g_scalar, i); + // select the point to add, in constant time + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0], + tmp[1], tmp[2]); + } + + // do other additions every 5 doublings + if (p_scalar != NULL && i % 5 == 0) { + bits = get_bit(p_scalar, i + 4) << 5; + bits |= get_bit(p_scalar, i + 3) << 4; + bits |= get_bit(p_scalar, i + 2) << 3; + bits |= get_bit(p_scalar, i + 1) << 2; + bits |= get_bit(p_scalar, i) << 1; + bits |= get_bit(p_scalar, i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + // select the point to add or subtract, in constant time. + select_point(digit, 17, p_pre_comp, tmp); + fe_opp(ftmp, tmp[1]); // (X, -Y, Z) is the negative point. + fe_cmovznz(tmp[1], sign, tmp[1], ftmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + fe_copy(nq[0], tmp[0]); + fe_copy(nq[1], tmp[1]); + fe_copy(nq[2], tmp[2]); + skip = 0; + } + } + + if (i == 0) { + break; + } + --i; + } + fe_copy(x_out, nq[0]); + fe_copy(y_out, nq[1]); + fe_copy(z_out, nq[2]); +} + +// OPENSSL EC_METHOD FUNCTIONS + +// Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = +// (X/Z^2, Y/Z^3). +static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x_out, + BIGNUM *y_out, + BN_CTX *ctx) { + fe x, y, z1, z2; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + if (!BN_to_fe(x, &point->X) || + !BN_to_fe(y, &point->Y) || + !BN_to_fe(z1, &point->Z)) { + return 0; + } + + fe_inv(z2, z1); + fe_sqr(z1, z2); + + // Instead of using |fe_from_montgomery| to convert the |x| coordinate and + // then calling |fe_from_montgomery| again to convert the |y| coordinate + // below, convert the common factor |z1| once now, saving one reduction. + fe_from_montgomery(z1); + + if (x_out != NULL) { + fe_mul(x, x, z1); + if (!fe_to_BN(x_out, x)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + } + + if (y_out != NULL) { + fe_mul(z1, z1, z2); + fe_mul(y, y, z1); + if (!fe_to_BN(y_out, y)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + } + + return 1; +} + +static int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, + const EC_SCALAR *g_scalar, + const EC_POINT *p, + const EC_SCALAR *p_scalar, + BN_CTX *unused_ctx) { + fe p_pre_comp[17][3]; + fe x_out, y_out, z_out; + + if (p != NULL && p_scalar != NULL) { + // We treat NULL scalars as 0, and NULL points as points at infinity, i.e., + // they contribute nothing to the linear combination. + OPENSSL_memset(&p_pre_comp, 0, sizeof(p_pre_comp)); + // Precompute multiples. + if (!BN_to_fe(p_pre_comp[1][0], &p->X) || + !BN_to_fe(p_pre_comp[1][1], &p->Y) || + !BN_to_fe(p_pre_comp[1][2], &p->Z)) { + return 0; + } + for (size_t j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(p_pre_comp[j][0], p_pre_comp[j][1], + p_pre_comp[j][2], p_pre_comp[1][0], + p_pre_comp[1][1], p_pre_comp[1][2], + 0, + p_pre_comp[j - 1][0], p_pre_comp[j - 1][1], + p_pre_comp[j - 1][2]); + } else { + point_double(p_pre_comp[j][0], p_pre_comp[j][1], + p_pre_comp[j][2], p_pre_comp[j / 2][0], + p_pre_comp[j / 2][1], p_pre_comp[j / 2][2]); + } + } + } + + batch_mul(x_out, y_out, z_out, + (p != NULL && p_scalar != NULL) ? p_scalar->bytes : NULL, + g_scalar != NULL ? g_scalar->bytes : NULL, + (const fe (*) [3])p_pre_comp); + + if (!fe_to_BN(&r->X, x_out) || + !fe_to_BN(&r->Y, y_out) || + !fe_to_BN(&r->Z, z_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + return 1; +} + +static int ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, EC_POINT *r, + const EC_SCALAR *g_scalar, + const EC_POINT *p, + const EC_SCALAR *p_scalar, + BN_CTX *unused_ctx) { +#define P256_WSIZE_PUBLIC 4 + // Precompute multiples of |p|. p_pre_comp[i] is (2*i+1) * |p|. + fe p_pre_comp[1 << (P256_WSIZE_PUBLIC-1)][3]; + if (!BN_to_fe(p_pre_comp[0][0], &p->X) || + !BN_to_fe(p_pre_comp[0][1], &p->Y) || + !BN_to_fe(p_pre_comp[0][2], &p->Z)) { + return 0; + } + fe p2[3]; + point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0], p_pre_comp[0][1], + p_pre_comp[0][2]); + for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) { + point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], + p_pre_comp[i - 1][0], p_pre_comp[i - 1][1], p_pre_comp[i - 1][2], + 0 /* not mixed */, p2[0], p2[1], p2[2]); + } + + // Set up the coefficients for |p_scalar|. + int8_t p_wNAF[257]; + if (!ec_compute_wNAF(group, p_wNAF, p_scalar, 256, P256_WSIZE_PUBLIC)) { + return 0; + } + + // Set |ret| to the point at infinity. + int skip = 1; // Save some point operations. + fe ret[3] = {{0},{0},{0}}; + for (int i = 256; i >= 0; i--) { + if (!skip) { + point_double(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2]); + } + + // For the |g_scalar|, we use the precomputed table without the + // constant-time lookup. + if (i <= 31) { + // First, look 32 bits upwards. + uint64_t bits = get_bit(g_scalar->bytes, i + 224) << 3; + bits |= get_bit(g_scalar->bytes, i + 160) << 2; + bits |= get_bit(g_scalar->bytes, i + 96) << 1; + bits |= get_bit(g_scalar->bytes, i + 32); + point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 1 /* mixed */, + g_pre_comp[1][bits][0], g_pre_comp[1][bits][1], + g_pre_comp[1][bits][2]); + skip = 0; + + // Second, look at the current position. + bits = get_bit(g_scalar->bytes, i + 192) << 3; + bits |= get_bit(g_scalar->bytes, i + 128) << 2; + bits |= get_bit(g_scalar->bytes, i + 64) << 1; + bits |= get_bit(g_scalar->bytes, i); + point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 1 /* mixed */, + g_pre_comp[0][bits][0], g_pre_comp[0][bits][1], + g_pre_comp[0][bits][2]); + } + + int digit = p_wNAF[i]; + if (digit != 0) { + assert(digit & 1); + int idx = digit < 0 ? (-digit) >> 1 : digit >> 1; + fe *y = &p_pre_comp[idx][1], tmp; + if (digit < 0) { + fe_opp(tmp, p_pre_comp[idx][1]); + y = &tmp; + } + if (!skip) { + point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], + 0 /* not mixed */, p_pre_comp[idx][0], *y, p_pre_comp[idx][2]); + } else { + fe_copy(ret[0], p_pre_comp[idx][0]); + fe_copy(ret[1], *y); + fe_copy(ret[2], p_pre_comp[idx][2]); + skip = 0; + } + } + } + + if (!fe_to_BN(&r->X, ret[0]) || + !fe_to_BN(&r->Y, ret[1]) || + !fe_to_BN(&r->Z, ret[2])) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + return 1; +} + +DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp256_method) { + out->group_init = ec_GFp_mont_group_init; + out->group_finish = ec_GFp_mont_group_finish; + out->group_set_curve = ec_GFp_mont_group_set_curve; + out->point_get_affine_coordinates = + ec_GFp_nistp256_point_get_affine_coordinates; + out->mul = ec_GFp_nistp256_points_mul; + out->mul_public = ec_GFp_nistp256_point_mul_public; + out->field_mul = ec_GFp_mont_field_mul; + out->field_sqr = ec_GFp_mont_field_sqr; + out->field_encode = ec_GFp_mont_field_encode; + out->field_decode = ec_GFp_mont_field_decode; +}; + +#undef BORINGSSL_NISTP256_64BIT diff --git a/Sources/CgRPC/include/grpc/grpc.h b/Sources/CgRPC/include/grpc/grpc.h index dd8a5d7d5..fec7f5269 100644 --- a/Sources/CgRPC/include/grpc/grpc.h +++ b/Sources/CgRPC/include/grpc/grpc.h @@ -60,6 +60,8 @@ GRPCAPI void grpc_register_plugin(void (*init)(void), void (*destroy)(void)); /** Initialize the grpc library. + After it's called, a matching invocation to grpc_shutdown() is expected. + It is not safe to call any other grpc functions before calling this. (To avoid overhead, little checking is done, and some things may work. We do not warrant that they will continue to do so in future revisions of this @@ -68,12 +70,21 @@ GRPCAPI void grpc_init(void); /** Shut down the grpc library. + Before it's called, there should haven been a matching invocation to + grpc_init(). + No memory is used by grpc after this call returns, nor are any instructions executing within the grpc library. Prior to calling, all application owned grpc objects must have been destroyed. */ GRPCAPI void grpc_shutdown(void); +/** EXPERIMENTAL. Returns 1 if the grpc library has been initialized. + TODO(ericgribkoff) Decide if this should be promoted to non-experimental as + part of stabilizing the fork support API, as tracked in + https://github.com/grpc/grpc/issues/15334 */ +GRPCAPI int grpc_is_initialized(void); + /** Return a string representing the current version of grpc */ GRPCAPI const char* grpc_version_string(void); @@ -96,6 +107,13 @@ GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_next( GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_pluck( void* reserved); +/** Helper function to create a completion queue with grpc_cq_completion_type + of GRPC_CQ_CALLBACK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING. + This function is experimental. */ +GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_callback( + grpc_experimental_completion_queue_functor* shutdown_callback, + void* reserved); + /** Create a completion queue */ GRPCAPI grpc_completion_queue* grpc_completion_queue_create( const grpc_completion_queue_factory* factory, @@ -230,10 +248,13 @@ GRPCAPI void* grpc_call_arena_alloc(grpc_call* call, size_t size); appropriate to call grpc_completion_queue_next or grpc_completion_queue_pluck consequent to the failed grpc_call_start_batch call. + If a call to grpc_call_start_batch with an empty batch returns + GRPC_CALL_OK, the tag is put in the completion queue immediately. THREAD SAFETY: access to grpc_call_start_batch in multi-threaded environment needs to be synchronized. As an optimization, you may synchronize batches containing just send operations independently from batches containing just - receive operations. */ + receive operations. Access to grpc_call_start_batch with an empty batch is + thread-compatible. */ GRPCAPI grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops, size_t nops, void* tag, void* reserved); @@ -269,6 +290,11 @@ GRPCAPI char* grpc_channel_get_target(grpc_channel* channel); GRPCAPI void grpc_channel_get_info(grpc_channel* channel, const grpc_channel_info* channel_info); +/** EXPERIMENTAL. Resets the channel's connect backoff. + TODO(roth): When we see whether this proves useful, either promote + to non-experimental or remove it. */ +GRPCAPI void grpc_channel_reset_connect_backoff(grpc_channel* channel); + /** Create a client channel to 'target'. Additional channel level configuration MAY be provided by grpc_channel_args, though the expectation is that most clients will want to simply pass NULL. The user data in 'args' need only @@ -286,14 +312,6 @@ GRPCAPI grpc_channel* grpc_lame_client_channel_create( /** Close and destroy a grpc channel */ GRPCAPI void grpc_channel_destroy(grpc_channel* channel); -/** Returns the JSON formatted channel trace for this channel. The caller - owns the returned string and is responsible for freeing it. */ -GRPCAPI char* grpc_channel_get_trace(grpc_channel* channel); - -/** Returns the channel uuid, which can be used to look up its trace at a - later time. */ -GRPCAPI intptr_t grpc_channel_get_uuid(grpc_channel* channel); - /** Error handling for grpc_call Most grpc_call functions return a grpc_error. If the error is not GRPC_OK then the operation failed due to some unsatisfied precondition. @@ -458,10 +476,56 @@ GRPCAPI void grpc_resource_quota_unref(grpc_resource_quota* resource_quota); GRPCAPI void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, size_t new_size); +/** Update the size of the maximum number of threads allowed */ +GRPCAPI void grpc_resource_quota_set_max_threads( + grpc_resource_quota* resource_quota, int new_max_threads); + /** Fetch a vtable for a grpc_channel_arg that points to a grpc_resource_quota */ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); +/************* CHANNELZ API *************/ +/** Channelz is under active development. The following APIs will see some + churn as the feature is implemented. This comment will be removed once + channelz is officially supported, and these APIs become stable. For now + you may track the progress by following this github issue: + https://github.com/grpc/grpc/issues/15340 + + the following APIs return allocated JSON strings that match the response + objects from the channelz proto, found here: + https://github.com/grpc/grpc/blob/master/src/proto/grpc/channelz/channelz.proto. + + For easy conversion to protobuf, The JSON is formatted according to: + https://developers.google.com/protocol-buffers/docs/proto3#json. */ + +/* Gets all root channels (i.e. channels the application has directly + created). This does not include subchannels nor non-top level channels. + The returned string is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); + +/* Gets all servers that exist in the process. */ +GRPCAPI char* grpc_channelz_get_servers(intptr_t start_server_id); + +/* Returns a single Server, or else a NOT_FOUND code. */ +GRPCAPI char* grpc_channelz_get_server(intptr_t server_id); + +/* Gets all server sockets that exist in the server. */ +GRPCAPI char* grpc_channelz_get_server_sockets(intptr_t server_id, + intptr_t start_socket_id, + intptr_t max_results); + +/* Returns a single Channel, or else a NOT_FOUND code. The returned string + is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id); + +/* Returns a single Subchannel, or else a NOT_FOUND code. The returned string + is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_subchannel(intptr_t subchannel_id); + +/* Returns a single Socket, or else a NOT_FOUND code. The returned string + is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_socket(intptr_t socket_id); + #ifdef __cplusplus } #endif diff --git a/Sources/CgRPC/include/grpc/grpc_posix.h b/Sources/CgRPC/include/grpc/grpc_posix.h index 5f1ada5aa..fbce5e13c 100644 --- a/Sources/CgRPC/include/grpc/grpc_posix.h +++ b/Sources/CgRPC/include/grpc/grpc_posix.h @@ -52,14 +52,6 @@ GRPCAPI grpc_channel* grpc_insecure_channel_create_from_fd( GRPCAPI void grpc_server_add_insecure_channel_from_fd(grpc_server* server, void* reserved, int fd); -/** GRPC Core POSIX library may internally use signals to optimize some work. - The library uses (SIGRTMIN + 6) signal by default. Use this API to instruct - the library to use a different signal i.e 'signum' instead. - Note: - - To prevent GRPC library from using any signals, pass a 'signum' of -1 - - This API is optional but if called, it MUST be called before grpc_init() */ -GRPCAPI void grpc_use_signal(int signum); - #ifdef __cplusplus } #endif diff --git a/Sources/CgRPC/include/grpc/grpc_security.h b/Sources/CgRPC/include/grpc/grpc_security.h index e1975a8e0..f0323eb16 100644 --- a/Sources/CgRPC/include/grpc/grpc_security.h +++ b/Sources/CgRPC/include/grpc/grpc_security.h @@ -163,6 +163,26 @@ typedef struct { const char* cert_chain; } grpc_ssl_pem_key_cert_pair; +/** Object that holds additional peer-verification options on a secure + channel. */ +typedef struct { + /** If non-NULL this callback will be invoked with the expected + target_name, the peer's certificate (in PEM format), and whatever + userdata pointer is set below. If a non-zero value is returned by this + callback then it is treated as a verification failure. Invocation of + the callback is blocking, so any implementation should be light-weight. + */ + int (*verify_peer_callback)(const char* target_name, const char* peer_pem, + void* userdata); + /** Arbitrary userdata that will be passed as the last argument to + verify_peer_callback. */ + void* verify_peer_callback_userdata; + /** A destruct callback that will be invoked when the channel is being + cleaned up. The userdata argument will be passed to it. The intent is + to perform any cleanup associated with that userdata. */ + void (*verify_peer_destruct)(void* userdata); +} verify_peer_options; + /** Creates an SSL credentials object. - pem_root_certs is the NULL-terminated string containing the PEM encoding of the server root certificates. If this parameter is NULL, the @@ -173,10 +193,17 @@ typedef struct { disk (in the grpc install directory). - pem_key_cert_pair is a pointer on the object containing client's private key and certificate chain. This parameter can be NULL if the client does - not have such a key/cert pair. */ + not have such a key/cert pair. + - verify_options is an optional verify_peer_options object which holds + additional options controlling how peer certificates are verified. For + example, you can supply a callback which receives the peer's certificate + with which you can do additional verification. Can be NULL, in which + case verification will retain default behavior. Any settings in + verify_options are copied during this call, so the verify_options + object can be released afterwards. */ GRPCAPI grpc_channel_credentials* grpc_ssl_credentials_create( const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, - void* reserved); + const verify_peer_options* verify_options, void* reserved); /** --- grpc_call_credentials object. @@ -505,14 +532,14 @@ typedef struct grpc_alts_credentials_options grpc_alts_credentials_options; * It is used for experimental purpose for now and subject to change. */ GRPCAPI grpc_alts_credentials_options* -grpc_alts_credentials_client_options_create(); +grpc_alts_credentials_client_options_create(void); /** * This method creates a grpc ALTS credentials server options instance. * It is used for experimental purpose for now and subject to change. */ GRPCAPI grpc_alts_credentials_options* -grpc_alts_credentials_server_options_create(); +grpc_alts_credentials_server_options_create(void); /** * This method adds a target service account to grpc client's ALTS credentials @@ -558,6 +585,225 @@ GRPCAPI grpc_channel_credentials* grpc_alts_credentials_create( GRPCAPI grpc_server_credentials* grpc_alts_server_credentials_create( const grpc_alts_credentials_options* options); +/** --- Local channel/server credentials --- **/ + +/** + * This method creates a local channel credential object. It is used for + * experimental purpose for now and subject to change. + * + * - type: local connection type + * + * It returns the created local channel credential object. + */ +GRPCAPI grpc_channel_credentials* grpc_local_credentials_create( + grpc_local_connect_type type); + +/** + * This method creates a local server credential object. It is used for + * experimental purpose for now and subject to change. + * + * - type: local connection type + * + * It returns the created local server credential object. + */ +GRPCAPI grpc_server_credentials* grpc_local_server_credentials_create( + grpc_local_connect_type type); + +/** --- SPIFFE and HTTPS-based TLS channel/server credentials --- + * It is used for experimental purpose for now and subject to change. */ + +/** Config for TLS key materials. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_key_materials_config grpc_tls_key_materials_config; + +/** Config for TLS credential reload. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_credential_reload_config + grpc_tls_credential_reload_config; + +/** Config for TLS server authorization check. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_server_authorization_check_config + grpc_tls_server_authorization_check_config; + +/** TLS credentials options. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_credentials_options grpc_tls_credentials_options; + +/** Create an empty TLS credentials options. It is used for + * experimental purpose for now and subject to change. */ +GRPCAPI grpc_tls_credentials_options* grpc_tls_credentials_options_create(); + +/** Set grpc_ssl_client_certificate_request_type field in credentials options + with the provided type. options should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_cert_request_type( + grpc_tls_credentials_options* options, + grpc_ssl_client_certificate_request_type type); + +/** Set grpc_tls_key_materials_config field in credentials options + with the provided config struct whose ownership is transferred. + Both parameters should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_key_materials_config( + grpc_tls_credentials_options* options, + grpc_tls_key_materials_config* config); + +/** Set grpc_tls_credential_reload_config field in credentials options + with the provided config struct whose ownership is transferred. + Both parameters should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_credential_reload_config( + grpc_tls_credentials_options* options, + grpc_tls_credential_reload_config* config); + +/** Set grpc_tls_server_authorization_check_config field in credentials options + with the provided config struct whose ownership is transferred. + Both parameters should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_server_authorization_check_config( + grpc_tls_credentials_options* options, + grpc_tls_server_authorization_check_config* config); + +/** --- TLS key materials config. --- + It is used for experimental purpose for now and subject to change. */ + +/** Create an empty grpc_tls_key_materials_config instance. + * It is used for experimental purpose for now and subject to change. */ +GRPCAPI grpc_tls_key_materials_config* grpc_tls_key_materials_config_create(); + +/** Set grpc_tls_key_materials_config instance with provided a TLS certificate. + config will take the ownership of pem_root_certs and pem_key_cert_pairs. + It's valid for the caller to provide nullptr pem_root_certs, in which case + the gRPC-provided root cert will be used. pem_key_cert_pairs should not be + NULL. It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. + */ +GRPCAPI int grpc_tls_key_materials_config_set_key_materials( + grpc_tls_key_materials_config* config, const char* pem_root_certs, + const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, + size_t num_key_cert_pairs); + +/** --- TLS credential reload config. --- + It is used for experimental purpose for now and subject to change.*/ + +typedef struct grpc_tls_credential_reload_arg grpc_tls_credential_reload_arg; + +/** A callback function provided by gRPC to handle the result of credential + reload. It is used when schedule API is implemented asynchronously and + serves to bring the control back to grpc C core. It is used for + experimental purpose for now and subject to change. */ +typedef void (*grpc_tls_on_credential_reload_done_cb)( + grpc_tls_credential_reload_arg* arg); + +/** A struct containing all information necessary to schedule/cancel + a credential reload request. cb and cb_user_data represent a gRPC-provided + callback and an argument passed to it. key_materials is an in/output + parameter containing currently used/newly reloaded credentials. status and + error_details are used to hold information about errors occurred when a + credential reload request is scheduled/cancelled. It is used for + experimental purpose for now and subject to change. */ +struct grpc_tls_credential_reload_arg { + grpc_tls_on_credential_reload_done_cb cb; + void* cb_user_data; + grpc_tls_key_materials_config* key_materials_config; + grpc_status_code status; + const char* error_details; +}; + +/** Create a grpc_tls_credential_reload_config instance. + - config_user_data is config-specific, read-only user data + that works for all channels created with a credential using the config. + - schedule is a pointer to an application-provided callback used to invoke + credential reload API. The implementation of this method has to be + non-blocking, but can be performed synchronously or asynchronously. + 1) If processing occurs synchronously, it populates arg->key_materials, + arg->status, and arg->error_details and returns zero. + 2) If processing occurs asynchronously, it returns a non-zero value. + The application then invokes arg->cb when processing is completed. Note + that arg->cb cannot be invoked before schedule API returns. + - cancel is a pointer to an application-provided callback used to cancel + a credential reload request scheduled via an asynchronous schedule API. + arg is used to pinpoint an exact reloading request to be cancelled. + The operation may not have any effect if the request has already been + processed. + - destruct is a pointer to an application-provided callback used to clean up + any data associated with the config. + It is used for experimental purpose for now and subject to change. +*/ +GRPCAPI grpc_tls_credential_reload_config* +grpc_tls_credential_reload_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)); + +/** --- TLS server authorization check config. --- + * It is used for experimental purpose for now and subject to change. */ + +typedef struct grpc_tls_server_authorization_check_arg + grpc_tls_server_authorization_check_arg; + +/** callback function provided by gRPC used to handle the result of server + authorization check. It is used when schedule API is implemented + asynchronously, and serves to bring the control back to gRPC C core. It is + used for experimental purpose for now and subject to change. */ +typedef void (*grpc_tls_on_server_authorization_check_done_cb)( + grpc_tls_server_authorization_check_arg* arg); + +/** A struct containing all information necessary to schedule/cancel a server + authorization check request. cb and cb_user_data represent a gRPC-provided + callback and an argument passed to it. result will store the result of + server authorization check. target_name is the name of an endpoint the + channel is connecting to and certificate represents a complete certificate + chain including both signing and leaf certificates. status and error_details + contain information about errors occurred when a server authorization check + request is scheduled/cancelled. It is used for experimental purpose for now + and subject to change.*/ +struct grpc_tls_server_authorization_check_arg { + grpc_tls_on_server_authorization_check_done_cb cb; + void* cb_user_data; + int result; + const char* target_name; + const char* peer_cert; + grpc_status_code status; + const char* error_details; +}; + +/** Create a grpc_tls_server_authorization_check_config instance. + - config_user_data is config-specific, read-only user data + that works for all channels created with a credential using the config. + - schedule is a pointer to an application-provided callback used to invoke + server authorization check API. The implementation of this method has to + be non-blocking, but can be performed synchronously or asynchronously. + 1)If processing occurs synchronously, it populates arg->result, + arg->status, and arg->error_details and returns zero. + 2) If processing occurs asynchronously, it returns a non-zero value. The + application then invokes arg->cb when processing is completed. Note that + arg->cb cannot be invoked before schedule API returns. + - cancel is a pointer to an application-provided callback used to cancel a + server authorization check request scheduled via an asynchronous schedule + API. arg is used to pinpoint an exact check request to be cancelled. The + operation may not have any effect if the request has already been + processed. + - destruct is a pointer to an application-provided callback used to clean up + any data associated with the config. + It is used for experimental purpose for now and subject to change. +*/ +GRPCAPI grpc_tls_server_authorization_check_config* +grpc_tls_server_authorization_check_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)); + #ifdef __cplusplus } #endif diff --git a/Sources/CgRPC/include/grpc/grpc_security_constants.h b/Sources/CgRPC/include/grpc/grpc_security_constants.h index 92580ea35..a082f6701 100644 --- a/Sources/CgRPC/include/grpc/grpc_security_constants.h +++ b/Sources/CgRPC/include/grpc/grpc_security_constants.h @@ -57,49 +57,60 @@ typedef enum { } grpc_ssl_certificate_config_reload_status; typedef enum { - /** Server does not request client certificate. A client can present a self - signed or signed certificates if it wishes to do so and they would be - accepted. */ + /** Server does not request client certificate. + The certificate presented by the client is not checked by the server at + all. (A client may present a self signed or signed certificate or not + present a certificate at all and any of those option would be accepted) */ GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, /** Server requests client certificate but does not enforce that the client presents a certificate. If the client presents a certificate, the client authentication is left to - the application based on the metadata like certificate etc. + the application (the necessary metadata will be available to the + application via authentication context properties, see grpc_auth_context). - The key cert pair should still be valid for the SSL connection to be - established. */ + The client's key certificate pair must be valid for the SSL connection to + be established. */ GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, /** Server requests client certificate but does not enforce that the client presents a certificate. If the client presents a certificate, the client authentication is done by - grpc framework (The client needs to either present a signed cert or skip no - certificate for a successful connection). + the gRPC framework. (For a successful connection the client needs to either + present a certificate that can be verified against the root certificate + configured by the server or not present a certificate at all) - The key cert pair should still be valid for the SSL connection to be - established. */ + The client's key certificate pair must be valid for the SSL connection to + be established. */ GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, - /** Server requests client certificate but enforces that the client presents a + /** Server requests client certificate and enforces that the client presents a certificate. If the client presents a certificate, the client authentication is left to - the application based on the metadata like certificate etc. + the application (the necessary metadata will be available to the + application via authentication context properties, see grpc_auth_context). - The key cert pair should still be valid for the SSL connection to be - established. */ + The client's key certificate pair must be valid for the SSL connection to + be established. */ GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, - /** Server requests client certificate but enforces that the client presents a + /** Server requests client certificate and enforces that the client presents a certificate. - The cerificate presented by the client is verified by grpc framework (The - client needs to present signed certs for a successful connection). + The cerificate presented by the client is verified by the gRPC framework. + (For a successful connection the client needs to present a certificate that + can be verified against the root certificate configured by the server) - The key cert pair should still be valid for the SSL connection to be - established. */ + The client's key certificate pair must be valid for the SSL connection to + be established. */ GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY } grpc_ssl_client_certificate_request_type; +/** + * Type of local connections for which local channel/server credentials will be + * applied. It supports UDS and local TCP connections. + */ +typedef enum { UDS = 0, LOCAL_TCP } grpc_local_connect_type; + #ifdef __cplusplus } #endif diff --git a/Sources/CgRPC/include/grpc/impl/codegen/atm_gcc_sync.h b/Sources/CgRPC/include/grpc/impl/codegen/atm_gcc_sync.h index c0010a346..728c3d541 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/atm_gcc_sync.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/atm_gcc_sync.h @@ -26,6 +26,8 @@ typedef intptr_t gpr_atm; #define GPR_ATM_MAX INTPTR_MAX #define GPR_ATM_MIN INTPTR_MIN +#define GPR_ATM_INC_CAS_THEN(blah) blah +#define GPR_ATM_INC_ADD_THEN(blah) blah #define GPR_ATM_COMPILE_BARRIER_() __asm__ __volatile__("" : : : "memory") diff --git a/Sources/CgRPC/include/grpc/impl/codegen/atm_windows.h b/Sources/CgRPC/include/grpc/impl/codegen/atm_windows.h index f6b27e5df..c016b9009 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/atm_windows.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/atm_windows.h @@ -25,6 +25,8 @@ typedef intptr_t gpr_atm; #define GPR_ATM_MAX INTPTR_MAX #define GPR_ATM_MIN INTPTR_MIN +#define GPR_ATM_INC_CAS_THEN(blah) blah +#define GPR_ATM_INC_ADD_THEN(blah) blah #define gpr_atm_full_barrier MemoryBarrier diff --git a/Sources/CgRPC/include/grpc/impl/codegen/compression_types.h b/Sources/CgRPC/include/grpc/impl/codegen/compression_types.h index e35d89296..f778b005b 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/compression_types.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/compression_types.h @@ -52,7 +52,8 @@ extern "C" { "grpc.compression_enabled_algorithms_bitset" /** \} */ -/** The various compression algorithms supported by gRPC */ +/** The various compression algorithms supported by gRPC (not sorted by + * compression level) */ typedef enum { GRPC_COMPRESS_NONE = 0, GRPC_COMPRESS_DEFLATE, diff --git a/Sources/CgRPC/include/grpc/impl/codegen/fork.h b/Sources/CgRPC/include/grpc/impl/codegen/fork.h index baec7a2f1..555df3490 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/fork.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/fork.h @@ -37,12 +37,12 @@ * } */ -void grpc_prefork(); +void grpc_prefork(void); -void grpc_postfork_parent(); +void grpc_postfork_parent(void); -void grpc_postfork_child(); +void grpc_postfork_child(void); -void grpc_fork_handlers_auto_register(); +void grpc_fork_handlers_auto_register(void); #endif /* GRPC_IMPL_CODEGEN_FORK_H */ diff --git a/Sources/CgRPC/include/grpc/impl/codegen/grpc_types.h b/Sources/CgRPC/include/grpc/impl/codegen/grpc_types.h index 022be5fec..79b182c45 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/grpc_types.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/grpc_types.h @@ -163,7 +163,7 @@ typedef struct { /** Maximum time that a channel may exist. Int valued, milliseconds. * INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_AGE_MS "grpc.max_connection_age_ms" -/** Grace period after the chennel reaches its max age. Int valued, +/** Grace period after the channel reaches its max age. Int valued, milliseconds. INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms" /** Enable/disable support for per-message compression. Defaults to 1, unless @@ -196,8 +196,8 @@ typedef struct { data frame, Int valued, milliseconds. */ #define GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS \ "grpc.http2.min_time_between_pings_ms" -/** Minimum allowed time between receiving successive ping frames without - sending any data frame. Int valued, milliseconds */ +/** Minimum allowed time between a server receiving successive ping frames + without sending any data frame. Int valued, milliseconds */ #define GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS \ "grpc.http2.min_ping_interval_without_data_ms" /** Channel arg to override the http2 :scheme header */ @@ -285,10 +285,16 @@ typedef struct { #define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator" /** The grpc_socket_factory instance to create and bind sockets. A pointer. */ #define GRPC_ARG_SOCKET_FACTORY "grpc.socket_factory" -/** The maximum number of trace events to keep in the tracer for each channel or - * subchannel. The default is 10. If set to 0, channel tracing is disabled. */ -#define GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE \ - "grpc.max_channel_trace_events_per_node" +/** The maximum amount of memory used by trace events per channel trace node. + * Once the maximum is reached, subsequent events will evict the oldest events + * from the buffer. The unit for this knob is bytes. Setting it to zero causes + * channel tracing to be disabled. */ +#define GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE \ + "grpc.max_channel_trace_event_memory_per_node" +/** If non-zero, gRPC library will track stats and information at at per channel + * level. Disabling channelz naturally disables channel tracing. The default + * is for channelz to be enabled. */ +#define GRPC_ARG_ENABLE_CHANNELZ "grpc.enable_channelz" /** If non-zero, Cronet transport will coalesce packets to fewer frames * when possible. */ #define GRPC_ARG_USE_CRONET_PACKET_COALESCING \ @@ -332,10 +338,35 @@ typedef struct { #define GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE "grpc.per_rpc_retry_buffer_size" /** Channel arg that carries the bridged objective c object for custom metrics * logging filter. */ -#define GRPC_ARG_MOBILE_LOG_CONFIG "grpc.mobile_log_config" +#define GRPC_ARG_MOBILE_LOG_CONTEXT "grpc.mobile_log_context" /** If non-zero, client authority filter is disabled for the channel */ #define GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER \ "grpc.disable_client_authority_filter" +/** If set to zero, disables use of http proxies. Enabled by default. */ +#define GRPC_ARG_ENABLE_HTTP_PROXY "grpc.enable_http_proxy" +/** If set to non zero, surfaces the user agent string to the server. User + agent is surfaced by default. */ +#define GRPC_ARG_SURFACE_USER_AGENT "grpc.surface_user_agent" +/** If set, inhibits health checking (which may be enabled via the + * service config.) */ +#define GRPC_ARG_INHIBIT_HEALTH_CHECKING "grpc.inhibit_health_checking" +/** If set, the channel's resolver is allowed to query for SRV records. + * For example, this is useful as a way to enable the "grpclb" + * load balancing policy. Note that this only works with the "ares" + * DNS resolver, and isn't supported by the "native" DNS resolver. */ +#define GRPC_ARG_DNS_ENABLE_SRV_QUERIES "grpc.dns_enable_srv_queries" +/** If set, determines the number of milliseconds that the c-ares based + * DNS resolver will wait on queries before cancelling them. The default value + * is 10000. Setting this to "0" will disable c-ares query timeouts + * entirely. */ +#define GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS "grpc.dns_ares_query_timeout" +/** If set, uses a local subchannel pool within the channel. Otherwise, uses the + * global subchannel pool. */ +#define GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL "grpc.use_local_subchannel_pool" +/** gRPC Objective-C channel pooling domain string. */ +#define GRPC_ARG_CHANNEL_POOL_DOMAIN "grpc.channel_pooling_domain" +/** gRPC Objective-C channel pooling id. */ +#define GRPC_ARG_CHANNEL_ID "grpc.channel_id" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a @@ -645,10 +676,33 @@ typedef enum { GRPC_CQ_NEXT, /** Events are popped out by calling grpc_completion_queue_pluck() API ONLY*/ - GRPC_CQ_PLUCK + GRPC_CQ_PLUCK, + + /** EXPERIMENTAL: Events trigger a callback specified as the tag */ + GRPC_CQ_CALLBACK } grpc_cq_completion_type; -#define GRPC_CQ_CURRENT_VERSION 1 +/** EXPERIMENTAL: Specifies an interface class to be used as a tag + for callback-based completion queues. This can be used directly, + as the first element of a struct in C, or as a base class in C++. + Its "run" value should be assigned to some non-member function, such as + a static method. */ +typedef struct grpc_experimental_completion_queue_functor { + /** The run member specifies a function that will be called when this + tag is extracted from the completion queue. Its arguments will be a + pointer to this functor and a boolean that indicates whether the + operation succeeded (non-zero) or failed (zero) */ + void (*functor_run)(struct grpc_experimental_completion_queue_functor*, int); + + /** The following fields are not API. They are meant for internal use. */ + int internal_success; + struct grpc_experimental_completion_queue_functor* internal_next; +} grpc_experimental_completion_queue_functor; + +/* The upgrade to version 2 is currently experimental. */ + +#define GRPC_CQ_CURRENT_VERSION 2 +#define GRPC_CQ_VERSION_MINIMUM_FOR_CALLBACKABLE 2 typedef struct grpc_completion_queue_attributes { /** The version number of this structure. More fields might be added to this structure in future. */ @@ -657,6 +711,15 @@ typedef struct grpc_completion_queue_attributes { grpc_cq_completion_type cq_completion_type; grpc_cq_polling_type cq_polling_type; + + /* END OF VERSION 1 CQ ATTRIBUTES */ + + /* EXPERIMENTAL: START OF VERSION 2 CQ ATTRIBUTES */ + /** When creating a callbackable CQ, pass in a functor to get invoked when + * shutdown is complete */ + grpc_experimental_completion_queue_functor* cq_shutdown_cb; + + /* END OF VERSION 2 CQ ATTRIBUTES */ } grpc_completion_queue_attributes; /** The completion queue factory structure is opaque to the callers of grpc */ diff --git a/Sources/CgRPC/include/grpc/impl/codegen/log.h b/Sources/CgRPC/include/grpc/impl/codegen/log.h new file mode 100644 index 000000000..ad7f02415 --- /dev/null +++ b/Sources/CgRPC/include/grpc/impl/codegen/log.h @@ -0,0 +1,112 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_IMPL_CODEGEN_LOG_H +#define GRPC_IMPL_CODEGEN_LOG_H + +#include + +#include +#include /* for abort() */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** GPR log API. + + Usage (within grpc): + + int argument1 = 3; + char* argument2 = "hello"; + gpr_log(GPR_DEBUG, "format string %d", argument1); + gpr_log(GPR_INFO, "hello world"); + gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */ + +/** The severity of a log message - use the #defines below when calling into + gpr_log to additionally supply file and line data */ +typedef enum gpr_log_severity { + GPR_LOG_SEVERITY_DEBUG, + GPR_LOG_SEVERITY_INFO, + GPR_LOG_SEVERITY_ERROR +} gpr_log_severity; + +#define GPR_LOG_VERBOSITY_UNSET -1 + +/** Returns a string representation of the log severity */ +GPRAPI const char* gpr_log_severity_string(gpr_log_severity severity); + +/** Macros to build log contexts at various severity levels */ +#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG +#define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO +#define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR + +/** Log a message. It's advised to use GPR_xxx above to generate the context + * for each message */ +GPRAPI void gpr_log(const char* file, int line, gpr_log_severity severity, + const char* format, ...) GPR_PRINT_FORMAT_CHECK(4, 5); + +GPRAPI int gpr_should_log(gpr_log_severity severity); + +GPRAPI void gpr_log_message(const char* file, int line, + gpr_log_severity severity, const char* message); + +/** Set global log verbosity */ +GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print); + +GPRAPI void gpr_log_verbosity_init(void); + +/** Log overrides: applications can use this API to intercept logging calls + and use their own implementations */ + +struct gpr_log_func_args { + const char* file; + int line; + gpr_log_severity severity; + const char* message; +}; + +typedef struct gpr_log_func_args gpr_log_func_args; + +typedef void (*gpr_log_func)(gpr_log_func_args* args); +GPRAPI void gpr_set_log_function(gpr_log_func func); + +/** abort() the process if x is zero, having written a line to the log. + + Intended for internal invariants. If the error can be recovered from, + without the possibility of corruption, or might best be reflected via + an exception in a higher-level language, consider returning error code. */ +#define GPR_ASSERT(x) \ + do { \ + if (GPR_UNLIKELY(!(x))) { \ + gpr_log(GPR_ERROR, "assertion failed: %s", #x); \ + abort(); \ + } \ + } while (0) + +#ifndef NDEBUG +#define GPR_DEBUG_ASSERT(x) GPR_ASSERT(x) +#else +#define GPR_DEBUG_ASSERT(x) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GRPC_IMPL_CODEGEN_LOG_H */ diff --git a/Sources/CgRPC/include/grpc/impl/codegen/port_platform.h b/Sources/CgRPC/include/grpc/impl/codegen/port_platform.h index 3cbc45ce2..75e0f8b2b 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/port_platform.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/port_platform.h @@ -121,9 +121,14 @@ #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ +#include #elif defined(ANDROID) || defined(__ANDROID__) #define GPR_PLATFORM_STRING "android" #define GPR_ANDROID 1 +// TODO(apolcyn): re-evaluate support for c-ares +// on android after upgrading our c-ares dependency. +// See https://github.com/grpc/grpc/issues/18038. +#define GRPC_ARES 0 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ @@ -174,6 +179,7 @@ #ifdef __GLIBC__ #define GPR_POSIX_CRASH_HANDLER 1 #define GPR_LINUX_PTHREAD_NAME 1 +#include #else /* musl libc */ #define GPR_MUSL_LIBC_COMPAT 1 #endif @@ -187,6 +193,8 @@ #define GPR_PLATFORM_STRING "ios" #define GPR_CPU_IPHONE 1 #define GPR_PTHREAD_TLS 1 +/* the c-ares resolver isnt safe to enable on iOS */ +#define GRPC_ARES 0 #else /* TARGET_OS_IPHONE */ #define GPR_PLATFORM_STRING "osx" #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED @@ -227,7 +235,10 @@ #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 +/* TODO(mxyan): Remove when CFStream becomes default */ +#ifndef GRPC_CFSTREAM #define GPR_SUPPORT_CHANNELS_FROM_FD 1 +#endif #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ @@ -279,6 +290,47 @@ #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ +#elif defined(__sun) && defined(__SVR4) +#define GPR_PLATFORM_STRING "solaris" +#define GPR_SOLARIS 1 +#define GPR_CPU_POSIX 1 +#define GPR_GCC_ATOMIC 1 +#define GPR_GCC_TLS 1 +#define GPR_POSIX_LOG 1 +#define GPR_POSIX_ENV 1 +#define GPR_POSIX_TMPFILE 1 +#define GPR_POSIX_STRING 1 +#define GPR_POSIX_SUBPROCESS 1 +#define GPR_POSIX_SYNC 1 +#define GPR_POSIX_TIME 1 +#define GPR_GETPID_IN_UNISTD_H 1 +#ifdef _LP64 +#define GPR_ARCH_64 1 +#else /* _LP64 */ +#define GPR_ARCH_32 1 +#endif /* _LP64 */ +#elif defined(_AIX) +#define GPR_PLATFORM_STRING "aix" +#ifndef _ALL_SOURCE +#define _ALL_SOURCE +#endif +#define GPR_AIX 1 +#define GPR_CPU_POSIX 1 +#define GPR_GCC_ATOMIC 1 +#define GPR_GCC_TLS 1 +#define GPR_POSIX_LOG 1 +#define GPR_POSIX_ENV 1 +#define GPR_POSIX_TMPFILE 1 +#define GPR_POSIX_STRING 1 +#define GPR_POSIX_SUBPROCESS 1 +#define GPR_POSIX_SYNC 1 +#define GPR_POSIX_TIME 1 +#define GPR_GETPID_IN_UNISTD_H 1 +#ifdef _LP64 +#define GPR_ARCH_64 1 +#else /* _LP64 */ +#define GPR_ARCH_32 1 +#endif /* _LP64 */ #elif defined(__native_client__) #define GPR_PLATFORM_STRING "nacl" #ifndef _BSD_SOURCE @@ -417,11 +469,11 @@ typedef unsigned __int64 uint64_t; #define GPR_MAX_ALIGNMENT 16 #ifndef GRPC_ARES -#ifdef GPR_WINDOWS -#define GRPC_ARES 0 -#else #define GRPC_ARES 0 #endif + +#ifndef GRPC_IF_NAMETOINDEX +#define GRPC_IF_NAMETOINDEX 1 #endif #ifndef GRPC_MUST_USE_RESULT @@ -474,6 +526,35 @@ typedef unsigned __int64 uint64_t; #define CENSUSAPI GRPCAPI #endif +#ifndef GPR_HAS_ATTRIBUTE +#ifdef __has_attribute +#define GPR_HAS_ATTRIBUTE(a) __has_attribute(a) +#else +#define GPR_HAS_ATTRIBUTE(a) 0 +#endif +#endif /* GPR_HAS_ATTRIBUTE */ + +#ifndef GPR_ATTRIBUTE_NOINLINE +#if GPR_HAS_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define GPR_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define GPR_HAS_ATTRIBUTE_NOINLINE 1 +#else +#define GPR_ATTRIBUTE_NOINLINE +#endif +#endif /* GPR_ATTRIBUTE_NOINLINE */ + +#ifndef GPR_ATTRIBUTE_WEAK +/* Attribute weak is broken on LLVM/windows: + * https://bugs.llvm.org/show_bug.cgi?id=37598 */ +#if (GPR_HAS_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__))) && \ + !(defined(__llvm__) && defined(_WIN32)) +#define GPR_ATTRIBUTE_WEAK __attribute__((weak)) +#define GPR_HAS_ATTRIBUTE_WEAK 1 +#else +#define GPR_ATTRIBUTE_WEAK +#endif +#endif /* GPR_ATTRIBUTE_WEAK */ + #ifndef GPR_ATTRIBUTE_NO_TSAN /* (1) */ #if defined(__has_feature) #if __has_feature(thread_sanitizer) @@ -485,6 +566,15 @@ typedef unsigned __int64 uint64_t; #endif /* GPR_ATTRIBUTE_NO_TSAN (2) */ #endif /* GPR_ATTRIBUTE_NO_TSAN (1) */ +/* GRPC_TSAN_ENABLED will be defined, when compiled with thread sanitizer. */ +#if defined(__SANITIZE_THREAD__) +#define GRPC_TSAN_ENABLED +#elif defined(__has_feature) +#if __has_feature(thread_sanitizer) +#define GRPC_TSAN_ENABLED +#endif +#endif + /* GRPC_ALLOW_EXCEPTIONS should be 0 or 1 if exceptions are allowed or not */ #ifndef GRPC_ALLOW_EXCEPTIONS /* If not already set, set to 1 on Windows (style guide standard) but to diff --git a/Sources/CgRPC/include/grpc/impl/codegen/slice.h b/Sources/CgRPC/include/grpc/impl/codegen/slice.h index 90dbfd3b1..62339daae 100644 --- a/Sources/CgRPC/include/grpc/impl/codegen/slice.h +++ b/Sources/CgRPC/include/grpc/impl/codegen/slice.h @@ -81,8 +81,8 @@ struct grpc_slice { struct grpc_slice_refcount* refcount; union grpc_slice_data { struct grpc_slice_refcounted { - uint8_t* bytes; size_t length; + uint8_t* bytes; } refcounted; struct grpc_slice_inlined { uint8_t length; diff --git a/Sources/CgRPC/include/grpc/support/log.h b/Sources/CgRPC/include/grpc/support/log.h index 1837d4bd2..8d8742b95 100644 --- a/Sources/CgRPC/include/grpc/support/log.h +++ b/Sources/CgRPC/include/grpc/support/log.h @@ -19,94 +19,8 @@ #ifndef GRPC_SUPPORT_LOG_H #define GRPC_SUPPORT_LOG_H -#include +#include -#include -#include /* for abort() */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** GPR log API. - - Usage (within grpc): - - int argument1 = 3; - char* argument2 = "hello"; - gpr_log(GPR_DEBUG, "format string %d", argument1); - gpr_log(GPR_INFO, "hello world"); - gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */ - -/** The severity of a log message - use the #defines below when calling into - gpr_log to additionally supply file and line data */ -typedef enum gpr_log_severity { - GPR_LOG_SEVERITY_DEBUG, - GPR_LOG_SEVERITY_INFO, - GPR_LOG_SEVERITY_ERROR -} gpr_log_severity; - -#define GPR_LOG_VERBOSITY_UNSET -1 - -/** Returns a string representation of the log severity */ -GPRAPI const char* gpr_log_severity_string(gpr_log_severity severity); - -/** Macros to build log contexts at various severity levels */ -#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG -#define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO -#define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR - -/** Log a message. It's advised to use GPR_xxx above to generate the context - * for each message */ -GPRAPI void gpr_log(const char* file, int line, gpr_log_severity severity, - const char* format, ...) GPR_PRINT_FORMAT_CHECK(4, 5); - -GPRAPI int gpr_should_log(gpr_log_severity severity); - -GPRAPI void gpr_log_message(const char* file, int line, - gpr_log_severity severity, const char* message); - -/** Set global log verbosity */ -GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print); - -GPRAPI void gpr_log_verbosity_init(void); - -/** Log overrides: applications can use this API to intercept logging calls - and use their own implementations */ - -struct gpr_log_func_args { - const char* file; - int line; - gpr_log_severity severity; - const char* message; -}; - -typedef struct gpr_log_func_args gpr_log_func_args; - -typedef void (*gpr_log_func)(gpr_log_func_args* args); -GPRAPI void gpr_set_log_function(gpr_log_func func); - -/** abort() the process if x is zero, having written a line to the log. - - Intended for internal invariants. If the error can be recovered from, - without the possibility of corruption, or might best be reflected via - an exception in a higher-level language, consider returning error code. */ -#define GPR_ASSERT(x) \ - do { \ - if (GPR_UNLIKELY(!(x))) { \ - gpr_log(GPR_ERROR, "assertion failed: %s", #x); \ - abort(); \ - } \ - } while (0) - -#ifndef NDEBUG -#define GPR_DEBUG_ASSERT(x) GPR_ASSERT(x) -#else -#define GPR_DEBUG_ASSERT(x) -#endif - -#ifdef __cplusplus -} -#endif +#include #endif /* GRPC_SUPPORT_LOG_H */ diff --git a/Sources/CgRPC/include/grpc/support/string_util.h b/Sources/CgRPC/include/grpc/support/string_util.h index 2c7460fa1..2679160c1 100644 --- a/Sources/CgRPC/include/grpc/support/string_util.h +++ b/Sources/CgRPC/include/grpc/support/string_util.h @@ -21,6 +21,8 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/Sources/CgRPC/include/grpc/support/sync.h b/Sources/CgRPC/include/grpc/support/sync.h index 91d1fa79b..da820dece 100644 --- a/Sources/CgRPC/include/grpc/support/sync.h +++ b/Sources/CgRPC/include/grpc/support/sync.h @@ -277,22 +277,6 @@ GPRAPI intptr_t gpr_stats_read(const gpr_stats_counter* c); #ifdef __cplusplus } // extern "C" - -namespace grpc_core { - -class mu_guard { - public: - mu_guard(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu); } - ~mu_guard() { gpr_mu_unlock(mu_); } - - mu_guard(const mu_guard&) = delete; - mu_guard& operator=(const mu_guard&) = delete; - - private: - gpr_mu* const mu_; -}; - -} // namespace grpc_core #endif #endif /* GRPC_SUPPORT_SYNC_H */ diff --git a/Sources/CgRPC/third_party/nanopb/pb.h b/Sources/CgRPC/include/pb.h similarity index 100% rename from Sources/CgRPC/third_party/nanopb/pb.h rename to Sources/CgRPC/include/pb.h diff --git a/Sources/CgRPC/third_party/nanopb/pb_common.h b/Sources/CgRPC/include/pb_common.h similarity index 100% rename from Sources/CgRPC/third_party/nanopb/pb_common.h rename to Sources/CgRPC/include/pb_common.h diff --git a/Sources/CgRPC/third_party/nanopb/pb_decode.h b/Sources/CgRPC/include/pb_decode.h similarity index 100% rename from Sources/CgRPC/third_party/nanopb/pb_decode.h rename to Sources/CgRPC/include/pb_decode.h diff --git a/Sources/CgRPC/third_party/nanopb/pb_encode.h b/Sources/CgRPC/include/pb_encode.h similarity index 100% rename from Sources/CgRPC/third_party/nanopb/pb_encode.h rename to Sources/CgRPC/include/pb_encode.h diff --git a/Sources/CgRPC/shim/channel.c b/Sources/CgRPC/shim/channel.c index 451c97d5c..8ee0408ab 100644 --- a/Sources/CgRPC/shim/channel.c +++ b/Sources/CgRPC/shim/channel.c @@ -53,7 +53,7 @@ cgrpc_channel *cgrpc_channel_create_secure(const char *address, client_credentials.private_key = client_private_key; client_credentials_pointer = &client_credentials; } - grpc_channel_credentials *creds = grpc_ssl_credentials_create(pem_root_certs, client_credentials_pointer, NULL); + grpc_channel_credentials *creds = grpc_ssl_credentials_create(pem_root_certs, client_credentials_pointer, NULL, NULL); c->channel = grpc_secure_channel_create(creds, address, &channel_args, NULL); c->completion_queue = grpc_completion_queue_create_for_next(NULL); diff --git a/Sources/CgRPC/src/core/ext/census/grpc_context.cc b/Sources/CgRPC/src/core/ext/filters/census/grpc_context.cc similarity index 100% rename from Sources/CgRPC/src/core/ext/census/grpc_context.cc rename to Sources/CgRPC/src/core/ext/filters/census/grpc_context.cc diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/channel_connectivity.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/channel_connectivity.cc index 37860e82e..9f970f6af 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/channel_connectivity.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/channel_connectivity.cc @@ -35,12 +35,13 @@ grpc_connectivity_state grpc_channel_check_connectivity_state( /* forward through to the underlying client channel */ grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; grpc_connectivity_state state; GRPC_API_TRACE( "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2, (channel, try_to_connect)); - if (client_channel_elem->filter == &grpc_client_channel_filter) { + if (GPR_LIKELY(client_channel_elem->filter == &grpc_client_channel_filter)) { state = grpc_client_channel_check_connectivity_state(client_channel_elem, try_to_connect); @@ -202,6 +203,7 @@ void grpc_channel_watch_connectivity_state( gpr_timespec deadline, grpc_completion_queue* cq, void* tag) { grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; state_watcher* w = static_cast(gpr_malloc(sizeof(*w))); diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.cc index 80a647fa9..38525dbf9 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.cc @@ -34,9 +34,10 @@ #include "src/core/ext/filters/client_channel/backup_poller.h" #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" -#include "src/core/ext/filters/client_channel/method_params.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" +#include "src/core/ext/filters/client_channel/request_routing.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/resolver_result_parsing.h" #include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/ext/filters/deadline/deadline_filter.h" @@ -63,6 +64,8 @@ #include "src/core/lib/transport/status_metadata.h" using grpc_core::internal::ClientChannelMethodParams; +using grpc_core::internal::ClientChannelMethodParamsTable; +using grpc_core::internal::ProcessedResolverResult; using grpc_core::internal::ServerRetryThrottleData; /* Client channel implementation */ @@ -83,36 +86,19 @@ grpc_core::TraceFlag grpc_client_channel_trace(false, "client_channel"); struct external_connectivity_watcher; -typedef grpc_core::SliceHashTable< - grpc_core::RefCountedPtr> - MethodParamsTable; - typedef struct client_channel_channel_data { - grpc_core::OrphanablePtr resolver; - bool started_resolving; + grpc_core::ManualConstructor request_router; + bool deadline_checking_enabled; - grpc_client_channel_factory* client_channel_factory; bool enable_retries; size_t per_rpc_retry_buffer_size; /** combiner protecting all variables below in this data structure */ grpc_combiner* combiner; - /** currently active load balancer */ - grpc_core::OrphanablePtr lb_policy; /** retry throttle data */ grpc_core::RefCountedPtr retry_throttle_data; /** maps method names to method_parameters structs */ - grpc_core::RefCountedPtr method_params_table; - /** incoming resolver result - set by resolver.next() */ - grpc_channel_args* resolver_result; - /** a list of closures that are all waiting for resolver result to come in */ - grpc_closure_list waiting_for_resolver_result_closures; - /** resolver callback */ - grpc_closure on_resolver_result_changed; - /** connectivity state being tracked */ - grpc_connectivity_state_tracker state_tracker; - /** when an lb_policy arrives, should we try to exit idle */ - bool exit_idle_when_lb_policy_arrives; + grpc_core::RefCountedPtr method_params_table; /** owning stack */ grpc_channel_stack* owning_stack; /** interested parties (owned) */ @@ -126,412 +112,43 @@ typedef struct client_channel_channel_data { /* the following properties are guarded by a mutex since APIs require them to be instantaneously available */ gpr_mu info_mu; - char* info_lb_policy_name; + grpc_core::UniquePtr info_lb_policy_name; /** service config in JSON form */ - char* info_service_config_json; + grpc_core::UniquePtr info_service_config_json; } channel_data; -typedef struct { - channel_data* chand; - /** used as an identifier, don't dereference it because the LB policy may be - * non-existing when the callback is run */ - grpc_core::LoadBalancingPolicy* lb_policy; - grpc_closure closure; -} reresolution_request_args; - -/** We create one watcher for each new lb_policy that is returned from a - resolver, to watch for state changes from the lb_policy. When a state - change is seen, we update the channel, and create a new watcher. */ -typedef struct { - channel_data* chand; - grpc_closure on_changed; - grpc_connectivity_state state; - grpc_core::LoadBalancingPolicy* lb_policy; -} lb_policy_connectivity_watcher; - -static void watch_lb_policy_locked(channel_data* chand, - grpc_core::LoadBalancingPolicy* lb_policy, - grpc_connectivity_state current_state); - -static void set_channel_connectivity_state_locked(channel_data* chand, - grpc_connectivity_state state, - grpc_error* error, - const char* reason) { - /* TODO: Improve failure handling: - * - Make it possible for policies to return GRPC_CHANNEL_TRANSIENT_FAILURE. - * - Hand over pending picks from old policies during the switch that happens - * when resolver provides an update. */ - if (chand->lb_policy != nullptr) { - if (state == GRPC_CHANNEL_TRANSIENT_FAILURE) { - /* cancel picks with wait_for_ready=false */ - chand->lb_policy->CancelMatchingPicksLocked( - /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY, - /* check= */ 0, GRPC_ERROR_REF(error)); - } else if (state == GRPC_CHANNEL_SHUTDOWN) { - /* cancel all picks */ - chand->lb_policy->CancelMatchingPicksLocked(/* mask= */ 0, /* check= */ 0, - GRPC_ERROR_REF(error)); - } - } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: setting connectivity state to %s", chand, - grpc_connectivity_state_name(state)); - } - grpc_connectivity_state_set(&chand->state_tracker, state, error, reason); -} - -static void on_lb_policy_state_changed_locked(void* arg, grpc_error* error) { - lb_policy_connectivity_watcher* w = - static_cast(arg); - /* check if the notification is for the latest policy */ - if (w->lb_policy == w->chand->lb_policy.get()) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: lb_policy=%p state changed to %s", w->chand, - w->lb_policy, grpc_connectivity_state_name(w->state)); - } - set_channel_connectivity_state_locked(w->chand, w->state, - GRPC_ERROR_REF(error), "lb_changed"); - if (w->state != GRPC_CHANNEL_SHUTDOWN) { - watch_lb_policy_locked(w->chand, w->lb_policy, w->state); - } - } - GRPC_CHANNEL_STACK_UNREF(w->chand->owning_stack, "watch_lb_policy"); - gpr_free(w); -} - -static void watch_lb_policy_locked(channel_data* chand, - grpc_core::LoadBalancingPolicy* lb_policy, - grpc_connectivity_state current_state) { - lb_policy_connectivity_watcher* w = - static_cast(gpr_malloc(sizeof(*w))); - GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy"); - w->chand = chand; - GRPC_CLOSURE_INIT(&w->on_changed, on_lb_policy_state_changed_locked, w, - grpc_combiner_scheduler(chand->combiner)); - w->state = current_state; - w->lb_policy = lb_policy; - lb_policy->NotifyOnStateChangeLocked(&w->state, &w->on_changed); -} - -static void start_resolving_locked(channel_data* chand) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: starting name resolution", chand); - } - GPR_ASSERT(!chand->started_resolving); - chand->started_resolving = true; - GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); - chand->resolver->NextLocked(&chand->resolver_result, - &chand->on_resolver_result_changed); -} - -typedef struct { - char* server_name; - grpc_core::RefCountedPtr retry_throttle_data; -} service_config_parsing_state; - -static void parse_retry_throttle_params( - const grpc_json* field, service_config_parsing_state* parsing_state) { - if (strcmp(field->key, "retryThrottling") == 0) { - if (parsing_state->retry_throttle_data != nullptr) return; // Duplicate. - if (field->type != GRPC_JSON_OBJECT) return; - int max_milli_tokens = 0; - int milli_token_ratio = 0; - for (grpc_json* sub_field = field->child; sub_field != nullptr; - sub_field = sub_field->next) { - if (sub_field->key == nullptr) return; - if (strcmp(sub_field->key, "maxTokens") == 0) { - if (max_milli_tokens != 0) return; // Duplicate. - if (sub_field->type != GRPC_JSON_NUMBER) return; - max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value); - if (max_milli_tokens == -1) return; - max_milli_tokens *= 1000; - } else if (strcmp(sub_field->key, "tokenRatio") == 0) { - if (milli_token_ratio != 0) return; // Duplicate. - if (sub_field->type != GRPC_JSON_NUMBER) return; - // We support up to 3 decimal digits. - size_t whole_len = strlen(sub_field->value); - uint32_t multiplier = 1; - uint32_t decimal_value = 0; - const char* decimal_point = strchr(sub_field->value, '.'); - if (decimal_point != nullptr) { - whole_len = static_cast(decimal_point - sub_field->value); - multiplier = 1000; - size_t decimal_len = strlen(decimal_point + 1); - if (decimal_len > 3) decimal_len = 3; - if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len, - &decimal_value)) { - return; - } - uint32_t decimal_multiplier = 1; - for (size_t i = 0; i < (3 - decimal_len); ++i) { - decimal_multiplier *= 10; - } - decimal_value *= decimal_multiplier; - } - uint32_t whole_value; - if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len, - &whole_value)) { - return; - } - milli_token_ratio = - static_cast((whole_value * multiplier) + decimal_value); - if (milli_token_ratio <= 0) return; - } - } - parsing_state->retry_throttle_data = - grpc_core::internal::ServerRetryThrottleMap::GetDataForServer( - parsing_state->server_name, max_milli_tokens, milli_token_ratio); - } -} - -static void request_reresolution_locked(void* arg, grpc_error* error) { - reresolution_request_args* args = - static_cast(arg); - channel_data* chand = args->chand; - // If this invocation is for a stale LB policy, treat it as an LB shutdown - // signal. - if (args->lb_policy != chand->lb_policy.get() || error != GRPC_ERROR_NONE || - chand->resolver == nullptr) { - GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "re-resolution"); - gpr_free(args); - return; - } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: started name re-resolving", chand); - } - chand->resolver->RequestReresolutionLocked(); - // Give back the closure to the LB policy. - chand->lb_policy->SetReresolutionClosureLocked(&args->closure); -} - -// TODO(roth): The logic in this function is very hard to follow. We -// should refactor this so that it's easier to understand, perhaps as -// part of changing the resolver API to more clearly differentiate -// between transient failures and shutdown. -static void on_resolver_result_changed_locked(void* arg, grpc_error* error) { +// Synchronous callback from chand->request_router to process a resolver +// result update. +static bool process_resolver_result_locked(void* arg, + const grpc_channel_args& args, + const char** lb_policy_name, + grpc_json** lb_policy_config) { channel_data* chand = static_cast(arg); + ProcessedResolverResult resolver_result(args, chand->enable_retries); + grpc_core::UniquePtr service_config_json = + resolver_result.service_config_json(); if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p: got resolver result: resolver_result=%p error=%s", chand, - chand->resolver_result, grpc_error_string(error)); - } - // Extract the following fields from the resolver result, if non-nullptr. - bool lb_policy_updated = false; - bool lb_policy_created = false; - char* lb_policy_name_dup = nullptr; - bool lb_policy_name_changed = false; - grpc_core::OrphanablePtr new_lb_policy; - char* service_config_json = nullptr; - grpc_core::RefCountedPtr retry_throttle_data; - grpc_core::RefCountedPtr method_params_table; - if (chand->resolver_result != nullptr) { - if (chand->resolver != nullptr) { - // Find LB policy name. - const grpc_arg* channel_arg = grpc_channel_args_find( - chand->resolver_result, GRPC_ARG_LB_POLICY_NAME); - const char* lb_policy_name = grpc_channel_arg_get_string(channel_arg); - // Special case: If at least one balancer address is present, we use - // the grpclb policy, regardless of what the resolver actually specified. - channel_arg = - grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES); - if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_POINTER) { - grpc_lb_addresses* addresses = - static_cast(channel_arg->value.pointer.p); - bool found_balancer_address = false; - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (addresses->addresses[i].is_balancer) { - found_balancer_address = true; - break; - } - } - if (found_balancer_address) { - if (lb_policy_name != nullptr && - strcmp(lb_policy_name, "grpclb") != 0) { - gpr_log(GPR_INFO, - "resolver requested LB policy %s but provided at least one " - "balancer address -- forcing use of grpclb LB policy", - lb_policy_name); - } - lb_policy_name = "grpclb"; - } - } - // Use pick_first if nothing was specified and we didn't select grpclb - // above. - if (lb_policy_name == nullptr) lb_policy_name = "pick_first"; - // Check to see if we're already using the right LB policy. - // Note: It's safe to use chand->info_lb_policy_name here without - // taking a lock on chand->info_mu, because this function is the - // only thing that modifies its value, and it can only be invoked - // once at any given time. - lb_policy_name_changed = - chand->info_lb_policy_name == nullptr || - gpr_stricmp(chand->info_lb_policy_name, lb_policy_name) != 0; - if (chand->lb_policy != nullptr && !lb_policy_name_changed) { - // Continue using the same LB policy. Update with new addresses. - lb_policy_updated = true; - chand->lb_policy->UpdateLocked(*chand->resolver_result); - } else { - // Instantiate new LB policy. - grpc_core::LoadBalancingPolicy::Args lb_policy_args; - lb_policy_args.combiner = chand->combiner; - lb_policy_args.client_channel_factory = chand->client_channel_factory; - lb_policy_args.args = chand->resolver_result; - new_lb_policy = - grpc_core::LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( - lb_policy_name, lb_policy_args); - if (new_lb_policy == nullptr) { - gpr_log(GPR_ERROR, "could not create LB policy \"%s\"", - lb_policy_name); - } else { - lb_policy_created = true; - reresolution_request_args* args = - static_cast( - gpr_zalloc(sizeof(*args))); - args->chand = chand; - args->lb_policy = new_lb_policy.get(); - GRPC_CLOSURE_INIT(&args->closure, request_reresolution_locked, args, - grpc_combiner_scheduler(chand->combiner)); - GRPC_CHANNEL_STACK_REF(chand->owning_stack, "re-resolution"); - new_lb_policy->SetReresolutionClosureLocked(&args->closure); - } - } - // Before we clean up, save a copy of lb_policy_name, since it might - // be pointing to data inside chand->resolver_result. - // The copy will be saved in chand->lb_policy_name below. - lb_policy_name_dup = gpr_strdup(lb_policy_name); - // Find service config. - channel_arg = grpc_channel_args_find(chand->resolver_result, - GRPC_ARG_SERVICE_CONFIG); - service_config_json = - gpr_strdup(grpc_channel_arg_get_string(channel_arg)); - if (service_config_json != nullptr) { - grpc_core::UniquePtr service_config = - grpc_core::ServiceConfig::Create(service_config_json); - if (service_config != nullptr) { - if (chand->enable_retries) { - channel_arg = grpc_channel_args_find(chand->resolver_result, - GRPC_ARG_SERVER_URI); - const char* server_uri = grpc_channel_arg_get_string(channel_arg); - GPR_ASSERT(server_uri != nullptr); - grpc_uri* uri = grpc_uri_parse(server_uri, true); - GPR_ASSERT(uri->path[0] != '\0'); - service_config_parsing_state parsing_state; - memset(&parsing_state, 0, sizeof(parsing_state)); - parsing_state.server_name = - uri->path[0] == '/' ? uri->path + 1 : uri->path; - service_config->ParseGlobalParams(parse_retry_throttle_params, - &parsing_state); - grpc_uri_destroy(uri); - retry_throttle_data = std::move(parsing_state.retry_throttle_data); - } - method_params_table = service_config->CreateMethodConfigTable( - ClientChannelMethodParams::CreateFromJson); - } - } - } + gpr_log(GPR_INFO, "chand=%p: resolver returned service config: \"%s\"", + chand, service_config_json.get()); } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p: resolver result: lb_policy_name=\"%s\"%s, " - "service_config=\"%s\"", - chand, lb_policy_name_dup, - lb_policy_name_changed ? " (changed)" : "", service_config_json); - } - // Now swap out fields in chand. Note that the new values may still - // be nullptr if (e.g.) the resolver failed to return results or the - // results did not contain the necessary data. - // - // First, swap out the data used by cc_get_channel_info(). + // Update channel state. + chand->retry_throttle_data = resolver_result.retry_throttle_data(); + chand->method_params_table = resolver_result.method_params_table(); + // Swap out the data used by cc_get_channel_info(). gpr_mu_lock(&chand->info_mu); - if (lb_policy_name_dup != nullptr) { - gpr_free(chand->info_lb_policy_name); - chand->info_lb_policy_name = lb_policy_name_dup; - } - if (service_config_json != nullptr) { - gpr_free(chand->info_service_config_json); - chand->info_service_config_json = service_config_json; - } + chand->info_lb_policy_name = resolver_result.lb_policy_name(); + const bool service_config_changed = + ((service_config_json == nullptr) != + (chand->info_service_config_json == nullptr)) || + (service_config_json != nullptr && + strcmp(service_config_json.get(), + chand->info_service_config_json.get()) != 0); + chand->info_service_config_json = std::move(service_config_json); gpr_mu_unlock(&chand->info_mu); - // Swap out the retry throttle data. - chand->retry_throttle_data = std::move(retry_throttle_data); - // Swap out the method params table. - chand->method_params_table = std::move(method_params_table); - // If we have a new LB policy or are shutting down (in which case - // new_lb_policy will be nullptr), swap out the LB policy, unreffing the - // old one and removing its fds from chand->interested_parties. - // Note that we do NOT do this if either (a) we updated the existing - // LB policy above or (b) we failed to create the new LB policy (in - // which case we want to continue using the most recent one we had). - if (new_lb_policy != nullptr || error != GRPC_ERROR_NONE || - chand->resolver == nullptr) { - if (chand->lb_policy != nullptr) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: unreffing lb_policy=%p", chand, - chand->lb_policy.get()); - } - grpc_pollset_set_del_pollset_set(chand->lb_policy->interested_parties(), - chand->interested_parties); - chand->lb_policy->HandOffPendingPicksLocked(new_lb_policy.get()); - chand->lb_policy.reset(); - } - chand->lb_policy = std::move(new_lb_policy); - } - // Now that we've swapped out the relevant fields of chand, check for - // error or shutdown. - if (error != GRPC_ERROR_NONE || chand->resolver == nullptr) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: shutting down", chand); - } - if (chand->resolver != nullptr) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: shutting down resolver", chand); - } - chand->resolver.reset(); - } - set_channel_connectivity_state_locked( - chand, GRPC_CHANNEL_SHUTDOWN, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Got resolver result after disconnection", &error, 1), - "resolver_gone"); - grpc_closure_list_fail_all(&chand->waiting_for_resolver_result_closures, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Channel disconnected", &error, 1)); - GRPC_CLOSURE_LIST_SCHED(&chand->waiting_for_resolver_result_closures); - GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "resolver"); - grpc_channel_args_destroy(chand->resolver_result); - chand->resolver_result = nullptr; - } else { // Not shutting down. - grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE; - grpc_error* state_error = - GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy"); - if (lb_policy_created) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p: initializing new LB policy", chand); - } - GRPC_ERROR_UNREF(state_error); - state = chand->lb_policy->CheckConnectivityLocked(&state_error); - grpc_pollset_set_add_pollset_set(chand->lb_policy->interested_parties(), - chand->interested_parties); - GRPC_CLOSURE_LIST_SCHED(&chand->waiting_for_resolver_result_closures); - if (chand->exit_idle_when_lb_policy_arrives) { - chand->lb_policy->ExitIdleLocked(); - chand->exit_idle_when_lb_policy_arrives = false; - } - watch_lb_policy_locked(chand, chand->lb_policy.get(), state); - } else if (chand->resolver_result == nullptr) { - // Transient failure. - GRPC_CLOSURE_LIST_SCHED(&chand->waiting_for_resolver_result_closures); - } - if (!lb_policy_updated) { - set_channel_connectivity_state_locked( - chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver"); - } - grpc_channel_args_destroy(chand->resolver_result); - chand->resolver_result = nullptr; - chand->resolver->NextLocked(&chand->resolver_result, - &chand->on_resolver_result_changed); - GRPC_ERROR_UNREF(state_error); - } + // Return results. + *lb_policy_name = chand->info_lb_policy_name.get(); + *lb_policy_config = resolver_result.lb_policy_config(); + return service_config_changed; } static void start_transport_op_locked(void* arg, grpc_error* error_ignored) { @@ -541,24 +158,35 @@ static void start_transport_op_locked(void* arg, grpc_error* error_ignored) { channel_data* chand = static_cast(elem->channel_data); if (op->on_connectivity_state_change != nullptr) { - grpc_connectivity_state_notify_on_state_change( - &chand->state_tracker, op->connectivity_state, - op->on_connectivity_state_change); + chand->request_router->NotifyOnConnectivityStateChange( + op->connectivity_state, op->on_connectivity_state_change); op->on_connectivity_state_change = nullptr; op->connectivity_state = nullptr; } if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) { - if (chand->lb_policy == nullptr) { - GRPC_CLOSURE_SCHED( - op->send_ping.on_initiate, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing")); - GRPC_CLOSURE_SCHED( - op->send_ping.on_ack, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing")); + if (chand->request_router->lb_policy() == nullptr) { + grpc_error* error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing"); + GRPC_CLOSURE_SCHED(op->send_ping.on_initiate, GRPC_ERROR_REF(error)); + GRPC_CLOSURE_SCHED(op->send_ping.on_ack, error); } else { - chand->lb_policy->PingOneLocked(op->send_ping.on_initiate, - op->send_ping.on_ack); + grpc_error* error = GRPC_ERROR_NONE; + grpc_core::LoadBalancingPolicy::PickState pick_state; + // Pick must return synchronously, because pick_state.on_complete is null. + GPR_ASSERT( + chand->request_router->lb_policy()->PickLocked(&pick_state, &error)); + if (pick_state.connected_subchannel != nullptr) { + pick_state.connected_subchannel->Ping(op->send_ping.on_initiate, + op->send_ping.on_ack); + } else { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "LB policy dropped call on ping"); + } + GRPC_CLOSURE_SCHED(op->send_ping.on_initiate, GRPC_ERROR_REF(error)); + GRPC_CLOSURE_SCHED(op->send_ping.on_ack, error); + } op->bind_pollset = nullptr; } op->send_ping.on_initiate = nullptr; @@ -566,26 +194,14 @@ static void start_transport_op_locked(void* arg, grpc_error* error_ignored) { } if (op->disconnect_with_error != GRPC_ERROR_NONE) { - if (chand->resolver != nullptr) { - set_channel_connectivity_state_locked( - chand, GRPC_CHANNEL_SHUTDOWN, - GRPC_ERROR_REF(op->disconnect_with_error), "disconnect"); - chand->resolver.reset(); - if (!chand->started_resolving) { - grpc_closure_list_fail_all(&chand->waiting_for_resolver_result_closures, - GRPC_ERROR_REF(op->disconnect_with_error)); - GRPC_CLOSURE_LIST_SCHED(&chand->waiting_for_resolver_result_closures); - } - if (chand->lb_policy != nullptr) { - grpc_pollset_set_del_pollset_set(chand->lb_policy->interested_parties(), - chand->interested_parties); - chand->lb_policy.reset(); - } - } - GRPC_ERROR_UNREF(op->disconnect_with_error); + chand->request_router->ShutdownLocked(op->disconnect_with_error); + } + + if (op->reset_connect_backoff) { + chand->request_router->ResetConnectionBackoffLocked(); } - GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "start_transport_op"); + GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "start_transport_op"); GRPC_CLOSURE_SCHED(op->on_consumed, GRPC_ERROR_NONE); } @@ -611,15 +227,11 @@ static void cc_get_channel_info(grpc_channel_element* elem, channel_data* chand = static_cast(elem->channel_data); gpr_mu_lock(&chand->info_mu); if (info->lb_policy_name != nullptr) { - *info->lb_policy_name = chand->info_lb_policy_name == nullptr - ? nullptr - : gpr_strdup(chand->info_lb_policy_name); + *info->lb_policy_name = gpr_strdup(chand->info_lb_policy_name.get()); } if (info->service_config_json != nullptr) { *info->service_config_json = - chand->info_service_config_json == nullptr - ? nullptr - : gpr_strdup(chand->info_service_config_json); + gpr_strdup(chand->info_service_config_json.get()); } gpr_mu_unlock(&chand->info_mu); } @@ -640,12 +252,9 @@ static grpc_error* cc_init_channel_elem(grpc_channel_element* elem, gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); chand->owning_stack = args->channel_stack; - GRPC_CLOSURE_INIT(&chand->on_resolver_result_changed, - on_resolver_result_changed_locked, chand, - grpc_combiner_scheduler(chand->combiner)); + chand->deadline_checking_enabled = + grpc_deadline_checking_enabled(args->channel_args); chand->interested_parties = grpc_pollset_set_create(); - grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, - "client_channel"); grpc_client_channel_start_backup_polling(chand->interested_parties); // Record max per-RPC retry buffer size. const grpc_arg* arg = grpc_channel_args_find( @@ -666,9 +275,7 @@ static grpc_error* cc_init_channel_elem(grpc_channel_element* elem, return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "client channel factory arg must be a pointer"); } - grpc_client_channel_factory_ref( - static_cast(arg->value.pointer.p)); - chand->client_channel_factory = + grpc_client_channel_factory* client_channel_factory = static_cast(arg->value.pointer.p); // Get server name to resolve, using proxy mapper if needed. arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI); @@ -684,49 +291,31 @@ static grpc_error* cc_init_channel_elem(grpc_channel_element* elem, grpc_channel_args* new_args = nullptr; grpc_proxy_mappers_map_name(arg->value.string, args->channel_args, &proxy_name, &new_args); - // Instantiate resolver. - chand->resolver = grpc_core::ResolverRegistry::CreateResolver( - proxy_name != nullptr ? proxy_name : arg->value.string, - new_args != nullptr ? new_args : args->channel_args, - chand->interested_parties, chand->combiner); - if (proxy_name != nullptr) gpr_free(proxy_name); - if (new_args != nullptr) grpc_channel_args_destroy(new_args); - if (chand->resolver == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed"); - } - chand->deadline_checking_enabled = - grpc_deadline_checking_enabled(args->channel_args); - return GRPC_ERROR_NONE; -} - -static void shutdown_resolver_locked(void* arg, grpc_error* error) { - grpc_core::Resolver* resolver = static_cast(arg); - resolver->Orphan(); + // Instantiate request router. + grpc_client_channel_factory_ref(client_channel_factory); + grpc_error* error = GRPC_ERROR_NONE; + chand->request_router.Init( + chand->owning_stack, chand->combiner, client_channel_factory, + chand->interested_parties, &grpc_client_channel_trace, + process_resolver_result_locked, chand, + proxy_name != nullptr ? proxy_name : arg->value.string /* target_uri */, + new_args != nullptr ? new_args : args->channel_args, &error); + gpr_free(proxy_name); + grpc_channel_args_destroy(new_args); + return error; } /* Destructor for channel_data */ static void cc_destroy_channel_elem(grpc_channel_element* elem) { channel_data* chand = static_cast(elem->channel_data); - if (chand->resolver != nullptr) { - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(shutdown_resolver_locked, chand->resolver.release(), - grpc_combiner_scheduler(chand->combiner)), - GRPC_ERROR_NONE); - } - if (chand->client_channel_factory != nullptr) { - grpc_client_channel_factory_unref(chand->client_channel_factory); - } - if (chand->lb_policy != nullptr) { - grpc_pollset_set_del_pollset_set(chand->lb_policy->interested_parties(), - chand->interested_parties); - chand->lb_policy.reset(); - } - gpr_free(chand->info_lb_policy_name); - gpr_free(chand->info_service_config_json); + chand->request_router.Destroy(); + // TODO(roth): Once we convert the filter API to C++, there will no + // longer be any need to explicitly reset these smart pointer data members. + chand->info_lb_policy_name.reset(); + chand->info_service_config_json.reset(); chand->retry_throttle_data.reset(); chand->method_params_table.reset(); grpc_client_channel_stop_backup_polling(chand->interested_parties); - grpc_connectivity_state_destroy(&chand->state_tracker); grpc_pollset_set_destroy(chand->interested_parties); GRPC_COMBINER_UNREF(chand->combiner, "client_channel"); gpr_mu_destroy(&chand->info_mu); @@ -782,18 +371,54 @@ static void cc_destroy_channel_elem(grpc_channel_element* elem) { // (census filter is on top of this one) // - add census stats for retries +namespace { + +struct call_data; + // State used for starting a retryable batch on a subchannel call. // This provides its own grpc_transport_stream_op_batch and other data // structures needed to populate the ops in the batch. // We allocate one struct on the arena for each attempt at starting a // batch on a given subchannel call. -typedef struct { +struct subchannel_batch_data { + subchannel_batch_data(grpc_call_element* elem, call_data* calld, int refcount, + bool set_on_complete); + // All dtor code must be added in `destroy`. This is because we may + // call closures in `subchannel_batch_data` after they are unrefed by + // `batch_data_unref`, and msan would complain about accessing this class + // after calling dtor. As a result we cannot call the `dtor` in + // `batch_data_unref`. + // TODO(soheil): We should try to call the dtor in `batch_data_unref`. + ~subchannel_batch_data() { destroy(); } + void destroy(); + gpr_refcount refs; grpc_call_element* elem; - grpc_subchannel_call* subchannel_call; // Holds a ref. + grpc_core::RefCountedPtr subchannel_call; // The batch to use in the subchannel call. // Its payload field points to subchannel_call_retry_state.batch_payload. grpc_transport_stream_op_batch batch; + // For intercepting on_complete. + grpc_closure on_complete; +}; + +// Retry state associated with a subchannel call. +// Stored in the parent_data of the subchannel call object. +struct subchannel_call_retry_state { + explicit subchannel_call_retry_state(grpc_call_context_element* context) + : batch_payload(context), + started_send_initial_metadata(false), + completed_send_initial_metadata(false), + started_send_trailing_metadata(false), + completed_send_trailing_metadata(false), + started_recv_initial_metadata(false), + completed_recv_initial_metadata(false), + started_recv_trailing_metadata(false), + completed_recv_trailing_metadata(false), + retry_dispatched(false) {} + + // subchannel_batch_data.batch.payload points to this. + grpc_transport_stream_op_batch_payload batch_payload; // For send_initial_metadata. // Note that we need to make a copy of the initial metadata for each // subchannel call instead of just referring to the copy in call_data, @@ -810,28 +435,20 @@ typedef struct { // For intercepting recv_initial_metadata. grpc_metadata_batch recv_initial_metadata; grpc_closure recv_initial_metadata_ready; - bool trailing_metadata_available; + bool trailing_metadata_available = false; // For intercepting recv_message. grpc_closure recv_message_ready; grpc_core::OrphanablePtr recv_message; // For intercepting recv_trailing_metadata. grpc_metadata_batch recv_trailing_metadata; grpc_transport_stream_stats collect_stats; - // For intercepting on_complete. - grpc_closure on_complete; -} subchannel_batch_data; - -// Retry state associated with a subchannel call. -// Stored in the parent_data of the subchannel call object. -typedef struct { - // subchannel_batch_data.batch.payload points to this. - grpc_transport_stream_op_batch_payload batch_payload; + grpc_closure recv_trailing_metadata_ready; // These fields indicate which ops have been started and completed on // this subchannel call. - size_t started_send_message_count; - size_t completed_send_message_count; - size_t started_recv_message_count; - size_t completed_recv_message_count; + size_t started_send_message_count = 0; + size_t completed_send_message_count = 0; + size_t started_recv_message_count = 0; + size_t completed_recv_message_count = 0; bool started_send_initial_metadata : 1; bool completed_send_initial_metadata : 1; bool started_send_trailing_metadata : 1; @@ -841,28 +458,62 @@ typedef struct { bool started_recv_trailing_metadata : 1; bool completed_recv_trailing_metadata : 1; // State for callback processing. + subchannel_batch_data* recv_initial_metadata_ready_deferred_batch = nullptr; + grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; + subchannel_batch_data* recv_message_ready_deferred_batch = nullptr; + grpc_error* recv_message_error = GRPC_ERROR_NONE; + subchannel_batch_data* recv_trailing_metadata_internal_batch = nullptr; + // NOTE: Do not move this next to the metadata bitfields above. That would + // save space but will also result in a data race because compiler will + // generate a 2 byte store which overwrites the meta-data fields upon + // setting this field. bool retry_dispatched : 1; - subchannel_batch_data* recv_initial_metadata_ready_deferred_batch; - grpc_error* recv_initial_metadata_error; - subchannel_batch_data* recv_message_ready_deferred_batch; - grpc_error* recv_message_error; - subchannel_batch_data* recv_trailing_metadata_internal_batch; -} subchannel_call_retry_state; +}; // Pending batches stored in call data. -typedef struct { +struct pending_batch { // The pending batch. If nullptr, this slot is empty. grpc_transport_stream_op_batch* batch; // Indicates whether payload for send ops has been cached in call data. bool send_ops_cached; -} pending_batch; +}; -/** Call data. Holds a pointer to grpc_subchannel_call and the +/** Call data. Holds a pointer to SubchannelCall and the associated machinery to create such a pointer. Handles queueing of stream ops until a call object is ready, waiting for initial metadata before trying to create a call object, and handling cancellation gracefully. */ -typedef struct client_channel_call_data { +struct call_data { + call_data(grpc_call_element* elem, const channel_data& chand, + const grpc_call_element_args& args) + : deadline_state(elem, args.call_stack, args.call_combiner, + GPR_LIKELY(chand.deadline_checking_enabled) + ? args.deadline + : GRPC_MILLIS_INF_FUTURE), + path(grpc_slice_ref_internal(args.path)), + call_start_time(args.start_time), + deadline(args.deadline), + arena(args.arena), + owning_call(args.call_stack), + call_combiner(args.call_combiner), + pending_send_initial_metadata(false), + pending_send_message(false), + pending_send_trailing_metadata(false), + enable_retries(chand.enable_retries), + retry_committed(false), + last_attempt_got_server_pushback(false) {} + + ~call_data() { + grpc_slice_unref_internal(path); + GRPC_ERROR_UNREF(cancel_error); + for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches); ++i) { + GPR_ASSERT(pending_batches[i].batch == nullptr); + } + if (have_request) { + request.Destroy(); + } + } + // State for handling deadlines. // The code in deadline_filter.c requires this to be the first field. // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state @@ -881,23 +532,23 @@ typedef struct client_channel_call_data { grpc_core::RefCountedPtr retry_throttle_data; grpc_core::RefCountedPtr method_params; - grpc_subchannel_call* subchannel_call; + grpc_core::RefCountedPtr subchannel_call; // Set when we get a cancel_stream op. - grpc_error* cancel_error; + grpc_error* cancel_error = GRPC_ERROR_NONE; - grpc_core::LoadBalancingPolicy::PickState pick; + grpc_core::ManualConstructor request; + bool have_request = false; grpc_closure pick_closure; - grpc_closure pick_cancel_closure; - grpc_polling_entity* pollent; + grpc_polling_entity* pollent = nullptr; // Batches are added to this list when received from above. // They are removed when we are done handling the batch (i.e., when // either we have invoked all of the batch's callbacks or we have // passed the batch down to the subchannel call and are not // intercepting any of its callbacks). - pending_batch pending_batches[MAX_PENDING_BATCHES]; + pending_batch pending_batches[MAX_PENDING_BATCHES] = {}; bool pending_send_initial_metadata : 1; bool pending_send_message : 1; bool pending_send_trailing_metadata : 1; @@ -906,15 +557,24 @@ typedef struct client_channel_call_data { bool enable_retries : 1; bool retry_committed : 1; bool last_attempt_got_server_pushback : 1; - int num_attempts_completed; - size_t bytes_buffered_for_retry; + int num_attempts_completed = 0; + size_t bytes_buffered_for_retry = 0; grpc_core::ManualConstructor retry_backoff; grpc_timer retry_timer; + // The number of pending retriable subchannel batches containing send ops. + // We hold a ref to the call stack while this is non-zero, since replay + // batches may not complete until after all callbacks have been returned + // to the surface, and we need to make sure that the call is not destroyed + // until all of these batches have completed. + // Note that we actually only need to track replay batches, but it's + // easier to track all batches with send ops. + int num_pending_retriable_subchannel_send_batches = 0; + // Cached data for retrying send ops. // send_initial_metadata - bool seen_send_initial_metadata; - grpc_linked_mdelem* send_initial_metadata_storage; + bool seen_send_initial_metadata = false; + grpc_linked_mdelem* send_initial_metadata_storage = nullptr; grpc_metadata_batch send_initial_metadata; uint32_t send_initial_metadata_flags; gpr_atm* peer_string; @@ -925,14 +585,14 @@ typedef struct client_channel_call_data { // Note: We inline the cache for the first 3 send_message ops and use // dynamic allocation after that. This number was essentially picked // at random; it could be changed in the future to tune performance. - grpc_core::ManualConstructor< - grpc_core::InlinedVector> - send_messages; + grpc_core::InlinedVector send_messages; // send_trailing_metadata - bool seen_send_trailing_metadata; - grpc_linked_mdelem* send_trailing_metadata_storage; + bool seen_send_trailing_metadata = false; + grpc_linked_mdelem* send_trailing_metadata_storage = nullptr; grpc_metadata_batch send_trailing_metadata; -} call_data; +}; + +} // namespace // Forward declarations. static void retry_commit(grpc_call_element* elem, @@ -940,7 +600,6 @@ static void retry_commit(grpc_call_element* elem, static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); -static void pick_after_resolver_result_start_locked(grpc_call_element* elem); static void start_pick_locked(void* arg, grpc_error* ignored); // @@ -977,7 +636,7 @@ static void maybe_cache_send_ops_for_batch(call_data* calld, gpr_arena_alloc(calld->arena, sizeof(grpc_core::ByteStreamCache))); new (cache) grpc_core::ByteStreamCache( std::move(batch->payload->send_message.send_message)); - calld->send_messages->push_back(cache); + calld->send_messages.push_back(cache); } // Save metadata batch for send_trailing_metadata ops. if (batch->send_trailing_metadata) { @@ -1014,7 +673,7 @@ static void free_cached_send_message(channel_data* chand, call_data* calld, "chand=%p calld=%p: destroying calld->send_messages[%" PRIuPTR "]", chand, calld, idx); } - (*calld->send_messages)[idx]->Destroy(); + calld->send_messages[idx]->Destroy(); } // Frees cached send_trailing_metadata. @@ -1064,6 +723,25 @@ static void free_cached_send_op_data_for_completed_batch( } } +// +// LB recv_trailing_metadata_ready handling +// + +void maybe_inject_recv_trailing_metadata_ready_for_lb( + const grpc_core::LoadBalancingPolicy::PickState& pick, + grpc_transport_stream_op_batch* batch) { + if (pick.recv_trailing_metadata_ready != nullptr) { + *pick.original_recv_trailing_metadata_ready = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + pick.recv_trailing_metadata_ready; + if (pick.recv_trailing_metadata != nullptr) { + *pick.recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + } + } +} + // // pending_batches management // @@ -1114,7 +792,8 @@ static void pending_batches_add(grpc_call_element* elem, if (batch->send_trailing_metadata) { calld->pending_send_trailing_metadata = true; } - if (calld->bytes_buffered_for_retry > chand->per_rpc_retry_buffer_size) { + if (GPR_UNLIKELY(calld->bytes_buffered_for_retry > + chand->per_rpc_retry_buffer_size)) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: exceeded retry buffer size, committing", @@ -1124,8 +803,8 @@ static void pending_batches_add(grpc_call_element* elem, calld->subchannel_call == nullptr ? nullptr : static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + + calld->subchannel_call->GetParentData()); retry_commit(elem, retry_state); // If we are not going to retry and have not yet started, pretend // retries are disabled so that we don't bother with retry overhead. @@ -1182,35 +861,28 @@ static void pending_batches_fail(grpc_call_element* elem, grpc_error* error, "chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s", elem->channel_data, calld, num_batches, grpc_error_string(error)); } - grpc_transport_stream_op_batch* - batches[GPR_ARRAY_SIZE(calld->pending_batches)]; - size_t num_batches = 0; + grpc_core::CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - batches[num_batches++] = batch; + if (batch->recv_trailing_metadata && calld->have_request) { + maybe_inject_recv_trailing_metadata_ready_for_lb( + *calld->request->pick(), batch); + } + batch->handler_private.extra_arg = calld; + GRPC_CLOSURE_INIT(&batch->handler_private.closure, + fail_pending_batch_in_call_combiner, batch, + grpc_schedule_on_exec_ctx); + closures.Add(&batch->handler_private.closure, GRPC_ERROR_REF(error), + "pending_batches_fail"); pending_batch_clear(calld, pending); } } - for (size_t i = yield_call_combiner ? 1 : 0; i < num_batches; ++i) { - grpc_transport_stream_op_batch* batch = batches[i]; - batch->handler_private.extra_arg = calld; - GRPC_CLOSURE_INIT(&batch->handler_private.closure, - fail_pending_batch_in_call_combiner, batch, - grpc_schedule_on_exec_ctx); - GRPC_CALL_COMBINER_START(calld->call_combiner, - &batch->handler_private.closure, - GRPC_ERROR_REF(error), "pending_batches_fail"); - } if (yield_call_combiner) { - if (num_batches > 0) { - // Note: This will release the call combiner. - grpc_transport_stream_op_batch_finish_with_failure( - batches[0], GRPC_ERROR_REF(error), calld->call_combiner); - } else { - GRPC_CALL_COMBINER_STOP(calld->call_combiner, "pending_batches_fail"); - } + closures.RunClosures(calld->call_combiner); + } else { + closures.RunClosuresWithoutYielding(calld->call_combiner); } GRPC_ERROR_UNREF(error); } @@ -1220,10 +892,10 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_core::SubchannelCall* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(subchannel_call, batch); + subchannel_call->StartTransportStreamOpBatch(batch); } // This is called via the call combiner, so access to calld is synchronized. @@ -1243,32 +915,28 @@ static void pending_batches_resume(grpc_call_element* elem) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " pending batches on subchannel_call=%p", - chand, calld, num_batches, calld->subchannel_call); + chand, calld, num_batches, calld->subchannel_call.get()); } - grpc_transport_stream_op_batch* - batches[GPR_ARRAY_SIZE(calld->pending_batches)]; - size_t num_batches = 0; + grpc_core::CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - batches[num_batches++] = batch; + if (batch->recv_trailing_metadata) { + maybe_inject_recv_trailing_metadata_ready_for_lb( + *calld->request->pick(), batch); + } + batch->handler_private.extra_arg = calld->subchannel_call.get(); + GRPC_CLOSURE_INIT(&batch->handler_private.closure, + resume_pending_batch_in_call_combiner, batch, + grpc_schedule_on_exec_ctx); + closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, + "pending_batches_resume"); pending_batch_clear(calld, pending); } } - for (size_t i = 1; i < num_batches; ++i) { - grpc_transport_stream_op_batch* batch = batches[i]; - batch->handler_private.extra_arg = calld->subchannel_call; - GRPC_CLOSURE_INIT(&batch->handler_private.closure, - resume_pending_batch_in_call_combiner, batch, - grpc_schedule_on_exec_ctx); - GRPC_CALL_COMBINER_START(calld->call_combiner, - &batch->handler_private.closure, GRPC_ERROR_NONE, - "pending_batches_resume"); - } - GPR_ASSERT(num_batches > 0); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, batches[0]); + closures.RunClosures(calld->call_combiner); } static void maybe_clear_pending_batch(grpc_call_element* elem, @@ -1283,7 +951,10 @@ static void maybe_clear_pending_batch(grpc_call_element* elem, batch->payload->recv_initial_metadata.recv_initial_metadata_ready == nullptr) && (!batch->recv_message || - batch->payload->recv_message.recv_message_ready == nullptr)) { + batch->payload->recv_message.recv_message_ready == nullptr) && + (!batch->recv_trailing_metadata || + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready == + nullptr)) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: clearing pending batch", chand, calld); @@ -1292,75 +963,27 @@ static void maybe_clear_pending_batch(grpc_call_element* elem, } } -// Returns true if all ops in the pending batch have been completed. -static bool pending_batch_is_completed( - pending_batch* pending, call_data* calld, - subchannel_call_retry_state* retry_state) { - if (pending->batch == nullptr || pending->batch->on_complete == nullptr) { - return false; - } - if (pending->batch->send_initial_metadata && - !retry_state->completed_send_initial_metadata) { - return false; - } - if (pending->batch->send_message && - retry_state->completed_send_message_count < - calld->send_messages->size()) { - return false; - } - if (pending->batch->send_trailing_metadata && - !retry_state->completed_send_trailing_metadata) { - return false; - } - if (pending->batch->recv_initial_metadata && - !retry_state->completed_recv_initial_metadata) { - return false; - } - if (pending->batch->recv_message && - retry_state->completed_recv_message_count < - retry_state->started_recv_message_count) { - return false; - } - if (pending->batch->recv_trailing_metadata && - !retry_state->completed_recv_trailing_metadata) { - return false; - } - return true; -} - -// Returns true if any op in the batch was not yet started. -static bool pending_batch_is_unstarted( - pending_batch* pending, call_data* calld, - subchannel_call_retry_state* retry_state) { - if (pending->batch == nullptr || pending->batch->on_complete == nullptr) { - return false; - } - if (pending->batch->send_initial_metadata && - !retry_state->started_send_initial_metadata) { - return true; - } - if (pending->batch->send_message && - retry_state->started_send_message_count < calld->send_messages->size()) { - return true; - } - if (pending->batch->send_trailing_metadata && - !retry_state->started_send_trailing_metadata) { - return true; - } - if (pending->batch->recv_initial_metadata && - !retry_state->started_recv_initial_metadata) { - return true; - } - if (pending->batch->recv_message && - retry_state->completed_recv_message_count == - retry_state->started_recv_message_count) { - return true; - } - if (pending->batch->recv_trailing_metadata && - !retry_state->started_recv_trailing_metadata) { - return true; +// Returns a pointer to the first pending batch for which predicate(batch) +// returns true, or null if not found. +template +static pending_batch* pending_batch_find(grpc_call_element* elem, + const char* log_message, + Predicate predicate) { + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { + pending_batch* pending = &calld->pending_batches[i]; + grpc_transport_stream_op_batch* batch = pending->batch; + if (batch != nullptr && predicate(batch)) { + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: %s pending batch at index %" PRIuPTR, chand, + calld, log_message, i); + } + return pending; + } } - return false; + return nullptr; } // @@ -1392,14 +1015,10 @@ static void do_retry(grpc_call_element* elem, const ClientChannelMethodParams::RetryPolicy* retry_policy = calld->method_params->retry_policy(); GPR_ASSERT(retry_policy != nullptr); - // Reset subchannel call and connected subchannel. - if (calld->subchannel_call != nullptr) { - GRPC_SUBCHANNEL_CALL_UNREF(calld->subchannel_call, - "client_channel_call_retry"); - calld->subchannel_call = nullptr; - } - if (calld->pick.connected_subchannel != nullptr) { - calld->pick.connected_subchannel.reset(); + calld->subchannel_call.reset(); + if (calld->have_request) { + calld->have_request = false; + calld->request.Destroy(); } // Compute backoff delay. grpc_millis next_attempt_time; @@ -1421,7 +1040,7 @@ static void do_retry(grpc_call_element* elem, } if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, - "chand=%p calld=%p: retrying failed call in %" PRIuPTR " ms", chand, + "chand=%p calld=%p: retrying failed call in %" PRId64 " ms", chand, calld, next_attempt_time - grpc_core::ExecCtx::Get()->Now()); } // Schedule retry after computed delay. @@ -1450,8 +1069,7 @@ static bool maybe_retry(grpc_call_element* elem, subchannel_call_retry_state* retry_state = nullptr; if (batch_data != nullptr) { retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); if (retry_state->retry_dispatched) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", chand, @@ -1461,7 +1079,7 @@ static bool maybe_retry(grpc_call_element* elem, } } // Check status. - if (status == GRPC_STATUS_OK) { + if (GPR_LIKELY(status == GRPC_STATUS_OK)) { if (calld->retry_throttle_data != nullptr) { calld->retry_throttle_data->RecordSuccess(); } @@ -1547,44 +1165,65 @@ static bool maybe_retry(grpc_call_element* elem, // subchannel_batch_data // -static subchannel_batch_data* batch_data_create(grpc_call_element* elem, - int refcount) { - call_data* calld = static_cast(elem->call_data); +namespace { + +subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, + call_data* calld, int refcount, + bool set_on_complete) + : elem(elem), subchannel_call(calld->subchannel_call) { subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); - subchannel_batch_data* batch_data = static_cast( - gpr_arena_alloc(calld->arena, sizeof(*batch_data))); - batch_data->elem = elem; - batch_data->subchannel_call = - GRPC_SUBCHANNEL_CALL_REF(calld->subchannel_call, "batch_data_create"); - batch_data->batch.payload = &retry_state->batch_payload; - gpr_ref_init(&batch_data->refs, refcount); - GRPC_CLOSURE_INIT(&batch_data->on_complete, on_complete, batch_data, - grpc_schedule_on_exec_ctx); - batch_data->batch.on_complete = &batch_data->on_complete; + calld->subchannel_call->GetParentData()); + batch.payload = &retry_state->batch_payload; + gpr_ref_init(&refs, refcount); + if (set_on_complete) { + GRPC_CLOSURE_INIT(&on_complete, ::on_complete, this, + grpc_schedule_on_exec_ctx); + batch.on_complete = &on_complete; + } GRPC_CALL_STACK_REF(calld->owning_call, "batch_data"); +} + +void subchannel_batch_data::destroy() { + subchannel_call_retry_state* retry_state = + static_cast( + subchannel_call->GetParentData()); + if (batch.send_initial_metadata) { + grpc_metadata_batch_destroy(&retry_state->send_initial_metadata); + } + if (batch.send_trailing_metadata) { + grpc_metadata_batch_destroy(&retry_state->send_trailing_metadata); + } + if (batch.recv_initial_metadata) { + grpc_metadata_batch_destroy(&retry_state->recv_initial_metadata); + } + if (batch.recv_trailing_metadata) { + grpc_metadata_batch_destroy(&retry_state->recv_trailing_metadata); + } + subchannel_call.reset(); + call_data* calld = static_cast(elem->call_data); + GRPC_CALL_STACK_UNREF(calld->owning_call, "batch_data"); +} + +} // namespace + +// Creates a subchannel_batch_data object on the call's arena with the +// specified refcount. If set_on_complete is true, the batch's +// on_complete callback will be set to point to on_complete(); +// otherwise, the batch's on_complete callback will be null. +static subchannel_batch_data* batch_data_create(grpc_call_element* elem, + int refcount, + bool set_on_complete) { + call_data* calld = static_cast(elem->call_data); + subchannel_batch_data* batch_data = + new (gpr_arena_alloc(calld->arena, sizeof(*batch_data))) + subchannel_batch_data(elem, calld, refcount, set_on_complete); return batch_data; } static void batch_data_unref(subchannel_batch_data* batch_data) { if (gpr_unref(&batch_data->refs)) { - if (batch_data->send_initial_metadata_storage != nullptr) { - grpc_metadata_batch_destroy(&batch_data->send_initial_metadata); - } - if (batch_data->send_trailing_metadata_storage != nullptr) { - grpc_metadata_batch_destroy(&batch_data->send_trailing_metadata); - } - if (batch_data->batch.recv_initial_metadata) { - grpc_metadata_batch_destroy(&batch_data->recv_initial_metadata); - } - if (batch_data->batch.recv_trailing_metadata) { - grpc_metadata_batch_destroy(&batch_data->recv_trailing_metadata); - } - GRPC_SUBCHANNEL_CALL_UNREF(batch_data->subchannel_call, "batch_data_unref"); - call_data* calld = static_cast(batch_data->elem->call_data); - GRPC_CALL_STACK_UNREF(calld->owning_call, "batch_data"); + batch_data->destroy(); } } @@ -1596,30 +1235,21 @@ static void batch_data_unref(subchannel_batch_data* batch_data) { static void invoke_recv_initial_metadata_callback(void* arg, grpc_error* error) { subchannel_batch_data* batch_data = static_cast(arg); - channel_data* chand = - static_cast(batch_data->elem->channel_data); - call_data* calld = static_cast(batch_data->elem->call_data); // Find pending batch. - pending_batch* pending = nullptr; - for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { - grpc_transport_stream_op_batch* batch = calld->pending_batches[i].batch; - if (batch != nullptr && batch->recv_initial_metadata && - batch->payload->recv_initial_metadata.recv_initial_metadata_ready != - nullptr) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: invoking recv_initial_metadata_ready for " - "pending batch at index %" PRIuPTR, - chand, calld, i); - } - pending = &calld->pending_batches[i]; - break; - } - } + pending_batch* pending = pending_batch_find( + batch_data->elem, "invoking recv_initial_metadata_ready for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_initial_metadata && + batch->payload->recv_initial_metadata + .recv_initial_metadata_ready != nullptr; + }); GPR_ASSERT(pending != nullptr); // Return metadata. + subchannel_call_retry_state* retry_state = + static_cast( + batch_data->subchannel_call->GetParentData()); grpc_metadata_batch_move( - &batch_data->recv_initial_metadata, + &retry_state->recv_initial_metadata, pending->batch->payload->recv_initial_metadata.recv_initial_metadata); // Update bookkeeping. // Note: Need to do this before invoking the callback, since invoking @@ -1649,14 +1279,23 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); + retry_state->completed_recv_initial_metadata = true; + // If a retry was already dispatched, then we're not going to use the + // result of this recv_initial_metadata op, so do nothing. + if (retry_state->retry_dispatched) { + GRPC_CALL_COMBINER_STOP( + calld->call_combiner, + "recv_initial_metadata_ready after retry dispatched"); + return; + } // If we got an error or a Trailers-Only response and have not yet gotten - // the recv_trailing_metadata on_complete callback, then defer - // propagating this callback back to the surface. We can evaluate whether - // to retry when recv_trailing_metadata comes back. - if ((batch_data->trailing_metadata_available || error != GRPC_ERROR_NONE) && - !retry_state->completed_recv_trailing_metadata) { + // the recv_trailing_metadata_ready callback, then defer propagating this + // callback back to the surface. We can evaluate whether to retry when + // recv_trailing_metadata comes back. + if (GPR_UNLIKELY((retry_state->trailing_metadata_available || + error != GRPC_ERROR_NONE) && + !retry_state->completed_recv_trailing_metadata)) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: deferring recv_initial_metadata_ready " @@ -1678,9 +1317,9 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { } // Received valid initial metadata, so commit the call. retry_commit(elem, retry_state); + // Invoke the callback to return the result to the surface. // Manually invoking a callback function; it does not take ownership of error. invoke_recv_initial_metadata_callback(batch_data, error); - GRPC_ERROR_UNREF(error); } // @@ -1690,29 +1329,20 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { // Invokes recv_message_ready for a subchannel batch. static void invoke_recv_message_callback(void* arg, grpc_error* error) { subchannel_batch_data* batch_data = static_cast(arg); - channel_data* chand = - static_cast(batch_data->elem->channel_data); - call_data* calld = static_cast(batch_data->elem->call_data); // Find pending op. - pending_batch* pending = nullptr; - for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { - grpc_transport_stream_op_batch* batch = calld->pending_batches[i].batch; - if (batch != nullptr && batch->recv_message && - batch->payload->recv_message.recv_message_ready != nullptr) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: invoking recv_message_ready for " - "pending batch at index %" PRIuPTR, - chand, calld, i); - } - pending = &calld->pending_batches[i]; - break; - } - } + pending_batch* pending = pending_batch_find( + batch_data->elem, "invoking recv_message_ready for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_message && + batch->payload->recv_message.recv_message_ready != nullptr; + }); GPR_ASSERT(pending != nullptr); // Return payload. + subchannel_call_retry_state* retry_state = + static_cast( + batch_data->subchannel_call->GetParentData()); *pending->batch->payload->recv_message.recv_message = - std::move(batch_data->recv_message); + std::move(retry_state->recv_message); // Update bookkeeping. // Note: Need to do this before invoking the callback, since invoking // the callback will result in yielding the call combiner. @@ -1738,14 +1368,22 @@ static void recv_message_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); + ++retry_state->completed_recv_message_count; + // If a retry was already dispatched, then we're not going to use the + // result of this recv_message op, so do nothing. + if (retry_state->retry_dispatched) { + GRPC_CALL_COMBINER_STOP(calld->call_combiner, + "recv_message_ready after retry dispatched"); + return; + } // If we got an error or the payload was nullptr and we have not yet gotten - // the recv_trailing_metadata on_complete callback, then defer - // propagating this callback back to the surface. We can evaluate whether - // to retry when recv_trailing_metadata comes back. - if ((batch_data->recv_message == nullptr || error != GRPC_ERROR_NONE) && - !retry_state->completed_recv_trailing_metadata) { + // the recv_trailing_metadata_ready callback, then defer propagating this + // callback back to the surface. We can evaluate whether to retry when + // recv_trailing_metadata comes back. + if (GPR_UNLIKELY( + (retry_state->recv_message == nullptr || error != GRPC_ERROR_NONE) && + !retry_state->completed_recv_trailing_metadata)) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: deferring recv_message_ready (nullptr " @@ -1765,135 +1403,274 @@ static void recv_message_ready(void* arg, grpc_error* error) { } // Received a valid message, so commit the call. retry_commit(elem, retry_state); + // Invoke the callback to return the result to the surface. // Manually invoking a callback function; it does not take ownership of error. invoke_recv_message_callback(batch_data, error); - GRPC_ERROR_UNREF(error); } // -// list of closures to execute in call combiner +// recv_trailing_metadata handling // -// Represents a closure that needs to run in the call combiner as part of -// starting or completing a batch. -typedef struct { - grpc_closure* closure; - grpc_error* error; - const char* reason; - bool free_reason = false; -} closure_to_execute; - -static void execute_closures_in_call_combiner(grpc_call_element* elem, - const char* caller, - closure_to_execute* closures, - size_t num_closures) { - channel_data* chand = static_cast(elem->channel_data); +// Sets *status and *server_pushback_md based on md_batch and error. +// Only sets *server_pushback_md if server_pushback_md != nullptr. +static void get_call_status(grpc_call_element* elem, + grpc_metadata_batch* md_batch, grpc_error* error, + grpc_status_code* status, + grpc_mdelem** server_pushback_md) { call_data* calld = static_cast(elem->call_data); - // Note that the call combiner will be yielded for each closure that - // we schedule. We're already running in the call combiner, so one of - // the closures can be scheduled directly, but the others will - // have to re-enter the call combiner. - if (num_closures > 0) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: %s starting closure: %s", chand, - calld, caller, closures[0].reason); - } - GRPC_CLOSURE_SCHED(closures[0].closure, closures[0].error); - if (closures[0].free_reason) { - gpr_free(const_cast(closures[0].reason)); - } - for (size_t i = 1; i < num_closures; ++i) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: %s starting closure in call combiner: %s", - chand, calld, caller, closures[i].reason); - } - GRPC_CALL_COMBINER_START(calld->call_combiner, closures[i].closure, - closures[i].error, closures[i].reason); - if (closures[i].free_reason) { - gpr_free(const_cast(closures[i].reason)); - } - } + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, calld->deadline, status, nullptr, nullptr, + nullptr); } else { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: no closures to run for %s", chand, - calld, caller); + GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); + *status = + grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md); + if (server_pushback_md != nullptr && + md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { + *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; } - GRPC_CALL_COMBINER_STOP(calld->call_combiner, "no closures to run"); } + GRPC_ERROR_UNREF(error); } -// -// on_complete callback handling -// - -// Updates retry_state to reflect the ops completed in batch_data. -static void update_retry_state_for_completed_batch( - subchannel_batch_data* batch_data, - subchannel_call_retry_state* retry_state) { - if (batch_data->batch.send_initial_metadata) { - retry_state->completed_send_initial_metadata = true; - } - if (batch_data->batch.send_message) { - ++retry_state->completed_send_message_count; - } - if (batch_data->batch.send_trailing_metadata) { - retry_state->completed_send_trailing_metadata = true; - } - if (batch_data->batch.recv_initial_metadata) { - retry_state->completed_recv_initial_metadata = true; - } - if (batch_data->batch.recv_message) { - ++retry_state->completed_recv_message_count; - } - if (batch_data->batch.recv_trailing_metadata) { - retry_state->completed_recv_trailing_metadata = true; +// Adds recv_trailing_metadata_ready closure to closures. +static void add_closure_for_recv_trailing_metadata_ready( + grpc_call_element* elem, subchannel_batch_data* batch_data, + grpc_error* error, grpc_core::CallCombinerClosureList* closures) { + // Find pending batch. + pending_batch* pending = pending_batch_find( + elem, "invoking recv_trailing_metadata for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_trailing_metadata && + batch->payload->recv_trailing_metadata + .recv_trailing_metadata_ready != nullptr; + }); + // If we generated the recv_trailing_metadata op internally via + // start_internal_recv_trailing_metadata(), then there will be no + // pending batch. + if (pending == nullptr) { + GRPC_ERROR_UNREF(error); + return; } + // Return metadata. + subchannel_call_retry_state* retry_state = + static_cast( + batch_data->subchannel_call->GetParentData()); + grpc_metadata_batch_move( + &retry_state->recv_trailing_metadata, + pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata); + // Add closure. + closures->Add(pending->batch->payload->recv_trailing_metadata + .recv_trailing_metadata_ready, + error, "recv_trailing_metadata_ready for pending batch"); + // Update bookkeeping. + pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + nullptr; + maybe_clear_pending_batch(elem, pending); } // Adds any necessary closures for deferred recv_initial_metadata and -// recv_message callbacks to closures, updating *num_closures as needed. +// recv_message callbacks to closures. static void add_closures_for_deferred_recv_callbacks( subchannel_batch_data* batch_data, subchannel_call_retry_state* retry_state, - closure_to_execute* closures, size_t* num_closures) { + grpc_core::CallCombinerClosureList* closures) { if (batch_data->batch.recv_trailing_metadata) { // Add closure for deferred recv_initial_metadata_ready. - if (retry_state->recv_initial_metadata_ready_deferred_batch != nullptr) { - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = GRPC_CLOSURE_INIT( - &batch_data->recv_initial_metadata_ready, - invoke_recv_initial_metadata_callback, - retry_state->recv_initial_metadata_ready_deferred_batch, - grpc_schedule_on_exec_ctx); - closure->error = retry_state->recv_initial_metadata_error; - closure->reason = "resuming recv_initial_metadata_ready"; + if (GPR_UNLIKELY(retry_state->recv_initial_metadata_ready_deferred_batch != + nullptr)) { + GRPC_CLOSURE_INIT(&retry_state->recv_initial_metadata_ready, + invoke_recv_initial_metadata_callback, + retry_state->recv_initial_metadata_ready_deferred_batch, + grpc_schedule_on_exec_ctx); + closures->Add(&retry_state->recv_initial_metadata_ready, + retry_state->recv_initial_metadata_error, + "resuming recv_initial_metadata_ready"); retry_state->recv_initial_metadata_ready_deferred_batch = nullptr; } // Add closure for deferred recv_message_ready. - if (retry_state->recv_message_ready_deferred_batch != nullptr) { - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = GRPC_CLOSURE_INIT( - &batch_data->recv_message_ready, invoke_recv_message_callback, - retry_state->recv_message_ready_deferred_batch, - grpc_schedule_on_exec_ctx); - closure->error = retry_state->recv_message_error; - closure->reason = "resuming recv_message_ready"; + if (GPR_UNLIKELY(retry_state->recv_message_ready_deferred_batch != + nullptr)) { + GRPC_CLOSURE_INIT(&retry_state->recv_message_ready, + invoke_recv_message_callback, + retry_state->recv_message_ready_deferred_batch, + grpc_schedule_on_exec_ctx); + closures->Add(&retry_state->recv_message_ready, + retry_state->recv_message_error, + "resuming recv_message_ready"); retry_state->recv_message_ready_deferred_batch = nullptr; } } } +// Returns true if any op in the batch was not yet started. +// Only looks at send ops, since recv ops are always started immediately. +static bool pending_batch_is_unstarted( + pending_batch* pending, call_data* calld, + subchannel_call_retry_state* retry_state) { + if (pending->batch == nullptr || pending->batch->on_complete == nullptr) { + return false; + } + if (pending->batch->send_initial_metadata && + !retry_state->started_send_initial_metadata) { + return true; + } + if (pending->batch->send_message && + retry_state->started_send_message_count < calld->send_messages.size()) { + return true; + } + if (pending->batch->send_trailing_metadata && + !retry_state->started_send_trailing_metadata) { + return true; + } + return false; +} + +// For any pending batch containing an op that has not yet been started, +// adds the pending batch's completion closures to closures. +static void add_closures_to_fail_unstarted_pending_batches( + grpc_call_element* elem, subchannel_call_retry_state* retry_state, + grpc_error* error, grpc_core::CallCombinerClosureList* closures) { + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { + pending_batch* pending = &calld->pending_batches[i]; + if (pending_batch_is_unstarted(pending, calld, retry_state)) { + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: failing unstarted pending batch at index " + "%" PRIuPTR, + chand, calld, i); + } + closures->Add(pending->batch->on_complete, GRPC_ERROR_REF(error), + "failing on_complete for pending batch"); + pending->batch->on_complete = nullptr; + maybe_clear_pending_batch(elem, pending); + } + } + GRPC_ERROR_UNREF(error); +} + +// Runs necessary closures upon completion of a call attempt. +static void run_closures_for_completed_call(subchannel_batch_data* batch_data, + grpc_error* error) { + grpc_call_element* elem = batch_data->elem; + call_data* calld = static_cast(elem->call_data); + subchannel_call_retry_state* retry_state = + static_cast( + batch_data->subchannel_call->GetParentData()); + // Construct list of closures to execute. + grpc_core::CallCombinerClosureList closures; + // First, add closure for recv_trailing_metadata_ready. + add_closure_for_recv_trailing_metadata_ready( + elem, batch_data, GRPC_ERROR_REF(error), &closures); + // If there are deferred recv_initial_metadata_ready or recv_message_ready + // callbacks, add them to closures. + add_closures_for_deferred_recv_callbacks(batch_data, retry_state, &closures); + // Add closures to fail any pending batches that have not yet been started. + add_closures_to_fail_unstarted_pending_batches( + elem, retry_state, GRPC_ERROR_REF(error), &closures); + // Don't need batch_data anymore. + batch_data_unref(batch_data); + // Schedule all of the closures identified above. + // Note: This will release the call combiner. + closures.RunClosures(calld->call_combiner); + GRPC_ERROR_UNREF(error); +} + +// Intercepts recv_trailing_metadata_ready callback for retries. +// Commits the call and returns the trailing metadata up the stack. +static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { + subchannel_batch_data* batch_data = static_cast(arg); + grpc_call_element* elem = batch_data->elem; + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready, error=%s", + chand, calld, grpc_error_string(error)); + } + subchannel_call_retry_state* retry_state = + static_cast( + batch_data->subchannel_call->GetParentData()); + retry_state->completed_recv_trailing_metadata = true; + // Get the call's status and check for server pushback metadata. + grpc_status_code status = GRPC_STATUS_OK; + grpc_mdelem* server_pushback_md = nullptr; + grpc_metadata_batch* md_batch = + batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, + &server_pushback_md); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand, + calld, grpc_status_code_to_string(status)); + } + // Check if we should retry. + if (maybe_retry(elem, batch_data, status, server_pushback_md)) { + // Unref batch_data for deferred recv_initial_metadata_ready or + // recv_message_ready callbacks, if any. + if (retry_state->recv_initial_metadata_ready_deferred_batch != nullptr) { + batch_data_unref(batch_data); + GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error); + } + if (retry_state->recv_message_ready_deferred_batch != nullptr) { + batch_data_unref(batch_data); + GRPC_ERROR_UNREF(retry_state->recv_message_error); + } + batch_data_unref(batch_data); + return; + } + // Not retrying, so commit the call. + retry_commit(elem, retry_state); + // Run any necessary closures. + run_closures_for_completed_call(batch_data, GRPC_ERROR_REF(error)); +} + +// +// on_complete callback handling +// + +// Adds the on_complete closure for the pending batch completed in +// batch_data to closures. +static void add_closure_for_completed_pending_batch( + grpc_call_element* elem, subchannel_batch_data* batch_data, + subchannel_call_retry_state* retry_state, grpc_error* error, + grpc_core::CallCombinerClosureList* closures) { + pending_batch* pending = pending_batch_find( + elem, "completed", [batch_data](grpc_transport_stream_op_batch* batch) { + // Match the pending batch with the same set of send ops as the + // subchannel batch we've just completed. + return batch->on_complete != nullptr && + batch_data->batch.send_initial_metadata == + batch->send_initial_metadata && + batch_data->batch.send_message == batch->send_message && + batch_data->batch.send_trailing_metadata == + batch->send_trailing_metadata; + }); + // If batch_data is a replay batch, then there will be no pending + // batch to complete. + if (pending == nullptr) { + GRPC_ERROR_UNREF(error); + return; + } + // Add closure. + closures->Add(pending->batch->on_complete, error, + "on_complete for pending batch"); + pending->batch->on_complete = nullptr; + maybe_clear_pending_batch(elem, pending); +} + // If there are any cached ops to replay or pending ops to start on the // subchannel call, adds a closure to closures to invoke -// start_retriable_subchannel_batches(), updating *num_closures as needed. +// start_retriable_subchannel_batches(). static void add_closures_for_replay_or_pending_send_ops( grpc_call_element* elem, subchannel_batch_data* batch_data, - subchannel_call_retry_state* retry_state, closure_to_execute* closures, - size_t* num_closures) { + subchannel_call_retry_state* retry_state, + grpc_core::CallCombinerClosureList* closures) { channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); bool have_pending_send_message_ops = - retry_state->started_send_message_count < calld->send_messages->size(); + retry_state->started_send_message_count < calld->send_messages.size(); bool have_pending_send_trailing_metadata_op = calld->seen_send_trailing_metadata && !retry_state->started_send_trailing_metadata; @@ -1915,93 +1692,12 @@ static void add_closures_for_replay_or_pending_send_ops( "chand=%p calld=%p: starting next batch for pending send op(s)", chand, calld); } - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = GRPC_CLOSURE_INIT( - &batch_data->batch.handler_private.closure, - start_retriable_subchannel_batches, elem, grpc_schedule_on_exec_ctx); - closure->error = GRPC_ERROR_NONE; - closure->reason = "starting next batch for send_* op(s)"; - } -} - -// For any pending batch completed in batch_data, adds the necessary -// completion closures to closures, updating *num_closures as needed. -static void add_closures_for_completed_pending_batches( - grpc_call_element* elem, subchannel_batch_data* batch_data, - subchannel_call_retry_state* retry_state, grpc_error* error, - closure_to_execute* closures, size_t* num_closures) { - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { - pending_batch* pending = &calld->pending_batches[i]; - if (pending_batch_is_completed(pending, calld, retry_state)) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: pending batch completed at index %" PRIuPTR, - chand, calld, i); - } - // Copy the trailing metadata to return it to the surface. - if (batch_data->batch.recv_trailing_metadata) { - grpc_metadata_batch_move(&batch_data->recv_trailing_metadata, - pending->batch->payload->recv_trailing_metadata - .recv_trailing_metadata); - } - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = pending->batch->on_complete; - closure->error = GRPC_ERROR_REF(error); - closure->reason = "on_complete for pending batch"; - pending->batch->on_complete = nullptr; - maybe_clear_pending_batch(elem, pending); - } - } - GRPC_ERROR_UNREF(error); -} - -// For any pending batch containing an op that has not yet been started, -// adds the pending batch's completion closures to closures, updating -// *num_closures as needed. -static void add_closures_to_fail_unstarted_pending_batches( - grpc_call_element* elem, subchannel_call_retry_state* retry_state, - grpc_error* error, closure_to_execute* closures, size_t* num_closures) { - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { - pending_batch* pending = &calld->pending_batches[i]; - if (pending_batch_is_unstarted(pending, calld, retry_state)) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: failing unstarted pending batch at index " - "%" PRIuPTR, - chand, calld, i); - } - if (pending->batch->recv_initial_metadata) { - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = pending->batch->payload->recv_initial_metadata - .recv_initial_metadata_ready; - closure->error = GRPC_ERROR_REF(error); - closure->reason = - "failing recv_initial_metadata_ready for pending batch"; - pending->batch->payload->recv_initial_metadata - .recv_initial_metadata_ready = nullptr; - } - if (pending->batch->recv_message) { - *pending->batch->payload->recv_message.recv_message = nullptr; - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = - pending->batch->payload->recv_message.recv_message_ready; - closure->error = GRPC_ERROR_REF(error); - closure->reason = "failing recv_message_ready for pending batch"; - pending->batch->payload->recv_message.recv_message_ready = nullptr; - } - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = pending->batch->on_complete; - closure->error = GRPC_ERROR_REF(error); - closure->reason = "failing on_complete for pending batch"; - pending->batch->on_complete = nullptr; - maybe_clear_pending_batch(elem, pending); - } + GRPC_CLOSURE_INIT(&batch_data->batch.handler_private.closure, + start_retriable_subchannel_batches, elem, + grpc_schedule_on_exec_ctx); + closures->Add(&batch_data->batch.handler_private.closure, GRPC_ERROR_NONE, + "starting next batch for send_* op(s)"); } - GRPC_ERROR_UNREF(error); } // Callback used to intercept on_complete from subchannel calls. @@ -2019,110 +1715,52 @@ static void on_complete(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); - // If we have previously completed recv_trailing_metadata, then the - // call is finished. - bool call_finished = retry_state->completed_recv_trailing_metadata; - // Record whether we were already committed before receiving this callback. - const bool previously_committed = calld->retry_committed; + batch_data->subchannel_call->GetParentData()); // Update bookkeeping in retry_state. - update_retry_state_for_completed_batch(batch_data, retry_state); - if (call_finished) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: call already finished", chand, - calld); - } - } else { - // Check if this batch finished the call, and if so, get its status. - // The call is finished if either (a) this callback was invoked with - // an error or (b) we receive status. - grpc_status_code status = GRPC_STATUS_OK; - grpc_mdelem* server_pushback_md = nullptr; - if (error != GRPC_ERROR_NONE) { // Case (a). - call_finished = true; - grpc_error_get_status(error, calld->deadline, &status, nullptr, nullptr, - nullptr); - } else if (batch_data->batch.recv_trailing_metadata) { // Case (b). - call_finished = true; - grpc_metadata_batch* md_batch = - batch_data->batch.payload->recv_trailing_metadata - .recv_trailing_metadata; - GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); - status = grpc_get_status_code_from_metadata( - md_batch->idx.named.grpc_status->md); - if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { - server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; - } - } - // If the call just finished, check if we should retry. - if (call_finished) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand, - calld, grpc_status_code_to_string(status)); - } - if (maybe_retry(elem, batch_data, status, server_pushback_md)) { - // Unref batch_data for deferred recv_initial_metadata_ready or - // recv_message_ready callbacks, if any. - if (batch_data->batch.recv_trailing_metadata && - retry_state->recv_initial_metadata_ready_deferred_batch != - nullptr) { - batch_data_unref(batch_data); - GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error); - } - if (batch_data->batch.recv_trailing_metadata && - retry_state->recv_message_ready_deferred_batch != nullptr) { - batch_data_unref(batch_data); - GRPC_ERROR_UNREF(retry_state->recv_message_error); - } - batch_data_unref(batch_data); - return; - } - // Not retrying, so commit the call. - retry_commit(elem, retry_state); - } + if (batch_data->batch.send_initial_metadata) { + retry_state->completed_send_initial_metadata = true; + } + if (batch_data->batch.send_message) { + ++retry_state->completed_send_message_count; + } + if (batch_data->batch.send_trailing_metadata) { + retry_state->completed_send_trailing_metadata = true; } - // If we were already committed before receiving this callback, free - // cached data for send ops that we've just completed. (If the call has - // just now finished, the call to retry_commit() above will have freed all - // cached send ops, so we don't need to do it here.) - if (previously_committed) { + // If the call is committed, free cached data for send ops that we've just + // completed. + if (calld->retry_committed) { free_cached_send_op_data_for_completed_batch(elem, batch_data, retry_state); } - // Call not being retried. // Construct list of closures to execute. - // Max number of closures is number of pending batches plus one for - // each of: - // - recv_initial_metadata_ready (either deferred or unstarted) - // - recv_message_ready (either deferred or unstarted) - // - starting a new batch for pending send ops - closure_to_execute closures[GPR_ARRAY_SIZE(calld->pending_batches) + 3]; - size_t num_closures = 0; - // If there are deferred recv_initial_metadata_ready or recv_message_ready - // callbacks, add them to closures. - add_closures_for_deferred_recv_callbacks(batch_data, retry_state, closures, - &num_closures); - // Find pending batches whose ops are now complete and add their - // on_complete callbacks to closures. - add_closures_for_completed_pending_batches(elem, batch_data, retry_state, - GRPC_ERROR_REF(error), closures, - &num_closures); - // Add closures to handle any pending batches that have not yet been started. - // If the call is finished, we fail these batches; otherwise, we add a - // callback to start_retriable_subchannel_batches() to start them on - // the subchannel call. - if (call_finished) { - add_closures_to_fail_unstarted_pending_batches( - elem, retry_state, GRPC_ERROR_REF(error), closures, &num_closures); - } else { - add_closures_for_replay_or_pending_send_ops(elem, batch_data, retry_state, - closures, &num_closures); - } + grpc_core::CallCombinerClosureList closures; + // If a retry was already dispatched, that means we saw + // recv_trailing_metadata before this, so we do nothing here. + // Otherwise, invoke the callback to return the result to the surface. + if (!retry_state->retry_dispatched) { + // Add closure for the completed pending batch, if any. + add_closure_for_completed_pending_batch(elem, batch_data, retry_state, + GRPC_ERROR_REF(error), &closures); + // If needed, add a callback to start any replay or pending send ops on + // the subchannel call. + if (!retry_state->completed_recv_trailing_metadata) { + add_closures_for_replay_or_pending_send_ops(elem, batch_data, retry_state, + &closures); + } + } + // Track number of pending subchannel send batches and determine if this + // was the last one. + --calld->num_pending_retriable_subchannel_send_batches; + const bool last_send_batch_complete = + calld->num_pending_retriable_subchannel_send_batches == 0; // Don't need batch_data anymore. batch_data_unref(batch_data); // Schedule all of the closures identified above. - execute_closures_in_call_combiner(elem, "on_complete", closures, - num_closures); + // Note: This yeilds the call combiner. + closures.RunClosures(calld->call_combiner); + // If this was the last subchannel send batch, unref the call stack. + if (last_send_batch_complete) { + GRPC_CALL_STACK_UNREF(calld->owning_call, "subchannel_send_batches"); + } } // @@ -2133,35 +1771,30 @@ static void on_complete(void* arg, grpc_error* error) { static void start_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_core::SubchannelCall* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(subchannel_call, batch); + subchannel_call->StartTransportStreamOpBatch(batch); } // Adds a closure to closures that will execute batch in the call combiner. static void add_closure_for_subchannel_batch( - call_data* calld, grpc_transport_stream_op_batch* batch, - closure_to_execute* closures, size_t* num_closures) { - batch->handler_private.extra_arg = calld->subchannel_call; + grpc_call_element* elem, grpc_transport_stream_op_batch* batch, + grpc_core::CallCombinerClosureList* closures) { + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + batch->handler_private.extra_arg = calld->subchannel_call.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, start_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = &batch->handler_private.closure; - closure->error = GRPC_ERROR_NONE; - // If the tracer is enabled, we log a more detailed message, which - // requires dynamic allocation. This will be freed in - // start_retriable_subchannel_batches(). if (grpc_client_channel_trace.enabled()) { char* batch_str = grpc_transport_stream_op_batch_string(batch); - gpr_asprintf(const_cast(&closure->reason), - "starting batch in call combiner: %s", batch_str); + gpr_log(GPR_INFO, "chand=%p calld=%p: starting subchannel batch: %s", chand, + calld, batch_str); gpr_free(batch_str); - closure->free_reason = true; - } else { - closure->reason = "start_subchannel_batch"; } + closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE, + "start_subchannel_batch"); } // Adds retriable send_initial_metadata op to batch_data. @@ -2177,30 +1810,30 @@ static void add_retriable_send_initial_metadata_op( // // If we've already completed one or more attempts, add the // grpc-retry-attempts header. - batch_data->send_initial_metadata_storage = + retry_state->send_initial_metadata_storage = static_cast(gpr_arena_alloc( calld->arena, sizeof(grpc_linked_mdelem) * (calld->send_initial_metadata.list.count + (calld->num_attempts_completed > 0)))); grpc_metadata_batch_copy(&calld->send_initial_metadata, - &batch_data->send_initial_metadata, - batch_data->send_initial_metadata_storage); - if (batch_data->send_initial_metadata.idx.named.grpc_previous_rpc_attempts != - nullptr) { - grpc_metadata_batch_remove( - &batch_data->send_initial_metadata, - batch_data->send_initial_metadata.idx.named.grpc_previous_rpc_attempts); - } - if (calld->num_attempts_completed > 0) { - grpc_mdelem retry_md = grpc_mdelem_from_slices( + &retry_state->send_initial_metadata, + retry_state->send_initial_metadata_storage); + if (GPR_UNLIKELY(retry_state->send_initial_metadata.idx.named + .grpc_previous_rpc_attempts != nullptr)) { + grpc_metadata_batch_remove(&retry_state->send_initial_metadata, + retry_state->send_initial_metadata.idx.named + .grpc_previous_rpc_attempts); + } + if (GPR_UNLIKELY(calld->num_attempts_completed > 0)) { + grpc_mdelem retry_md = grpc_mdelem_create( GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS, - *retry_count_strings[calld->num_attempts_completed - 1]); + *retry_count_strings[calld->num_attempts_completed - 1], nullptr); grpc_error* error = grpc_metadata_batch_add_tail( - &batch_data->send_initial_metadata, - &batch_data->send_initial_metadata_storage[calld->send_initial_metadata - .list.count], + &retry_state->send_initial_metadata, + &retry_state->send_initial_metadata_storage[calld->send_initial_metadata + .list.count], retry_md); - if (error != GRPC_ERROR_NONE) { + if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { gpr_log(GPR_ERROR, "error adding retry metadata: %s", grpc_error_string(error)); GPR_ASSERT(false); @@ -2209,7 +1842,7 @@ static void add_retriable_send_initial_metadata_op( retry_state->started_send_initial_metadata = true; batch_data->batch.send_initial_metadata = true; batch_data->batch.payload->send_initial_metadata.send_initial_metadata = - &batch_data->send_initial_metadata; + &retry_state->send_initial_metadata; batch_data->batch.payload->send_initial_metadata.send_initial_metadata_flags = calld->send_initial_metadata_flags; batch_data->batch.payload->send_initial_metadata.peer_string = @@ -2228,12 +1861,12 @@ static void add_retriable_send_message_op( chand, calld, retry_state->started_send_message_count); } grpc_core::ByteStreamCache* cache = - (*calld->send_messages)[retry_state->started_send_message_count]; + calld->send_messages[retry_state->started_send_message_count]; ++retry_state->started_send_message_count; - batch_data->send_message.Init(cache); + retry_state->send_message.Init(cache); batch_data->batch.send_message = true; batch_data->batch.payload->send_message.send_message.reset( - batch_data->send_message.get()); + retry_state->send_message.get()); } // Adds retriable send_trailing_metadata op to batch_data. @@ -2243,17 +1876,17 @@ static void add_retriable_send_trailing_metadata_op( // We need to make a copy of the metadata batch for each attempt, since // the filters in the subchannel stack may modify this batch, and we don't // want those modifications to be passed forward to subsequent attempts. - batch_data->send_trailing_metadata_storage = + retry_state->send_trailing_metadata_storage = static_cast(gpr_arena_alloc( calld->arena, sizeof(grpc_linked_mdelem) * calld->send_trailing_metadata.list.count)); grpc_metadata_batch_copy(&calld->send_trailing_metadata, - &batch_data->send_trailing_metadata, - batch_data->send_trailing_metadata_storage); + &retry_state->send_trailing_metadata, + retry_state->send_trailing_metadata_storage); retry_state->started_send_trailing_metadata = true; batch_data->batch.send_trailing_metadata = true; batch_data->batch.payload->send_trailing_metadata.send_trailing_metadata = - &batch_data->send_trailing_metadata; + &retry_state->send_trailing_metadata; } // Adds retriable recv_initial_metadata op to batch_data. @@ -2262,16 +1895,16 @@ static void add_retriable_recv_initial_metadata_op( subchannel_batch_data* batch_data) { retry_state->started_recv_initial_metadata = true; batch_data->batch.recv_initial_metadata = true; - grpc_metadata_batch_init(&batch_data->recv_initial_metadata); + grpc_metadata_batch_init(&retry_state->recv_initial_metadata); batch_data->batch.payload->recv_initial_metadata.recv_initial_metadata = - &batch_data->recv_initial_metadata; + &retry_state->recv_initial_metadata; batch_data->batch.payload->recv_initial_metadata.trailing_metadata_available = - &batch_data->trailing_metadata_available; - GRPC_CLOSURE_INIT(&batch_data->recv_initial_metadata_ready, + &retry_state->trailing_metadata_available; + GRPC_CLOSURE_INIT(&retry_state->recv_initial_metadata_ready, recv_initial_metadata_ready, batch_data, grpc_schedule_on_exec_ctx); batch_data->batch.payload->recv_initial_metadata.recv_initial_metadata_ready = - &batch_data->recv_initial_metadata_ready; + &retry_state->recv_initial_metadata_ready; } // Adds retriable recv_message op to batch_data. @@ -2281,11 +1914,11 @@ static void add_retriable_recv_message_op( ++retry_state->started_recv_message_count; batch_data->batch.recv_message = true; batch_data->batch.payload->recv_message.recv_message = - &batch_data->recv_message; - GRPC_CLOSURE_INIT(&batch_data->recv_message_ready, recv_message_ready, + &retry_state->recv_message; + GRPC_CLOSURE_INIT(&retry_state->recv_message_ready, recv_message_ready, batch_data, grpc_schedule_on_exec_ctx); batch_data->batch.payload->recv_message.recv_message_ready = - &batch_data->recv_message_ready; + &retry_state->recv_message_ready; } // Adds retriable recv_trailing_metadata op to batch_data. @@ -2294,12 +1927,19 @@ static void add_retriable_recv_trailing_metadata_op( subchannel_batch_data* batch_data) { retry_state->started_recv_trailing_metadata = true; batch_data->batch.recv_trailing_metadata = true; - grpc_metadata_batch_init(&batch_data->recv_trailing_metadata); + grpc_metadata_batch_init(&retry_state->recv_trailing_metadata); batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata = - &batch_data->recv_trailing_metadata; - batch_data->batch.collect_stats = true; - batch_data->batch.payload->collect_stats.collect_stats = - &batch_data->collect_stats; + &retry_state->recv_trailing_metadata; + batch_data->batch.payload->recv_trailing_metadata.collect_stats = + &retry_state->collect_stats; + GRPC_CLOSURE_INIT(&retry_state->recv_trailing_metadata_ready, + recv_trailing_metadata_ready, batch_data, + grpc_schedule_on_exec_ctx); + batch_data->batch.payload->recv_trailing_metadata + .recv_trailing_metadata_ready = + &retry_state->recv_trailing_metadata_ready; + maybe_inject_recv_trailing_metadata_ready_for_lb(*calld->request->pick(), + &batch_data->batch); } // Helper function used to start a recv_trailing_metadata batch. This @@ -2317,16 +1957,17 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); // Create batch_data with 2 refs, since this batch will be unreffed twice: - // once when the subchannel batch returns, and again when we actually get - // a recv_trailing_metadata op from the surface. - subchannel_batch_data* batch_data = batch_data_create(elem, 2); + // once for the recv_trailing_metadata_ready callback when the subchannel + // batch returns, and again when we actually get a recv_trailing_metadata + // op from the surface. + subchannel_batch_data* batch_data = + batch_data_create(elem, 2, false /* set_on_complete */); add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data); retry_state->recv_trailing_metadata_internal_batch = batch_data; // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, &batch_data->batch); + calld->subchannel_call->StartTransportStreamOpBatch(&batch_data->batch); } // If there are any cached send ops that need to be replayed on the @@ -2347,13 +1988,13 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay( "send_initial_metadata op", chand, calld); } - replay_batch_data = batch_data_create(elem, 1); + replay_batch_data = batch_data_create(elem, 1, true /* set_on_complete */); add_retriable_send_initial_metadata_op(calld, retry_state, replay_batch_data); } // send_message. // Note that we can only have one send_message op in flight at a time. - if (retry_state->started_send_message_count < calld->send_messages->size() && + if (retry_state->started_send_message_count < calld->send_messages.size() && retry_state->started_send_message_count == retry_state->completed_send_message_count && !calld->pending_send_message) { @@ -2364,7 +2005,8 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay( chand, calld); } if (replay_batch_data == nullptr) { - replay_batch_data = batch_data_create(elem, 1); + replay_batch_data = + batch_data_create(elem, 1, true /* set_on_complete */); } add_retriable_send_message_op(elem, retry_state, replay_batch_data); } @@ -2373,7 +2015,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay( // to start, since we can't send down any more send_message ops after // send_trailing_metadata. if (calld->seen_send_trailing_metadata && - retry_state->started_send_message_count == calld->send_messages->size() && + retry_state->started_send_message_count == calld->send_messages.size() && !retry_state->started_send_trailing_metadata && !calld->pending_send_trailing_metadata) { if (grpc_client_channel_trace.enabled()) { @@ -2383,7 +2025,8 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay( chand, calld); } if (replay_batch_data == nullptr) { - replay_batch_data = batch_data_create(elem, 1); + replay_batch_data = + batch_data_create(elem, 1, true /* set_on_complete */); } add_retriable_send_trailing_metadata_op(calld, retry_state, replay_batch_data); @@ -2395,7 +2038,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay( // *num_batches as needed. static void add_subchannel_batches_for_pending_batches( grpc_call_element* elem, subchannel_call_retry_state* retry_state, - closure_to_execute* closures, size_t* num_closures) { + grpc_core::CallCombinerClosureList* closures) { call_data* calld = static_cast(elem->call_data); for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { pending_batch* pending = &calld->pending_batches[i]; @@ -2424,7 +2067,7 @@ static void add_subchannel_batches_for_pending_batches( // send_message ops after send_trailing_metadata. if (batch->send_trailing_metadata && (retry_state->started_send_message_count + batch->send_message < - calld->send_messages->size() || + calld->send_messages.size() || retry_state->started_send_trailing_metadata)) { continue; } @@ -2441,22 +2084,19 @@ static void add_subchannel_batches_for_pending_batches( // If we previously completed a recv_trailing_metadata op // initiated by start_internal_recv_trailing_metadata(), use the // result of that instead of trying to re-start this op. - if (retry_state->recv_trailing_metadata_internal_batch != nullptr) { + if (GPR_UNLIKELY((retry_state->recv_trailing_metadata_internal_batch != + nullptr))) { // If the batch completed, then trigger the completion callback // directly, so that we return the previously returned results to // the application. Otherwise, just unref the internally // started subchannel batch, since we'll propagate the // completion when it completes. if (retry_state->completed_recv_trailing_metadata) { - subchannel_batch_data* batch_data = - retry_state->recv_trailing_metadata_internal_batch; - closure_to_execute* closure = &closures[(*num_closures)++]; - closure->closure = &batch_data->on_complete; // Batches containing recv_trailing_metadata always succeed. - closure->error = GRPC_ERROR_NONE; - closure->reason = - "re-executing on_complete for recv_trailing_metadata " - "to propagate internally triggered result"; + closures->Add( + &retry_state->recv_trailing_metadata_ready, GRPC_ERROR_NONE, + "re-executing recv_trailing_metadata_ready to propagate " + "internally triggered result"); } else { batch_data_unref(retry_state->recv_trailing_metadata_internal_batch); } @@ -2468,14 +2108,19 @@ static void add_subchannel_batches_for_pending_batches( if (calld->method_params == nullptr || calld->method_params->retry_policy() == nullptr || calld->retry_committed) { - add_closure_for_subchannel_batch(calld, batch, closures, num_closures); + add_closure_for_subchannel_batch(elem, batch, closures); pending_batch_clear(calld, pending); continue; } // Create batch with the right number of callbacks. - const int num_callbacks = - 1 + batch->recv_initial_metadata + batch->recv_message; - subchannel_batch_data* batch_data = batch_data_create(elem, num_callbacks); + const bool has_send_ops = batch->send_initial_metadata || + batch->send_message || + batch->send_trailing_metadata; + const int num_callbacks = has_send_ops + batch->recv_initial_metadata + + batch->recv_message + + batch->recv_trailing_metadata; + subchannel_batch_data* batch_data = batch_data_create( + elem, num_callbacks, has_send_ops /* set_on_complete */); // Cache send ops if needed. maybe_cache_send_ops_for_batch(calld, pending); // send_initial_metadata. @@ -2502,11 +2147,18 @@ static void add_subchannel_batches_for_pending_batches( } // recv_trailing_metadata. if (batch->recv_trailing_metadata) { - GPR_ASSERT(batch->collect_stats); add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data); } - add_closure_for_subchannel_batch(calld, &batch_data->batch, closures, - num_closures); + add_closure_for_subchannel_batch(elem, &batch_data->batch, closures); + // Track number of pending subchannel send batches. + // If this is the first one, take a ref to the call stack. + if (batch->send_initial_metadata || batch->send_message || + batch->send_trailing_metadata) { + if (calld->num_pending_retriable_subchannel_send_batches == 0) { + GRPC_CALL_STACK_REF(calld->owning_call, "subchannel_send_batches"); + } + ++calld->num_pending_retriable_subchannel_send_batches; + } } } @@ -2522,31 +2174,33 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); // Construct list of closures to execute, one for each pending batch. - // We can start up to 6 batches. - closure_to_execute closures[GPR_ARRAY_SIZE(calld->pending_batches)]; - size_t num_closures = 0; + grpc_core::CallCombinerClosureList closures; // Replay previously-returned send_* ops if needed. subchannel_batch_data* replay_batch_data = maybe_create_subchannel_batch_for_replay(elem, retry_state); if (replay_batch_data != nullptr) { - add_closure_for_subchannel_batch(calld, &replay_batch_data->batch, closures, - &num_closures); + add_closure_for_subchannel_batch(elem, &replay_batch_data->batch, + &closures); + // Track number of pending subchannel send batches. + // If this is the first one, take a ref to the call stack. + if (calld->num_pending_retriable_subchannel_send_batches == 0) { + GRPC_CALL_STACK_REF(calld->owning_call, "subchannel_send_batches"); + } + ++calld->num_pending_retriable_subchannel_send_batches; } // Now add pending batches. - add_subchannel_batches_for_pending_batches(elem, retry_state, closures, - &num_closures); + add_subchannel_batches_for_pending_batches(elem, retry_state, &closures); // Start batches on subchannel call. if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " retriable batches on subchannel_call=%p", - chand, calld, num_closures, calld->subchannel_call); + chand, calld, closures.size(), calld->subchannel_call.get()); } - execute_closures_in_call_combiner(elem, "start_retriable_subchannel_batches", - closures, num_closures); + // Note: This will yield the call combiner. + closures.RunClosures(calld->call_combiner); } // @@ -2559,31 +2213,31 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { const size_t parent_data_size = calld->enable_retries ? sizeof(subchannel_call_retry_state) : 0; const grpc_core::ConnectedSubchannel::CallArgs call_args = { - calld->pollent, // pollent - calld->path, // path - calld->call_start_time, // start_time - calld->deadline, // deadline - calld->arena, // arena - calld->pick.subchannel_call_context, // context - calld->call_combiner, // call_combiner - parent_data_size // parent_data_size + calld->pollent, // pollent + calld->path, // path + calld->call_start_time, // start_time + calld->deadline, // deadline + calld->arena, // arena + calld->request->pick()->subchannel_call_context, // context + calld->call_combiner, // call_combiner + parent_data_size // parent_data_size }; - grpc_error* new_error = calld->pick.connected_subchannel->CreateCall( - call_args, &calld->subchannel_call); + grpc_error* new_error = GRPC_ERROR_NONE; + calld->subchannel_call = + calld->request->pick()->connected_subchannel->CreateCall(call_args, + &new_error); if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s", - chand, calld, calld->subchannel_call, grpc_error_string(new_error)); + chand, calld, calld->subchannel_call.get(), + grpc_error_string(new_error)); } - if (new_error != GRPC_ERROR_NONE) { + if (GPR_UNLIKELY(new_error != GRPC_ERROR_NONE)) { new_error = grpc_error_add_child(new_error, error); pending_batches_fail(elem, new_error, true /* yield_call_combiner */); } else { if (parent_data_size > 0) { - subchannel_call_retry_state* retry_state = - static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); - retry_state->batch_payload.context = calld->pick.subchannel_call_context; + new (calld->subchannel_call->GetParentData()) subchannel_call_retry_state( + calld->request->pick()->subchannel_call_context); } pending_batches_resume(elem); } @@ -2595,7 +2249,7 @@ static void pick_done(void* arg, grpc_error* error) { grpc_call_element* elem = static_cast(arg); channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); - if (calld->pick.connected_subchannel == nullptr) { + if (GPR_UNLIKELY(calld->request->pick()->connected_subchannel == nullptr)) { // Failed to create subchannel. // If there was no error, this is an LB policy drop, in which case // we return an error; otherwise, we may retry. @@ -2624,58 +2278,25 @@ static void pick_done(void* arg, grpc_error* error) { } } -// Invoked when a pick is completed to leave the client_channel combiner -// and continue processing in the call combiner. -static void pick_done_locked(grpc_call_element* elem, grpc_error* error) { - call_data* calld = static_cast(elem->call_data); - GRPC_CLOSURE_INIT(&calld->pick_closure, pick_done, elem, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_SCHED(&calld->pick_closure, error); -} - -// A wrapper around pick_done_locked() that is used in cases where -// either (a) the pick was deferred pending a resolver result or (b) the -// pick was done asynchronously. Removes the call's polling entity from -// chand->interested_parties before invoking pick_done_locked(). -static void async_pick_done_locked(grpc_call_element* elem, grpc_error* error) { - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - grpc_polling_entity_del_from_pollset_set(calld->pollent, - chand->interested_parties); - pick_done_locked(elem, error); -} - -// Note: This runs under the client_channel combiner, but will NOT be -// holding the call combiner. -static void pick_callback_cancel_locked(void* arg, grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - // Note: chand->lb_policy may have changed since we started our pick, - // in which case we will be cancelling the pick on a policy other than - // the one we started it on. However, this will just be a no-op. - if (error != GRPC_ERROR_NONE && chand->lb_policy != nullptr) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling pick from LB policy %p", - chand, calld, chand->lb_policy.get()); - } - chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error)); - } - GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback_cancel"); -} - -// Callback invoked by LoadBalancingPolicy::PickLocked() for async picks. -// Unrefs the LB policy and invokes async_pick_done_locked(). -static void pick_callback_done_locked(void* arg, grpc_error* error) { - grpc_call_element* elem = static_cast(arg); +// If the channel is in TRANSIENT_FAILURE and the call is not +// wait_for_ready=true, fails the call and returns true. +static bool fail_call_if_in_transient_failure(grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed asynchronously", chand, - calld); + grpc_transport_stream_op_batch* batch = calld->pending_batches[0].batch; + if (chand->request_router->GetConnectivityState() == + GRPC_CHANNEL_TRANSIENT_FAILURE && + (batch->payload->send_initial_metadata.send_initial_metadata_flags & + GRPC_INITIAL_METADATA_WAIT_FOR_READY) == 0) { + pending_batches_fail( + elem, + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "channel is in state TRANSIENT_FAILURE"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + true /* yield_call_combiner */); + return true; } - async_pick_done_locked(elem, GRPC_ERROR_REF(error)); - GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback"); + return false; } // Applies service config to the call. Must be invoked once we know @@ -2706,6 +2327,24 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) { grpc_deadline_state_reset(elem, calld->deadline); } } + // If the service config set wait_for_ready and the application + // did not explicitly set it, use the value from the service config. + uint32_t* send_initial_metadata_flags = + &calld->pending_batches[0] + .batch->payload->send_initial_metadata + .send_initial_metadata_flags; + if (GPR_UNLIKELY( + calld->method_params->wait_for_ready() != + ClientChannelMethodParams::WAIT_FOR_READY_UNSET && + !(*send_initial_metadata_flags & + GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET))) { + if (calld->method_params->wait_for_ready() == + ClientChannelMethodParams::WAIT_FOR_READY_TRUE) { + *send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY; + } else { + *send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; + } + } } } // If no retry policy, disable retries. @@ -2716,247 +2355,66 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) { } } -// Starts a pick on chand->lb_policy. -// Returns true if pick is completed synchronously. -static bool pick_callback_start_locked(grpc_call_element* elem) { - channel_data* chand = static_cast(elem->channel_data); +// Invoked once resolver results are available. +static bool maybe_apply_service_config_to_call_locked(void* arg) { + grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: starting pick on lb_policy=%p", chand, - calld, chand->lb_policy.get()); - } // Only get service config data on the first attempt. - if (calld->num_attempts_completed == 0) { + if (GPR_LIKELY(calld->num_attempts_completed == 0)) { apply_service_config_to_call_locked(elem); + // Check this after applying service config, since it may have + // affected the call's wait_for_ready value. + if (fail_call_if_in_transient_failure(elem)) return false; } - // If the application explicitly set wait_for_ready, use that. - // Otherwise, if the service config specified a value for this - // method, use that. - // - // The send_initial_metadata batch will be the first one in the list, - // as set by get_batch_index() above. - calld->pick.initial_metadata = - calld->seen_send_initial_metadata - ? &calld->send_initial_metadata - : calld->pending_batches[0] - .batch->payload->send_initial_metadata.send_initial_metadata; - uint32_t send_initial_metadata_flags = - calld->seen_send_initial_metadata - ? calld->send_initial_metadata_flags - : calld->pending_batches[0] - .batch->payload->send_initial_metadata - .send_initial_metadata_flags; - const bool wait_for_ready_set_from_api = - send_initial_metadata_flags & - GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET; - const bool wait_for_ready_set_from_service_config = - calld->method_params != nullptr && - calld->method_params->wait_for_ready() != - ClientChannelMethodParams::WAIT_FOR_READY_UNSET; - if (!wait_for_ready_set_from_api && wait_for_ready_set_from_service_config) { - if (calld->method_params->wait_for_ready() == - ClientChannelMethodParams::WAIT_FOR_READY_TRUE) { - send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY; - } else { - send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; - } - } - calld->pick.initial_metadata_flags = send_initial_metadata_flags; - GRPC_CLOSURE_INIT(&calld->pick_closure, pick_callback_done_locked, elem, - grpc_combiner_scheduler(chand->combiner)); - calld->pick.on_complete = &calld->pick_closure; - GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback"); - const bool pick_done = chand->lb_policy->PickLocked(&calld->pick); - if (pick_done) { - // Pick completed synchronously. - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed synchronously", - chand, calld); - } - GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback"); - } else { - GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback_cancel"); - grpc_call_combiner_set_notify_on_cancel( - calld->call_combiner, - GRPC_CLOSURE_INIT(&calld->pick_cancel_closure, - pick_callback_cancel_locked, elem, - grpc_combiner_scheduler(chand->combiner))); - } - return pick_done; -} - -typedef struct { - grpc_call_element* elem; - bool finished; - grpc_closure closure; - grpc_closure cancel_closure; -} pick_after_resolver_result_args; - -// Note: This runs under the client_channel combiner, but will NOT be -// holding the call combiner. -static void pick_after_resolver_result_cancel_locked(void* arg, - grpc_error* error) { - pick_after_resolver_result_args* args = - static_cast(arg); - if (args->finished) { - gpr_free(args); - return; - } - // If we don't yet have a resolver result, then a closure for - // pick_after_resolver_result_done_locked() will have been added to - // chand->waiting_for_resolver_result_closures, and it may not be invoked - // until after this call has been destroyed. We mark the operation as - // finished, so that when pick_after_resolver_result_done_locked() - // is called, it will be a no-op. We also immediately invoke - // async_pick_done_locked() to propagate the error back to the caller. - args->finished = true; - grpc_call_element* elem = args->elem; - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: cancelling pick waiting for resolver result", - chand, calld); - } - // Note: Although we are not in the call combiner here, we are - // basically stealing the call combiner from the pending pick, so - // it's safe to call async_pick_done_locked() here -- we are - // essentially calling it here instead of calling it in - // pick_after_resolver_result_done_locked(). - async_pick_done_locked(elem, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Pick cancelled", &error, 1)); -} - -static void pick_after_resolver_result_done_locked(void* arg, - grpc_error* error) { - pick_after_resolver_result_args* args = - static_cast(arg); - if (args->finished) { - /* cancelled, do nothing */ - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "call cancelled before resolver result"); - } - gpr_free(args); - return; - } - args->finished = true; - grpc_call_element* elem = args->elem; - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (error != GRPC_ERROR_NONE) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: resolver failed to return data", - chand, calld); - } - async_pick_done_locked(elem, GRPC_ERROR_REF(error)); - } else if (chand->resolver == nullptr) { - // Shutting down. - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand, - calld); - } - async_pick_done_locked( - elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); - } else if (chand->lb_policy == nullptr) { - // Transient resolver failure. - // If call has wait_for_ready=true, try again; otherwise, fail. - uint32_t send_initial_metadata_flags = - calld->seen_send_initial_metadata - ? calld->send_initial_metadata_flags - : calld->pending_batches[0] - .batch->payload->send_initial_metadata - .send_initial_metadata_flags; - if (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: resolver returned but no LB policy; " - "wait_for_ready=true; trying again", - chand, calld); - } - pick_after_resolver_result_start_locked(elem); - } else { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: resolver returned but no LB policy; " - "wait_for_ready=false; failing", - chand, calld); - } - async_pick_done_locked( - elem, - grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); - } - } else { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing pick", - chand, calld); - } - if (pick_callback_start_locked(elem)) { - // Even if the LB policy returns a result synchronously, we have - // already added our polling entity to chand->interested_parties - // in order to wait for the resolver result, so we need to - // remove it here. Therefore, we call async_pick_done_locked() - // instead of pick_done_locked(). - async_pick_done_locked(elem, GRPC_ERROR_NONE); - } - } -} - -static void pick_after_resolver_result_start_locked(grpc_call_element* elem) { - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: deferring pick pending resolver result", chand, - calld); - } - pick_after_resolver_result_args* args = - static_cast(gpr_zalloc(sizeof(*args))); - args->elem = elem; - GRPC_CLOSURE_INIT(&args->closure, pick_after_resolver_result_done_locked, - args, grpc_combiner_scheduler(chand->combiner)); - grpc_closure_list_append(&chand->waiting_for_resolver_result_closures, - &args->closure, GRPC_ERROR_NONE); - grpc_call_combiner_set_notify_on_cancel( - calld->call_combiner, - GRPC_CLOSURE_INIT(&args->cancel_closure, - pick_after_resolver_result_cancel_locked, args, - grpc_combiner_scheduler(chand->combiner))); + return true; } static void start_pick_locked(void* arg, grpc_error* ignored) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); - GPR_ASSERT(calld->pick.connected_subchannel == nullptr); + GPR_ASSERT(!calld->have_request); GPR_ASSERT(calld->subchannel_call == nullptr); - if (chand->lb_policy != nullptr) { - // We already have an LB policy, so ask it for a pick. - if (pick_callback_start_locked(elem)) { - // Pick completed synchronously. - pick_done_locked(elem, GRPC_ERROR_NONE); - return; - } - } else { - // We do not yet have an LB policy, so wait for a resolver result. - if (chand->resolver == nullptr) { - pick_done_locked(elem, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); - return; - } - if (!chand->started_resolving) { - start_resolving_locked(chand); - } - pick_after_resolver_result_start_locked(elem); + // Normally, we want to do this check until after we've processed the + // service config, so that we can honor the wait_for_ready setting in + // the service config. However, if the channel is in TRANSIENT_FAILURE + // and we don't have an LB policy at this point, that means that the + // resolver has returned a failure, so we're not going to get a service + // config right away. In that case, we fail the call now based on the + // wait_for_ready value passed in from the application. + if (chand->request_router->lb_policy() == nullptr && + fail_call_if_in_transient_failure(elem)) { + return; } - // We need to wait for either a resolver result or for an async result - // from the LB policy. Add the polling entity from call_data to the - // channel_data's interested_parties, so that the I/O of the LB policy - // and resolver can be done under it. The polling entity will be - // removed in async_pick_done_locked(). - grpc_polling_entity_add_to_pollset_set(calld->pollent, - chand->interested_parties); + // If this is a retry, use the send_initial_metadata payload that + // we've cached; otherwise, use the pending batch. The + // send_initial_metadata batch will be the first pending batch in the + // list, as set by get_batch_index() above. + // TODO(roth): What if the LB policy needs to add something to the + // call's initial metadata, and then there's a retry? We don't want + // the new metadata to be added twice. We might need to somehow + // allocate the subchannel batch earlier so that we can give the + // subchannel's copy of the metadata batch (which is copied for each + // attempt) to the LB policy instead the one from the parent channel. + grpc_metadata_batch* initial_metadata = + calld->seen_send_initial_metadata + ? &calld->send_initial_metadata + : calld->pending_batches[0] + .batch->payload->send_initial_metadata.send_initial_metadata; + uint32_t* initial_metadata_flags = + calld->seen_send_initial_metadata + ? &calld->send_initial_metadata_flags + : &calld->pending_batches[0] + .batch->payload->send_initial_metadata + .send_initial_metadata_flags; + GRPC_CLOSURE_INIT(&calld->pick_closure, pick_done, elem, + grpc_schedule_on_exec_ctx); + calld->request.Init(calld->owning_call, calld->call_combiner, calld->pollent, + initial_metadata, initial_metadata_flags, + maybe_apply_service_config_to_call_locked, elem, + &calld->pick_closure); + calld->have_request = true; + chand->request_router->RouteCallLocked(calld->request.get()); } // @@ -2968,11 +2426,11 @@ static void cc_start_transport_stream_op_batch( GPR_TIMER_SCOPE("cc_start_transport_stream_op_batch", 0); call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); - if (chand->deadline_checking_enabled) { + if (GPR_LIKELY(chand->deadline_checking_enabled)) { grpc_deadline_state_client_start_transport_stream_op_batch(elem, batch); } // If we've previously been cancelled, immediately fail any new batches. - if (calld->cancel_error != GRPC_ERROR_NONE) { + if (GPR_UNLIKELY(calld->cancel_error != GRPC_ERROR_NONE)) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: failing batch with error: %s", chand, calld, grpc_error_string(calld->cancel_error)); @@ -2983,7 +2441,7 @@ static void cc_start_transport_stream_op_batch( return; } // Handle cancellation. - if (batch->cancel_stream) { + if (GPR_UNLIKELY(batch->cancel_stream)) { // Stash a copy of cancel_error in our call data, so that we can use // it for subsequent operations. This ensures that if the call is // cancelled before any batches are passed down (e.g., if the deadline @@ -3007,7 +2465,7 @@ static void cc_start_transport_stream_op_batch( batch, GRPC_ERROR_REF(calld->cancel_error), calld->call_combiner); } else { // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, batch); + calld->subchannel_call->StartTransportStreamOpBatch(batch); } return; } @@ -3021,7 +2479,7 @@ static void cc_start_transport_stream_op_batch( if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting batch on subchannel_call=%p", chand, - calld, calld->subchannel_call); + calld, calld->subchannel_call.get()); } pending_batches_resume(elem); return; @@ -3029,7 +2487,7 @@ static void cc_start_transport_stream_op_batch( // We do not yet have a subchannel call. // For batches containing a send_initial_metadata op, enter the channel // combiner to start a pick. - if (batch->send_initial_metadata) { + if (GPR_LIKELY(batch->send_initial_metadata)) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: entering client_channel combiner", chand, calld); @@ -3042,7 +2500,7 @@ static void cc_start_transport_stream_op_batch( // For all other batches, release the call combiner. if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, - "chand=%p calld=%p: saved batch, yeilding call combiner", chand, + "chand=%p calld=%p: saved batch, yielding call combiner", chand, calld); } GRPC_CALL_COMBINER_STOP(calld->call_combiner, @@ -3053,21 +2511,8 @@ static void cc_start_transport_stream_op_batch( /* Constructor for call_data */ static grpc_error* cc_init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); - // Initialize data members. - calld->path = grpc_slice_ref_internal(args->path); - calld->call_start_time = args->start_time; - calld->deadline = args->deadline; - calld->arena = args->arena; - calld->owning_call = args->call_stack; - calld->call_combiner = args->call_combiner; - if (chand->deadline_checking_enabled) { - grpc_deadline_state_init(elem, args->call_stack, args->call_combiner, - calld->deadline); - } - calld->enable_retries = chand->enable_retries; - calld->send_messages.Init(); + new (elem->call_data) call_data(elem, *chand, *args); return GRPC_ERROR_NONE; } @@ -3076,34 +2521,11 @@ static void cc_destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* then_schedule_closure) { call_data* calld = static_cast(elem->call_data); - channel_data* chand = static_cast(elem->channel_data); - if (chand->deadline_checking_enabled) { - grpc_deadline_state_destroy(elem); - } - grpc_slice_unref_internal(calld->path); - calld->retry_throttle_data.reset(); - calld->method_params.reset(); - GRPC_ERROR_UNREF(calld->cancel_error); - if (calld->subchannel_call != nullptr) { - grpc_subchannel_call_set_cleanup_closure(calld->subchannel_call, - then_schedule_closure); + if (GPR_LIKELY(calld->subchannel_call != nullptr)) { + calld->subchannel_call->SetAfterCallStackDestroy(then_schedule_closure); then_schedule_closure = nullptr; - GRPC_SUBCHANNEL_CALL_UNREF(calld->subchannel_call, - "client_channel_destroy_call"); - } - for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { - GPR_ASSERT(calld->pending_batches[i].batch == nullptr); - } - if (calld->pick.connected_subchannel != nullptr) { - calld->pick.connected_subchannel.reset(); - } - for (size_t i = 0; i < GRPC_CONTEXT_COUNT; ++i) { - if (calld->pick.subchannel_call_context[i].value != nullptr) { - calld->pick.subchannel_call_context[i].destroy( - calld->pick.subchannel_call_context[i].value); - } } - calld->send_messages.Destroy(); + calld->~call_data(); GRPC_CLOSURE_SCHED(then_schedule_closure, GRPC_ERROR_NONE); } @@ -3131,24 +2553,33 @@ const grpc_channel_filter grpc_client_channel_filter = { "client-channel", }; +void grpc_client_channel_set_channelz_node( + grpc_channel_element* elem, grpc_core::channelz::ClientChannelNode* node) { + channel_data* chand = static_cast(elem->channel_data); + chand->request_router->set_channelz_node(node); +} + +void grpc_client_channel_populate_child_refs( + grpc_channel_element* elem, + grpc_core::channelz::ChildRefsList* child_subchannels, + grpc_core::channelz::ChildRefsList* child_channels) { + channel_data* chand = static_cast(elem->channel_data); + if (chand->request_router->lb_policy() != nullptr) { + chand->request_router->lb_policy()->FillChildRefsForChannelz( + child_subchannels, child_channels); + } +} + static void try_to_connect_locked(void* arg, grpc_error* error_ignored) { channel_data* chand = static_cast(arg); - if (chand->lb_policy != nullptr) { - chand->lb_policy->ExitIdleLocked(); - } else { - chand->exit_idle_when_lb_policy_arrives = true; - if (!chand->started_resolving && chand->resolver != nullptr) { - start_resolving_locked(chand); - } - } + chand->request_router->ExitIdleLocked(); GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "try_to_connect"); } grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_channel_element* elem, int try_to_connect) { channel_data* chand = static_cast(elem->channel_data); - grpc_connectivity_state out = - grpc_connectivity_state_check(&chand->state_tracker); + grpc_connectivity_state out = chand->request_router->GetConnectivityState(); if (out == GRPC_CHANNEL_IDLE && try_to_connect) { GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect"); GRPC_CLOSURE_SCHED( @@ -3193,19 +2624,19 @@ static void external_connectivity_watcher_list_append( } static void external_connectivity_watcher_list_remove( - channel_data* chand, external_connectivity_watcher* too_remove) { + channel_data* chand, external_connectivity_watcher* to_remove) { GPR_ASSERT( - lookup_external_connectivity_watcher(chand, too_remove->on_complete)); + lookup_external_connectivity_watcher(chand, to_remove->on_complete)); gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - if (too_remove == chand->external_connectivity_watcher_list_head) { - chand->external_connectivity_watcher_list_head = too_remove->next; + if (to_remove == chand->external_connectivity_watcher_list_head) { + chand->external_connectivity_watcher_list_head = to_remove->next; gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); return; } external_connectivity_watcher* w = chand->external_connectivity_watcher_list_head; while (w != nullptr) { - if (w->next == too_remove) { + if (w->next == to_remove) { w->next = w->next->next; gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); return; @@ -3242,7 +2673,7 @@ static void on_external_watch_complete_locked(void* arg, grpc_error* error) { "external_connectivity_watcher"); external_connectivity_watcher_list_remove(w->chand, w); gpr_free(w); - GRPC_CLOSURE_RUN(follow_up, GRPC_ERROR_REF(error)); + GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); } static void watch_connectivity_state_locked(void* arg, @@ -3257,15 +2688,15 @@ static void watch_connectivity_state_locked(void* arg, GRPC_CLOSURE_RUN(w->watcher_timer_init, GRPC_ERROR_NONE); GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete_locked, w, grpc_combiner_scheduler(w->chand->combiner)); - grpc_connectivity_state_notify_on_state_change(&w->chand->state_tracker, - w->state, &w->my_closure); + w->chand->request_router->NotifyOnConnectivityStateChange(w->state, + &w->my_closure); } else { GPR_ASSERT(w->watcher_timer_init == nullptr); found = lookup_external_connectivity_watcher(w->chand, w->on_complete); if (found) { GPR_ASSERT(found->on_complete == w->on_complete); - grpc_connectivity_state_notify_on_state_change( - &found->chand->state_tracker, nullptr, &found->my_closure); + found->chand->request_router->NotifyOnConnectivityStateChange( + nullptr, &found->my_closure); } grpc_polling_entity_del_from_pollset_set(&w->pollent, w->chand->interested_parties); @@ -3297,8 +2728,8 @@ void grpc_client_channel_watch_connectivity_state( GRPC_ERROR_NONE); } -grpc_subchannel_call* grpc_client_channel_get_subchannel_call( - grpc_call_element* elem) { +grpc_core::RefCountedPtr +grpc_client_channel_get_subchannel_call(grpc_call_element* elem) { call_data* calld = static_cast(elem->call_data); return calld->subchannel_call; } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.h b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.h index a21e5623a..5bfff4df9 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel.h @@ -21,6 +21,7 @@ #include +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/lib/channel/channel_stack.h" @@ -39,6 +40,14 @@ extern grpc_core::TraceFlag grpc_client_channel_trace; extern const grpc_channel_filter grpc_client_channel_filter; +void grpc_client_channel_set_channelz_node( + grpc_channel_element* elem, grpc_core::channelz::ClientChannelNode* node); + +void grpc_client_channel_populate_child_refs( + grpc_channel_element* elem, + grpc_core::channelz::ChildRefsList* child_subchannels, + grpc_core::channelz::ChildRefsList* child_channels); + grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_channel_element* elem, int try_to_connect); @@ -51,7 +60,7 @@ void grpc_client_channel_watch_connectivity_state( grpc_closure* watcher_timer_init); /* Debug helper: pull the subchannel call from a call stack element */ -grpc_subchannel_call* grpc_client_channel_get_subchannel_call( - grpc_call_element* elem); +grpc_core::RefCountedPtr +grpc_client_channel_get_subchannel_call(grpc_call_element* elem); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_channelz.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_channelz.cc new file mode 100644 index 000000000..76c5a7862 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -0,0 +1,185 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include "src/core/lib/channel/channelz_registry.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/connectivity_state.h" + +#include + +namespace grpc_core { +namespace channelz { +namespace { + +void* client_channel_channelz_copy(void* p) { return p; } + +void client_channel_channelz_destroy(void* p) {} + +int client_channel_channelz_cmp(void* a, void* b) { return GPR_ICMP(a, b); } + +} // namespace + +static const grpc_arg_pointer_vtable client_channel_channelz_vtable = { + client_channel_channelz_copy, client_channel_channelz_destroy, + client_channel_channelz_cmp}; + +ClientChannelNode::ClientChannelNode(grpc_channel* channel, + size_t channel_tracer_max_nodes, + bool is_top_level_channel) + : ChannelNode(channel, channel_tracer_max_nodes, is_top_level_channel) { + client_channel_ = + grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + grpc_client_channel_set_channelz_node(client_channel_, this); + GPR_ASSERT(client_channel_->filter == &grpc_client_channel_filter); +} + +void ClientChannelNode::PopulateConnectivityState(grpc_json* json) { + grpc_connectivity_state state; + if (ChannelIsDestroyed()) { + state = GRPC_CHANNEL_SHUTDOWN; + } else { + state = + grpc_client_channel_check_connectivity_state(client_channel_, false); + } + json = grpc_json_create_child(nullptr, json, "state", nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_create_child(nullptr, json, "state", + grpc_connectivity_state_name(state), GRPC_JSON_STRING, + false); +} + +void ClientChannelNode::PopulateChildRefs(grpc_json* json) { + ChildRefsList child_subchannels; + ChildRefsList child_channels; + grpc_json* json_iterator = nullptr; + grpc_client_channel_populate_child_refs(client_channel_, &child_subchannels, + &child_channels); + if (!child_subchannels.empty()) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < child_subchannels.size(); ++i) { + json_iterator = + grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId", + child_subchannels[i]); + } + } + if (!child_channels.empty()) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false); + json_iterator = nullptr; + for (size_t i = 0; i < child_channels.size(); ++i) { + json_iterator = + grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_add_number_string_child(json_iterator, nullptr, "channelId", + child_channels[i]); + } + } +} + +grpc_arg ClientChannelNode::CreateChannelArg() { + return grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), + reinterpret_cast(MakeClientChannelNode), + &client_channel_channelz_vtable); +} + +RefCountedPtr ClientChannelNode::MakeClientChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) { + return MakeRefCounted(channel, channel_tracer_max_nodes, + is_top_level_channel); +} + +SubchannelNode::SubchannelNode(Subchannel* subchannel, + size_t channel_tracer_max_nodes) + : BaseNode(EntityType::kSubchannel), + subchannel_(subchannel), + target_(UniquePtr(gpr_strdup(subchannel_->GetTargetAddress()))), + trace_(channel_tracer_max_nodes) {} + +SubchannelNode::~SubchannelNode() {} + +void SubchannelNode::PopulateConnectivityState(grpc_json* json) { + grpc_connectivity_state state; + if (subchannel_ == nullptr) { + state = GRPC_CHANNEL_SHUTDOWN; + } else { + state = subchannel_->CheckConnectivity(nullptr, + true /* inhibit_health_checking */); + } + json = grpc_json_create_child(nullptr, json, "state", nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_create_child(nullptr, json, "state", + grpc_connectivity_state_name(state), GRPC_JSON_STRING, + false); +} + +grpc_json* SubchannelNode::RenderJson() { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "subchannelId", uuid()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); + // fill in the channel trace if applicable + grpc_json* trace_json = trace_.RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallCounts(json); + json = top_level_json; + // populate the child socket. + intptr_t socket_uuid = subchannel_->GetChildSocketUuid(); + if (socket_uuid != 0) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); + json_iterator = grpc_json_create_child(json_iterator, array_parent, nullptr, + nullptr, GRPC_JSON_OBJECT, false); + grpc_json_add_number_string_child(json_iterator, nullptr, "socketId", + socket_uuid); + } + return top_level_json; +} + +} // namespace channelz +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_channelz.h b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_channelz.h new file mode 100644 index 000000000..1dc1bf595 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -0,0 +1,99 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_CHANNELZ_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_CHANNELZ_H + +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" + +namespace grpc_core { + +class Subchannel; + +namespace channelz { + +// Subtype of ChannelNode that overrides and provides client_channel specific +// functionality like querying for connectivity_state and subchannel data. +class ClientChannelNode : public ChannelNode { + public: + static RefCountedPtr MakeClientChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + + ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + virtual ~ClientChannelNode() {} + + // Overriding template methods from ChannelNode to render information that + // only ClientChannelNode knows about. + void PopulateConnectivityState(grpc_json* json) override; + void PopulateChildRefs(grpc_json* json) override; + + // Helper to create a channel arg to ensure this type of ChannelNode is + // created. + static grpc_arg CreateChannelArg(); + + private: + grpc_channel_element* client_channel_; +}; + +// Handles channelz bookkeeping for sockets +class SubchannelNode : public BaseNode { + public: + SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes); + ~SubchannelNode() override; + + void MarkSubchannelDestroyed() { + GPR_ASSERT(subchannel_ != nullptr); + subchannel_ = nullptr; + } + + grpc_json* RenderJson() override; + + // proxy methods to composed classes. + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_.AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); + } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } + + private: + Subchannel* subchannel_; + UniquePtr target_; + CallCountingHelper call_counter_; + ChannelTrace trace_; + + void PopulateConnectivityState(grpc_json* json); +}; + +} // namespace channelz +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_CHANNELZ_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.cc index 172e9f03c..8c558382f 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.cc @@ -29,8 +29,8 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) { factory->vtable->unref(factory); } -grpc_subchannel* grpc_client_channel_factory_create_subchannel( - grpc_client_channel_factory* factory, const grpc_subchannel_args* args) { +grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel( + grpc_client_channel_factory* factory, const grpc_channel_args* args) { return factory->vtable->create_subchannel(factory, args); } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.h b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.h index 601ec46b2..4b72aa464 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_factory.h @@ -48,8 +48,8 @@ struct grpc_client_channel_factory { struct grpc_client_channel_factory_vtable { void (*ref)(grpc_client_channel_factory* factory); void (*unref)(grpc_client_channel_factory* factory); - grpc_subchannel* (*create_subchannel)(grpc_client_channel_factory* factory, - const grpc_subchannel_args* args); + grpc_core::Subchannel* (*create_subchannel)( + grpc_client_channel_factory* factory, const grpc_channel_args* args); grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory, const char* target, grpc_client_channel_type type, @@ -60,8 +60,8 @@ void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory); void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory); /** Create a new grpc_subchannel */ -grpc_subchannel* grpc_client_channel_factory_create_subchannel( - grpc_client_channel_factory* factory, const grpc_subchannel_args* args); +grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel( + grpc_client_channel_factory* factory, const grpc_channel_args* args); /** Create a new grpc_channel */ grpc_channel* grpc_client_channel_factory_create_channel( diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_plugin.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_plugin.cc index 8385852d1..2031ab449 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -25,16 +25,25 @@ #include #include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include "src/core/ext/filters/client_channel/global_subchannel_pool.h" #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/http_proxy.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/retry_throttle.h" -#include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/lib/surface/channel_init.h" static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { + const grpc_channel_args* args = + grpc_channel_stack_builder_get_channel_arguments(builder); + grpc_arg args_to_add[] = { + grpc_core::channelz::ClientChannelNode::CreateChannelArg()}; + grpc_channel_args* new_args = grpc_channel_args_copy_and_add( + args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); + grpc_channel_stack_builder_set_channel_arguments(builder, new_args); + grpc_channel_args_destroy(new_args); return grpc_channel_stack_builder_append_filter( builder, static_cast(arg), nullptr, nullptr); } @@ -45,7 +54,7 @@ void grpc_client_channel_init(void) { grpc_core::internal::ServerRetryThrottleMap::Init(); grpc_proxy_mapper_registry_init(); grpc_register_http_proxy_mapper(); - grpc_subchannel_index_init(); + grpc_core::GlobalSubchannelPool::Init(); grpc_channel_init_register_stage( GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter, (void*)&grpc_client_channel_filter); @@ -53,7 +62,7 @@ void grpc_client_channel_init(void) { } void grpc_client_channel_shutdown(void) { - grpc_subchannel_index_shutdown(); + grpc_core::GlobalSubchannelPool::Shutdown(); grpc_channel_init_shutdown(); grpc_proxy_mapper_registry_shutdown(); grpc_core::internal::ServerRetryThrottleMap::Shutdown(); diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/connector.h b/Sources/CgRPC/src/core/ext/filters/client_channel/connector.h index 556594929..ea34dcdab 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/connector.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/connector.h @@ -47,6 +47,9 @@ typedef struct { /** channel arguments (to be passed to the filters) */ grpc_channel_args* channel_args; + + /** socket uuid of the connected transport. 0 if not available */ + intptr_t socket_uuid; } grpc_connect_out_args; struct grpc_connector_vtable { diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/global_subchannel_pool.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/global_subchannel_pool.cc new file mode 100644 index 000000000..ee6e58159 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/global_subchannel_pool.cc @@ -0,0 +1,176 @@ +// +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include + +#include "src/core/ext/filters/client_channel/global_subchannel_pool.h" + +#include "src/core/ext/filters/client_channel/subchannel.h" + +namespace grpc_core { + +GlobalSubchannelPool::GlobalSubchannelPool() { + subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_); + gpr_mu_init(&mu_); +} + +GlobalSubchannelPool::~GlobalSubchannelPool() { + gpr_mu_destroy(&mu_); + grpc_avl_unref(subchannel_map_, nullptr); +} + +void GlobalSubchannelPool::Init() { + instance_ = New>( + MakeRefCounted()); +} + +void GlobalSubchannelPool::Shutdown() { + // To ensure Init() was called before. + GPR_ASSERT(instance_ != nullptr); + // To ensure Shutdown() was not called before. + GPR_ASSERT(*instance_ != nullptr); + instance_->reset(); + Delete(instance_); +} + +RefCountedPtr GlobalSubchannelPool::instance() { + GPR_ASSERT(instance_ != nullptr); + GPR_ASSERT(*instance_ != nullptr); + return *instance_; +} + +Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) { + Subchannel* c = nullptr; + // Compare and swap (CAS) loop: + while (c == nullptr) { + // Ref the shared map to have a local copy. + gpr_mu_lock(&mu_); + grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); + gpr_mu_unlock(&mu_); + // Check to see if a subchannel already exists. + c = static_cast(grpc_avl_get(old_map, key, nullptr)); + if (c != nullptr) { + // The subchannel already exists. Reuse it. + c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse"); + GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing"); + // Exit the CAS loop without modifying the shared map. + } else { + // There hasn't been such subchannel. Add one. + // Note that we should ref the old map first because grpc_avl_add() will + // unref it while we still need to access it later. + grpc_avl new_map = grpc_avl_add( + grpc_avl_ref(old_map, nullptr), New(*key), + GRPC_SUBCHANNEL_WEAK_REF(constructed, "subchannel_register+new"), + nullptr); + // Try to publish the change to the shared map. It may happen (but + // unlikely) that some other thread has changed the shared map, so compare + // to make sure it's unchanged before swapping. Retry if it's changed. + gpr_mu_lock(&mu_); + if (old_map.root == subchannel_map_.root) { + GPR_SWAP(grpc_avl, new_map, subchannel_map_); + c = constructed; + } + gpr_mu_unlock(&mu_); + grpc_avl_unref(new_map, nullptr); + } + grpc_avl_unref(old_map, nullptr); + } + return c; +} + +void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { + bool done = false; + // Compare and swap (CAS) loop: + while (!done) { + // Ref the shared map to have a local copy. + gpr_mu_lock(&mu_); + grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); + gpr_mu_unlock(&mu_); + // Remove the subchannel. + // Note that we should ref the old map first because grpc_avl_remove() will + // unref it while we still need to access it later. + grpc_avl new_map = + grpc_avl_remove(grpc_avl_ref(old_map, nullptr), key, nullptr); + // Try to publish the change to the shared map. It may happen (but + // unlikely) that some other thread has changed the shared map, so compare + // to make sure it's unchanged before swapping. Retry if it's changed. + gpr_mu_lock(&mu_); + if (old_map.root == subchannel_map_.root) { + GPR_SWAP(grpc_avl, new_map, subchannel_map_); + done = true; + } + gpr_mu_unlock(&mu_); + grpc_avl_unref(new_map, nullptr); + grpc_avl_unref(old_map, nullptr); + } +} + +Subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { + // Lock, and take a reference to the subchannel map. + // We don't need to do the search under a lock as AVL's are immutable. + gpr_mu_lock(&mu_); + grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr); + gpr_mu_unlock(&mu_); + Subchannel* c = static_cast(grpc_avl_get(index, key, nullptr)); + if (c != nullptr) GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "found_from_pool"); + grpc_avl_unref(index, nullptr); + return c; +} + +RefCountedPtr* GlobalSubchannelPool::instance_ = nullptr; + +namespace { + +void sck_avl_destroy(void* p, void* user_data) { + SubchannelKey* key = static_cast(p); + Delete(key); +} + +void* sck_avl_copy(void* p, void* unused) { + const SubchannelKey* key = static_cast(p); + auto* new_key = New(*key); + return static_cast(new_key); +} + +long sck_avl_compare(void* a, void* b, void* unused) { + const SubchannelKey* key_a = static_cast(a); + const SubchannelKey* key_b = static_cast(b); + return key_a->Cmp(*key_b); +} + +void scv_avl_destroy(void* p, void* user_data) { + GRPC_SUBCHANNEL_WEAK_UNREF((Subchannel*)p, "global_subchannel_pool"); +} + +void* scv_avl_copy(void* p, void* unused) { + GRPC_SUBCHANNEL_WEAK_REF((Subchannel*)p, "global_subchannel_pool"); + return p; +} + +} // namespace + +const grpc_avl_vtable GlobalSubchannelPool::subchannel_avl_vtable_ = { + sck_avl_destroy, // destroy_key + sck_avl_copy, // copy_key + sck_avl_compare, // compare_keys + scv_avl_destroy, // destroy_value + scv_avl_copy // copy_value +}; + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/global_subchannel_pool.h b/Sources/CgRPC/src/core/ext/filters/client_channel/global_subchannel_pool.h new file mode 100644 index 000000000..96dc8d7b3 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/global_subchannel_pool.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H + +#include + +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" + +namespace grpc_core { + +// The global subchannel pool. It shares subchannels among channels. There +// should be only one instance of this class. Init() should be called once at +// the filter initialization time; Shutdown() should be called once at the +// filter shutdown time. +// TODO(juanlishen): Enable subchannel retention. +class GlobalSubchannelPool final : public SubchannelPoolInterface { + public: + // The ctor and dtor are not intended to use directly. + GlobalSubchannelPool(); + ~GlobalSubchannelPool() override; + + // Should be called exactly once at filter initialization time. + static void Init(); + // Should be called exactly once at filter shutdown time. + static void Shutdown(); + + // Gets the singleton instance. + static RefCountedPtr instance(); + + // Implements interface methods. + Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) override; + void UnregisterSubchannel(SubchannelKey* key) override; + Subchannel* FindSubchannel(SubchannelKey* key) override; + + private: + // The singleton instance. (It's a pointer to RefCountedPtr so that this + // non-local static object can be trivially destructible.) + static RefCountedPtr* instance_; + + // The vtable for subchannel operations in an AVL tree. + static const grpc_avl_vtable subchannel_avl_vtable_; + // A map from subchannel key to subchannel. + grpc_avl subchannel_map_; + // To protect subchannel_map_. + gpr_mu mu_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/health/health.pb.c b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health.pb.c new file mode 100644 index 000000000..5499c549c --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health.pb.c @@ -0,0 +1,23 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.7-dev */ + +#include "src/core/ext/filters/client_channel/health/health.pb.h" +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2] = { + PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_health_v1_HealthCheckRequest, service, service, 0), + PB_LAST_FIELD +}; + +const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, grpc_health_v1_HealthCheckResponse, status, status, 0), + PB_LAST_FIELD +}; + + +/* @@protoc_insertion_point(eof) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/health/health.pb.h b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health.pb.h new file mode 100644 index 000000000..9d54ccd61 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health.pb.h @@ -0,0 +1,73 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.7-dev */ + +#ifndef PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED +#define PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED +#include "pb.h" +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enum definitions */ +typedef enum _grpc_health_v1_HealthCheckResponse_ServingStatus { + grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN = 0, + grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING = 1, + grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING = 2, + grpc_health_v1_HealthCheckResponse_ServingStatus_SERVICE_UNKNOWN = 3 +} grpc_health_v1_HealthCheckResponse_ServingStatus; +#define _grpc_health_v1_HealthCheckResponse_ServingStatus_MIN grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN +#define _grpc_health_v1_HealthCheckResponse_ServingStatus_MAX grpc_health_v1_HealthCheckResponse_ServingStatus_SERVICE_UNKNOWN +#define _grpc_health_v1_HealthCheckResponse_ServingStatus_ARRAYSIZE ((grpc_health_v1_HealthCheckResponse_ServingStatus)(grpc_health_v1_HealthCheckResponse_ServingStatus_SERVICE_UNKNOWN+1)) + +/* Struct definitions */ +typedef struct _grpc_health_v1_HealthCheckRequest { + bool has_service; + char service[200]; +/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckRequest) */ +} grpc_health_v1_HealthCheckRequest; + +typedef struct _grpc_health_v1_HealthCheckResponse { + bool has_status; + grpc_health_v1_HealthCheckResponse_ServingStatus status; +/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckResponse) */ +} grpc_health_v1_HealthCheckResponse; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define grpc_health_v1_HealthCheckRequest_init_default {false, ""} +#define grpc_health_v1_HealthCheckResponse_init_default {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0} +#define grpc_health_v1_HealthCheckRequest_init_zero {false, ""} +#define grpc_health_v1_HealthCheckResponse_init_zero {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0} + +/* Field tags (for use in manual encoding/decoding) */ +#define grpc_health_v1_HealthCheckRequest_service_tag 1 +#define grpc_health_v1_HealthCheckResponse_status_tag 1 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2]; +extern const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2]; + +/* Maximum encoded size of messages (where known) */ +#define grpc_health_v1_HealthCheckRequest_size 203 +#define grpc_health_v1_HealthCheckResponse_size 2 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define HEALTH_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/health/health_check_client.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health_check_client.cc new file mode 100644 index 000000000..e845d63d2 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -0,0 +1,652 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/ext/filters/client_channel/health/health_check_client.h" + +#include "pb_decode.h" +#include "pb_encode.h" +#include "src/core/ext/filters/client_channel/health/health.pb.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/transport/status_metadata.h" + +#define HEALTH_CHECK_INITIAL_CONNECT_BACKOFF_SECONDS 1 +#define HEALTH_CHECK_RECONNECT_BACKOFF_MULTIPLIER 1.6 +#define HEALTH_CHECK_RECONNECT_MAX_BACKOFF_SECONDS 120 +#define HEALTH_CHECK_RECONNECT_JITTER 0.2 + +grpc_core::TraceFlag grpc_health_check_client_trace(false, + "health_check_client"); + +namespace grpc_core { + +// +// HealthCheckClient +// + +HealthCheckClient::HealthCheckClient( + const char* service_name, + RefCountedPtr connected_subchannel, + grpc_pollset_set* interested_parties, + grpc_core::RefCountedPtr channelz_node) + : InternallyRefCounted(&grpc_health_check_client_trace), + service_name_(service_name), + connected_subchannel_(std::move(connected_subchannel)), + interested_parties_(interested_parties), + channelz_node_(std::move(channelz_node)), + retry_backoff_( + BackOff::Options() + .set_initial_backoff( + HEALTH_CHECK_INITIAL_CONNECT_BACKOFF_SECONDS * 1000) + .set_multiplier(HEALTH_CHECK_RECONNECT_BACKOFF_MULTIPLIER) + .set_jitter(HEALTH_CHECK_RECONNECT_JITTER) + .set_max_backoff(HEALTH_CHECK_RECONNECT_MAX_BACKOFF_SECONDS * + 1000)) { + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "created HealthCheckClient %p", this); + } + GRPC_CLOSURE_INIT(&retry_timer_callback_, OnRetryTimer, this, + grpc_schedule_on_exec_ctx); + gpr_mu_init(&mu_); + StartCall(); +} + +HealthCheckClient::~HealthCheckClient() { + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "destroying HealthCheckClient %p", this); + } + GRPC_ERROR_UNREF(error_); + gpr_mu_destroy(&mu_); +} + +void HealthCheckClient::NotifyOnHealthChange(grpc_connectivity_state* state, + grpc_closure* closure) { + MutexLock lock(&mu_); + GPR_ASSERT(notify_state_ == nullptr); + if (*state != state_) { + *state = state_; + GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_REF(error_)); + return; + } + notify_state_ = state; + on_health_changed_ = closure; +} + +void HealthCheckClient::SetHealthStatus(grpc_connectivity_state state, + grpc_error* error) { + MutexLock lock(&mu_); + SetHealthStatusLocked(state, error); +} + +void HealthCheckClient::SetHealthStatusLocked(grpc_connectivity_state state, + grpc_error* error) { + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%d error=%s", this, + state, grpc_error_string(error)); + } + if (notify_state_ != nullptr && *notify_state_ != state) { + *notify_state_ = state; + notify_state_ = nullptr; + GRPC_CLOSURE_SCHED(on_health_changed_, GRPC_ERROR_REF(error)); + on_health_changed_ = nullptr; + } + state_ = state; + GRPC_ERROR_UNREF(error_); + error_ = error; +} + +void HealthCheckClient::Orphan() { + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "HealthCheckClient %p: shutting down", this); + } + { + MutexLock lock(&mu_); + if (on_health_changed_ != nullptr) { + *notify_state_ = GRPC_CHANNEL_SHUTDOWN; + notify_state_ = nullptr; + GRPC_CLOSURE_SCHED(on_health_changed_, GRPC_ERROR_NONE); + on_health_changed_ = nullptr; + } + shutting_down_ = true; + call_state_.reset(); + if (retry_timer_callback_pending_) { + grpc_timer_cancel(&retry_timer_); + } + } + Unref(DEBUG_LOCATION, "orphan"); +} + +void HealthCheckClient::StartCall() { + MutexLock lock(&mu_); + StartCallLocked(); +} + +void HealthCheckClient::StartCallLocked() { + if (shutting_down_) return; + GPR_ASSERT(call_state_ == nullptr); + SetHealthStatusLocked(GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE); + call_state_ = MakeOrphanable(Ref(), interested_parties_); + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "HealthCheckClient %p: created CallState %p", this, + call_state_.get()); + } + call_state_->StartCall(); +} + +void HealthCheckClient::StartRetryTimer() { + MutexLock lock(&mu_); + SetHealthStatusLocked( + GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "health check call failed; will retry after backoff")); + grpc_millis next_try = retry_backoff_.NextAttemptTime(); + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "HealthCheckClient %p: health check call lost...", this); + grpc_millis timeout = next_try - ExecCtx::Get()->Now(); + if (timeout > 0) { + gpr_log(GPR_INFO, + "HealthCheckClient %p: ... will retry in %" PRId64 "ms.", this, + timeout); + } else { + gpr_log(GPR_INFO, "HealthCheckClient %p: ... retrying immediately.", + this); + } + } + // Ref for callback, tracked manually. + Ref(DEBUG_LOCATION, "health_retry_timer").release(); + retry_timer_callback_pending_ = true; + grpc_timer_init(&retry_timer_, next_try, &retry_timer_callback_); +} + +void HealthCheckClient::OnRetryTimer(void* arg, grpc_error* error) { + HealthCheckClient* self = static_cast(arg); + { + MutexLock lock(&self->mu_); + self->retry_timer_callback_pending_ = false; + if (!self->shutting_down_ && error == GRPC_ERROR_NONE && + self->call_state_ == nullptr) { + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "HealthCheckClient %p: restarting health check call", + self); + } + self->StartCallLocked(); + } + } + self->Unref(DEBUG_LOCATION, "health_retry_timer"); +} + +// +// protobuf helpers +// + +namespace { + +void EncodeRequest(const char* service_name, + ManualConstructor* send_message) { + grpc_health_v1_HealthCheckRequest request_struct; + request_struct.has_service = true; + snprintf(request_struct.service, sizeof(request_struct.service), "%s", + service_name); + pb_ostream_t ostream; + memset(&ostream, 0, sizeof(ostream)); + pb_encode(&ostream, grpc_health_v1_HealthCheckRequest_fields, + &request_struct); + grpc_slice request_slice = GRPC_SLICE_MALLOC(ostream.bytes_written); + ostream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(request_slice), + GRPC_SLICE_LENGTH(request_slice)); + GPR_ASSERT(pb_encode(&ostream, grpc_health_v1_HealthCheckRequest_fields, + &request_struct) != 0); + grpc_slice_buffer slice_buffer; + grpc_slice_buffer_init(&slice_buffer); + grpc_slice_buffer_add(&slice_buffer, request_slice); + send_message->Init(&slice_buffer, 0); + grpc_slice_buffer_destroy_internal(&slice_buffer); +} + +// Returns true if healthy. +// If there was an error parsing the response, sets *error and returns false. +bool DecodeResponse(grpc_slice_buffer* slice_buffer, grpc_error** error) { + // If message is empty, assume unhealthy. + if (slice_buffer->length == 0) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("health check response was empty"); + return false; + } + // Concatenate the slices to form a single string. + UniquePtr recv_message_deleter; + uint8_t* recv_message; + if (slice_buffer->count == 1) { + recv_message = GRPC_SLICE_START_PTR(slice_buffer->slices[0]); + } else { + recv_message = static_cast(gpr_malloc(slice_buffer->length)); + recv_message_deleter.reset(recv_message); + size_t offset = 0; + for (size_t i = 0; i < slice_buffer->count; ++i) { + memcpy(recv_message + offset, + GRPC_SLICE_START_PTR(slice_buffer->slices[i]), + GRPC_SLICE_LENGTH(slice_buffer->slices[i])); + offset += GRPC_SLICE_LENGTH(slice_buffer->slices[i]); + } + } + // Deserialize message. + grpc_health_v1_HealthCheckResponse response_struct; + pb_istream_t istream = + pb_istream_from_buffer(recv_message, slice_buffer->length); + if (!pb_decode(&istream, grpc_health_v1_HealthCheckResponse_fields, + &response_struct)) { + // Can't parse message; assume unhealthy. + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "cannot parse health check response"); + return false; + } + if (!response_struct.has_status) { + // Field not present; assume unhealthy. + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "status field not present in health check response"); + return false; + } + return response_struct.status == + grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING; +} + +} // namespace + +// +// HealthCheckClient::CallState +// + +HealthCheckClient::CallState::CallState( + RefCountedPtr health_check_client, + grpc_pollset_set* interested_parties) + : InternallyRefCounted(&grpc_health_check_client_trace), + health_check_client_(std::move(health_check_client)), + pollent_(grpc_polling_entity_create_from_pollset_set(interested_parties)), + arena_(gpr_arena_create(health_check_client_->connected_subchannel_ + ->GetInitialCallSizeEstimate(0))), + payload_(context_) { + grpc_call_combiner_init(&call_combiner_); + gpr_atm_rel_store(&seen_response_, static_cast(0)); +} + +HealthCheckClient::CallState::~CallState() { + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", + health_check_client_.get(), this); + } + // The subchannel call is in the arena, so reset the pointer before we destroy + // the arena. + call_.reset(); + for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { + if (context_[i].destroy != nullptr) { + context_[i].destroy(context_[i].value); + } + } + // Unset the call combiner cancellation closure. This has the + // effect of scheduling the previously set cancellation closure, if + // any, so that it can release any internal references it may be + // holding to the call stack. Also flush the closures on exec_ctx so that + // filters that schedule cancel notification closures on exec_ctx do not + // need to take a ref of the call stack to guarantee closure liveness. + grpc_call_combiner_set_notify_on_cancel(&call_combiner_, nullptr); + grpc_core::ExecCtx::Get()->Flush(); + grpc_call_combiner_destroy(&call_combiner_); + gpr_arena_destroy(arena_); +} + +void HealthCheckClient::CallState::Orphan() { + grpc_call_combiner_cancel(&call_combiner_, GRPC_ERROR_CANCELLED); + Cancel(); +} + +void HealthCheckClient::CallState::StartCall() { + ConnectedSubchannel::CallArgs args = { + &pollent_, + GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH, + gpr_now(GPR_CLOCK_MONOTONIC), // start_time + GRPC_MILLIS_INF_FUTURE, // deadline + arena_, + context_, + &call_combiner_, + 0, // parent_data_size + }; + grpc_error* error = GRPC_ERROR_NONE; + call_ = health_check_client_->connected_subchannel_->CreateCall(args, &error); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, + "HealthCheckClient %p CallState %p: error creating health " + "checking call on subchannel (%s); will retry", + health_check_client_.get(), this, grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + // Schedule instead of running directly, since we must not be + // holding health_check_client_->mu_ when CallEnded() is called. + Ref(DEBUG_LOCATION, "call_end_closure").release(); + GRPC_CLOSURE_SCHED( + GRPC_CLOSURE_INIT(&batch_.handler_private.closure, CallEndedRetry, this, + grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); + return; + } + // Initialize payload and batch. + memset(&batch_, 0, sizeof(batch_)); + payload_.context = context_; + batch_.payload = &payload_; + // on_complete callback takes ref, handled manually. + Ref(DEBUG_LOCATION, "on_complete").release(); + batch_.on_complete = GRPC_CLOSURE_INIT(&on_complete_, OnComplete, this, + grpc_schedule_on_exec_ctx); + // Add send_initial_metadata op. + grpc_metadata_batch_init(&send_initial_metadata_); + error = grpc_metadata_batch_add_head( + &send_initial_metadata_, &path_metadata_storage_, + grpc_mdelem_from_slices( + GRPC_MDSTR_PATH, + GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH)); + GPR_ASSERT(error == GRPC_ERROR_NONE); + payload_.send_initial_metadata.send_initial_metadata = + &send_initial_metadata_; + payload_.send_initial_metadata.send_initial_metadata_flags = 0; + payload_.send_initial_metadata.peer_string = nullptr; + batch_.send_initial_metadata = true; + // Add send_message op. + EncodeRequest(health_check_client_->service_name_, &send_message_); + payload_.send_message.send_message.reset(send_message_.get()); + batch_.send_message = true; + // Add send_trailing_metadata op. + grpc_metadata_batch_init(&send_trailing_metadata_); + payload_.send_trailing_metadata.send_trailing_metadata = + &send_trailing_metadata_; + batch_.send_trailing_metadata = true; + // Add recv_initial_metadata op. + grpc_metadata_batch_init(&recv_initial_metadata_); + payload_.recv_initial_metadata.recv_initial_metadata = + &recv_initial_metadata_; + payload_.recv_initial_metadata.recv_flags = nullptr; + payload_.recv_initial_metadata.trailing_metadata_available = nullptr; + payload_.recv_initial_metadata.peer_string = nullptr; + // recv_initial_metadata_ready callback takes ref, handled manually. + Ref(DEBUG_LOCATION, "recv_initial_metadata_ready").release(); + payload_.recv_initial_metadata.recv_initial_metadata_ready = + GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, RecvInitialMetadataReady, + this, grpc_schedule_on_exec_ctx); + batch_.recv_initial_metadata = true; + // Add recv_message op. + payload_.recv_message.recv_message = &recv_message_; + // recv_message callback takes ref, handled manually. + Ref(DEBUG_LOCATION, "recv_message_ready").release(); + payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT( + &recv_message_ready_, RecvMessageReady, this, grpc_schedule_on_exec_ctx); + batch_.recv_message = true; + // Start batch. + StartBatch(&batch_); + // Initialize recv_trailing_metadata batch. + memset(&recv_trailing_metadata_batch_, 0, + sizeof(recv_trailing_metadata_batch_)); + recv_trailing_metadata_batch_.payload = &payload_; + // Add recv_trailing_metadata op. + grpc_metadata_batch_init(&recv_trailing_metadata_); + payload_.recv_trailing_metadata.recv_trailing_metadata = + &recv_trailing_metadata_; + payload_.recv_trailing_metadata.collect_stats = &collect_stats_; + // This callback signals the end of the call, so it relies on the + // initial ref instead of taking a new ref. When it's invoked, the + // initial ref is released. + payload_.recv_trailing_metadata.recv_trailing_metadata_ready = + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, + RecvTrailingMetadataReady, this, + grpc_schedule_on_exec_ctx); + recv_trailing_metadata_batch_.recv_trailing_metadata = true; + // Start recv_trailing_metadata batch. + StartBatch(&recv_trailing_metadata_batch_); +} + +void HealthCheckClient::CallState::StartBatchInCallCombiner(void* arg, + grpc_error* error) { + grpc_transport_stream_op_batch* batch = + static_cast(arg); + SubchannelCall* call = + static_cast(batch->handler_private.extra_arg); + call->StartTransportStreamOpBatch(batch); +} + +void HealthCheckClient::CallState::StartBatch( + grpc_transport_stream_op_batch* batch) { + batch->handler_private.extra_arg = call_.get(); + GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, + batch, grpc_schedule_on_exec_ctx); + GRPC_CALL_COMBINER_START(&call_combiner_, &batch->handler_private.closure, + GRPC_ERROR_NONE, "start_subchannel_batch"); +} + +void HealthCheckClient::CallState::OnCancelComplete(void* arg, + grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "health_cancel"); + self->Unref(DEBUG_LOCATION, "cancel"); +} + +void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + auto* batch = grpc_make_transport_stream_op( + GRPC_CLOSURE_CREATE(OnCancelComplete, self, grpc_schedule_on_exec_ctx)); + batch->cancel_stream = true; + batch->payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; + self->call_->StartTransportStreamOpBatch(batch); +} + +void HealthCheckClient::CallState::Cancel() { + if (call_ != nullptr) { + Ref(DEBUG_LOCATION, "cancel").release(); + GRPC_CALL_COMBINER_START( + &call_combiner_, + GRPC_CLOSURE_CREATE(StartCancel, this, grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE, "health_cancel"); + } +} + +void HealthCheckClient::CallState::OnComplete(void* arg, grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "on_complete"); + grpc_metadata_batch_destroy(&self->send_initial_metadata_); + grpc_metadata_batch_destroy(&self->send_trailing_metadata_); + self->Unref(DEBUG_LOCATION, "on_complete"); +} + +void HealthCheckClient::CallState::RecvInitialMetadataReady(void* arg, + grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "recv_initial_metadata_ready"); + grpc_metadata_batch_destroy(&self->recv_initial_metadata_); + self->Unref(DEBUG_LOCATION, "recv_initial_metadata_ready"); +} + +void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { + recv_message_.reset(); + if (error != GRPC_ERROR_NONE) { + GRPC_ERROR_UNREF(error); + Cancel(); + grpc_slice_buffer_destroy_internal(&recv_message_buffer_); + Unref(DEBUG_LOCATION, "recv_message_ready"); + return; + } + const bool healthy = DecodeResponse(&recv_message_buffer_, &error); + const grpc_connectivity_state state = + healthy ? GRPC_CHANNEL_READY : GRPC_CHANNEL_TRANSIENT_FAILURE; + if (error == GRPC_ERROR_NONE && !healthy) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("backend unhealthy"); + } + health_check_client_->SetHealthStatus(state, error); + gpr_atm_rel_store(&seen_response_, static_cast(1)); + grpc_slice_buffer_destroy_internal(&recv_message_buffer_); + // Start another recv_message batch. + // This re-uses the ref we're holding. + // Note: Can't just reuse batch_ here, since we don't know that all + // callbacks from the original batch have completed yet. + memset(&recv_message_batch_, 0, sizeof(recv_message_batch_)); + recv_message_batch_.payload = &payload_; + payload_.recv_message.recv_message = &recv_message_; + payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT( + &recv_message_ready_, RecvMessageReady, this, grpc_schedule_on_exec_ctx); + recv_message_batch_.recv_message = true; + StartBatch(&recv_message_batch_); +} + +grpc_error* HealthCheckClient::CallState::PullSliceFromRecvMessage() { + grpc_slice slice; + grpc_error* error = recv_message_->Pull(&slice); + if (error == GRPC_ERROR_NONE) { + grpc_slice_buffer_add(&recv_message_buffer_, slice); + } + return error; +} + +void HealthCheckClient::CallState::ContinueReadingRecvMessage() { + while (recv_message_->Next(SIZE_MAX, &recv_message_ready_)) { + grpc_error* error = PullSliceFromRecvMessage(); + if (error != GRPC_ERROR_NONE) { + DoneReadingRecvMessage(error); + return; + } + if (recv_message_buffer_.length == recv_message_->length()) { + DoneReadingRecvMessage(GRPC_ERROR_NONE); + break; + } + } +} + +void HealthCheckClient::CallState::OnByteStreamNext(void* arg, + grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + if (error != GRPC_ERROR_NONE) { + self->DoneReadingRecvMessage(GRPC_ERROR_REF(error)); + return; + } + error = self->PullSliceFromRecvMessage(); + if (error != GRPC_ERROR_NONE) { + self->DoneReadingRecvMessage(error); + return; + } + if (self->recv_message_buffer_.length == self->recv_message_->length()) { + self->DoneReadingRecvMessage(GRPC_ERROR_NONE); + } else { + self->ContinueReadingRecvMessage(); + } +} + +void HealthCheckClient::CallState::RecvMessageReady(void* arg, + grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "recv_message_ready"); + if (self->recv_message_ == nullptr) { + self->Unref(DEBUG_LOCATION, "recv_message_ready"); + return; + } + grpc_slice_buffer_init(&self->recv_message_buffer_); + GRPC_CLOSURE_INIT(&self->recv_message_ready_, OnByteStreamNext, self, + grpc_schedule_on_exec_ctx); + self->ContinueReadingRecvMessage(); + // Ref will continue to be held until we finish draining the byte stream. +} + +void HealthCheckClient::CallState::RecvTrailingMetadataReady( + void* arg, grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + GRPC_CALL_COMBINER_STOP(&self->call_combiner_, + "recv_trailing_metadata_ready"); + // Get call status. + grpc_status_code status = GRPC_STATUS_UNKNOWN; + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status, + nullptr /* slice */, nullptr /* http_error */, + nullptr /* error_string */); + } else if (self->recv_trailing_metadata_.idx.named.grpc_status != nullptr) { + status = grpc_get_status_code_from_metadata( + self->recv_trailing_metadata_.idx.named.grpc_status->md); + } + if (grpc_health_check_client_trace.enabled()) { + gpr_log(GPR_INFO, + "HealthCheckClient %p CallState %p: health watch failed with " + "status %d", + self->health_check_client_.get(), self, status); + } + // Clean up. + grpc_metadata_batch_destroy(&self->recv_trailing_metadata_); + // For status UNIMPLEMENTED, give up and assume always healthy. + bool retry = true; + if (status == GRPC_STATUS_UNIMPLEMENTED) { + static const char kErrorMessage[] = + "health checking Watch method returned UNIMPLEMENTED; " + "disabling health checks but assuming server is healthy"; + gpr_log(GPR_ERROR, kErrorMessage); + if (self->health_check_client_->channelz_node_ != nullptr) { + self->health_check_client_->channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Error, + grpc_slice_from_static_string(kErrorMessage)); + } + self->health_check_client_->SetHealthStatus(GRPC_CHANNEL_READY, + GRPC_ERROR_NONE); + retry = false; + } + self->CallEnded(retry); +} + +void HealthCheckClient::CallState::CallEndedRetry(void* arg, + grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + self->CallEnded(true /* retry */); + self->Unref(DEBUG_LOCATION, "call_end_closure"); +} + +void HealthCheckClient::CallState::CallEnded(bool retry) { + // If this CallState is still in use, this call ended because of a failure, + // so we need to stop using it and optionally create a new one. + // Otherwise, we have deliberately ended this call, and no further action + // is required. + if (this == health_check_client_->call_state_.get()) { + health_check_client_->call_state_.reset(); + if (retry) { + GPR_ASSERT(!health_check_client_->shutting_down_); + if (static_cast(gpr_atm_acq_load(&seen_response_))) { + // If the call fails after we've gotten a successful response, reset + // the backoff and restart the call immediately. + health_check_client_->retry_backoff_.Reset(); + health_check_client_->StartCall(); + } else { + // If the call failed without receiving any messages, retry later. + health_check_client_->StartRetryTimer(); + } + } + } + Unref(DEBUG_LOCATION, "call_ended"); +} + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/health/health_check_client.h b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health_check_client.h new file mode 100644 index 000000000..7af88a54c --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/health/health_check_client.h @@ -0,0 +1,172 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HEALTH_HEALTH_CHECK_CLIENT_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HEALTH_HEALTH_CHECK_CLIENT_H + +#include + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include "src/core/ext/filters/client_channel/subchannel.h" +#include "src/core/lib/backoff/backoff.h" +#include "src/core/lib/gpr/arena.h" +#include "src/core/lib/gprpp/orphanable.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/call_combiner.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/transport/byte_stream.h" +#include "src/core/lib/transport/metadata_batch.h" +#include "src/core/lib/transport/transport.h" + +namespace grpc_core { + +class HealthCheckClient : public InternallyRefCounted { + public: + HealthCheckClient(const char* service_name, + RefCountedPtr connected_subchannel, + grpc_pollset_set* interested_parties, + RefCountedPtr channelz_node); + + ~HealthCheckClient(); + + // When the health state changes from *state, sets *state to the new + // value and schedules closure. + // Only one closure can be outstanding at a time. + void NotifyOnHealthChange(grpc_connectivity_state* state, + grpc_closure* closure); + + void Orphan() override; + + private: + // Contains a call to the backend and all the data related to the call. + class CallState : public InternallyRefCounted { + public: + CallState(RefCountedPtr health_check_client, + grpc_pollset_set* interested_parties_); + ~CallState(); + + void Orphan() override; + + void StartCall(); + + private: + void Cancel(); + + void StartBatch(grpc_transport_stream_op_batch* batch); + static void StartBatchInCallCombiner(void* arg, grpc_error* error); + + static void CallEndedRetry(void* arg, grpc_error* error); + void CallEnded(bool retry); + + static void OnComplete(void* arg, grpc_error* error); + static void RecvInitialMetadataReady(void* arg, grpc_error* error); + static void RecvMessageReady(void* arg, grpc_error* error); + static void RecvTrailingMetadataReady(void* arg, grpc_error* error); + static void StartCancel(void* arg, grpc_error* error); + static void OnCancelComplete(void* arg, grpc_error* error); + + static void OnByteStreamNext(void* arg, grpc_error* error); + void ContinueReadingRecvMessage(); + grpc_error* PullSliceFromRecvMessage(); + void DoneReadingRecvMessage(grpc_error* error); + + RefCountedPtr health_check_client_; + grpc_polling_entity pollent_; + + gpr_arena* arena_; + grpc_call_combiner call_combiner_; + grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {}; + + // The streaming call to the backend. Always non-NULL. + RefCountedPtr call_; + + grpc_transport_stream_op_batch_payload payload_; + grpc_transport_stream_op_batch batch_; + grpc_transport_stream_op_batch recv_message_batch_; + grpc_transport_stream_op_batch recv_trailing_metadata_batch_; + + grpc_closure on_complete_; + + // send_initial_metadata + grpc_metadata_batch send_initial_metadata_; + grpc_linked_mdelem path_metadata_storage_; + + // send_message + ManualConstructor send_message_; + + // send_trailing_metadata + grpc_metadata_batch send_trailing_metadata_; + + // recv_initial_metadata + grpc_metadata_batch recv_initial_metadata_; + grpc_closure recv_initial_metadata_ready_; + + // recv_message + OrphanablePtr recv_message_; + grpc_closure recv_message_ready_; + grpc_slice_buffer recv_message_buffer_; + gpr_atm seen_response_; + + // recv_trailing_metadata + grpc_metadata_batch recv_trailing_metadata_; + grpc_transport_stream_stats collect_stats_; + grpc_closure recv_trailing_metadata_ready_; + }; + + void StartCall(); + void StartCallLocked(); // Requires holding mu_. + + void StartRetryTimer(); + static void OnRetryTimer(void* arg, grpc_error* error); + + void SetHealthStatus(grpc_connectivity_state state, grpc_error* error); + void SetHealthStatusLocked(grpc_connectivity_state state, + grpc_error* error); // Requires holding mu_. + + const char* service_name_; // Do not own. + RefCountedPtr connected_subchannel_; + grpc_pollset_set* interested_parties_; // Do not own. + RefCountedPtr channelz_node_; + + gpr_mu mu_; + grpc_connectivity_state state_ = GRPC_CHANNEL_CONNECTING; + grpc_error* error_ = GRPC_ERROR_NONE; + grpc_connectivity_state* notify_state_ = nullptr; + grpc_closure* on_health_changed_ = nullptr; + bool shutting_down_ = false; + + // The data associated with the current health check call. It holds a ref + // to this HealthCheckClient object. + OrphanablePtr call_state_; + + // Call retry state. + BackOff retry_backoff_; + grpc_timer retry_timer_; + grpc_closure retry_timer_callback_; + bool retry_timer_callback_pending_ = false; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HEALTH_HEALTH_CHECK_CLIENT_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 4e8b8b71d..fa5aaa9e7 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -29,155 +29,164 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/uri/uri_parser.h" -typedef struct http_connect_handshaker { - // Base class. Must be first. - grpc_handshaker base; +namespace grpc_core { - gpr_refcount refcount; - gpr_mu mu; +namespace { - bool shutdown; +class HttpConnectHandshaker : public Handshaker { + public: + HttpConnectHandshaker(); + void Shutdown(grpc_error* why) override; + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override; + const char* name() const override { return "http_connect"; } + + private: + virtual ~HttpConnectHandshaker(); + void CleanupArgsForFailureLocked(); + void HandshakeFailedLocked(grpc_error* error); + static void OnWriteDone(void* arg, grpc_error* error); + static void OnReadDone(void* arg, grpc_error* error); + + gpr_mu mu_; + + bool is_shutdown_ = false; // Endpoint and read buffer to destroy after a shutdown. - grpc_endpoint* endpoint_to_destroy; - grpc_slice_buffer* read_buffer_to_destroy; + grpc_endpoint* endpoint_to_destroy_ = nullptr; + grpc_slice_buffer* read_buffer_to_destroy_ = nullptr; // State saved while performing the handshake. - grpc_handshaker_args* args; - grpc_closure* on_handshake_done; + HandshakerArgs* args_ = nullptr; + grpc_closure* on_handshake_done_ = nullptr; // Objects for processing the HTTP CONNECT request and response. - grpc_slice_buffer write_buffer; - grpc_closure request_done_closure; - grpc_closure response_read_closure; - grpc_http_parser http_parser; - grpc_http_response http_response; -} http_connect_handshaker; + grpc_slice_buffer write_buffer_; + grpc_closure request_done_closure_; + grpc_closure response_read_closure_; + grpc_http_parser http_parser_; + grpc_http_response http_response_; +}; -// Unref and clean up handshaker. -static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) { - if (gpr_unref(&handshaker->refcount)) { - gpr_mu_destroy(&handshaker->mu); - if (handshaker->endpoint_to_destroy != nullptr) { - grpc_endpoint_destroy(handshaker->endpoint_to_destroy); - } - if (handshaker->read_buffer_to_destroy != nullptr) { - grpc_slice_buffer_destroy_internal(handshaker->read_buffer_to_destroy); - gpr_free(handshaker->read_buffer_to_destroy); - } - grpc_slice_buffer_destroy_internal(&handshaker->write_buffer); - grpc_http_parser_destroy(&handshaker->http_parser); - grpc_http_response_destroy(&handshaker->http_response); - gpr_free(handshaker); +HttpConnectHandshaker::~HttpConnectHandshaker() { + gpr_mu_destroy(&mu_); + if (endpoint_to_destroy_ != nullptr) { + grpc_endpoint_destroy(endpoint_to_destroy_); + } + if (read_buffer_to_destroy_ != nullptr) { + grpc_slice_buffer_destroy_internal(read_buffer_to_destroy_); + gpr_free(read_buffer_to_destroy_); } + grpc_slice_buffer_destroy_internal(&write_buffer_); + grpc_http_parser_destroy(&http_parser_); + grpc_http_response_destroy(&http_response_); } // Set args fields to nullptr, saving the endpoint and read buffer for // later destruction. -static void cleanup_args_for_failure_locked( - http_connect_handshaker* handshaker) { - handshaker->endpoint_to_destroy = handshaker->args->endpoint; - handshaker->args->endpoint = nullptr; - handshaker->read_buffer_to_destroy = handshaker->args->read_buffer; - handshaker->args->read_buffer = nullptr; - grpc_channel_args_destroy(handshaker->args->args); - handshaker->args->args = nullptr; +void HttpConnectHandshaker::CleanupArgsForFailureLocked() { + endpoint_to_destroy_ = args_->endpoint; + args_->endpoint = nullptr; + read_buffer_to_destroy_ = args_->read_buffer; + args_->read_buffer = nullptr; + grpc_channel_args_destroy(args_->args); + args_->args = nullptr; } // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. -static void handshake_failed_locked(http_connect_handshaker* handshaker, - grpc_error* error) { +void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error* error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after an endpoint operation succeeded but // before the endpoint callback was invoked, we need to generate our // own error. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } - if (!handshaker->shutdown) { + if (!is_shutdown_) { // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. - grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(error)); + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(error)); // Not shutting down, so the handshake failed. Clean up before // invoking the callback. - cleanup_args_for_failure_locked(handshaker); + CleanupArgsForFailureLocked(); // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. - handshaker->shutdown = true; + is_shutdown_ = true; } // Invoke callback. - GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error); + GRPC_CLOSURE_SCHED(on_handshake_done_, error); } // Callback invoked when finished writing HTTP CONNECT request. -static void on_write_done(void* arg, grpc_error* error) { - http_connect_handshaker* handshaker = - static_cast(arg); - gpr_mu_lock(&handshaker->mu); - if (error != GRPC_ERROR_NONE || handshaker->shutdown) { +void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error* error) { + auto* handshaker = static_cast(arg); + gpr_mu_lock(&handshaker->mu_); + if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) { // If the write failed or we're shutting down, clean up and invoke the // callback with the error. - handshake_failed_locked(handshaker, GRPC_ERROR_REF(error)); - gpr_mu_unlock(&handshaker->mu); - http_connect_handshaker_unref(handshaker); + handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error)); + gpr_mu_unlock(&handshaker->mu_); + handshaker->Unref(); } else { // Otherwise, read the response. // The read callback inherits our ref to the handshaker. - grpc_endpoint_read(handshaker->args->endpoint, - handshaker->args->read_buffer, - &handshaker->response_read_closure); - gpr_mu_unlock(&handshaker->mu); + grpc_endpoint_read(handshaker->args_->endpoint, + handshaker->args_->read_buffer, + &handshaker->response_read_closure_); + gpr_mu_unlock(&handshaker->mu_); } } // Callback invoked for reading HTTP CONNECT response. -static void on_read_done(void* arg, grpc_error* error) { - http_connect_handshaker* handshaker = - static_cast(arg); - gpr_mu_lock(&handshaker->mu); - if (error != GRPC_ERROR_NONE || handshaker->shutdown) { +void HttpConnectHandshaker::OnReadDone(void* arg, grpc_error* error) { + auto* handshaker = static_cast(arg); + + gpr_mu_lock(&handshaker->mu_); + if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) { // If the read failed or we're shutting down, clean up and invoke the // callback with the error. - handshake_failed_locked(handshaker, GRPC_ERROR_REF(error)); + handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error)); goto done; } // Add buffer to parser. - for (size_t i = 0; i < handshaker->args->read_buffer->count; ++i) { - if (GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i]) > 0) { + for (size_t i = 0; i < handshaker->args_->read_buffer->count; ++i) { + if (GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i]) > 0) { size_t body_start_offset = 0; - error = grpc_http_parser_parse(&handshaker->http_parser, - handshaker->args->read_buffer->slices[i], + error = grpc_http_parser_parse(&handshaker->http_parser_, + handshaker->args_->read_buffer->slices[i], &body_start_offset); if (error != GRPC_ERROR_NONE) { - handshake_failed_locked(handshaker, error); + handshaker->HandshakeFailedLocked(error); goto done; } - if (handshaker->http_parser.state == GRPC_HTTP_BODY) { + if (handshaker->http_parser_.state == GRPC_HTTP_BODY) { // Remove the data we've already read from the read buffer, // leaving only the leftover bytes (if any). grpc_slice_buffer tmp_buffer; grpc_slice_buffer_init(&tmp_buffer); if (body_start_offset < - GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i])) { + GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i])) { grpc_slice_buffer_add( &tmp_buffer, - grpc_slice_split_tail(&handshaker->args->read_buffer->slices[i], + grpc_slice_split_tail(&handshaker->args_->read_buffer->slices[i], body_start_offset)); } grpc_slice_buffer_addn(&tmp_buffer, - &handshaker->args->read_buffer->slices[i + 1], - handshaker->args->read_buffer->count - i - 1); - grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer); + &handshaker->args_->read_buffer->slices[i + 1], + handshaker->args_->read_buffer->count - i - 1); + grpc_slice_buffer_swap(handshaker->args_->read_buffer, &tmp_buffer); grpc_slice_buffer_destroy_internal(&tmp_buffer); break; } @@ -194,64 +203,53 @@ static void on_read_done(void* arg, grpc_error* error) { // need to fix the HTTP parser to understand when the body is // complete (e.g., handling chunked transfer encoding or looking // at the Content-Length: header). - if (handshaker->http_parser.state != GRPC_HTTP_BODY) { - grpc_slice_buffer_reset_and_unref_internal(handshaker->args->read_buffer); - grpc_endpoint_read(handshaker->args->endpoint, - handshaker->args->read_buffer, - &handshaker->response_read_closure); - gpr_mu_unlock(&handshaker->mu); + if (handshaker->http_parser_.state != GRPC_HTTP_BODY) { + grpc_slice_buffer_reset_and_unref_internal(handshaker->args_->read_buffer); + grpc_endpoint_read(handshaker->args_->endpoint, + handshaker->args_->read_buffer, + &handshaker->response_read_closure_); + gpr_mu_unlock(&handshaker->mu_); return; } // Make sure we got a 2xx response. - if (handshaker->http_response.status < 200 || - handshaker->http_response.status >= 300) { + if (handshaker->http_response_.status < 200 || + handshaker->http_response_.status >= 300) { char* msg; gpr_asprintf(&msg, "HTTP proxy returned response code %d", - handshaker->http_response.status); + handshaker->http_response_.status); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); - handshake_failed_locked(handshaker, error); + handshaker->HandshakeFailedLocked(error); goto done; } // Success. Invoke handshake-done callback. - GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error); + GRPC_CLOSURE_SCHED(handshaker->on_handshake_done_, error); done: // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. - handshaker->shutdown = true; - gpr_mu_unlock(&handshaker->mu); - http_connect_handshaker_unref(handshaker); + handshaker->is_shutdown_ = true; + gpr_mu_unlock(&handshaker->mu_); + handshaker->Unref(); } // // Public handshaker methods // -static void http_connect_handshaker_destroy(grpc_handshaker* handshaker_in) { - http_connect_handshaker* handshaker = - reinterpret_cast(handshaker_in); - http_connect_handshaker_unref(handshaker); -} - -static void http_connect_handshaker_shutdown(grpc_handshaker* handshaker_in, - grpc_error* why) { - http_connect_handshaker* handshaker = - reinterpret_cast(handshaker_in); - gpr_mu_lock(&handshaker->mu); - if (!handshaker->shutdown) { - handshaker->shutdown = true; - grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(why)); - cleanup_args_for_failure_locked(handshaker); +void HttpConnectHandshaker::Shutdown(grpc_error* why) { + gpr_mu_lock(&mu_); + if (!is_shutdown_) { + is_shutdown_ = true; + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why)); + CleanupArgsForFailureLocked(); } - gpr_mu_unlock(&handshaker->mu); + gpr_mu_unlock(&mu_); GRPC_ERROR_UNREF(why); } -static void http_connect_handshaker_do_handshake( - grpc_handshaker* handshaker_in, grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, grpc_handshaker_args* args) { - http_connect_handshaker* handshaker = - reinterpret_cast(handshaker_in); +void HttpConnectHandshaker::DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) { // Check for HTTP CONNECT channel arg. // If not found, invoke on_handshake_done without doing anything. const grpc_arg* arg = @@ -260,9 +258,9 @@ static void http_connect_handshaker_do_handshake( if (server_name == nullptr) { // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. - gpr_mu_lock(&handshaker->mu); - handshaker->shutdown = true; - gpr_mu_unlock(&handshaker->mu); + gpr_mu_lock(&mu_); + is_shutdown_ = true; + gpr_mu_unlock(&mu_); GRPC_CLOSURE_SCHED(on_handshake_done, GRPC_ERROR_NONE); return; } @@ -280,6 +278,7 @@ static void http_connect_handshaker_do_handshake( gpr_malloc(sizeof(grpc_http_header) * num_header_strings)); for (size_t i = 0; i < num_header_strings; ++i) { char* sep = strchr(header_strings[i], ':'); + if (sep == nullptr) { gpr_log(GPR_ERROR, "skipping unparseable HTTP CONNECT header: %s", header_strings[i]); @@ -292,9 +291,9 @@ static void http_connect_handshaker_do_handshake( } } // Save state in the handshaker object. - gpr_mu_lock(&handshaker->mu); - handshaker->args = args; - handshaker->on_handshake_done = on_handshake_done; + MutexLock lock(&mu_); + args_ = args; + on_handshake_done_ = on_handshake_done; // Log connection via proxy. char* proxy_name = grpc_endpoint_get_peer(args->endpoint); gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", server_name, @@ -302,15 +301,18 @@ static void http_connect_handshaker_do_handshake( gpr_free(proxy_name); // Construct HTTP CONNECT request. grpc_httpcli_request request; - memset(&request, 0, sizeof(request)); request.host = server_name; + request.ssl_host_override = nullptr; request.http.method = (char*)"CONNECT"; request.http.path = server_name; + request.http.version = GRPC_HTTP_HTTP10; // Set by OnReadDone request.http.hdrs = headers; request.http.hdr_count = num_headers; + request.http.body_length = 0; + request.http.body = nullptr; request.handshaker = &grpc_httpcli_plaintext; grpc_slice request_slice = grpc_httpcli_format_connect_request(&request); - grpc_slice_buffer_add(&handshaker->write_buffer, request_slice); + grpc_slice_buffer_add(&write_buffer_, request_slice); // Clean up. gpr_free(headers); for (size_t i = 0; i < num_header_strings; ++i) { @@ -318,53 +320,42 @@ static void http_connect_handshaker_do_handshake( } gpr_free(header_strings); // Take a new ref to be held by the write callback. - gpr_ref(&handshaker->refcount); - grpc_endpoint_write(args->endpoint, &handshaker->write_buffer, - &handshaker->request_done_closure); - gpr_mu_unlock(&handshaker->mu); + Ref().release(); + grpc_endpoint_write(args->endpoint, &write_buffer_, &request_done_closure_, + nullptr); } -static const grpc_handshaker_vtable http_connect_handshaker_vtable = { - http_connect_handshaker_destroy, http_connect_handshaker_shutdown, - http_connect_handshaker_do_handshake, "http_connect"}; - -static grpc_handshaker* grpc_http_connect_handshaker_create() { - http_connect_handshaker* handshaker = - static_cast(gpr_malloc(sizeof(*handshaker))); - memset(handshaker, 0, sizeof(*handshaker)); - grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base); - gpr_mu_init(&handshaker->mu); - gpr_ref_init(&handshaker->refcount, 1); - grpc_slice_buffer_init(&handshaker->write_buffer); - GRPC_CLOSURE_INIT(&handshaker->request_done_closure, on_write_done, - handshaker, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&handshaker->response_read_closure, on_read_done, - handshaker, grpc_schedule_on_exec_ctx); - grpc_http_parser_init(&handshaker->http_parser, GRPC_HTTP_RESPONSE, - &handshaker->http_response); - return &handshaker->base; +HttpConnectHandshaker::HttpConnectHandshaker() { + gpr_mu_init(&mu_); + grpc_slice_buffer_init(&write_buffer_); + GRPC_CLOSURE_INIT(&request_done_closure_, &HttpConnectHandshaker::OnWriteDone, + this, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&response_read_closure_, &HttpConnectHandshaker::OnReadDone, + this, grpc_schedule_on_exec_ctx); + grpc_http_parser_init(&http_parser_, GRPC_HTTP_RESPONSE, &http_response_); } // // handshaker factory // -static void handshaker_factory_add_handshakers( - grpc_handshaker_factory* factory, const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr) { - grpc_handshake_manager_add(handshake_mgr, - grpc_http_connect_handshaker_create()); -} - -static void handshaker_factory_destroy(grpc_handshaker_factory* factory) {} +class HttpConnectHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(MakeRefCounted()); + } + ~HttpConnectHandshakerFactory() override = default; +}; -static const grpc_handshaker_factory_vtable handshaker_factory_vtable = { - handshaker_factory_add_handshakers, handshaker_factory_destroy}; +} // namespace -static grpc_handshaker_factory handshaker_factory = { - &handshaker_factory_vtable}; +} // namespace grpc_core void grpc_http_connect_register_handshaker_factory() { - grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_CLIENT, - &handshaker_factory); + using namespace grpc_core; + HandshakerRegistry::RegisterHandshakerFactory( + true /* at_start */, HANDSHAKER_CLIENT, + UniquePtr(New())); } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/http_proxy.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/http_proxy.cc index 29a6c0e36..8951a2920 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/http_proxy.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/http_proxy.cc @@ -29,25 +29,29 @@ #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/slice/b64.h" +#include "src/core/lib/uri/uri_parser.h" /** - * Parses the 'http_proxy' env var and returns the proxy hostname to resolve or - * nullptr on error. Also sets 'user_cred' to user credentials if present in the - * 'http_proxy' env var, otherwise leaves it unchanged. It is caller's - * responsibility to gpr_free user_cred. + * Parses the 'https_proxy' env var (fallback on 'http_proxy') and returns the + * proxy hostname to resolve or nullptr on error. Also sets 'user_cred' to user + * credentials if present in the 'http_proxy' env var, otherwise leaves it + * unchanged. It is caller's responsibility to gpr_free user_cred. */ static char* get_http_proxy_server(char** user_cred) { GPR_ASSERT(user_cred != nullptr); char* proxy_name = nullptr; - char* uri_str = gpr_getenv("http_proxy"); char** authority_strs = nullptr; size_t authority_nstrs; + /* Prefer using 'https_proxy'. Fallback on 'http_proxy' if it is not set. The + * fallback behavior can be removed if there's a demand for it. + */ + char* uri_str = gpr_getenv("https_proxy"); + if (uri_str == nullptr) uri_str = gpr_getenv("http_proxy"); if (uri_str == nullptr) return nullptr; grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */); if (uri == nullptr || uri->authority == nullptr) { @@ -83,11 +87,24 @@ static char* get_http_proxy_server(char** user_cred) { return proxy_name; } +/** + * Checks the value of GRPC_ARG_ENABLE_HTTP_PROXY to determine if http_proxy + * should be used. + */ +bool http_proxy_enabled(const grpc_channel_args* args) { + const grpc_arg* arg = + grpc_channel_args_find(args, GRPC_ARG_ENABLE_HTTP_PROXY); + return grpc_channel_arg_get_bool(arg, true); +} + static bool proxy_mapper_map_name(grpc_proxy_mapper* mapper, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args) { + if (!http_proxy_enabled(args)) { + return false; + } char* user_cred = nullptr; *name_to_resolve = get_http_proxy_server(&user_cred); if (*name_to_resolve == nullptr) return false; diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.cc index e065f4563..d9b3927d1 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.cc @@ -19,6 +19,8 @@ #include #include "src/core/ext/filters/client_channel/lb_policy.h" + +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/lib/iomgr/combiner.h" grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount( @@ -26,10 +28,37 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount( namespace grpc_core { -LoadBalancingPolicy::LoadBalancingPolicy(const Args& args) - : InternallyRefCountedWithTracing(&grpc_trace_lb_policy_refcount), +grpc_json* LoadBalancingPolicy::ParseLoadBalancingConfig( + const grpc_json* lb_config_array) { + if (lb_config_array == nullptr || lb_config_array->type != GRPC_JSON_ARRAY) { + return nullptr; + } + // Find the first LB policy that this client supports. + for (const grpc_json* lb_config = lb_config_array->child; + lb_config != nullptr; lb_config = lb_config->next) { + if (lb_config->type != GRPC_JSON_OBJECT) return nullptr; + grpc_json* policy = nullptr; + for (grpc_json* field = lb_config->child; field != nullptr; + field = field->next) { + if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) + return nullptr; + if (policy != nullptr) return nullptr; // Violate "oneof" type. + policy = field; + } + if (policy == nullptr) return nullptr; + // If we support this policy, then select it. + if (LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(policy->key)) { + return policy; + } + } + return nullptr; +} + +LoadBalancingPolicy::LoadBalancingPolicy(Args args) + : InternallyRefCounted(&grpc_trace_lb_policy_refcount), combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")), client_channel_factory_(args.client_channel_factory), + subchannel_pool_(std::move(args.subchannel_pool)), interested_parties_(grpc_pollset_set_create()), request_reresolution_(nullptr) {} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.h index 454e00a69..56bf1951c 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy.h @@ -21,8 +21,10 @@ #include +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/subchannel.h" +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" @@ -41,8 +43,7 @@ namespace grpc_core { /// /// Any I/O done by the LB policy should be done under the pollset_set /// returned by \a interested_parties(). -class LoadBalancingPolicy - : public InternallyRefCountedWithTracing { +class LoadBalancingPolicy : public InternallyRefCounted { public: struct Args { /// The combiner under which all LB policy calls will be run. @@ -53,55 +54,77 @@ class LoadBalancingPolicy grpc_combiner* combiner = nullptr; /// Used to create channels and subchannels. grpc_client_channel_factory* client_channel_factory = nullptr; + /// Subchannel pool. + RefCountedPtr subchannel_pool; /// Channel args from the resolver. /// Note that the LB policy gets the set of addresses from the - /// GRPC_ARG_LB_ADDRESSES channel arg. + /// GRPC_ARG_SERVER_ADDRESS_LIST channel arg. grpc_channel_args* args = nullptr; + /// Load balancing config from the resolver. + grpc_json* lb_config = nullptr; }; /// State used for an LB pick. struct PickState { /// Initial metadata associated with the picking call. - grpc_metadata_batch* initial_metadata; - /// Bitmask used for selective cancelling. See + grpc_metadata_batch* initial_metadata = nullptr; + /// Pointer to bitmask used for selective cancelling. See /// \a CancelMatchingPicksLocked() and \a GRPC_INITIAL_METADATA_* in /// grpc_types.h. - uint32_t initial_metadata_flags; + uint32_t* initial_metadata_flags = nullptr; /// Storage for LB token in \a initial_metadata, or nullptr if not used. grpc_linked_mdelem lb_token_mdelem_storage; /// Closure to run when pick is complete, if not completed synchronously. - grpc_closure* on_complete; + /// If null, pick will fail if a result is not available synchronously. + grpc_closure* on_complete = nullptr; + // Callback set by lb policy to be notified of trailing metadata. + // The callback must be scheduled on grpc_schedule_on_exec_ctx. + grpc_closure* recv_trailing_metadata_ready = nullptr; + // The address that will be set to point to the original + // recv_trailing_metadata_ready callback, to be invoked by the LB + // policy's recv_trailing_metadata_ready callback when complete. + // Must be non-null if recv_trailing_metadata_ready is non-null. + grpc_closure** original_recv_trailing_metadata_ready = nullptr; + // If this is not nullptr, then the client channel will point it to the + // call's trailing metadata before invoking recv_trailing_metadata_ready. + // If this is nullptr, then the callback will still be called. + // The lb does not have ownership of the metadata. + grpc_metadata_batch** recv_trailing_metadata = nullptr; /// Will be set to the selected subchannel, or nullptr on failure or when /// the LB policy decides to drop the call. RefCountedPtr connected_subchannel; /// Will be populated with context to pass to the subchannel call, if /// needed. - grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT]; - /// Upon success, \a *user_data will be set to whatever opaque information - /// may need to be propagated from the LB policy, or nullptr if not needed. - // TODO(roth): As part of revamping our metadata APIs, try to find a - // way to clean this up and C++-ify it. - void** user_data; + grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT] = {}; /// Next pointer. For internal use by LB policy. - PickState* next; + PickState* next = nullptr; }; // Not copyable nor movable. LoadBalancingPolicy(const LoadBalancingPolicy&) = delete; LoadBalancingPolicy& operator=(const LoadBalancingPolicy&) = delete; - /// Updates the policy with a new set of \a args from the resolver. - /// Note that the LB policy gets the set of addresses from the - /// GRPC_ARG_LB_ADDRESSES channel arg. - virtual void UpdateLocked(const grpc_channel_args& args) GRPC_ABSTRACT; + /// Returns the name of the LB policy. + virtual const char* name() const GRPC_ABSTRACT; + + /// Updates the policy with a new set of \a args and a new \a lb_config from + /// the resolver. Note that the LB policy gets the set of addresses from the + /// GRPC_ARG_SERVER_ADDRESS_LIST channel arg. + virtual void UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) GRPC_ABSTRACT; /// Finds an appropriate subchannel for a call, based on data in \a pick. /// \a pick must remain alive until the pick is complete. /// - /// If the pick succeeds and a result is known immediately, returns true. - /// Otherwise, \a pick->on_complete will be invoked once the pick is - /// complete with its error argument set to indicate success or failure. - virtual bool PickLocked(PickState* pick) GRPC_ABSTRACT; + /// If a result is known immediately, returns true, setting \a *error + /// upon failure. Otherwise, \a pick->on_complete will be invoked once + /// the pick is complete with its error argument set to indicate success + /// or failure. + /// + /// If \a pick->on_complete is null and no result is known immediately, + /// a synchronous failure will be returned (i.e., \a *error will be + /// set and true will be returned). + virtual bool PickLocked(PickState* pick, grpc_error** error) GRPC_ABSTRACT; /// Cancels \a pick. /// The \a on_complete callback of the pending pick will be invoked with @@ -132,17 +155,22 @@ class LoadBalancingPolicy virtual void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) GRPC_ABSTRACT; - /// Performs a connected subchannel ping via \a ConnectedSubchannel::Ping() - /// against one of the connected subchannels managed by the policy. - /// Note: This is intended only for use in tests. - virtual void PingOneLocked(grpc_closure* on_initiate, - grpc_closure* on_ack) GRPC_ABSTRACT; - /// Tries to enter a READY connectivity state. /// TODO(roth): As part of restructuring how we handle IDLE state, /// consider whether this method is still needed. virtual void ExitIdleLocked() GRPC_ABSTRACT; + /// Resets connection backoff. + virtual void ResetBackoffLocked() GRPC_ABSTRACT; + + /// Populates child_subchannels and child_channels with the uuids of this + /// LB policy's referenced children. This is not invoked from the + /// client_channel's combiner. The implementation is responsible for + /// providing its own synchronization. + virtual void FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) GRPC_ABSTRACT; + void Orphan() override { // Invoke ShutdownAndUnrefLocked() inside of the combiner. GRPC_CLOSURE_SCHED( @@ -151,6 +179,10 @@ class LoadBalancingPolicy GRPC_ERROR_NONE); } + /// Returns the JSON node of policy (with both policy name and config content) + /// given the JSON node of a LoadBalancingConfig array. + static grpc_json* ParseLoadBalancingConfig(const grpc_json* lb_config_array); + /// Sets the re-resolution closure to \a request_reresolution. void SetReresolutionClosureLocked(grpc_closure* request_reresolution) { GPR_ASSERT(request_reresolution_ == nullptr); @@ -159,14 +191,18 @@ class LoadBalancingPolicy grpc_pollset_set* interested_parties() const { return interested_parties_; } + // Callers that need their own reference can call the returned + // object's Ref() method. + SubchannelPoolInterface* subchannel_pool() const { + return subchannel_pool_.get(); + } + GRPC_ABSTRACT_BASE_CLASS protected: - // So Delete() can access our protected dtor. - template - friend void Delete(T*); + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - explicit LoadBalancingPolicy(const Args& args); + explicit LoadBalancingPolicy(Args args); virtual ~LoadBalancingPolicy(); grpc_combiner* combiner() const { return combiner_; } @@ -194,6 +230,8 @@ class LoadBalancingPolicy grpc_combiner* combiner_; /// Client channel factory, used to create channels and subchannels. grpc_client_channel_factory* client_channel_factory_; + /// Subchannel pool. + RefCountedPtr subchannel_pool_; /// Owned pointer to interested parties in load balancing decisions. grpc_pollset_set* interested_parties_; /// Callback to force a re-resolution. diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc index 18ef1f6ff..399bb452f 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc @@ -35,18 +35,31 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, static void destroy_channel_elem(grpc_channel_element* elem) {} namespace { + struct call_data { + call_data(const grpc_call_element_args& args) { + if (args.context[GRPC_GRPCLB_CLIENT_STATS].value != nullptr) { + // Get stats object from context and take a ref. + client_stats = static_cast( + args.context[GRPC_GRPCLB_CLIENT_STATS].value) + ->Ref(); + // Record call started. + client_stats->AddCallStarted(); + } + } + // Stats object to update. - grpc_grpclb_client_stats* client_stats; + grpc_core::RefCountedPtr client_stats; // State for intercepting send_initial_metadata. grpc_closure on_complete_for_send; grpc_closure* original_on_complete_for_send; - bool send_initial_metadata_succeeded; + bool send_initial_metadata_succeeded = false; // State for intercepting recv_initial_metadata. grpc_closure recv_initial_metadata_ready; grpc_closure* original_recv_initial_metadata_ready; - bool recv_initial_metadata_succeeded; + bool recv_initial_metadata_succeeded = false; }; + } // namespace static void on_complete_for_send(void* arg, grpc_error* error) { @@ -68,16 +81,8 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); - // Get stats object from context and take a ref. GPR_ASSERT(args->context != nullptr); - if (args->context[GRPC_GRPCLB_CLIENT_STATS].value != nullptr) { - calld->client_stats = - grpc_grpclb_client_stats_ref(static_cast( - args->context[GRPC_GRPCLB_CLIENT_STATS].value)); - // Record call started. - grpc_grpclb_client_stats_add_call_started(calld->client_stats); - } + new (elem->call_data) call_data(*args); return GRPC_ERROR_NONE; } @@ -88,13 +93,14 @@ static void destroy_call_elem(grpc_call_element* elem, if (calld->client_stats != nullptr) { // Record call finished, optionally setting client_failed_to_send and // received. - grpc_grpclb_client_stats_add_call_finished( + calld->client_stats->AddCallFinished( !calld->send_initial_metadata_succeeded /* client_failed_to_send */, - calld->recv_initial_metadata_succeeded /* known_received */, - calld->client_stats); + calld->recv_initial_metadata_succeeded /* known_received */); // All done, so unref the stats object. - grpc_grpclb_client_stats_unref(calld->client_stats); + // TODO(roth): Eliminate this once filter stack is converted to C++. + calld->client_stats.reset(); } + calld->~call_data(); } static void start_transport_stream_op_batch( diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 1a675476f..63e381d64 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -76,6 +76,7 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" @@ -83,7 +84,7 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" -#include "src/core/ext/filters/client_channel/subchannel_index.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" @@ -91,6 +92,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" @@ -111,18 +113,25 @@ #define GRPC_GRPCLB_RECONNECT_JITTER 0.2 #define GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS 10000 +#define GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN "grpc.grpclb_address_lb_token" + namespace grpc_core { TraceFlag grpc_lb_glb_trace(false, "glb"); namespace { +constexpr char kGrpclb[] = "grpclb"; + class GrpcLb : public LoadBalancingPolicy { public: - GrpcLb(const grpc_lb_addresses* addresses, const Args& args); + explicit GrpcLb(Args args); + + const char* name() const override { return kGrpclb; } - void UpdateLocked(const grpc_channel_args& args) override; - bool PickLocked(PickState* pick) override; + void UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) override; + bool PickLocked(PickState* pick, grpc_error** error) override; void CancelPickLocked(PickState* pick, grpc_error* error) override; void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, @@ -132,8 +141,11 @@ class GrpcLb : public LoadBalancingPolicy { grpc_connectivity_state CheckConnectivityLocked( grpc_error** connectivity_error) override; void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; - void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override; void ExitIdleLocked() override; + void ResetBackoffLocked() override; + void FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) override; private: /// Linked list of pending pick requests. It stores all information needed to @@ -155,26 +167,14 @@ class GrpcLb : public LoadBalancingPolicy { // Our on_complete closure and the original one. grpc_closure on_complete; grpc_closure* original_on_complete; - // The LB token associated with the pick. This is set via user_data in - // the pick. - grpc_mdelem lb_token; - // Stats for client-side load reporting. Note that this holds a - // reference, which must be either passed on via context or unreffed. - grpc_grpclb_client_stats* client_stats = nullptr; + // Stats for client-side load reporting. + RefCountedPtr client_stats; // Next pending pick. PendingPick* next = nullptr; }; - /// A linked list of pending pings waiting for the RR policy to be created. - struct PendingPing { - grpc_closure* on_initiate; - grpc_closure* on_ack; - PendingPing* next = nullptr; - }; - /// Contains a call to the LB server and all the data related to the call. - class BalancerCallState - : public InternallyRefCountedWithTracing { + class BalancerCallState : public InternallyRefCounted { public: explicit BalancerCallState( RefCountedPtr parent_grpclb_policy); @@ -185,7 +185,8 @@ class GrpcLb : public LoadBalancingPolicy { void StartQuery(); - grpc_grpclb_client_stats* client_stats() const { return client_stats_; } + GrpcLbClientStats* client_stats() const { return client_stats_.get(); } + bool seen_initial_response() const { return seen_initial_response_; } private: @@ -236,7 +237,7 @@ class GrpcLb : public LoadBalancingPolicy { // The stats for client-side load reporting associated with this LB call. // Created after the first serverlist is received. - grpc_grpclb_client_stats* client_stats_ = nullptr; + RefCountedPtr client_stats_; grpc_millis client_stats_report_interval_ = 0; grpc_timer client_load_report_timer_; bool client_load_report_timer_callback_pending_ = false; @@ -269,14 +270,12 @@ class GrpcLb : public LoadBalancingPolicy { void AddPendingPick(PendingPick* pp); static void OnPendingPickComplete(void* arg, grpc_error* error); - // Pending ping methods. - void AddPendingPing(grpc_closure* on_initiate, grpc_closure* on_ack); - // Methods for dealing with the RR policy. void CreateOrUpdateRoundRobinPolicyLocked(); grpc_channel_args* CreateRoundRobinPolicyArgsLocked(); - void CreateRoundRobinPolicyLocked(const Args& args); - bool PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp); + void CreateRoundRobinPolicyLocked(Args args); + bool PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp, + grpc_error** error); void UpdateConnectivityStateFromRoundRobinPolicyLocked( grpc_error* rr_state_error); static void OnRoundRobinConnectivityChangedLocked(void* arg, @@ -297,6 +296,8 @@ class GrpcLb : public LoadBalancingPolicy { // The channel for communicating with the LB server. grpc_channel* lb_channel_ = nullptr; + // Uuid of the lb channel. Used for channelz. + gpr_atm lb_channel_uuid_ = 0; grpc_connectivity_state lb_channel_connectivity_; grpc_closure lb_channel_on_connectivity_changed_; // Are we already watching the LB channel's connectivity? @@ -330,15 +331,14 @@ class GrpcLb : public LoadBalancingPolicy { // 0 means not using fallback. int lb_fallback_timeout_ms_ = 0; // The backend addresses from the resolver. - grpc_lb_addresses* fallback_backend_addresses_ = nullptr; + UniquePtr fallback_backend_addresses_; // Fallback timer. bool fallback_timer_callback_pending_ = false; grpc_timer lb_fallback_timer_; grpc_closure lb_on_fallback_; - // Pending picks and pings that are waiting on the RR policy's connectivity. + // Pending picks that are waiting on the RR policy's connectivity. PendingPick* pending_picks_ = nullptr; - PendingPing* pending_pings_ = nullptr; // The RR policy to use for the backends. OrphanablePtr rr_policy_; @@ -351,7 +351,7 @@ class GrpcLb : public LoadBalancingPolicy { // serverlist parsing code // -// vtable for LB tokens in grpc_lb_addresses +// vtable for LB token channel arg. void* lb_token_copy(void* token) { return token == nullptr ? nullptr @@ -363,42 +363,17 @@ void lb_token_destroy(void* token) { } } int lb_token_cmp(void* token1, void* token2) { - if (token1 > token2) return 1; - if (token1 < token2) return -1; + // Always indicate a match, since we don't want this channel arg to + // affect the subchannel's key in the index. return 0; } -const grpc_lb_user_data_vtable lb_token_vtable = { +const grpc_arg_pointer_vtable lb_token_arg_vtable = { lb_token_copy, lb_token_destroy, lb_token_cmp}; -// Returns the backend addresses extracted from the given addresses. -grpc_lb_addresses* ExtractBackendAddresses(const grpc_lb_addresses* addresses) { - // First pass: count the number of backend addresses. - size_t num_backends = 0; - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (!addresses->addresses[i].is_balancer) { - ++num_backends; - } - } - // Second pass: actually populate the addresses and (empty) LB tokens. - grpc_lb_addresses* backend_addresses = - grpc_lb_addresses_create(num_backends, &lb_token_vtable); - size_t num_copied = 0; - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (addresses->addresses[i].is_balancer) continue; - const grpc_resolved_address* addr = &addresses->addresses[i].address; - grpc_lb_addresses_set_address(backend_addresses, num_copied, &addr->addr, - addr->len, false /* is_balancer */, - nullptr /* balancer_name */, - (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload); - ++num_copied; - } - return backend_addresses; -} - bool IsServerValid(const grpc_grpclb_server* server, size_t idx, bool log) { if (server->drop) return false; const grpc_grpclb_ip_address* ip = &server->ip_address; - if (server->port >> 16 != 0) { + if (GPR_UNLIKELY(server->port >> 16 != 0)) { if (log) { gpr_log(GPR_ERROR, "Invalid port '%d' at index %lu of serverlist. Ignoring.", @@ -406,7 +381,7 @@ bool IsServerValid(const grpc_grpclb_server* server, size_t idx, bool log) { } return false; } - if (ip->size != 4 && ip->size != 16) { + if (GPR_UNLIKELY(ip->size != 4 && ip->size != 16)) { if (log) { gpr_log(GPR_ERROR, "Expected IP to be 4 or 16 bytes, got %d at index %lu of " @@ -442,30 +417,16 @@ void ParseServer(const grpc_grpclb_server* server, } // Returns addresses extracted from \a serverlist. -grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) { - size_t num_valid = 0; - /* first pass: count how many are valid in order to allocate the necessary - * memory in a single block */ +ServerAddressList ProcessServerlist(const grpc_grpclb_serverlist* serverlist) { + ServerAddressList addresses; for (size_t i = 0; i < serverlist->num_servers; ++i) { - if (IsServerValid(serverlist->servers[i], i, true)) ++num_valid; - } - grpc_lb_addresses* lb_addresses = - grpc_lb_addresses_create(num_valid, &lb_token_vtable); - /* second pass: actually populate the addresses and LB tokens (aka user data - * to the outside world) to be read by the RR policy during its creation. - * Given that the validity tests are very cheap, they are performed again - * instead of marking the valid ones during the first pass, as this would - * incurr in an allocation due to the arbitrary number of server */ - size_t addr_idx = 0; - for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) { - const grpc_grpclb_server* server = serverlist->servers[sl_idx]; - if (!IsServerValid(serverlist->servers[sl_idx], sl_idx, false)) continue; - GPR_ASSERT(addr_idx < num_valid); - /* address processing */ + const grpc_grpclb_server* server = serverlist->servers[i]; + if (!IsServerValid(serverlist->servers[i], i, false)) continue; + // Address processing. grpc_resolved_address addr; ParseServer(server, &addr); - /* lb token processing */ - void* user_data; + // LB token processing. + grpc_mdelem lb_token; if (server->has_load_balance_token) { const size_t lb_token_max_length = GPR_ARRAY_SIZE(server->load_balance_token); @@ -473,9 +434,7 @@ grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) { strnlen(server->load_balance_token, lb_token_max_length); grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer( server->load_balance_token, lb_token_length); - user_data = - (void*)grpc_mdelem_from_slices(GRPC_MDSTR_LB_TOKEN, lb_token_mdstr) - .payload; + lb_token = grpc_mdelem_from_slices(GRPC_MDSTR_LB_TOKEN, lb_token_mdstr); } else { char* uri = grpc_sockaddr_to_uri(&addr); gpr_log(GPR_INFO, @@ -483,15 +442,18 @@ grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) { "be used instead", uri); gpr_free(uri); - user_data = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload; + lb_token = GRPC_MDELEM_LB_TOKEN_EMPTY; } - grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len, - false /* is_balancer */, - nullptr /* balancer_name */, user_data); - ++addr_idx; - } - GPR_ASSERT(addr_idx == num_valid); - return lb_addresses; + // Add address. + grpc_arg arg = grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), + (void*)lb_token.payload, &lb_token_arg_vtable); + grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); + addresses.emplace_back(addr, args); + // Clean up. + GRPC_MDELEM_UNREF(lb_token); + } + return addresses; } // @@ -500,7 +462,7 @@ grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) { GrpcLb::BalancerCallState::BalancerCallState( RefCountedPtr parent_grpclb_policy) - : InternallyRefCountedWithTracing(&grpc_lb_glb_trace), + : InternallyRefCounted(&grpc_lb_glb_trace), grpclb_policy_(std::move(parent_grpclb_policy)) { GPR_ASSERT(grpclb_policy_ != nullptr); GPR_ASSERT(!grpclb_policy()->shutting_down_); @@ -547,9 +509,6 @@ GrpcLb::BalancerCallState::~BalancerCallState() { grpc_byte_buffer_destroy(send_message_payload_); grpc_byte_buffer_destroy(recv_message_payload_); grpc_slice_unref_internal(lb_call_status_details_); - if (client_stats_ != nullptr) { - grpc_grpclb_client_stats_unref(client_stats_); - } } void GrpcLb::BalancerCallState::Orphan() { @@ -570,8 +529,7 @@ void GrpcLb::BalancerCallState::Orphan() { void GrpcLb::BalancerCallState::StartQuery() { GPR_ASSERT(lb_call_ != nullptr); if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, - "[grpclb %p] Starting LB call (lb_calld: %p, lb_call: %p)", + gpr_log(GPR_INFO, "[grpclb %p] lb_calld=%p: Starting LB call %p", grpclb_policy_.get(), this, lb_call_); } // Create the ops. @@ -672,22 +630,22 @@ void GrpcLb::BalancerCallState::MaybeSendClientLoadReportLocked( bool GrpcLb::BalancerCallState::LoadReportCountersAreZero( grpc_grpclb_request* request) { - grpc_grpclb_dropped_call_counts* drop_entries = - static_cast( + GrpcLbClientStats::DroppedCallCounts* drop_entries = + static_cast( request->client_stats.calls_finished_with_drop.arg); return request->client_stats.num_calls_started == 0 && request->client_stats.num_calls_finished == 0 && request->client_stats.num_calls_finished_with_client_failed_to_send == 0 && request->client_stats.num_calls_finished_known_received == 0 && - (drop_entries == nullptr || drop_entries->num_entries == 0); + (drop_entries == nullptr || drop_entries->size() == 0); } void GrpcLb::BalancerCallState::SendClientLoadReportLocked() { // Construct message payload. GPR_ASSERT(send_message_payload_ == nullptr); grpc_grpclb_request* request = - grpc_grpclb_load_report_request_create_locked(client_stats_); + grpc_grpclb_load_report_request_create_locked(client_stats_.get()); // Skip client load report if the counters were all zero in the last // report and they are still zero in this one. if (LoadReportCountersAreZero(request)) { @@ -714,9 +672,10 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() { this, grpc_combiner_scheduler(grpclb_policy()->combiner())); grpc_call_error call_error = grpc_call_start_batch_and_execute( lb_call_, &op, 1, &client_load_report_closure_); - if (call_error != GRPC_CALL_OK) { - gpr_log(GPR_ERROR, "[grpclb %p] call_error=%d", grpclb_policy_.get(), - call_error); + if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) { + gpr_log(GPR_ERROR, + "[grpclb %p] lb_calld=%p call_error=%d sending client load report", + grpclb_policy_.get(), this, call_error); GPR_ASSERT(GRPC_CALL_OK == call_error); } } @@ -753,7 +712,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked( void* arg, grpc_error* error) { BalancerCallState* lb_calld = static_cast(arg); GrpcLb* grpclb_policy = lb_calld->grpclb_policy(); - // Empty payload means the LB call was cancelled. + // Null payload means the LB call was cancelled. if (lb_calld != grpclb_policy->lb_calld_.get() || lb_calld->recv_message_payload_ == nullptr) { lb_calld->Unref(DEBUG_LOCATION, "on_message_received"); @@ -777,15 +736,17 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked( &initial_response->client_stats_report_interval)); if (grpc_lb_glb_trace.enabled()) { gpr_log(GPR_INFO, - "[grpclb %p] Received initial LB response message; " - "client load reporting interval = %" PRIdPTR " milliseconds", - grpclb_policy, lb_calld->client_stats_report_interval_); + "[grpclb %p] lb_calld=%p: Received initial LB response " + "message; client load reporting interval = %" PRId64 + " milliseconds", + grpclb_policy, lb_calld, + lb_calld->client_stats_report_interval_); } } else if (grpc_lb_glb_trace.enabled()) { gpr_log(GPR_INFO, - "[grpclb %p] Received initial LB response message; client load " - "reporting NOT enabled", - grpclb_policy); + "[grpclb %p] lb_calld=%p: Received initial LB response message; " + "client load reporting NOT enabled", + grpclb_policy, lb_calld); } grpc_grpclb_initial_response_destroy(initial_response); lb_calld->seen_initial_response_ = true; @@ -795,73 +756,68 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked( GPR_ASSERT(lb_calld->lb_call_ != nullptr); if (grpc_lb_glb_trace.enabled()) { gpr_log(GPR_INFO, - "[grpclb %p] Serverlist with %" PRIuPTR " servers received", - grpclb_policy, serverlist->num_servers); + "[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR + " servers received", + grpclb_policy, lb_calld, serverlist->num_servers); for (size_t i = 0; i < serverlist->num_servers; ++i) { grpc_resolved_address addr; ParseServer(serverlist->servers[i], &addr); char* ipport; grpc_sockaddr_to_string(&ipport, &addr, false); - gpr_log(GPR_INFO, "[grpclb %p] Serverlist[%" PRIuPTR "]: %s", - grpclb_policy, i, ipport); + gpr_log(GPR_INFO, + "[grpclb %p] lb_calld=%p: Serverlist[%" PRIuPTR "]: %s", + grpclb_policy, lb_calld, i, ipport); gpr_free(ipport); } } - /* update serverlist */ - if (serverlist->num_servers > 0) { - // Start sending client load report only after we start using the - // serverlist returned from the current LB call. - if (lb_calld->client_stats_report_interval_ > 0 && - lb_calld->client_stats_ == nullptr) { - lb_calld->client_stats_ = grpc_grpclb_client_stats_create(); - // TODO(roth): We currently track this ref manually. Once the - // ClosureRef API is ready, we should pass the RefCountedPtr<> along - // with the callback. - auto self = lb_calld->Ref(DEBUG_LOCATION, "client_load_report"); - self.release(); - lb_calld->ScheduleNextClientLoadReportLocked(); - } - if (grpc_grpclb_serverlist_equals(grpclb_policy->serverlist_, - serverlist)) { - if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, - "[grpclb %p] Incoming server list identical to current, " - "ignoring.", - grpclb_policy); - } - grpc_grpclb_destroy_serverlist(serverlist); - } else { /* new serverlist */ - if (grpclb_policy->serverlist_ != nullptr) { - /* dispose of the old serverlist */ - grpc_grpclb_destroy_serverlist(grpclb_policy->serverlist_); - } else { - /* or dispose of the fallback */ - grpc_lb_addresses_destroy(grpclb_policy->fallback_backend_addresses_); - grpclb_policy->fallback_backend_addresses_ = nullptr; - if (grpclb_policy->fallback_timer_callback_pending_) { - grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_); - } - } - // and update the copy in the GrpcLb instance. This - // serverlist instance will be destroyed either upon the next - // update or when the GrpcLb instance is destroyed. - grpclb_policy->serverlist_ = serverlist; - grpclb_policy->serverlist_index_ = 0; - grpclb_policy->CreateOrUpdateRoundRobinPolicyLocked(); - } - } else { + // Start sending client load report only after we start using the + // serverlist returned from the current LB call. + if (lb_calld->client_stats_report_interval_ > 0 && + lb_calld->client_stats_ == nullptr) { + lb_calld->client_stats_.reset(New()); + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = lb_calld->Ref(DEBUG_LOCATION, "client_load_report"); + self.release(); + lb_calld->ScheduleNextClientLoadReportLocked(); + } + // Check if the serverlist differs from the previous one. + if (grpc_grpclb_serverlist_equals(grpclb_policy->serverlist_, serverlist)) { if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, "[grpclb %p] Received empty server list, ignoring.", - grpclb_policy); + gpr_log(GPR_INFO, + "[grpclb %p] lb_calld=%p: Incoming server list identical to " + "current, ignoring.", + grpclb_policy, lb_calld); } grpc_grpclb_destroy_serverlist(serverlist); + } else { // New serverlist. + if (grpclb_policy->serverlist_ != nullptr) { + // Dispose of the old serverlist. + grpc_grpclb_destroy_serverlist(grpclb_policy->serverlist_); + } else { + // Dispose of the fallback. + grpclb_policy->fallback_backend_addresses_.reset(); + if (grpclb_policy->fallback_timer_callback_pending_) { + grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_); + } + } + // Update the serverlist in the GrpcLb instance. This serverlist + // instance will be destroyed either upon the next update or when the + // GrpcLb instance is destroyed. + grpclb_policy->serverlist_ = serverlist; + grpclb_policy->serverlist_index_ = 0; + grpclb_policy->CreateOrUpdateRoundRobinPolicyLocked(); } } else { // No valid initial response or serverlist found. + char* response_slice_str = + grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX); gpr_log(GPR_ERROR, - "[grpclb %p] Invalid LB response received: '%s'. Ignoring.", - grpclb_policy, - grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX)); + "[grpclb %p] lb_calld=%p: Invalid LB response received: '%s'. " + "Ignoring.", + grpclb_policy, lb_calld, response_slice_str); + gpr_free(response_slice_str); } grpc_slice_unref_internal(response_slice); if (!grpclb_policy->shutting_down_) { @@ -891,9 +847,9 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked( char* status_details = grpc_slice_to_c_string(lb_calld->lb_call_status_details_); gpr_log(GPR_INFO, - "[grpclb %p] Status from LB server received. Status = %d, details " - "= '%s', (lb_calld: %p, lb_call: %p), error '%s'", - grpclb_policy, lb_calld->lb_call_status_, status_details, lb_calld, + "[grpclb %p] lb_calld=%p: Status from LB server received. " + "Status = %d, details = '%s', (lb_call: %p), error '%s'", + grpclb_policy, lb_calld, lb_calld->lb_call_status_, status_details, lb_calld->lb_call_, grpc_error_string(error)); gpr_free(status_details); } @@ -922,31 +878,25 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked( // helper code for creating balancer channel // -grpc_lb_addresses* ExtractBalancerAddresses( - const grpc_lb_addresses* addresses) { - size_t num_grpclb_addrs = 0; - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs; - } - // There must be at least one balancer address, or else the - // client_channel would not have chosen this LB policy. - GPR_ASSERT(num_grpclb_addrs > 0); - grpc_lb_addresses* lb_addresses = - grpc_lb_addresses_create(num_grpclb_addrs, nullptr); - size_t lb_addresses_idx = 0; - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (!addresses->addresses[i].is_balancer) continue; - if (addresses->addresses[i].user_data != nullptr) { - gpr_log(GPR_ERROR, - "This LB policy doesn't support user data. It will be ignored"); +ServerAddressList ExtractBalancerAddresses(const ServerAddressList& addresses) { + ServerAddressList balancer_addresses; + for (size_t i = 0; i < addresses.size(); ++i) { + if (addresses[i].IsBalancer()) { + // Strip out the is_balancer channel arg, since we don't want to + // recursively use the grpclb policy in the channel used to talk to + // the balancers. Note that we do NOT strip out the balancer_name + // channel arg, since we need that to set the authority correctly + // to talk to the balancers. + static const char* args_to_remove[] = { + GRPC_ARG_ADDRESS_IS_BALANCER, + }; + balancer_addresses.emplace_back( + addresses[i].address(), + grpc_channel_args_copy_and_remove(addresses[i].args(), args_to_remove, + GPR_ARRAY_SIZE(args_to_remove))); } - grpc_lb_addresses_set_address( - lb_addresses, lb_addresses_idx++, addresses->addresses[i].address.addr, - addresses->addresses[i].address.len, false /* is balancer */, - addresses->addresses[i].balancer_name, nullptr /* user data */); } - GPR_ASSERT(num_grpclb_addrs == lb_addresses_idx); - return lb_addresses; + return balancer_addresses; } /* Returns the channel args for the LB channel, used to create a bidirectional @@ -958,15 +908,18 @@ grpc_lb_addresses* ExtractBalancerAddresses( * above the grpclb policy. * - \a args: other args inherited from the grpclb policy. */ grpc_channel_args* BuildBalancerChannelArgs( - const grpc_lb_addresses* addresses, + const ServerAddressList& addresses, FakeResolverResponseGenerator* response_generator, const grpc_channel_args* args) { - grpc_lb_addresses* lb_addresses = ExtractBalancerAddresses(addresses); + ServerAddressList balancer_addresses = ExtractBalancerAddresses(addresses); // Channel args to remove. static const char* args_to_remove[] = { // LB policy name, since we want to use the default (pick_first) in // the LB channel. GRPC_ARG_LB_POLICY_NAME, + // Strip out the service config, since we don't want the LB policy + // config specified for the parent channel to affect the LB channel. + GRPC_ARG_SERVICE_CONFIG, // The channel arg for the server URI, since that will be different for // the LB channel than for the parent channel. The client channel // factory will re-add this arg with the right value. @@ -978,8 +931,8 @@ grpc_channel_args* BuildBalancerChannelArgs( // resolver will have is_balancer=false, whereas our own addresses have // is_balancer=true. We need the LB channel to return addresses with // is_balancer=false so that it does not wind up recursively using the - // grpclb LB policy, as per the special case logic in client_channel.c. - GRPC_ARG_LB_ADDRESSES, + // grpclb LB policy. + GRPC_ARG_SERVER_ADDRESS_LIST, // The fake resolver response generator, because we are replacing it // with the one from the grpclb policy, used to propagate updates to // the LB channel. @@ -995,33 +948,36 @@ grpc_channel_args* BuildBalancerChannelArgs( }; // Channel args to add. const grpc_arg args_to_add[] = { - // New LB addresses. + // New address list. // Note that we pass these in both when creating the LB channel // and via the fake resolver. The latter is what actually gets used. - grpc_lb_addresses_create_channel_arg(lb_addresses), + CreateServerAddressListChannelArg(&balancer_addresses), // The fake resolver response generator, which we use to inject // address updates into the LB channel. grpc_core::FakeResolverResponseGenerator::MakeChannelArg( response_generator), + // A channel arg indicating the target is a grpclb load balancer. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1), + // A channel arg indicating this is an internal channels, aka it is + // owned by components in Core, not by the user application. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), 1), }; // Construct channel args. grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove( args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add, GPR_ARRAY_SIZE(args_to_add)); // Make any necessary modifications for security. - new_args = grpc_lb_policy_grpclb_modify_lb_channel_args(new_args); - // Clean up. - grpc_lb_addresses_destroy(lb_addresses); - return new_args; + return grpc_lb_policy_grpclb_modify_lb_channel_args(new_args); } // // ctor and dtor // -GrpcLb::GrpcLb(const grpc_lb_addresses* addresses, - const LoadBalancingPolicy::Args& args) - : LoadBalancingPolicy(args), +GrpcLb::GrpcLb(LoadBalancingPolicy::Args args) + : LoadBalancingPolicy(std::move(args)), response_generator_(MakeRefCounted()), lb_call_backoff_( BackOff::Options() @@ -1032,7 +988,6 @@ GrpcLb::GrpcLb(const grpc_lb_addresses* addresses, .set_max_backoff(GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000)) { // Initialization. - grpc_subchannel_index_ref(); GRPC_CLOSURE_INIT(&lb_channel_on_connectivity_changed_, &GrpcLb::OnBalancerChannelConnectivityChangedLocked, this, grpc_combiner_scheduler(args.combiner)); @@ -1069,17 +1024,12 @@ GrpcLb::GrpcLb(const grpc_lb_addresses* addresses, GrpcLb::~GrpcLb() { GPR_ASSERT(pending_picks_ == nullptr); - GPR_ASSERT(pending_pings_ == nullptr); gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); grpc_connectivity_state_destroy(&state_tracker_); if (serverlist_ != nullptr) { grpc_grpclb_destroy_serverlist(serverlist_); } - if (fallback_backend_addresses_ != nullptr) { - grpc_lb_addresses_destroy(fallback_backend_addresses_); - } - grpc_subchannel_index_unref(); } void GrpcLb::ShutdownLocked() { @@ -1101,6 +1051,7 @@ void GrpcLb::ShutdownLocked() { if (lb_channel_ != nullptr) { grpc_channel_destroy(lb_channel_); lb_channel_ = nullptr; + gpr_atm_no_barrier_store(&lb_channel_uuid_, 0); } grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "grpclb_shutdown"); @@ -1112,14 +1063,6 @@ void GrpcLb::ShutdownLocked() { // Note: pp is deleted in this callback. GRPC_CLOSURE_SCHED(&pp->on_complete, GRPC_ERROR_REF(error)); } - // Clear pending pings. - PendingPing* pping; - while ((pping = pending_pings_) != nullptr) { - pending_pings_ = pping->next; - GRPC_CLOSURE_SCHED(pping->on_initiate, GRPC_ERROR_REF(error)); - GRPC_CLOSURE_SCHED(pping->on_ack, GRPC_ERROR_REF(error)); - Delete(pping); - } GRPC_ERROR_UNREF(error); } @@ -1132,10 +1075,10 @@ void GrpcLb::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) { while ((pp = pending_picks_) != nullptr) { pending_picks_ = pp->next; pp->pick->on_complete = pp->original_on_complete; - pp->pick->user_data = nullptr; - if (new_policy->PickLocked(pp->pick)) { + grpc_error* error = GRPC_ERROR_NONE; + if (new_policy->PickLocked(pp->pick, &error)) { // Synchronous return; schedule closure. - GRPC_CLOSURE_SCHED(pp->pick->on_complete, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(pp->pick->on_complete, error); } Delete(pp); } @@ -1193,7 +1136,7 @@ void GrpcLb::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, pending_picks_ = nullptr; while (pp != nullptr) { PendingPick* next = pp->next; - if ((pp->pick->initial_metadata_flags & initial_metadata_flags_mask) == + if ((*pp->pick->initial_metadata_flags & initial_metadata_flags_mask) == initial_metadata_flags_eq) { // Note: pp is deleted in this callback. GRPC_CLOSURE_SCHED(&pp->on_complete, @@ -1219,55 +1162,56 @@ void GrpcLb::ExitIdleLocked() { } } -bool GrpcLb::PickLocked(PickState* pick) { +void GrpcLb::ResetBackoffLocked() { + if (lb_channel_ != nullptr) { + grpc_channel_reset_connect_backoff(lb_channel_); + } + if (rr_policy_ != nullptr) { + rr_policy_->ResetBackoffLocked(); + } +} + +bool GrpcLb::PickLocked(PickState* pick, grpc_error** error) { PendingPick* pp = PendingPickCreate(pick); bool pick_done = false; if (rr_policy_ != nullptr) { - const grpc_connectivity_state rr_connectivity_state = - rr_policy_->CheckConnectivityLocked(nullptr); - // The RR policy may have transitioned to SHUTDOWN but the callback - // registered to capture this event (on_rr_connectivity_changed_) may not - // have been invoked yet. We need to make sure we aren't trying to pick - // from an RR policy instance that's in shutdown. - if (rr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) { + if (grpc_lb_glb_trace.enabled()) { + gpr_log(GPR_INFO, "[grpclb %p] about to PICK from RR %p", this, + rr_policy_.get()); + } + pick_done = + PickFromRoundRobinPolicyLocked(false /* force_async */, pp, error); + } else { // rr_policy_ == NULL + if (pick->on_complete == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No pick result available but synchronous result required."); + pick_done = true; + } else { if (grpc_lb_glb_trace.enabled()) { gpr_log(GPR_INFO, - "[grpclb %p] NOT picking from from RR %p: RR conn state=%s", - this, rr_policy_.get(), - grpc_connectivity_state_name(rr_connectivity_state)); + "[grpclb %p] No RR policy. Adding to grpclb's pending picks", + this); } AddPendingPick(pp); - pick_done = false; - } else { // RR not in shutdown - if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, "[grpclb %p] about to PICK from RR %p", this, - rr_policy_.get()); + if (!started_picking_) { + StartPickingLocked(); } - pick_done = PickFromRoundRobinPolicyLocked(false /* force_async */, pp); - } - } else { // rr_policy_ == NULL - if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, - "[grpclb %p] No RR policy. Adding to grpclb's pending picks", - this); - } - AddPendingPick(pp); - if (!started_picking_) { - StartPickingLocked(); + pick_done = false; } - pick_done = false; } return pick_done; } -void GrpcLb::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) { +void GrpcLb::FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) { + // delegate to the RoundRobin to fill the children subchannels. if (rr_policy_ != nullptr) { - rr_policy_->PingOneLocked(on_initiate, on_ack); - } else { - AddPendingPing(on_initiate, on_ack); - if (!started_picking_) { - StartPickingLocked(); - } + rr_policy_->FillChildRefsForChannelz(child_subchannels, child_channels); + } + gpr_atm uuid = gpr_atm_no_barrier_load(&lb_channel_uuid_); + if (uuid != 0) { + child_channels->push_back(uuid); } } @@ -1282,9 +1226,27 @@ void GrpcLb::NotifyOnStateChangeLocked(grpc_connectivity_state* current, notify); } +// Returns the backend addresses extracted from the given addresses. +UniquePtr ExtractBackendAddresses( + const ServerAddressList& addresses) { + void* lb_token = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload; + grpc_arg arg = grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), lb_token, + &lb_token_arg_vtable); + auto backend_addresses = MakeUnique(); + for (size_t i = 0; i < addresses.size(); ++i) { + if (!addresses[i].IsBalancer()) { + backend_addresses->emplace_back( + addresses[i].address(), + grpc_channel_args_copy_and_add(addresses[i].args(), &arg, 1)); + } + } + return backend_addresses; +} + void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { - const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES); - if (arg == nullptr || arg->type != GRPC_ARG_POINTER) { + const ServerAddressList* addresses = FindServerAddressListChannelArg(&args); + if (addresses == nullptr) { // Ignore this update. gpr_log( GPR_ERROR, @@ -1292,13 +1254,8 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { this); return; } - const grpc_lb_addresses* addresses = - static_cast(arg->value.pointer.p); // Update fallback address list. - if (fallback_backend_addresses_ != nullptr) { - grpc_lb_addresses_destroy(fallback_backend_addresses_); - } - fallback_backend_addresses_ = ExtractBackendAddresses(addresses); + fallback_backend_addresses_ = ExtractBackendAddresses(*addresses); // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args, // since we use this to trigger the client_load_reporting filter. static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME}; @@ -1309,7 +1266,7 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { &args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1); // Construct args for balancer channel. grpc_channel_args* lb_channel_args = - BuildBalancerChannelArgs(addresses, response_generator_.get(), &args); + BuildBalancerChannelArgs(*addresses, response_generator_.get(), &args); // Create balancer channel if needed. if (lb_channel_ == nullptr) { char* uri_str; @@ -1318,6 +1275,11 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { client_channel_factory(), uri_str, GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, lb_channel_args); GPR_ASSERT(lb_channel_ != nullptr); + grpc_core::channelz::ChannelNode* channel_node = + grpc_channel_get_channelz_node(lb_channel_); + if (channel_node != nullptr) { + gpr_atm_no_barrier_store(&lb_channel_uuid_, channel_node->uuid()); + } gpr_free(uri_str); } // Propagate updates to the LB channel (pick_first) through the fake @@ -1326,13 +1288,10 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { grpc_channel_args_destroy(lb_channel_args); } -void GrpcLb::UpdateLocked(const grpc_channel_args& args) { +void GrpcLb::UpdateLocked(const grpc_channel_args& args, grpc_json* lb_config) { ProcessChannelArgsLocked(args); - // If fallback is configured and the RR policy already exists, update - // it with the new fallback addresses. - if (lb_fallback_timeout_ms_ > 0 && rr_policy_ != nullptr) { - CreateOrUpdateRoundRobinPolicyLocked(); - } + // Update the existing RR policy. + if (rr_policy_ != nullptr) CreateOrUpdateRoundRobinPolicyLocked(); // Start watching the LB channel connectivity for connection, if not // already doing so. if (!watching_lb_channel_) { @@ -1416,7 +1375,7 @@ void GrpcLb::StartBalancerCallRetryTimerLocked() { gpr_log(GPR_INFO, "[grpclb %p] Connection to LB server lost...", this); grpc_millis timeout = next_try - ExecCtx::Get()->Now(); if (timeout > 0) { - gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.", + gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active in %" PRId64 "ms.", this, timeout); } else { gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active immediately.", @@ -1486,7 +1445,7 @@ void GrpcLb::OnBalancerChannelConnectivityChangedLocked(void* arg, grpclb_policy->lb_call_backoff_.Reset(); grpclb_policy->StartBalancerCallLocked(); } - // Fall through. + // fallthrough case GRPC_CHANNEL_SHUTDOWN: done: grpclb_policy->watching_lb_channel_ = false; @@ -1512,16 +1471,21 @@ grpc_error* AddLbTokenToInitialMetadata( // Destroy function used when embedding client stats in call context. void DestroyClientStats(void* arg) { - grpc_grpclb_client_stats_unref(static_cast(arg)); + static_cast(arg)->Unref(); } void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) { - /* if connected_subchannel is nullptr, no pick has been made by the RR - * policy (e.g., all addresses failed to connect). There won't be any - * user_data/token available */ + // If connected_subchannel is nullptr, no pick has been made by the RR + // policy (e.g., all addresses failed to connect). There won't be any + // LB token available. if (pp->pick->connected_subchannel != nullptr) { - if (!GRPC_MDISNULL(pp->lb_token)) { - AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(pp->lb_token), + const grpc_arg* arg = + grpc_channel_args_find(pp->pick->connected_subchannel->args(), + GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN); + if (arg != nullptr) { + grpc_mdelem lb_token = { + reinterpret_cast(arg->value.pointer.p)}; + AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(lb_token), &pp->pick->lb_token_mdelem_storage, pp->pick->initial_metadata); } else { @@ -1533,14 +1497,12 @@ void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) { // Pass on client stats via context. Passes ownership of the reference. if (pp->client_stats != nullptr) { pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].value = - pp->client_stats; + pp->client_stats.release(); pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].destroy = DestroyClientStats; } } else { - if (pp->client_stats != nullptr) { - grpc_grpclb_client_stats_unref(pp->client_stats); - } + pp->client_stats.reset(); } } @@ -1570,18 +1532,6 @@ void GrpcLb::AddPendingPick(PendingPick* pp) { pending_picks_ = pp; } -// -// PendingPing -// - -void GrpcLb::AddPendingPing(grpc_closure* on_initiate, grpc_closure* on_ack) { - PendingPing* pping = New(); - pping->on_initiate = on_initiate; - pping->on_ack = on_ack; - pping->next = pending_pings_; - pending_pings_ = pping; -} - // // code for interacting with the RR policy // @@ -1591,9 +1541,10 @@ void GrpcLb::AddPendingPing(grpc_closure* on_initiate, grpc_closure* on_ack) { // cleanups this callback would otherwise be responsible for. // If \a force_async is true, then we will manually schedule the // completion callback even if the pick is available immediately. -bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp) { +bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp, + grpc_error** error) { // Check for drops if we are not using fallback backend addresses. - if (serverlist_ != nullptr) { + if (serverlist_ != nullptr && serverlist_->num_servers > 0) { // Look at the index into the serverlist to see if we should drop this call. grpc_grpclb_server* server = serverlist_->servers[serverlist_index_++]; if (serverlist_index_ == serverlist_->num_servers) { @@ -1606,8 +1557,8 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp) { // subchannel call (and therefore no client_load_reporting filter) // for dropped calls. if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) { - grpc_grpclb_client_stats_add_call_dropped_locked( - server->load_balance_token, lb_calld_->client_stats()); + lb_calld_->client_stats()->AddCallDroppedLocked( + server->load_balance_token); } if (force_async) { GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_NONE); @@ -1618,18 +1569,17 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp) { return true; } } - // Set client_stats and user_data. + // Set client_stats. if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) { - pp->client_stats = grpc_grpclb_client_stats_ref(lb_calld_->client_stats()); + pp->client_stats = lb_calld_->client_stats()->Ref(); } - GPR_ASSERT(pp->pick->user_data == nullptr); - pp->pick->user_data = (void**)&pp->lb_token; // Pick via the RR policy. - bool pick_done = rr_policy_->PickLocked(pp->pick); + bool pick_done = rr_policy_->PickLocked(pp->pick, error); if (pick_done) { PendingPickSetMetadataAndContext(pp); if (force_async) { - GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(pp->original_on_complete, *error); + *error = GRPC_ERROR_NONE; pick_done = false; } Delete(pp); @@ -1641,15 +1591,19 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp) { return pick_done; } -void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) { +void GrpcLb::CreateRoundRobinPolicyLocked(Args args) { GPR_ASSERT(rr_policy_ == nullptr); rr_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( - "round_robin", args); - if (rr_policy_ == nullptr) { + "round_robin", std::move(args)); + if (GPR_UNLIKELY(rr_policy_ == nullptr)) { gpr_log(GPR_ERROR, "[grpclb %p] Failure creating a RoundRobin policy", this); return; } + if (grpc_lb_glb_trace.enabled()) { + gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this, + rr_policy_.get()); + } // TODO(roth): We currently track this ref manually. Once the new // ClosureRef API is done, pass the RefCountedPtr<> along with the closure. auto self = Ref(DEBUG_LOCATION, "on_rr_reresolution_requested"); @@ -1681,26 +1635,18 @@ void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) { "[grpclb %p] Pending pick about to (async) PICK from RR %p", this, rr_policy_.get()); } - PickFromRoundRobinPolicyLocked(true /* force_async */, pp); - } - // Send pending pings to RR policy. - PendingPing* pping; - while ((pping = pending_pings_)) { - pending_pings_ = pping->next; - if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, "[grpclb %p] Pending ping about to PING from RR %p", - this, rr_policy_.get()); - } - rr_policy_->PingOneLocked(pping->on_initiate, pping->on_ack); - Delete(pping); + grpc_error* error = GRPC_ERROR_NONE; + PickFromRoundRobinPolicyLocked(true /* force_async */, pp, &error); } } grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() { - grpc_lb_addresses* addresses; + ServerAddressList tmp_addresses; + ServerAddressList* addresses = &tmp_addresses; + bool is_backend_from_grpclb_load_balancer = false; if (serverlist_ != nullptr) { - GPR_ASSERT(serverlist_->num_servers > 0); - addresses = ProcessServerlist(serverlist_); + tmp_addresses = ProcessServerlist(serverlist_); + is_backend_from_grpclb_load_balancer = true; } else { // If CreateOrUpdateRoundRobinPolicyLocked() is invoked when we haven't // received any serverlist from the balancer, we use the fallback backends @@ -1708,16 +1654,30 @@ grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() { // empty, in which case the new round_robin policy will keep the requested // picks pending. GPR_ASSERT(fallback_backend_addresses_ != nullptr); - addresses = grpc_lb_addresses_copy(fallback_backend_addresses_); + addresses = fallback_backend_addresses_.get(); } GPR_ASSERT(addresses != nullptr); - // Replace the LB addresses in the channel args that we pass down to + // Replace the server address list in the channel args that we pass down to // the subchannel. - static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES}; - const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses); + static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST}; + grpc_arg args_to_add[3] = { + CreateServerAddressListChannelArg(addresses), + // A channel arg indicating if the target is a backend inferred from a + // grpclb load balancer. + grpc_channel_arg_integer_create( + const_cast( + GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER), + is_backend_from_grpclb_load_balancer), + }; + size_t num_args_to_add = 2; + if (is_backend_from_grpclb_load_balancer) { + args_to_add[2] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1); + ++num_args_to_add; + } grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove( - args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg, 1); - grpc_lb_addresses_destroy(addresses); + args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add, + num_args_to_add); return args; } @@ -1730,17 +1690,14 @@ void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() { gpr_log(GPR_INFO, "[grpclb %p] Updating RR policy %p", this, rr_policy_.get()); } - rr_policy_->UpdateLocked(*args); + rr_policy_->UpdateLocked(*args, nullptr); } else { LoadBalancingPolicy::Args lb_policy_args; lb_policy_args.combiner = combiner(); lb_policy_args.client_channel_factory = client_channel_factory(); lb_policy_args.args = args; - CreateRoundRobinPolicyLocked(lb_policy_args); - if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this, - rr_policy_.get()); - } + lb_policy_args.subchannel_pool = subchannel_pool()->Ref(); + CreateRoundRobinPolicyLocked(std::move(lb_policy_args)); } grpc_channel_args_destroy(args); } @@ -1848,24 +1805,23 @@ void GrpcLb::OnRoundRobinConnectivityChangedLocked(void* arg, class GrpcLbFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr CreateLoadBalancingPolicy( - const LoadBalancingPolicy::Args& args) const override { + LoadBalancingPolicy::Args args) const override { /* Count the number of gRPC-LB addresses. There must be at least one. */ - const grpc_arg* arg = - grpc_channel_args_find(args.args, GRPC_ARG_LB_ADDRESSES); - if (arg == nullptr || arg->type != GRPC_ARG_POINTER) { - return nullptr; - } - grpc_lb_addresses* addresses = - static_cast(arg->value.pointer.p); - size_t num_grpclb_addrs = 0; - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs; + const ServerAddressList* addresses = + FindServerAddressListChannelArg(args.args); + if (addresses == nullptr) return nullptr; + bool found_balancer = false; + for (size_t i = 0; i < addresses->size(); ++i) { + if ((*addresses)[i].IsBalancer()) { + found_balancer = true; + break; + } } - if (num_grpclb_addrs == 0) return nullptr; - return OrphanablePtr(New(addresses, args)); + if (!found_balancer) return nullptr; + return OrphanablePtr(New(std::move(args))); } - const char* name() const override { return "grpclb"; } + const char* name() const override { return kGrpclb; } }; } // namespace diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h new file mode 100644 index 000000000..4d39c4d50 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H + +#include + +/** Channel arg indicating if a target corresponding to the address is grpclb + * loadbalancer. The type of this arg is an integer and the value is treated as + * a bool. */ +#define GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER \ + "grpc.address_is_grpclb_load_balancer" +/** Channel arg indicating if a target corresponding to the address is a backend + * received from a balancer. The type of this arg is an integer and the value is + * treated as a bool. */ +#define GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER \ + "grpc.address_is_backend_from_grpclb_load_balancer" + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H \ + */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h index 825065a9c..3b2dc370e 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h @@ -21,7 +21,7 @@ #include -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include /// Makes any necessary modifications to \a args for use in the grpclb /// balancer channel. diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc index 441efd5e2..657ff6931 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc @@ -26,6 +26,7 @@ #include #include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -42,22 +43,23 @@ int BalancerNameCmp(const grpc_core::UniquePtr& a, } RefCountedPtr CreateTargetAuthorityTable( - grpc_lb_addresses* addresses) { + const ServerAddressList& addresses) { TargetAuthorityTable::Entry* target_authority_entries = - static_cast(gpr_zalloc( - sizeof(*target_authority_entries) * addresses->num_addresses)); - for (size_t i = 0; i < addresses->num_addresses; ++i) { + static_cast( + gpr_zalloc(sizeof(*target_authority_entries) * addresses.size())); + for (size_t i = 0; i < addresses.size(); ++i) { char* addr_str; - GPR_ASSERT(grpc_sockaddr_to_string( - &addr_str, &addresses->addresses[i].address, true) > 0); + GPR_ASSERT( + grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true) > 0); target_authority_entries[i].key = grpc_slice_from_copied_string(addr_str); - target_authority_entries[i].value.reset( - gpr_strdup(addresses->addresses[i].balancer_name)); gpr_free(addr_str); + char* balancer_name = grpc_channel_arg_get_string(grpc_channel_args_find( + addresses[i].args(), GRPC_ARG_ADDRESS_BALANCER_NAME)); + target_authority_entries[i].value.reset(gpr_strdup(balancer_name)); } RefCountedPtr target_authority_table = - TargetAuthorityTable::Create(addresses->num_addresses, - target_authority_entries, BalancerNameCmp); + TargetAuthorityTable::Create(addresses.size(), target_authority_entries, + BalancerNameCmp); gpr_free(target_authority_entries); return target_authority_table; } @@ -72,13 +74,12 @@ grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args( grpc_arg args_to_add[2]; size_t num_args_to_add = 0; // Add arg for targets info table. - const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_LB_ADDRESSES); - GPR_ASSERT(arg != nullptr); - GPR_ASSERT(arg->type == GRPC_ARG_POINTER); - grpc_lb_addresses* addresses = - static_cast(arg->value.pointer.p); + grpc_core::ServerAddressList* addresses = + grpc_core::FindServerAddressListChannelArg(args); + GPR_ASSERT(addresses != nullptr); grpc_core::RefCountedPtr - target_authority_table = grpc_core::CreateTargetAuthorityTable(addresses); + target_authority_table = + grpc_core::CreateTargetAuthorityTable(*addresses); args_to_add[num_args_to_add++] = grpc_core::CreateTargetAuthorityTableChannelArg( target_authority_table.get()); @@ -87,22 +88,18 @@ grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args( // bearer token credentials. grpc_channel_credentials* channel_credentials = grpc_channel_credentials_find_in_args(args); - grpc_channel_credentials* creds_sans_call_creds = nullptr; + grpc_core::RefCountedPtr creds_sans_call_creds; if (channel_credentials != nullptr) { creds_sans_call_creds = - grpc_channel_credentials_duplicate_without_call_credentials( - channel_credentials); + channel_credentials->duplicate_without_call_credentials(); GPR_ASSERT(creds_sans_call_creds != nullptr); args_to_remove[num_args_to_remove++] = GRPC_ARG_CHANNEL_CREDENTIALS; args_to_add[num_args_to_add++] = - grpc_channel_credentials_to_arg(creds_sans_call_creds); + grpc_channel_credentials_to_arg(creds_sans_call_creds.get()); } grpc_channel_args* result = grpc_channel_args_copy_and_add_and_remove( args, args_to_remove, num_args_to_remove, args_to_add, num_args_to_add); // Clean up. grpc_channel_args_destroy(args); - if (creds_sans_call_creds != nullptr) { - grpc_channel_credentials_unref(creds_sans_call_creds); - } return result; } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc index dfbaead7d..087cd8f27 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc @@ -22,131 +22,65 @@ #include -#include #include #include -#include -#include "src/core/lib/channel/channel_args.h" +namespace grpc_core { -#define GRPC_ARG_GRPCLB_CLIENT_STATS "grpc.grpclb_client_stats" - -struct grpc_grpclb_client_stats { - gpr_refcount refs; - // This field must only be accessed via *_locked() methods. - grpc_grpclb_dropped_call_counts* drop_token_counts; - // These fields may be accessed from multiple threads at a time. - gpr_atm num_calls_started; - gpr_atm num_calls_finished; - gpr_atm num_calls_finished_with_client_failed_to_send; - gpr_atm num_calls_finished_known_received; -}; - -grpc_grpclb_client_stats* grpc_grpclb_client_stats_create() { - grpc_grpclb_client_stats* client_stats = - static_cast(gpr_zalloc(sizeof(*client_stats))); - gpr_ref_init(&client_stats->refs, 1); - return client_stats; -} - -grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref( - grpc_grpclb_client_stats* client_stats) { - gpr_ref(&client_stats->refs); - return client_stats; -} - -void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats) { - if (gpr_unref(&client_stats->refs)) { - grpc_grpclb_dropped_call_counts_destroy(client_stats->drop_token_counts); - gpr_free(client_stats); - } -} - -void grpc_grpclb_client_stats_add_call_started( - grpc_grpclb_client_stats* client_stats) { - gpr_atm_full_fetch_add(&client_stats->num_calls_started, (gpr_atm)1); +void GrpcLbClientStats::AddCallStarted() { + gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1); } -void grpc_grpclb_client_stats_add_call_finished( - bool finished_with_client_failed_to_send, bool finished_known_received, - grpc_grpclb_client_stats* client_stats) { - gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1); +void GrpcLbClientStats::AddCallFinished( + bool finished_with_client_failed_to_send, bool finished_known_received) { + gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1); if (finished_with_client_failed_to_send) { - gpr_atm_full_fetch_add( - &client_stats->num_calls_finished_with_client_failed_to_send, - (gpr_atm)1); + gpr_atm_full_fetch_add(&num_calls_finished_with_client_failed_to_send_, + (gpr_atm)1); } if (finished_known_received) { - gpr_atm_full_fetch_add(&client_stats->num_calls_finished_known_received, - (gpr_atm)1); + gpr_atm_full_fetch_add(&num_calls_finished_known_received_, (gpr_atm)1); } } -void grpc_grpclb_client_stats_add_call_dropped_locked( - char* token, grpc_grpclb_client_stats* client_stats) { +void GrpcLbClientStats::AddCallDroppedLocked(char* token) { // Increment num_calls_started and num_calls_finished. - gpr_atm_full_fetch_add(&client_stats->num_calls_started, (gpr_atm)1); - gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1); + gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1); + gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1); // Record the drop. - if (client_stats->drop_token_counts == nullptr) { - client_stats->drop_token_counts = - static_cast( - gpr_zalloc(sizeof(grpc_grpclb_dropped_call_counts))); + if (drop_token_counts_ == nullptr) { + drop_token_counts_.reset(New()); } - grpc_grpclb_dropped_call_counts* drop_token_counts = - client_stats->drop_token_counts; - for (size_t i = 0; i < drop_token_counts->num_entries; ++i) { - if (strcmp(drop_token_counts->token_counts[i].token, token) == 0) { - ++drop_token_counts->token_counts[i].count; + for (size_t i = 0; i < drop_token_counts_->size(); ++i) { + if (strcmp((*drop_token_counts_)[i].token.get(), token) == 0) { + ++(*drop_token_counts_)[i].count; return; } } - // Not found, so add a new entry. We double the size of the array each time. - size_t new_num_entries = 2; - while (new_num_entries < drop_token_counts->num_entries + 1) { - new_num_entries *= 2; - } - drop_token_counts->token_counts = static_cast( - gpr_realloc(drop_token_counts->token_counts, - new_num_entries * sizeof(grpc_grpclb_drop_token_count))); - grpc_grpclb_drop_token_count* new_entry = - &drop_token_counts->token_counts[drop_token_counts->num_entries++]; - new_entry->token = gpr_strdup(token); - new_entry->count = 1; + // Not found, so add a new entry. + drop_token_counts_->emplace_back(UniquePtr(gpr_strdup(token)), 1); } -static void atomic_get_and_reset_counter(int64_t* value, gpr_atm* counter) { - *value = static_cast(gpr_atm_acq_load(counter)); - gpr_atm_full_fetch_add(counter, (gpr_atm)(-*value)); +namespace { + +void AtomicGetAndResetCounter(int64_t* value, gpr_atm* counter) { + *value = static_cast(gpr_atm_full_xchg(counter, (gpr_atm)0)); } -void grpc_grpclb_client_stats_get_locked( - grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started, - int64_t* num_calls_finished, +} // namespace + +void GrpcLbClientStats::GetLocked( + int64_t* num_calls_started, int64_t* num_calls_finished, int64_t* num_calls_finished_with_client_failed_to_send, int64_t* num_calls_finished_known_received, - grpc_grpclb_dropped_call_counts** drop_token_counts) { - atomic_get_and_reset_counter(num_calls_started, - &client_stats->num_calls_started); - atomic_get_and_reset_counter(num_calls_finished, - &client_stats->num_calls_finished); - atomic_get_and_reset_counter( - num_calls_finished_with_client_failed_to_send, - &client_stats->num_calls_finished_with_client_failed_to_send); - atomic_get_and_reset_counter( - num_calls_finished_known_received, - &client_stats->num_calls_finished_known_received); - *drop_token_counts = client_stats->drop_token_counts; - client_stats->drop_token_counts = nullptr; + UniquePtr* drop_token_counts) { + AtomicGetAndResetCounter(num_calls_started, &num_calls_started_); + AtomicGetAndResetCounter(num_calls_finished, &num_calls_finished_); + AtomicGetAndResetCounter(num_calls_finished_with_client_failed_to_send, + &num_calls_finished_with_client_failed_to_send_); + AtomicGetAndResetCounter(num_calls_finished_known_received, + &num_calls_finished_known_received_); + *drop_token_counts = std::move(drop_token_counts_); } -void grpc_grpclb_dropped_call_counts_destroy( - grpc_grpclb_dropped_call_counts* drop_entries) { - if (drop_entries != nullptr) { - for (size_t i = 0; i < drop_entries->num_entries; ++i) { - gpr_free(drop_entries->token_counts[i].token); - } - gpr_free(drop_entries->token_counts); - gpr_free(drop_entries); - } -} +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index c971e5688..18ab2c945 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -21,47 +21,52 @@ #include -#include +#include -#include +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/ref_counted.h" -typedef struct grpc_grpclb_client_stats grpc_grpclb_client_stats; +namespace grpc_core { -typedef struct { - char* token; - int64_t count; -} grpc_grpclb_drop_token_count; +class GrpcLbClientStats : public RefCounted { + public: + struct DropTokenCount { + UniquePtr token; + int64_t count; -typedef struct { - grpc_grpclb_drop_token_count* token_counts; - size_t num_entries; -} grpc_grpclb_dropped_call_counts; + DropTokenCount(UniquePtr token, int64_t count) + : token(std::move(token)), count(count) {} + }; -grpc_grpclb_client_stats* grpc_grpclb_client_stats_create(); -grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref( - grpc_grpclb_client_stats* client_stats); -void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats); + typedef InlinedVector DroppedCallCounts; -void grpc_grpclb_client_stats_add_call_started( - grpc_grpclb_client_stats* client_stats); -void grpc_grpclb_client_stats_add_call_finished( - bool finished_with_client_failed_to_send, bool finished_known_received, - grpc_grpclb_client_stats* client_stats); + GrpcLbClientStats() {} -// This method is not thread-safe; caller must synchronize. -void grpc_grpclb_client_stats_add_call_dropped_locked( - char* token, grpc_grpclb_client_stats* client_stats); + void AddCallStarted(); + void AddCallFinished(bool finished_with_client_failed_to_send, + bool finished_known_received); -// This method is not thread-safe; caller must synchronize. -void grpc_grpclb_client_stats_get_locked( - grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started, - int64_t* num_calls_finished, - int64_t* num_calls_finished_with_client_failed_to_send, - int64_t* num_calls_finished_known_received, - grpc_grpclb_dropped_call_counts** drop_token_counts); + // This method is not thread-safe; caller must synchronize. + void AddCallDroppedLocked(char* token); -void grpc_grpclb_dropped_call_counts_destroy( - grpc_grpclb_dropped_call_counts* drop_entries); + // This method is not thread-safe; caller must synchronize. + void GetLocked(int64_t* num_calls_started, int64_t* num_calls_finished, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received, + UniquePtr* drop_token_counts); + + private: + // This field must only be accessed via *_locked() methods. + UniquePtr drop_token_counts_; + // These fields may be accessed from multiple threads at a time. + gpr_atm num_calls_started_ = 0; + gpr_atm num_calls_finished_ = 0; + gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; + gpr_atm num_calls_finished_known_received_ = 0; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CLIENT_STATS_H \ */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc index 7ef3bcf24..f24281a5b 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc @@ -18,9 +18,9 @@ #include +#include "pb_decode.h" +#include "pb_encode.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" -#include "third_party/nanopb/pb_decode.h" -#include "third_party/nanopb/pb_encode.h" #include @@ -29,7 +29,7 @@ static bool count_serverlist(pb_istream_t* stream, const pb_field_t* field, void** arg) { grpc_grpclb_serverlist* sl = static_cast(*arg); grpc_grpclb_server server; - if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) { + if (GPR_UNLIKELY(!pb_decode(stream, grpc_lb_v1_Server_fields, &server))) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream)); return false; } @@ -52,7 +52,7 @@ static bool decode_serverlist(pb_istream_t* stream, const pb_field_t* field, GPR_ASSERT(dec_arg->serverlist->num_servers >= dec_arg->decoding_idx); grpc_grpclb_server* server = static_cast(gpr_zalloc(sizeof(grpc_grpclb_server))); - if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) { + if (GPR_UNLIKELY(!pb_decode(stream, grpc_lb_v1_Server_fields, server))) { gpr_free(server); gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream)); return false; @@ -73,7 +73,7 @@ grpc_grpclb_request* grpc_grpclb_request_create(const char* lb_service_name) { } static void populate_timestamp(gpr_timespec timestamp, - struct _grpc_lb_v1_Timestamp* timestamp_pb) { + grpc_grpclb_timestamp* timestamp_pb) { timestamp_pb->has_seconds = true; timestamp_pb->seconds = timestamp.tv_sec; timestamp_pb->has_nanos = true; @@ -89,16 +89,16 @@ static bool encode_string(pb_ostream_t* stream, const pb_field_t* field, static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) { - grpc_grpclb_dropped_call_counts* drop_entries = - static_cast(*arg); + grpc_core::GrpcLbClientStats::DroppedCallCounts* drop_entries = + static_cast(*arg); if (drop_entries == nullptr) return true; - for (size_t i = 0; i < drop_entries->num_entries; ++i) { + for (size_t i = 0; i < drop_entries->size(); ++i) { if (!pb_encode_tag_for_field(stream, field)) return false; grpc_lb_v1_ClientStatsPerToken drop_message; drop_message.load_balance_token.funcs.encode = encode_string; - drop_message.load_balance_token.arg = drop_entries->token_counts[i].token; + drop_message.load_balance_token.arg = (*drop_entries)[i].token.get(); drop_message.has_num_calls = true; - drop_message.num_calls = drop_entries->token_counts[i].count; + drop_message.num_calls = (*drop_entries)[i].count; if (!pb_encode_submessage(stream, grpc_lb_v1_ClientStatsPerToken_fields, &drop_message)) { return false; @@ -108,7 +108,7 @@ static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field, } grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( - grpc_grpclb_client_stats* client_stats) { + grpc_core::GrpcLbClientStats* client_stats) { grpc_grpclb_request* req = static_cast( gpr_zalloc(sizeof(grpc_grpclb_request))); req->has_client_stats = true; @@ -120,13 +120,15 @@ grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( req->client_stats.has_num_calls_finished_with_client_failed_to_send = true; req->client_stats.has_num_calls_finished_known_received = true; req->client_stats.calls_finished_with_drop.funcs.encode = encode_drops; - grpc_grpclb_client_stats_get_locked( - client_stats, &req->client_stats.num_calls_started, + grpc_core::UniquePtr + drop_counts; + client_stats->GetLocked( + &req->client_stats.num_calls_started, &req->client_stats.num_calls_finished, &req->client_stats.num_calls_finished_with_client_failed_to_send, - &req->client_stats.num_calls_finished_known_received, - reinterpret_cast( - &req->client_stats.calls_finished_with_drop.arg)); + &req->client_stats.num_calls_finished_known_received, &drop_counts); + // Will be deleted in grpc_grpclb_request_destroy(). + req->client_stats.calls_finished_with_drop.arg = drop_counts.release(); return req; } @@ -149,10 +151,10 @@ grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request* request) { void grpc_grpclb_request_destroy(grpc_grpclb_request* request) { if (request->has_client_stats) { - grpc_grpclb_dropped_call_counts* drop_entries = - static_cast( + grpc_core::GrpcLbClientStats::DroppedCallCounts* drop_entries = + static_cast( request->client_stats.calls_finished_with_drop.arg); - grpc_grpclb_dropped_call_counts_destroy(drop_entries); + grpc_core::Delete(drop_entries); } gpr_free(request); } @@ -165,7 +167,8 @@ grpc_grpclb_initial_response* grpc_grpclb_initial_response_parse( GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response)); grpc_grpclb_response res; memset(&res, 0, sizeof(grpc_grpclb_response)); - if (!pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res)) { + if (GPR_UNLIKELY( + !pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res))) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return nullptr; } @@ -195,7 +198,7 @@ grpc_grpclb_serverlist* grpc_grpclb_response_parse_serverlist( res.server_list.servers.funcs.decode = count_serverlist; res.server_list.servers.arg = sl; bool status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res); - if (!status) { + if (GPR_UNLIKELY(!status)) { gpr_free(sl); gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return nullptr; @@ -211,7 +214,7 @@ grpc_grpclb_serverlist* grpc_grpclb_response_parse_serverlist( res.server_list.servers.arg = &decode_arg; status = pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res); - if (!status) { + if (GPR_UNLIKELY(!status)) { grpc_grpclb_destroy_serverlist(sl); gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return nullptr; diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h index d4270f253..71d371c88 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h @@ -25,7 +25,7 @@ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/lib/iomgr/exec_ctx.h" #define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128 @@ -33,7 +33,9 @@ typedef grpc_lb_v1_Server_ip_address_t grpc_grpclb_ip_address; typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request; typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response; typedef grpc_lb_v1_Server grpc_grpclb_server; -typedef grpc_lb_v1_Duration grpc_grpclb_duration; +typedef google_protobuf_Duration grpc_grpclb_duration; +typedef google_protobuf_Timestamp grpc_grpclb_timestamp; + typedef struct { grpc_grpclb_server** servers; size_t num_servers; @@ -42,7 +44,7 @@ typedef struct { /** Create a request for a gRPC LB service under \a lb_service_name */ grpc_grpclb_request* grpc_grpclb_request_create(const char* lb_service_name); grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( - grpc_grpclb_client_stats* client_stats); + grpc_core::GrpcLbClientStats* client_stats); /** Protocol Buffers v3-encode \a request */ grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request* request); diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c new file mode 100644 index 000000000..131d9b7ca --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c @@ -0,0 +1,19 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.7-dev */ + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h" +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t google_protobuf_Duration_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_protobuf_Duration, seconds, seconds, 0), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, google_protobuf_Duration, nanos, seconds, 0), + PB_LAST_FIELD +}; + + +/* @@protoc_insertion_point(eof) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h new file mode 100644 index 000000000..93070c65b --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h @@ -0,0 +1,54 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.7-dev */ + +#ifndef PB_GOOGLE_PROTOBUF_DURATION_PB_H_INCLUDED +#define PB_GOOGLE_PROTOBUF_DURATION_PB_H_INCLUDED +#include "pb.h" +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef struct _google_protobuf_Duration { + bool has_seconds; + int64_t seconds; + bool has_nanos; + int32_t nanos; +/* @@protoc_insertion_point(struct:google_protobuf_Duration) */ +} google_protobuf_Duration; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define google_protobuf_Duration_init_default {false, 0, false, 0} +#define google_protobuf_Duration_init_zero {false, 0, false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define google_protobuf_Duration_seconds_tag 1 +#define google_protobuf_Duration_nanos_tag 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t google_protobuf_Duration_fields[3]; + +/* Maximum encoded size of messages (where known) */ +#define google_protobuf_Duration_size 22 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define DURATION_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c new file mode 100644 index 000000000..b6f8ffc55 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c @@ -0,0 +1,19 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.7-dev */ + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h" +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t google_protobuf_Timestamp_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_protobuf_Timestamp, seconds, seconds, 0), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, google_protobuf_Timestamp, nanos, seconds, 0), + PB_LAST_FIELD +}; + + +/* @@protoc_insertion_point(eof) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h new file mode 100644 index 000000000..7f4848152 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h @@ -0,0 +1,54 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.7-dev */ + +#ifndef PB_GOOGLE_PROTOBUF_TIMESTAMP_PB_H_INCLUDED +#define PB_GOOGLE_PROTOBUF_TIMESTAMP_PB_H_INCLUDED +#include "pb.h" +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef struct _google_protobuf_Timestamp { + bool has_seconds; + int64_t seconds; + bool has_nanos; + int32_t nanos; +/* @@protoc_insertion_point(struct:google_protobuf_Timestamp) */ +} google_protobuf_Timestamp; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define google_protobuf_Timestamp_init_default {false, 0, false, 0} +#define google_protobuf_Timestamp_init_zero {false, 0, false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define google_protobuf_Timestamp_seconds_tag 1 +#define google_protobuf_Timestamp_nanos_tag 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t google_protobuf_Timestamp_fields[3]; + +/* Maximum encoded size of messages (where known) */ +#define google_protobuf_Timestamp_size 22 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define TIMESTAMP_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c index 4e6c5cc83..f6538e134 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c @@ -2,7 +2,6 @@ /* Generated by nanopb-0.3.7-dev */ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" - /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. @@ -10,18 +9,6 @@ -const pb_field_t grpc_lb_v1_Duration_fields[3] = { - PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Duration, seconds, seconds, 0), - PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Duration, nanos, seconds, 0), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v1_Timestamp_fields[3] = { - PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Timestamp, seconds, seconds, 0), - PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Timestamp, nanos, seconds, 0), - PB_LAST_FIELD -}; - const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3] = { PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v1_InitialLoadBalanceRequest_fields), PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v1_ClientStats_fields), @@ -40,7 +27,7 @@ const pb_field_t grpc_lb_v1_ClientStatsPerToken_fields[3] = { }; const pb_field_t grpc_lb_v1_ClientStats_fields[7] = { - PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, timestamp, timestamp, &grpc_lb_v1_Timestamp_fields), + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, timestamp, timestamp, &google_protobuf_Timestamp_fields), PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, num_calls_started, timestamp, 0), PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, num_calls_finished, num_calls_started, 0), PB_FIELD( 6, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_with_client_failed_to_send, num_calls_finished, 0), @@ -57,7 +44,7 @@ const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3] = { const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3] = { PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceResponse, load_balancer_delegate, load_balancer_delegate, 0), - PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v1_Duration_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &google_protobuf_Duration_fields), PB_LAST_FIELD }; @@ -84,7 +71,7 @@ const pb_field_t grpc_lb_v1_Server_fields[5] = { * numbers or field sizes that are larger than what can fit in 8 or 16 bit * field descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) @@ -95,7 +82,7 @@ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h index 066c07620..a4ff516d8 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h @@ -3,7 +3,9 @@ #ifndef PB_GRPC_LB_V1_LOAD_BALANCER_PB_H_INCLUDED #define PB_GRPC_LB_V1_LOAD_BALANCER_PB_H_INCLUDED -#include "third_party/nanopb/pb.h" +#include "pb.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. @@ -19,6 +21,21 @@ typedef struct _grpc_lb_v1_ServerList { /* @@protoc_insertion_point(struct:grpc_lb_v1_ServerList) */ } grpc_lb_v1_ServerList; +typedef struct _grpc_lb_v1_ClientStats { + bool has_timestamp; + google_protobuf_Timestamp timestamp; + bool has_num_calls_started; + int64_t num_calls_started; + bool has_num_calls_finished; + int64_t num_calls_finished; + bool has_num_calls_finished_with_client_failed_to_send; + int64_t num_calls_finished_with_client_failed_to_send; + bool has_num_calls_finished_known_received; + int64_t num_calls_finished_known_received; + pb_callback_t calls_finished_with_drop; +/* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStats) */ +} grpc_lb_v1_ClientStats; + typedef struct _grpc_lb_v1_ClientStatsPerToken { pb_callback_t load_balance_token; bool has_num_calls; @@ -26,20 +43,20 @@ typedef struct _grpc_lb_v1_ClientStatsPerToken { /* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStatsPerToken) */ } grpc_lb_v1_ClientStatsPerToken; -typedef struct _grpc_lb_v1_Duration { - bool has_seconds; - int64_t seconds; - bool has_nanos; - int32_t nanos; -/* @@protoc_insertion_point(struct:grpc_lb_v1_Duration) */ -} grpc_lb_v1_Duration; - typedef struct _grpc_lb_v1_InitialLoadBalanceRequest { bool has_name; char name[128]; /* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceRequest) */ } grpc_lb_v1_InitialLoadBalanceRequest; +typedef struct _grpc_lb_v1_InitialLoadBalanceResponse { + bool has_load_balancer_delegate; + char load_balancer_delegate[64]; + bool has_client_stats_report_interval; + google_protobuf_Duration client_stats_report_interval; +/* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceResponse) */ +} grpc_lb_v1_InitialLoadBalanceResponse; + typedef PB_BYTES_ARRAY_T(16) grpc_lb_v1_Server_ip_address_t; typedef struct _grpc_lb_v1_Server { bool has_ip_address; @@ -53,37 +70,6 @@ typedef struct _grpc_lb_v1_Server { /* @@protoc_insertion_point(struct:grpc_lb_v1_Server) */ } grpc_lb_v1_Server; -typedef struct _grpc_lb_v1_Timestamp { - bool has_seconds; - int64_t seconds; - bool has_nanos; - int32_t nanos; -/* @@protoc_insertion_point(struct:grpc_lb_v1_Timestamp) */ -} grpc_lb_v1_Timestamp; - -typedef struct _grpc_lb_v1_ClientStats { - bool has_timestamp; - grpc_lb_v1_Timestamp timestamp; - bool has_num_calls_started; - int64_t num_calls_started; - bool has_num_calls_finished; - int64_t num_calls_finished; - bool has_num_calls_finished_with_client_failed_to_send; - int64_t num_calls_finished_with_client_failed_to_send; - bool has_num_calls_finished_known_received; - int64_t num_calls_finished_known_received; - pb_callback_t calls_finished_with_drop; -/* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStats) */ -} grpc_lb_v1_ClientStats; - -typedef struct _grpc_lb_v1_InitialLoadBalanceResponse { - bool has_load_balancer_delegate; - char load_balancer_delegate[64]; - bool has_client_stats_report_interval; - grpc_lb_v1_Duration client_stats_report_interval; -/* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceResponse) */ -} grpc_lb_v1_InitialLoadBalanceResponse; - typedef struct _grpc_lb_v1_LoadBalanceRequest { bool has_initial_request; grpc_lb_v1_InitialLoadBalanceRequest initial_request; @@ -103,56 +89,46 @@ typedef struct _grpc_lb_v1_LoadBalanceResponse { /* Default values for struct fields */ /* Initializer values for message structs */ -#define grpc_lb_v1_Duration_init_default {false, 0, false, 0} -#define grpc_lb_v1_Timestamp_init_default {false, 0, false, 0} #define grpc_lb_v1_LoadBalanceRequest_init_default {false, grpc_lb_v1_InitialLoadBalanceRequest_init_default, false, grpc_lb_v1_ClientStats_init_default} #define grpc_lb_v1_InitialLoadBalanceRequest_init_default {false, ""} #define grpc_lb_v1_ClientStatsPerToken_init_default {{{NULL}, NULL}, false, 0} -#define grpc_lb_v1_ClientStats_init_default {false, grpc_lb_v1_Timestamp_init_default, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}} +#define grpc_lb_v1_ClientStats_init_default {false, google_protobuf_Timestamp_init_default, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}} #define grpc_lb_v1_LoadBalanceResponse_init_default {false, grpc_lb_v1_InitialLoadBalanceResponse_init_default, false, grpc_lb_v1_ServerList_init_default} -#define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, grpc_lb_v1_Duration_init_default} +#define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, google_protobuf_Duration_init_default} #define grpc_lb_v1_ServerList_init_default {{{NULL}, NULL}} #define grpc_lb_v1_Server_init_default {false, {0, {0}}, false, 0, false, "", false, 0} -#define grpc_lb_v1_Duration_init_zero {false, 0, false, 0} -#define grpc_lb_v1_Timestamp_init_zero {false, 0, false, 0} #define grpc_lb_v1_LoadBalanceRequest_init_zero {false, grpc_lb_v1_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v1_ClientStats_init_zero} #define grpc_lb_v1_InitialLoadBalanceRequest_init_zero {false, ""} #define grpc_lb_v1_ClientStatsPerToken_init_zero {{{NULL}, NULL}, false, 0} -#define grpc_lb_v1_ClientStats_init_zero {false, grpc_lb_v1_Timestamp_init_zero, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}} +#define grpc_lb_v1_ClientStats_init_zero {false, google_protobuf_Timestamp_init_zero, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}} #define grpc_lb_v1_LoadBalanceResponse_init_zero {false, grpc_lb_v1_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v1_ServerList_init_zero} -#define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, grpc_lb_v1_Duration_init_zero} +#define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, google_protobuf_Duration_init_zero} #define grpc_lb_v1_ServerList_init_zero {{{NULL}, NULL}} #define grpc_lb_v1_Server_init_zero {false, {0, {0}}, false, 0, false, "", false, 0} /* Field tags (for use in manual encoding/decoding) */ #define grpc_lb_v1_ServerList_servers_tag 1 -#define grpc_lb_v1_ClientStatsPerToken_load_balance_token_tag 1 -#define grpc_lb_v1_ClientStatsPerToken_num_calls_tag 2 -#define grpc_lb_v1_Duration_seconds_tag 1 -#define grpc_lb_v1_Duration_nanos_tag 2 -#define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1 -#define grpc_lb_v1_Server_ip_address_tag 1 -#define grpc_lb_v1_Server_port_tag 2 -#define grpc_lb_v1_Server_load_balance_token_tag 3 -#define grpc_lb_v1_Server_drop_tag 4 -#define grpc_lb_v1_Timestamp_seconds_tag 1 -#define grpc_lb_v1_Timestamp_nanos_tag 2 #define grpc_lb_v1_ClientStats_timestamp_tag 1 #define grpc_lb_v1_ClientStats_num_calls_started_tag 2 #define grpc_lb_v1_ClientStats_num_calls_finished_tag 3 #define grpc_lb_v1_ClientStats_num_calls_finished_with_client_failed_to_send_tag 6 #define grpc_lb_v1_ClientStats_num_calls_finished_known_received_tag 7 #define grpc_lb_v1_ClientStats_calls_finished_with_drop_tag 8 +#define grpc_lb_v1_ClientStatsPerToken_load_balance_token_tag 1 +#define grpc_lb_v1_ClientStatsPerToken_num_calls_tag 2 +#define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1 #define grpc_lb_v1_InitialLoadBalanceResponse_load_balancer_delegate_tag 1 #define grpc_lb_v1_InitialLoadBalanceResponse_client_stats_report_interval_tag 2 +#define grpc_lb_v1_Server_ip_address_tag 1 +#define grpc_lb_v1_Server_port_tag 2 +#define grpc_lb_v1_Server_load_balance_token_tag 3 +#define grpc_lb_v1_Server_drop_tag 4 #define grpc_lb_v1_LoadBalanceRequest_initial_request_tag 1 #define grpc_lb_v1_LoadBalanceRequest_client_stats_tag 2 #define grpc_lb_v1_LoadBalanceResponse_initial_response_tag 1 #define grpc_lb_v1_LoadBalanceResponse_server_list_tag 2 /* Struct field encoding specification for nanopb */ -extern const pb_field_t grpc_lb_v1_Duration_fields[3]; -extern const pb_field_t grpc_lb_v1_Timestamp_fields[3]; extern const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3]; extern const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2]; extern const pb_field_t grpc_lb_v1_ClientStatsPerToken_fields[3]; @@ -163,8 +139,6 @@ extern const pb_field_t grpc_lb_v1_ServerList_fields[2]; extern const pb_field_t grpc_lb_v1_Server_fields[5]; /* Maximum encoded size of messages (where known) */ -#define grpc_lb_v1_Duration_size 22 -#define grpc_lb_v1_Timestamp_size 22 #define grpc_lb_v1_LoadBalanceRequest_size (140 + grpc_lb_v1_ClientStats_size) #define grpc_lb_v1_InitialLoadBalanceRequest_size 131 /* grpc_lb_v1_ClientStatsPerToken_size depends on runtime parameters */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 76df97669..dc716a6ad 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -24,9 +24,10 @@ #include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" -#include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -41,12 +42,17 @@ namespace { // pick_first LB policy // +constexpr char kPickFirst[] = "pick_first"; + class PickFirst : public LoadBalancingPolicy { public: - explicit PickFirst(const Args& args); + explicit PickFirst(Args args); + + const char* name() const override { return kPickFirst; } - void UpdateLocked(const grpc_channel_args& args) override; - bool PickLocked(PickState* pick) override; + void UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) override; + bool PickLocked(PickState* pick, grpc_error** error) override; void CancelPickLocked(PickState* pick, grpc_error* error) override; void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, @@ -56,8 +62,10 @@ class PickFirst : public LoadBalancingPolicy { grpc_connectivity_state CheckConnectivityLocked( grpc_error** connectivity_error) override; void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; - void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override; void ExitIdleLocked() override; + void ResetBackoffLocked() override; + void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* ignored) override; private: ~PickFirst(); @@ -68,16 +76,20 @@ class PickFirst : public LoadBalancingPolicy { : public SubchannelData { public: - PickFirstSubchannelData(PickFirstSubchannelList* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, - grpc_subchannel* subchannel, - grpc_combiner* combiner) - : SubchannelData(subchannel_list, user_data_vtable, address, subchannel, - combiner) {} + PickFirstSubchannelData( + SubchannelList* + subchannel_list, + const ServerAddress& address, Subchannel* subchannel, + grpc_combiner* combiner) + : SubchannelData(subchannel_list, address, subchannel, combiner) {} void ProcessConnectivityChangeLocked( grpc_connectivity_state connectivity_state, grpc_error* error) override; + + // Processes the connectivity change to READY for an unselected subchannel. + void ProcessUnselectedReadyLocked(); + + void CheckConnectivityStateAndStartWatchingLocked(); }; class PickFirstSubchannelList @@ -85,7 +97,7 @@ class PickFirst : public LoadBalancingPolicy { PickFirstSubchannelData> { public: PickFirstSubchannelList(PickFirst* policy, TraceFlag* tracer, - const grpc_lb_addresses* addresses, + const ServerAddressList& addresses, grpc_combiner* combiner, grpc_client_channel_factory* client_channel_factory, const grpc_channel_args& args) @@ -103,10 +115,22 @@ class PickFirst : public LoadBalancingPolicy { } }; + // Helper class to ensure that any function that modifies the child refs + // data structures will update the channelz snapshot data structures before + // returning. + class AutoChildRefsUpdater { + public: + explicit AutoChildRefsUpdater(PickFirst* pf) : pf_(pf) {} + ~AutoChildRefsUpdater() { pf_->UpdateChildRefsLocked(); } + + private: + PickFirst* pf_; + }; + void ShutdownLocked() override; void StartPickingLocked(); - void DestroyUnselectedSubchannelsLocked(); + void UpdateChildRefsLocked(); // All our subchannels. OrphanablePtr subchannel_list_; @@ -122,42 +146,50 @@ class PickFirst : public LoadBalancingPolicy { PickState* pending_picks_ = nullptr; // Our connectivity state tracker. grpc_connectivity_state_tracker state_tracker_; + + /// Lock and data used to capture snapshots of this channels child + /// channels and subchannels. This data is consumed by channelz. + gpr_mu child_refs_mu_; + channelz::ChildRefsList child_subchannels_; + channelz::ChildRefsList child_channels_; }; -PickFirst::PickFirst(const Args& args) : LoadBalancingPolicy(args) { +PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) { GPR_ASSERT(args.client_channel_factory != nullptr); + gpr_mu_init(&child_refs_mu_); grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "pick_first"); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p created.", this); } - UpdateLocked(*args.args); - grpc_subchannel_index_ref(); + UpdateLocked(*args.args, args.lb_config); } PickFirst::~PickFirst() { if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Destroying Pick First %p", this); } + gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); GPR_ASSERT(pending_picks_ == nullptr); grpc_connectivity_state_destroy(&state_tracker_); - grpc_subchannel_index_unref(); } void PickFirst::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) { PickState* pick; while ((pick = pending_picks_) != nullptr) { pending_picks_ = pick->next; - if (new_policy->PickLocked(pick)) { + grpc_error* error = GRPC_ERROR_NONE; + if (new_policy->PickLocked(pick, &error)) { // Synchronous return, schedule closure. - GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(pick->on_complete, error); } } } void PickFirst::ShutdownLocked() { + AutoChildRefsUpdater guard(this); grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p Shutting down", this); @@ -203,7 +235,7 @@ void PickFirst::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, pending_picks_ = nullptr; while (pick != nullptr) { PickState* next = pick->next; - if ((pick->initial_metadata_flags & initial_metadata_flags_mask) == + if ((*pick->initial_metadata_flags & initial_metadata_flags_mask) == initial_metadata_flags_eq) { GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( @@ -219,13 +251,9 @@ void PickFirst::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, void PickFirst::StartPickingLocked() { started_picking_ = true; - if (subchannel_list_ != nullptr) { - for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) { - if (subchannel_list_->subchannel(i)->subchannel() != nullptr) { - subchannel_list_->subchannel(i)->StartConnectivityWatchLocked(); - break; - } - } + if (subchannel_list_ != nullptr && subchannel_list_->num_subchannels() > 0) { + subchannel_list_->subchannel(0) + ->CheckConnectivityStateAndStartWatchingLocked(); } } @@ -235,28 +263,31 @@ void PickFirst::ExitIdleLocked() { } } -bool PickFirst::PickLocked(PickState* pick) { +void PickFirst::ResetBackoffLocked() { + subchannel_list_->ResetBackoffLocked(); + if (latest_pending_subchannel_list_ != nullptr) { + latest_pending_subchannel_list_->ResetBackoffLocked(); + } +} + +bool PickFirst::PickLocked(PickState* pick, grpc_error** error) { // If we have a selected subchannel already, return synchronously. if (selected_ != nullptr) { pick->connected_subchannel = selected_->connected_subchannel()->Ref(); return true; } // No subchannel selected yet, so handle asynchronously. - if (!started_picking_) { - StartPickingLocked(); + if (pick->on_complete == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No pick result available but synchronous result required."); + return true; } pick->next = pending_picks_; pending_picks_ = pick; - return false; -} - -void PickFirst::DestroyUnselectedSubchannelsLocked() { - for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) { - PickFirstSubchannelData* sd = subchannel_list_->subchannel(i); - if (selected_ != sd) { - sd->UnrefSubchannelLocked("selected_different_subchannel"); - } + if (!started_picking_) { + StartPickingLocked(); } + return false; } grpc_connectivity_state PickFirst::CheckConnectivityLocked(grpc_error** error) { @@ -269,20 +300,45 @@ void PickFirst::NotifyOnStateChangeLocked(grpc_connectivity_state* current, notify); } -void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) { - if (selected_ != nullptr) { - selected_->connected_subchannel()->Ping(on_initiate, on_ack); - } else { - GRPC_CLOSURE_SCHED(on_initiate, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected")); - GRPC_CLOSURE_SCHED(on_ack, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected")); +void PickFirst::FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels_to_fill, + channelz::ChildRefsList* ignored) { + MutexLock lock(&child_refs_mu_); + for (size_t i = 0; i < child_subchannels_.size(); ++i) { + // TODO(ncteisen): implement a de dup loop that is not O(n^2). Might + // have to implement lightweight set. For now, we don't care about + // performance when channelz requests are made. + bool found = false; + for (size_t j = 0; j < child_subchannels_to_fill->size(); ++j) { + if ((*child_subchannels_to_fill)[j] == child_subchannels_[i]) { + found = true; + break; + } + } + if (!found) { + child_subchannels_to_fill->push_back(child_subchannels_[i]); + } } } -void PickFirst::UpdateLocked(const grpc_channel_args& args) { - const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES); - if (arg == nullptr || arg->type != GRPC_ARG_POINTER) { +void PickFirst::UpdateChildRefsLocked() { + channelz::ChildRefsList cs; + if (subchannel_list_ != nullptr) { + subchannel_list_->PopulateChildRefsList(&cs); + } + if (latest_pending_subchannel_list_ != nullptr) { + latest_pending_subchannel_list_->PopulateChildRefsList(&cs); + } + // atomically update the data that channelz will actually be looking at. + MutexLock lock(&child_refs_mu_); + child_subchannels_ = std::move(cs); +} + +void PickFirst::UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) { + AutoChildRefsUpdater guard(this); + const ServerAddressList* addresses = FindServerAddressListChannelArg(&args); + if (addresses == nullptr) { if (subchannel_list_ == nullptr) { // If we don't have a current subchannel list, go into TRANSIENT FAILURE. grpc_connectivity_state_set( @@ -298,16 +354,19 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) { } return; } - const grpc_lb_addresses* addresses = - static_cast(arg->value.pointer.p); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p received update with %" PRIuPTR " addresses", this, - addresses->num_addresses); + addresses->size()); } + grpc_arg new_arg = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1); + grpc_channel_args* new_args = + grpc_channel_args_copy_and_add(&args, &new_arg, 1); auto subchannel_list = MakeOrphanable( - this, &grpc_lb_pick_first_trace, addresses, combiner(), - client_channel_factory(), args); + this, &grpc_lb_pick_first_trace, *addresses, combiner(), + client_channel_factory(), *new_args); + grpc_channel_args_destroy(new_args); if (subchannel_list->num_subchannels() == 0) { // Empty update or no valid subchannels. Unsubscribe from all current // subchannels and put the channel in TRANSIENT_FAILURE. @@ -319,6 +378,31 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) { selected_ = nullptr; return; } + // If one of the subchannels in the new list is already in state + // READY, then select it immediately. This can happen when the + // currently selected subchannel is also present in the update. It + // can also happen if one of the subchannels in the update is already + // in the subchannel index because it's in use by another channel. + for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) { + PickFirstSubchannelData* sd = subchannel_list->subchannel(i); + grpc_error* error = GRPC_ERROR_NONE; + grpc_connectivity_state state = sd->CheckConnectivityStateLocked(&error); + GRPC_ERROR_UNREF(error); + if (state == GRPC_CHANNEL_READY) { + subchannel_list_ = std::move(subchannel_list); + sd->ProcessUnselectedReadyLocked(); + sd->StartConnectivityWatchLocked(); + // If there was a previously pending update (which may or may + // not have contained the currently selected subchannel), drop + // it, so that it doesn't override what we've done here. + latest_pending_subchannel_list_.reset(); + // Make sure that subsequent calls to ExitIdleLocked() don't cause + // us to start watching a subchannel other than the one we've + // selected. + started_picking_ = true; + return; + } + } if (selected_ == nullptr) { // We don't yet have a selected subchannel, so replace the current // subchannel list immediately. @@ -326,46 +410,14 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) { // If we've started picking, start trying to connect to the first // subchannel in the new list. if (started_picking_) { + // Note: No need to use CheckConnectivityStateAndStartWatchingLocked() + // here, since we've already checked the initial connectivity + // state of all subchannels above. subchannel_list_->subchannel(0)->StartConnectivityWatchLocked(); } } else { - // We do have a selected subchannel. - // Check if it's present in the new list. If so, we're done. - for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) { - PickFirstSubchannelData* sd = subchannel_list->subchannel(i); - if (sd->subchannel() == selected_->subchannel()) { - // The currently selected subchannel is in the update: we are done. - if (grpc_lb_pick_first_trace.enabled()) { - gpr_log(GPR_INFO, - "Pick First %p found already selected subchannel %p " - "at update index %" PRIuPTR " of %" PRIuPTR "; update done", - this, selected_->subchannel(), i, - subchannel_list->num_subchannels()); - } - // Make sure it's in state READY. It might not be if we grabbed - // the combiner while a connectivity state notification - // informing us otherwise is pending. - // Note that CheckConnectivityStateLocked() also takes a ref to - // the connected subchannel. - grpc_error* error = GRPC_ERROR_NONE; - if (sd->CheckConnectivityStateLocked(&error) == GRPC_CHANNEL_READY) { - selected_ = sd; - subchannel_list_ = std::move(subchannel_list); - DestroyUnselectedSubchannelsLocked(); - sd->StartConnectivityWatchLocked(); - // If there was a previously pending update (which may or may - // not have contained the currently selected subchannel), drop - // it, so that it doesn't override what we've done here. - latest_pending_subchannel_list_.reset(); - return; - } - GRPC_ERROR_UNREF(error); - } - } - // Not keeping the previous selected subchannel, so set the latest - // pending subchannel list to the new subchannel list. We will wait - // for it to report READY before swapping it into the current - // subchannel list. + // We do have a selected subchannel, so keep using it until one of + // the subchannels in the new list reports READY. if (latest_pending_subchannel_list_ != nullptr) { if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, @@ -379,6 +431,9 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) { // If we've started picking, start trying to connect to the first // subchannel in the new list. if (started_picking_) { + // Note: No need to use CheckConnectivityStateAndStartWatchingLocked() + // here, since we've already checked the initial connectivity + // state of all subchannels above. latest_pending_subchannel_list_->subchannel(0) ->StartConnectivityWatchLocked(); } @@ -388,10 +443,12 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) { void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( grpc_connectivity_state connectivity_state, grpc_error* error) { PickFirst* p = static_cast(subchannel_list()->policy()); + AutoChildRefsUpdater guard(p); // The notification must be for a subchannel in either the current or // latest pending subchannel lists. GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() || subchannel_list() == p->latest_pending_subchannel_list_.get()); + GPR_ASSERT(connectivity_state != GRPC_CHANNEL_SHUTDOWN); // Handle updates for the currently selected subchannel. if (p->selected_ == this) { if (grpc_lb_pick_first_trace.enabled()) { @@ -421,14 +478,12 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( "update"), "selected_not_ready+switch_to_update"); } else { - // TODO(juanlishen): we re-resolve when the selected subchannel goes to - // TRANSIENT_FAILURE because we used to shut down in this case before - // re-resolution is introduced. But we need to investigate whether we - // really want to take any action instead of waiting for the selected - // subchannel reconnecting. - GPR_ASSERT(connectivity_state != GRPC_CHANNEL_SHUTDOWN); if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { - // If the selected channel goes bad, request a re-resolution. + // If the selected subchannel goes bad, request a re-resolution. We also + // set the channel state to IDLE and reset started_picking_. The reason + // is that if the new state is TRANSIENT_FAILURE due to a GOAWAY + // reception we don't want to connect to the re-resolved backends until + // we leave the IDLE state. grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_IDLE, GRPC_ERROR_NONE, "selected_changed+reresolve"); @@ -436,7 +491,6 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( p->TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_NONE); // In transient failure. Rely on re-resolution to recover. p->selected_ = nullptr; - UnrefSubchannelLocked("pf_selected_shutdown"); StopConnectivityWatchLocked(); } else { grpc_connectivity_state_set(&p->state_tracker_, connectivity_state, @@ -459,41 +513,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( // select in place of the current one. switch (connectivity_state) { case GRPC_CHANNEL_READY: { - // Case 2. Promote p->latest_pending_subchannel_list_ to - // p->subchannel_list_. - if (subchannel_list() == p->latest_pending_subchannel_list_.get()) { - if (grpc_lb_pick_first_trace.enabled()) { - gpr_log(GPR_INFO, - "Pick First %p promoting pending subchannel list %p to " - "replace %p", - p, p->latest_pending_subchannel_list_.get(), - p->subchannel_list_.get()); - } - p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); - } - // Cases 1 and 2. - grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY, - GRPC_ERROR_NONE, "connecting_ready"); - p->selected_ = this; - if (grpc_lb_pick_first_trace.enabled()) { - gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, - subchannel()); - } - // Drop all other subchannels, since we are now connected. - p->DestroyUnselectedSubchannelsLocked(); - // Update any calls that were waiting for a pick. - PickState* pick; - while ((pick = p->pending_picks_)) { - p->pending_picks_ = pick->next; - pick->connected_subchannel = - p->selected_->connected_subchannel()->Ref(); - if (grpc_lb_pick_first_trace.enabled()) { - gpr_log(GPR_INFO, - "Servicing pending pick with selected subchannel %p", - p->selected_); - } - GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE); - } + ProcessUnselectedReadyLocked(); // Renew notification. RenewConnectivityWatchLocked(); break; @@ -501,19 +521,18 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( case GRPC_CHANNEL_TRANSIENT_FAILURE: { StopConnectivityWatchLocked(); PickFirstSubchannelData* sd = this; - do { - size_t next_index = - (sd->Index() + 1) % subchannel_list()->num_subchannels(); - sd = subchannel_list()->subchannel(next_index); - } while (sd->subchannel() == nullptr); + size_t next_index = + (sd->Index() + 1) % subchannel_list()->num_subchannels(); + sd = subchannel_list()->subchannel(next_index); // Case 1: Only set state to TRANSIENT_FAILURE if we've tried // all subchannels. if (sd->Index() == 0 && subchannel_list() == p->subchannel_list_.get()) { + p->TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_NONE); grpc_connectivity_state_set( &p->state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), "connecting_transient_failure"); + GRPC_ERROR_REF(error), "exhausted_subchannels"); } - sd->StartConnectivityWatchLocked(); + sd->CheckConnectivityStateAndStartWatchingLocked(); break; } case GRPC_CHANNEL_CONNECTING: @@ -534,6 +553,65 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( GRPC_ERROR_UNREF(error); } +void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() { + PickFirst* p = static_cast(subchannel_list()->policy()); + // If we get here, there are two possible cases: + // 1. We do not currently have a selected subchannel, and the update is + // for a subchannel in p->subchannel_list_ that we're trying to + // connect to. The goal here is to find a subchannel that we can + // select. + // 2. We do currently have a selected subchannel, and the update is + // for a subchannel in p->latest_pending_subchannel_list_. The + // goal here is to find a subchannel from the update that we can + // select in place of the current one. + GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() || + subchannel_list() == p->latest_pending_subchannel_list_.get()); + // Case 2. Promote p->latest_pending_subchannel_list_ to p->subchannel_list_. + if (subchannel_list() == p->latest_pending_subchannel_list_.get()) { + if (grpc_lb_pick_first_trace.enabled()) { + gpr_log(GPR_INFO, + "Pick First %p promoting pending subchannel list %p to " + "replace %p", + p, p->latest_pending_subchannel_list_.get(), + p->subchannel_list_.get()); + } + p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); + } + // Cases 1 and 2. + grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY, + GRPC_ERROR_NONE, "subchannel_ready"); + p->selected_ = this; + if (grpc_lb_pick_first_trace.enabled()) { + gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, subchannel()); + } + // Update any calls that were waiting for a pick. + PickState* pick; + while ((pick = p->pending_picks_)) { + p->pending_picks_ = pick->next; + pick->connected_subchannel = p->selected_->connected_subchannel()->Ref(); + if (grpc_lb_pick_first_trace.enabled()) { + gpr_log(GPR_INFO, "Servicing pending pick with selected subchannel %p", + p->selected_->subchannel()); + } + GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE); + } +} + +void PickFirst::PickFirstSubchannelData:: + CheckConnectivityStateAndStartWatchingLocked() { + PickFirst* p = static_cast(subchannel_list()->policy()); + grpc_error* error = GRPC_ERROR_NONE; + if (p->selected_ != this && + CheckConnectivityStateLocked(&error) == GRPC_CHANNEL_READY) { + // We must process the READY subchannel before we start watching it. + // Otherwise, we won't know it's READY because we will be waiting for its + // connectivity state to change from READY. + ProcessUnselectedReadyLocked(); + } + GRPC_ERROR_UNREF(error); + StartConnectivityWatchLocked(); +} + // // factory // @@ -541,11 +619,11 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( class PickFirstFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr CreateLoadBalancingPolicy( - const LoadBalancingPolicy::Args& args) const override { - return OrphanablePtr(New(args)); + LoadBalancingPolicy::Args args) const override { + return OrphanablePtr(New(std::move(args))); } - const char* name() const override { return "pick_first"; } + const char* name() const override { return kPickFirst; } }; } // namespace diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 79e8ad566..aab6dd682 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -33,9 +33,9 @@ #include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/subchannel.h" -#include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -52,12 +52,17 @@ namespace { // round_robin LB policy // +constexpr char kRoundRobin[] = "round_robin"; + class RoundRobin : public LoadBalancingPolicy { public: - explicit RoundRobin(const Args& args); + explicit RoundRobin(Args args); + + const char* name() const override { return kRoundRobin; } - void UpdateLocked(const grpc_channel_args& args) override; - bool PickLocked(PickState* pick) override; + void UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) override; + bool PickLocked(PickState* pick, grpc_error** error) override; void CancelPickLocked(PickState* pick, grpc_error* error) override; void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, @@ -67,8 +72,10 @@ class RoundRobin : public LoadBalancingPolicy { grpc_connectivity_state CheckConnectivityLocked( grpc_error** connectivity_error) override; void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; - void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override; void ExitIdleLocked() override; + void ResetBackoffLocked() override; + void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* ignored) override; private: ~RoundRobin(); @@ -78,36 +85,18 @@ class RoundRobin : public LoadBalancingPolicy { // Data for a particular subchannel in a subchannel list. // This subclass adds the following functionality: - // - Tracks user_data associated with each address, which will be - // returned along with picks that select the subchannel. // - Tracks the previous connectivity state of the subchannel, so that // we know how many subchannels are in each state. class RoundRobinSubchannelData : public SubchannelData { public: - RoundRobinSubchannelData(RoundRobinSubchannelList* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, - grpc_subchannel* subchannel, - grpc_combiner* combiner) - : SubchannelData(subchannel_list, user_data_vtable, address, subchannel, - combiner), - user_data_vtable_(user_data_vtable), - user_data_(user_data_vtable_ != nullptr - ? user_data_vtable_->copy(address.user_data) - : nullptr) {} - - void UnrefSubchannelLocked(const char* reason) override { - SubchannelData::UnrefSubchannelLocked(reason); - if (user_data_ != nullptr) { - GPR_ASSERT(user_data_vtable_ != nullptr); - user_data_vtable_->destroy(user_data_); - user_data_ = nullptr; - } - } - - void* user_data() const { return user_data_; } + RoundRobinSubchannelData( + SubchannelList* + subchannel_list, + const ServerAddress& address, Subchannel* subchannel, + grpc_combiner* combiner) + : SubchannelData(subchannel_list, address, subchannel, combiner) {} grpc_connectivity_state connectivity_state() const { return last_connectivity_state_; @@ -120,8 +109,6 @@ class RoundRobin : public LoadBalancingPolicy { void ProcessConnectivityChangeLocked( grpc_connectivity_state connectivity_state, grpc_error* error) override; - const grpc_lb_user_data_vtable* user_data_vtable_; - void* user_data_ = nullptr; grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_IDLE; }; @@ -132,11 +119,12 @@ class RoundRobin : public LoadBalancingPolicy { public: RoundRobinSubchannelList( RoundRobin* policy, TraceFlag* tracer, - const grpc_lb_addresses* addresses, grpc_combiner* combiner, + const ServerAddressList& addresses, grpc_combiner* combiner, grpc_client_channel_factory* client_channel_factory, const grpc_channel_args& args) : SubchannelList(policy, tracer, addresses, combiner, - client_channel_factory, args) { + client_channel_factory, args), + last_ready_index_(num_subchannels() - 1) { // Need to maintain a ref to the LB policy as long as we maintain // any references to subchannels, since the subchannels' // pollset_sets will include the LB policy's pollset_set. @@ -177,7 +165,19 @@ class RoundRobin : public LoadBalancingPolicy { size_t num_connecting_ = 0; size_t num_transient_failure_ = 0; grpc_error* last_transient_failure_error_ = GRPC_ERROR_NONE; - size_t last_ready_index_ = -1; // Index into list of last pick. + size_t last_ready_index_; // Index into list of last pick. + }; + + // Helper class to ensure that any function that modifies the child refs + // data structures will update the channelz snapshot data structures before + // returning. + class AutoChildRefsUpdater { + public: + explicit AutoChildRefsUpdater(RoundRobin* rr) : rr_(rr) {} + ~AutoChildRefsUpdater() { rr_->UpdateChildRefsLocked(); } + + private: + RoundRobin* rr_; }; void ShutdownLocked() override; @@ -185,6 +185,7 @@ class RoundRobin : public LoadBalancingPolicy { void StartPickingLocked(); bool DoPickLocked(PickState* pick); void DrainPendingPicksLocked(); + void UpdateChildRefsLocked(); /** list of subchannels */ OrphanablePtr subchannel_list_; @@ -202,43 +203,50 @@ class RoundRobin : public LoadBalancingPolicy { PickState* pending_picks_ = nullptr; /** our connectivity state tracker */ grpc_connectivity_state_tracker state_tracker_; + /// Lock and data used to capture snapshots of this channel's child + /// channels and subchannels. This data is consumed by channelz. + gpr_mu child_refs_mu_; + channelz::ChildRefsList child_subchannels_; + channelz::ChildRefsList child_channels_; }; -RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) { +RoundRobin::RoundRobin(Args args) : LoadBalancingPolicy(std::move(args)) { GPR_ASSERT(args.client_channel_factory != nullptr); + gpr_mu_init(&child_refs_mu_); grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "round_robin"); - UpdateLocked(*args.args); + UpdateLocked(*args.args, args.lb_config); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Created with %" PRIuPTR " subchannels", this, subchannel_list_->num_subchannels()); } - grpc_subchannel_index_ref(); } RoundRobin::~RoundRobin() { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this); } + gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); GPR_ASSERT(pending_picks_ == nullptr); grpc_connectivity_state_destroy(&state_tracker_); - grpc_subchannel_index_unref(); } void RoundRobin::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) { PickState* pick; while ((pick = pending_picks_) != nullptr) { pending_picks_ = pick->next; - if (new_policy->PickLocked(pick)) { + grpc_error* error = GRPC_ERROR_NONE; + if (new_policy->PickLocked(pick, &error)) { // Synchronous return, schedule closure. - GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(pick->on_complete, error); } } } void RoundRobin::ShutdownLocked() { + AutoChildRefsUpdater guard(this); grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Shutting down", this); @@ -284,7 +292,7 @@ void RoundRobin::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, pending_picks_ = nullptr; while (pick != nullptr) { PickState* next = pick->next; - if ((pick->initial_metadata_flags & initial_metadata_flags_mask) == + if ((*pick->initial_metadata_flags & initial_metadata_flags_mask) == initial_metadata_flags_eq) { pick->connected_subchannel.reset(); GRPC_CLOSURE_SCHED(pick->on_complete, @@ -310,6 +318,13 @@ void RoundRobin::ExitIdleLocked() { } } +void RoundRobin::ResetBackoffLocked() { + subchannel_list_->ResetBackoffLocked(); + if (latest_pending_subchannel_list_ != nullptr) { + latest_pending_subchannel_list_->ResetBackoffLocked(); + } +} + bool RoundRobin::DoPickLocked(PickState* pick) { const size_t next_ready_index = subchannel_list_->GetNextReadySubchannelIndexLocked(); @@ -319,9 +334,6 @@ bool RoundRobin::DoPickLocked(PickState* pick) { subchannel_list_->subchannel(next_ready_index); GPR_ASSERT(sd->connected_subchannel() != nullptr); pick->connected_subchannel = sd->connected_subchannel()->Ref(); - if (pick->user_data != nullptr) { - *pick->user_data = sd->user_data(); - } if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, " @@ -345,7 +357,7 @@ void RoundRobin::DrainPendingPicksLocked() { } } -bool RoundRobin::PickLocked(PickState* pick) { +bool RoundRobin::PickLocked(PickState* pick, grpc_error** error) { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Trying to pick (shutdown: %d)", this, shutdown_); } @@ -353,15 +365,54 @@ bool RoundRobin::PickLocked(PickState* pick) { if (subchannel_list_ != nullptr) { if (DoPickLocked(pick)) return true; } + if (pick->on_complete == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No pick result available but synchronous result required."); + return true; + } /* no pick currently available. Save for later in list of pending picks */ + pick->next = pending_picks_; + pending_picks_ = pick; if (!started_picking_) { StartPickingLocked(); } - pick->next = pending_picks_; - pending_picks_ = pick; return false; } +void RoundRobin::FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels_to_fill, + channelz::ChildRefsList* ignored) { + MutexLock lock(&child_refs_mu_); + for (size_t i = 0; i < child_subchannels_.size(); ++i) { + // TODO(ncteisen): implement a de dup loop that is not O(n^2). Might + // have to implement lightweight set. For now, we don't care about + // performance when channelz requests are made. + bool found = false; + for (size_t j = 0; j < child_subchannels_to_fill->size(); ++j) { + if ((*child_subchannels_to_fill)[j] == child_subchannels_[i]) { + found = true; + break; + } + } + if (!found) { + child_subchannels_to_fill->push_back(child_subchannels_[i]); + } + } +} + +void RoundRobin::UpdateChildRefsLocked() { + channelz::ChildRefsList cs; + if (subchannel_list_ != nullptr) { + subchannel_list_->PopulateChildRefsList(&cs); + } + if (latest_pending_subchannel_list_ != nullptr) { + latest_pending_subchannel_list_->PopulateChildRefsList(&cs); + } + // atomically update the data that channelz will actually be looking at. + MutexLock lock(&child_refs_mu_); + child_subchannels_ = std::move(cs); +} + void RoundRobin::RoundRobinSubchannelList::StartWatchingLocked() { if (num_subchannels() == 0) return; // Check current state of each subchannel synchronously, since any @@ -452,6 +503,7 @@ void RoundRobin::RoundRobinSubchannelList:: void RoundRobin::RoundRobinSubchannelList:: UpdateRoundRobinStateFromSubchannelStateCountsLocked() { RoundRobin* p = static_cast(policy()); + AutoChildRefsUpdater guard(p); if (num_ready_ > 0) { if (p->subchannel_list_.get() != this) { // Promote this list to p->subchannel_list_. @@ -590,25 +642,11 @@ void RoundRobin::NotifyOnStateChangeLocked(grpc_connectivity_state* current, notify); } -void RoundRobin::PingOneLocked(grpc_closure* on_initiate, - grpc_closure* on_ack) { - const size_t next_ready_index = - subchannel_list_->GetNextReadySubchannelIndexLocked(); - if (next_ready_index < subchannel_list_->num_subchannels()) { - RoundRobinSubchannelData* selected = - subchannel_list_->subchannel(next_ready_index); - selected->connected_subchannel()->Ping(on_initiate, on_ack); - } else { - GRPC_CLOSURE_SCHED(on_initiate, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Round Robin not connected")); - GRPC_CLOSURE_SCHED(on_ack, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Round Robin not connected")); - } -} - -void RoundRobin::UpdateLocked(const grpc_channel_args& args) { - const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES); - if (arg == nullptr || arg->type != GRPC_ARG_POINTER) { +void RoundRobin::UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) { + AutoChildRefsUpdater guard(this); + const ServerAddressList* addresses = FindServerAddressListChannelArg(&args); + if (addresses == nullptr) { gpr_log(GPR_ERROR, "[RR %p] update provided no addresses; ignoring", this); // If we don't have a current subchannel list, go into TRANSIENT_FAILURE. // Otherwise, keep using the current subchannel list (ignore this update). @@ -620,11 +658,9 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args) { } return; } - grpc_lb_addresses* addresses = - static_cast(arg->value.pointer.p); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses", - this, addresses->num_addresses); + this, addresses->size()); } // Replace latest_pending_subchannel_list_. if (latest_pending_subchannel_list_ != nullptr) { @@ -635,7 +671,7 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args) { } } latest_pending_subchannel_list_ = MakeOrphanable( - this, &grpc_lb_round_robin_trace, addresses, combiner(), + this, &grpc_lb_round_robin_trace, *addresses, combiner(), client_channel_factory(), args); // If we haven't started picking yet or the new list is empty, // immediately promote the new list to the current list. @@ -661,11 +697,11 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args) { class RoundRobinFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr CreateLoadBalancingPolicy( - const LoadBalancingPolicy::Args& args) const override { - return OrphanablePtr(New(args)); + LoadBalancingPolicy::Args args) const override { + return OrphanablePtr(New(std::move(args))); } - const char* name() const override { return "round_robin"; } + const char* name() const override { return kRoundRobin; } }; } // namespace diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 7e2046bcd..0174a98a7 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -26,6 +26,7 @@ #include #include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" @@ -65,6 +66,10 @@ class MySubchannelList namespace grpc_core { +// Forward declaration. +template +class SubchannelList; + // Stores data for a particular subchannel in a subchannel list. // Callers must create a subclass that implements the // ProcessConnectivityChangeLocked() method. @@ -72,7 +77,9 @@ template class SubchannelData { public: // Returns a pointer to the subchannel list containing this object. - SubchannelListType* subchannel_list() const { return subchannel_list_; } + SubchannelListType* subchannel_list() const { + return static_cast(subchannel_list_); + } // Returns the index into the subchannel list of this object. size_t Index() const { @@ -81,7 +88,7 @@ class SubchannelData { } // Returns a pointer to the subchannel. - grpc_subchannel* subchannel() const { return subchannel_; } + Subchannel* subchannel() const { return subchannel_; } // Returns the connected subchannel. Will be null if the subchannel // is not connected. @@ -96,16 +103,16 @@ class SubchannelData { // ProcessConnectivityChangeLocked()). grpc_connectivity_state CheckConnectivityStateLocked(grpc_error** error) { GPR_ASSERT(!connectivity_notification_pending_); - pending_connectivity_state_unsafe_ = - grpc_subchannel_check_connectivity(subchannel(), error); + pending_connectivity_state_unsafe_ = subchannel()->CheckConnectivity( + error, subchannel_list_->inhibit_health_checking()); UpdateConnectedSubchannelLocked(); return pending_connectivity_state_unsafe_; } - // Unrefs the subchannel. May be used if an individual subchannel is - // no longer needed even though the subchannel list as a whole is not - // being unreffed. - virtual void UnrefSubchannelLocked(const char* reason); + // Resets the connection backoff. + // TODO(roth): This method should go away when we move the backoff + // code out of the subchannel and into the LB policies. + void ResetBackoffLocked(); // Starts watching the connectivity state of the subchannel. // ProcessConnectivityChangeLocked() will be called when the @@ -133,10 +140,10 @@ class SubchannelData { GRPC_ABSTRACT_BASE_CLASS protected: - SubchannelData(SubchannelListType* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, grpc_subchannel* subchannel, - grpc_combiner* combiner); + SubchannelData( + SubchannelList* subchannel_list, + const ServerAddress& address, Subchannel* subchannel, + grpc_combiner* combiner); virtual ~SubchannelData(); @@ -149,6 +156,9 @@ class SubchannelData { grpc_connectivity_state connectivity_state, grpc_error* error) GRPC_ABSTRACT; + // Unrefs the subchannel. + void UnrefSubchannelLocked(const char* reason); + private: // Updates connected_subchannel_ based on pending_connectivity_state_unsafe_. // Returns true if the connectivity state should be reported. @@ -157,10 +167,10 @@ class SubchannelData { static void OnConnectivityChangedLocked(void* arg, grpc_error* error); // Backpointer to owning subchannel list. Not owned. - SubchannelListType* subchannel_list_; + SubchannelList* subchannel_list_; // The subchannel and connected subchannel. - grpc_subchannel* subchannel_; + Subchannel* subchannel_; RefCountedPtr connected_subchannel_; // Notification that connectivity has changed on subchannel. @@ -175,8 +185,7 @@ class SubchannelData { // A list of subchannels. template -class SubchannelList - : public InternallyRefCountedWithTracing { +class SubchannelList : public InternallyRefCounted { public: typedef InlinedVector SubchannelVector; @@ -189,22 +198,40 @@ class SubchannelList // Returns true if the subchannel list is shutting down. bool shutting_down() const { return shutting_down_; } + // Populates refs_list with the uuids of this SubchannelLists's subchannels. + void PopulateChildRefsList(channelz::ChildRefsList* refs_list) { + for (size_t i = 0; i < subchannels_.size(); ++i) { + if (subchannels_[i].subchannel() != nullptr) { + grpc_core::channelz::SubchannelNode* subchannel_node = + subchannels_[i].subchannel()->channelz_node(); + if (subchannel_node != nullptr) { + refs_list->push_back(subchannel_node->uuid()); + } + } + } + } + // Accessors. LoadBalancingPolicy* policy() const { return policy_; } TraceFlag* tracer() const { return tracer_; } + bool inhibit_health_checking() const { return inhibit_health_checking_; } + + // Resets connection backoff of all subchannels. + // TODO(roth): We will probably need to rethink this as part of moving + // the backoff code out of subchannels and into LB policies. + void ResetBackoffLocked(); // Note: Caller must ensure that this is invoked inside of the combiner. void Orphan() override { ShutdownLocked(); - InternallyRefCountedWithTracing::Unref(DEBUG_LOCATION, - "shutdown"); + InternallyRefCounted::Unref(DEBUG_LOCATION, "shutdown"); } GRPC_ABSTRACT_BASE_CLASS protected: SubchannelList(LoadBalancingPolicy* policy, TraceFlag* tracer, - const grpc_lb_addresses* addresses, grpc_combiner* combiner, + const ServerAddressList& addresses, grpc_combiner* combiner, grpc_client_channel_factory* client_channel_factory, const grpc_channel_args& args); @@ -225,6 +252,8 @@ class SubchannelList TraceFlag* tracer_; + bool inhibit_health_checking_; + grpc_combiner* combiner_; // The list of subchannels. @@ -246,9 +275,8 @@ class SubchannelList template SubchannelData::SubchannelData( - SubchannelListType* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, grpc_subchannel* subchannel, + SubchannelList* subchannel_list, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : subchannel_list_(subchannel_list), subchannel_(subchannel), @@ -285,6 +313,14 @@ void SubchannelData:: } } +template +void SubchannelData::ResetBackoffLocked() { + if (subchannel_ != nullptr) { + subchannel_->ResetBackoff(); + } +} + template void SubchannelData::StartConnectivityWatchLocked() { @@ -301,9 +337,10 @@ void SubchannelDataRef(DEBUG_LOCATION, "connectivity_watch").release(); - grpc_subchannel_notify_on_state_change( - subchannel_, subchannel_list_->policy()->interested_parties(), - &pending_connectivity_state_unsafe_, &connectivity_changed_closure_); + subchannel_->NotifyOnStateChange( + subchannel_list_->policy()->interested_parties(), + &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, + subchannel_list_->inhibit_health_checking()); } template @@ -320,9 +357,10 @@ void SubchannelDatapolicy()->interested_parties(), - &pending_connectivity_state_unsafe_, &connectivity_changed_closure_); + subchannel_->NotifyOnStateChange( + subchannel_list_->policy()->interested_parties(), + &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, + subchannel_list_->inhibit_health_checking()); } template @@ -353,8 +391,9 @@ void SubchannelData:: subchannel_, reason); } GPR_ASSERT(connectivity_notification_pending_); - grpc_subchannel_notify_on_state_change(subchannel_, nullptr, nullptr, - &connectivity_changed_closure_); + subchannel_->NotifyOnStateChange(nullptr, nullptr, + &connectivity_changed_closure_, + subchannel_list_->inhibit_health_checking()); } template @@ -362,8 +401,7 @@ bool SubchannelData::UpdateConnectedSubchannelLocked() { // If the subchannel is READY, take a ref to the connected subchannel. if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) { - connected_subchannel_ = - grpc_subchannel_get_connected_subchannel(subchannel_); + connected_subchannel_ = subchannel_->connected_subchannel(); // If the subchannel became disconnected between the time that READY // was reported and the time we got here (e.g., between when a // notification callback is scheduled and when it was actually run in @@ -447,43 +485,55 @@ void SubchannelData::ShutdownLocked() { template SubchannelList::SubchannelList( LoadBalancingPolicy* policy, TraceFlag* tracer, - const grpc_lb_addresses* addresses, grpc_combiner* combiner, + const ServerAddressList& addresses, grpc_combiner* combiner, grpc_client_channel_factory* client_channel_factory, const grpc_channel_args& args) - : InternallyRefCountedWithTracing(tracer), + : InternallyRefCounted(tracer), policy_(policy), tracer_(tracer), combiner_(GRPC_COMBINER_REF(combiner, "subchannel_list")) { if (tracer_->enabled()) { gpr_log(GPR_INFO, "[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels", - tracer_->name(), policy, this, addresses->num_addresses); + tracer_->name(), policy, this, addresses.size()); } - subchannels_.reserve(addresses->num_addresses); + subchannels_.reserve(addresses.size()); // We need to remove the LB addresses in order to be able to compare the // subchannel keys of subchannels from a different batch of addresses. + // We also remove the inhibit-health-checking arg, since we are + // handling that here. + inhibit_health_checking_ = grpc_channel_arg_get_bool( + grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false); static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS, - GRPC_ARG_LB_ADDRESSES}; + GRPC_ARG_SERVER_ADDRESS_LIST, + GRPC_ARG_INHIBIT_HEALTH_CHECKING}; // Create a subchannel for each address. - grpc_subchannel_args sc_args; - for (size_t i = 0; i < addresses->num_addresses; i++) { - // If there were any balancer, we would have chosen grpclb policy instead. - GPR_ASSERT(!addresses->addresses[i].is_balancer); - memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - grpc_arg addr_arg = - grpc_create_subchannel_address_arg(&addresses->addresses[i].address); + for (size_t i = 0; i < addresses.size(); i++) { + // If there were any balancer addresses, we would have chosen grpclb + // policy, which does not use a SubchannelList. + GPR_ASSERT(!addresses[i].IsBalancer()); + InlinedVector args_to_add; + args_to_add.emplace_back( + SubchannelPoolInterface::CreateChannelArg(policy_->subchannel_pool())); + const size_t subchannel_address_arg_index = args_to_add.size(); + args_to_add.emplace_back( + Subchannel::CreateSubchannelAddressArg(&addresses[i].address())); + if (addresses[i].args() != nullptr) { + for (size_t j = 0; j < addresses[i].args()->num_args; ++j) { + args_to_add.emplace_back(addresses[i].args()->args[j]); + } + } grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove( - &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1); - gpr_free(addr_arg.value.string); - sc_args.args = new_args; - grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel( - client_channel_factory, &sc_args); + &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), + args_to_add.data(), args_to_add.size()); + gpr_free(args_to_add[subchannel_address_arg_index].value.string); + Subchannel* subchannel = grpc_client_channel_factory_create_subchannel( + client_channel_factory, new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) { // Subchannel could not be created. if (tracer_->enabled()) { - char* address_uri = - grpc_sockaddr_to_uri(&addresses->addresses[i].address); + char* address_uri = grpc_sockaddr_to_uri(&addresses[i].address()); gpr_log(GPR_INFO, "[%s %p] could not create subchannel for address uri %s, " "ignoring", @@ -493,8 +543,7 @@ SubchannelList::SubchannelList( continue; } if (tracer_->enabled()) { - char* address_uri = - grpc_sockaddr_to_uri(&addresses->addresses[i].address); + char* address_uri = grpc_sockaddr_to_uri(&addresses[i].address()); gpr_log(GPR_INFO, "[%s %p] subchannel list %p index %" PRIuPTR ": Created subchannel %p for address uri %s", @@ -502,9 +551,7 @@ SubchannelList::SubchannelList( address_uri); gpr_free(address_uri); } - subchannels_.emplace_back(static_cast(this), - addresses->user_data_vtable, - addresses->addresses[i], subchannel, combiner); + subchannels_.emplace_back(this, addresses[i], subchannel, combiner); } } @@ -531,6 +578,15 @@ void SubchannelList::ShutdownLocked() { } } +template +void SubchannelList::ResetBackoffLocked() { + for (size_t i = 0; i < subchannels_.size(); i++) { + SubchannelDataType* sd = &subchannels_[i]; + sd->ResetBackoffLocked(); + } +} + } // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc new file mode 100644 index 000000000..678b4d75e --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -0,0 +1,1741 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/// Implementation of the gRPC LB policy. +/// +/// This policy takes as input a list of resolved addresses, which must +/// include at least one balancer address. +/// +/// An internal channel (\a lb_channel_) is created for the addresses +/// from that are balancers. This channel behaves just like a regular +/// channel that uses pick_first to select from the list of balancer +/// addresses. +/// +/// The first time the xDS policy gets a request for a pick or to exit the idle +/// state, \a StartPickingLocked() is called. This method is responsible for +/// instantiating the internal *streaming* call to the LB server (whichever +/// address pick_first chose). The call will be complete when either the +/// balancer sends status or when we cancel the call (e.g., because we are +/// shutting down). In needed, we retry the call. If we received at least one +/// valid message from the server, a new call attempt will be made immediately; +/// otherwise, we apply back-off delays between attempts. +/// +/// We maintain an internal child policy (round_robin) instance for distributing +/// requests across backends. Whenever we receive a new serverlist from +/// the balancer, we update the child policy with the new list of +/// addresses. +/// +/// Once a child policy instance is in place (and getting updated as +/// described), calls for a pick, or a cancellation will be serviced right away +/// by forwarding them to the child policy instance. Any time there's no child +/// policy available (i.e., right after the creation of the xDS policy), pick +/// requests are added to a list of pending picks to be flushed and serviced +/// when the child policy instance becomes available. +/// +/// \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the +/// high level design and details. + +// With the addition of a libuv endpoint, sockaddr.h now includes uv.h when +// using that endpoint. Because of various transitive includes in uv.h, +// including windows.h on Windows, uv.h must be included before other system +// headers. Therefore, sockaddr.h must always be included first. +#include + +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/socket_utils.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel_factory.h" +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds.h" +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h" +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h" +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/backoff/backoff.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/orphanable.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/slice/slice_hash_table.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/channel_init.h" +#include "src/core/lib/transport/service_config.h" +#include "src/core/lib/transport/static_metadata.h" + +#define GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS 1 +#define GRPC_XDS_RECONNECT_BACKOFF_MULTIPLIER 1.6 +#define GRPC_XDS_RECONNECT_MAX_BACKOFF_SECONDS 120 +#define GRPC_XDS_RECONNECT_JITTER 0.2 +#define GRPC_XDS_DEFAULT_FALLBACK_TIMEOUT_MS 10000 + +namespace grpc_core { + +TraceFlag grpc_lb_xds_trace(false, "xds"); + +namespace { + +constexpr char kXds[] = "xds_experimental"; + +class XdsLb : public LoadBalancingPolicy { + public: + explicit XdsLb(Args args); + + const char* name() const override { return kXds; } + + void UpdateLocked(const grpc_channel_args& args, + grpc_json* lb_config) override; + bool PickLocked(PickState* pick, grpc_error** error) override; + void CancelPickLocked(PickState* pick, grpc_error* error) override; + void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq, + grpc_error* error) override; + void NotifyOnStateChangeLocked(grpc_connectivity_state* state, + grpc_closure* closure) override; + grpc_connectivity_state CheckConnectivityLocked( + grpc_error** connectivity_error) override; + void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; + void ExitIdleLocked() override; + void ResetBackoffLocked() override; + void FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) override; + + private: + /// Linked list of pending pick requests. It stores all information needed to + /// eventually call pick() on them. They mainly stay pending waiting for the + /// child policy to be created. + /// + /// Note that when a pick is sent to the child policy, we inject our own + /// on_complete callback, so that we can intercept the result before + /// invoking the original on_complete callback. This allows us to set the + /// LB token metadata and add client_stats to the call context. + /// See \a pending_pick_complete() for details. + struct PendingPick { + // The xds lb instance that created the wrapping. This instance is not + // owned; reference counts are untouched. It's used only for logging + // purposes. + XdsLb* xdslb_policy; + // The original pick. + PickState* pick; + // Our on_complete closure and the original one. + grpc_closure on_complete; + grpc_closure* original_on_complete; + // Stats for client-side load reporting. + RefCountedPtr client_stats; + // Next pending pick. + PendingPick* next = nullptr; + }; + + /// Contains a call to the LB server and all the data related to the call. + class BalancerCallState : public InternallyRefCounted { + public: + explicit BalancerCallState( + RefCountedPtr parent_xdslb_policy); + + // It's the caller's responsibility to ensure that Orphan() is called from + // inside the combiner. + void Orphan() override; + + void StartQuery(); + + XdsLbClientStats* client_stats() const { return client_stats_.get(); } + + bool seen_initial_response() const { return seen_initial_response_; } + + private: + // So Delete() can access our private dtor. + template + friend void grpc_core::Delete(T*); + + ~BalancerCallState(); + + XdsLb* xdslb_policy() const { + return static_cast(xdslb_policy_.get()); + } + + void ScheduleNextClientLoadReportLocked(); + void SendClientLoadReportLocked(); + + static bool LoadReportCountersAreZero(xds_grpclb_request* request); + + static void MaybeSendClientLoadReportLocked(void* arg, grpc_error* error); + static void OnInitialRequestSentLocked(void* arg, grpc_error* error); + static void OnBalancerMessageReceivedLocked(void* arg, grpc_error* error); + static void OnBalancerStatusReceivedLocked(void* arg, grpc_error* error); + + // The owning LB policy. + RefCountedPtr xdslb_policy_; + + // The streaming call to the LB server. Always non-NULL. + grpc_call* lb_call_ = nullptr; + + // recv_initial_metadata + grpc_metadata_array lb_initial_metadata_recv_; + + // send_message + grpc_byte_buffer* send_message_payload_ = nullptr; + grpc_closure lb_on_initial_request_sent_; + + // recv_message + grpc_byte_buffer* recv_message_payload_ = nullptr; + grpc_closure lb_on_balancer_message_received_; + bool seen_initial_response_ = false; + + // recv_trailing_metadata + grpc_closure lb_on_balancer_status_received_; + grpc_metadata_array lb_trailing_metadata_recv_; + grpc_status_code lb_call_status_; + grpc_slice lb_call_status_details_; + + // The stats for client-side load reporting associated with this LB call. + // Created after the first serverlist is received. + RefCountedPtr client_stats_; + grpc_millis client_stats_report_interval_ = 0; + grpc_timer client_load_report_timer_; + bool client_load_report_timer_callback_pending_ = false; + bool last_client_load_report_counters_were_zero_ = false; + bool client_load_report_is_due_ = false; + // The closure used for either the load report timer or the callback for + // completion of sending the load report. + grpc_closure client_load_report_closure_; + }; + + ~XdsLb(); + + void ShutdownLocked() override; + + // Helper function used in ctor and UpdateLocked(). + void ProcessChannelArgsLocked(const grpc_channel_args& args); + + // Parses the xds config given the JSON node of the first child of XdsConfig. + // If parsing succeeds, updates \a balancer_name, and updates \a + // child_policy_json_dump_ and \a fallback_policy_json_dump_ if they are also + // found. Does nothing upon failure. + void ParseLbConfig(grpc_json* xds_config_json); + + // Methods for dealing with the balancer channel and call. + void StartPickingLocked(); + void StartBalancerCallLocked(); + static void OnFallbackTimerLocked(void* arg, grpc_error* error); + void StartBalancerCallRetryTimerLocked(); + static void OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error); + static void OnBalancerChannelConnectivityChangedLocked(void* arg, + grpc_error* error); + + // Pending pick methods. + static void PendingPickCleanup(PendingPick* pp); + PendingPick* PendingPickCreate(PickState* pick); + void AddPendingPick(PendingPick* pp); + static void OnPendingPickComplete(void* arg, grpc_error* error); + + // Methods for dealing with the child policy. + void CreateOrUpdateChildPolicyLocked(); + grpc_channel_args* CreateChildPolicyArgsLocked(); + void CreateChildPolicyLocked(const char* name, Args args); + bool PickFromChildPolicyLocked(bool force_async, PendingPick* pp, + grpc_error** error); + void UpdateConnectivityStateFromChildPolicyLocked( + grpc_error* child_state_error); + static void OnChildPolicyConnectivityChangedLocked(void* arg, + grpc_error* error); + static void OnChildPolicyRequestReresolutionLocked(void* arg, + grpc_error* error); + + // Who the client is trying to communicate with. + const char* server_name_ = nullptr; + + // Name of the balancer to connect to. + UniquePtr balancer_name_; + + // Current channel args from the resolver. + grpc_channel_args* args_ = nullptr; + + // Internal state. + bool started_picking_ = false; + bool shutting_down_ = false; + grpc_connectivity_state_tracker state_tracker_; + + // The channel for communicating with the LB server. + grpc_channel* lb_channel_ = nullptr; + // Mutex to protect the channel to the LB server. This is used when + // processing a channelz request. + gpr_mu lb_channel_mu_; + grpc_connectivity_state lb_channel_connectivity_; + grpc_closure lb_channel_on_connectivity_changed_; + // Are we already watching the LB channel's connectivity? + bool watching_lb_channel_ = false; + // Response generator to inject address updates into lb_channel_. + RefCountedPtr response_generator_; + + // The data associated with the current LB call. It holds a ref to this LB + // policy. It's initialized every time we query for backends. It's reset to + // NULL whenever the current LB call is no longer needed (e.g., the LB policy + // is shutting down, or the LB call has ended). A non-NULL lb_calld_ always + // contains a non-NULL lb_call_. + OrphanablePtr lb_calld_; + // Timeout in milliseconds for the LB call. 0 means no deadline. + int lb_call_timeout_ms_ = 0; + // Balancer call retry state. + BackOff lb_call_backoff_; + bool retry_timer_callback_pending_ = false; + grpc_timer lb_call_retry_timer_; + grpc_closure lb_on_call_retry_; + + // The deserialized response from the balancer. May be nullptr until one + // such response has arrived. + xds_grpclb_serverlist* serverlist_ = nullptr; + + // Timeout in milliseconds for before using fallback backend addresses. + // 0 means not using fallback. + UniquePtr fallback_policy_json_string_; + int lb_fallback_timeout_ms_ = 0; + // The backend addresses from the resolver. + UniquePtr fallback_backend_addresses_; + // Fallback timer. + bool fallback_timer_callback_pending_ = false; + grpc_timer lb_fallback_timer_; + grpc_closure lb_on_fallback_; + + // Pending picks that are waiting on the xDS policy's connectivity. + PendingPick* pending_picks_ = nullptr; + + // The policy to use for the backends. + OrphanablePtr child_policy_; + UniquePtr child_policy_json_string_; + grpc_connectivity_state child_connectivity_state_; + grpc_closure on_child_connectivity_changed_; + grpc_closure on_child_request_reresolution_; +}; + +// +// serverlist parsing code +// + +// Returns the backend addresses extracted from the given addresses. +UniquePtr ExtractBackendAddresses( + const ServerAddressList& addresses) { + auto backend_addresses = MakeUnique(); + for (size_t i = 0; i < addresses.size(); ++i) { + if (!addresses[i].IsBalancer()) { + backend_addresses->emplace_back(addresses[i]); + } + } + return backend_addresses; +} + +bool IsServerValid(const xds_grpclb_server* server, size_t idx, bool log) { + if (server->drop) return false; + const xds_grpclb_ip_address* ip = &server->ip_address; + if (GPR_UNLIKELY(server->port >> 16 != 0)) { + if (log) { + gpr_log(GPR_ERROR, + "Invalid port '%d' at index %lu of serverlist. Ignoring.", + server->port, (unsigned long)idx); + } + return false; + } + if (GPR_UNLIKELY(ip->size != 4 && ip->size != 16)) { + if (log) { + gpr_log(GPR_ERROR, + "Expected IP to be 4 or 16 bytes, got %d at index %lu of " + "serverlist. Ignoring", + ip->size, (unsigned long)idx); + } + return false; + } + return true; +} + +void ParseServer(const xds_grpclb_server* server, grpc_resolved_address* addr) { + memset(addr, 0, sizeof(*addr)); + if (server->drop) return; + const uint16_t netorder_port = grpc_htons((uint16_t)server->port); + /* the addresses are given in binary format (a in(6)_addr struct) in + * server->ip_address.bytes. */ + const xds_grpclb_ip_address* ip = &server->ip_address; + if (ip->size == 4) { + addr->len = static_cast(sizeof(grpc_sockaddr_in)); + grpc_sockaddr_in* addr4 = reinterpret_cast(&addr->addr); + addr4->sin_family = GRPC_AF_INET; + memcpy(&addr4->sin_addr, ip->bytes, ip->size); + addr4->sin_port = netorder_port; + } else if (ip->size == 16) { + addr->len = static_cast(sizeof(grpc_sockaddr_in6)); + grpc_sockaddr_in6* addr6 = (grpc_sockaddr_in6*)&addr->addr; + addr6->sin6_family = GRPC_AF_INET6; + memcpy(&addr6->sin6_addr, ip->bytes, ip->size); + addr6->sin6_port = netorder_port; + } +} + +// Returns addresses extracted from \a serverlist. +UniquePtr ProcessServerlist( + const xds_grpclb_serverlist* serverlist) { + auto addresses = MakeUnique(); + for (size_t i = 0; i < serverlist->num_servers; ++i) { + const xds_grpclb_server* server = serverlist->servers[i]; + if (!IsServerValid(serverlist->servers[i], i, false)) continue; + grpc_resolved_address addr; + ParseServer(server, &addr); + addresses->emplace_back(addr, nullptr); + } + return addresses; +} + +// +// XdsLb::BalancerCallState +// + +XdsLb::BalancerCallState::BalancerCallState( + RefCountedPtr parent_xdslb_policy) + : InternallyRefCounted(&grpc_lb_xds_trace), + xdslb_policy_(std::move(parent_xdslb_policy)) { + GPR_ASSERT(xdslb_policy_ != nullptr); + GPR_ASSERT(!xdslb_policy()->shutting_down_); + // Init the LB call. Note that the LB call will progress every time there's + // activity in xdslb_policy_->interested_parties(), which is comprised of + // the polling entities from client_channel. + GPR_ASSERT(xdslb_policy()->server_name_ != nullptr); + GPR_ASSERT(xdslb_policy()->server_name_[0] != '\0'); + const grpc_millis deadline = + xdslb_policy()->lb_call_timeout_ms_ == 0 + ? GRPC_MILLIS_INF_FUTURE + : ExecCtx::Get()->Now() + xdslb_policy()->lb_call_timeout_ms_; + lb_call_ = grpc_channel_create_pollset_set_call( + xdslb_policy()->lb_channel_, nullptr, GRPC_PROPAGATE_DEFAULTS, + xdslb_policy_->interested_parties(), + GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD, + nullptr, deadline, nullptr); + // Init the LB call request payload. + xds_grpclb_request* request = + xds_grpclb_request_create(xdslb_policy()->server_name_); + grpc_slice request_payload_slice = xds_grpclb_request_encode(request); + send_message_payload_ = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_slice_unref_internal(request_payload_slice); + xds_grpclb_request_destroy(request); + // Init other data associated with the LB call. + grpc_metadata_array_init(&lb_initial_metadata_recv_); + grpc_metadata_array_init(&lb_trailing_metadata_recv_); + GRPC_CLOSURE_INIT(&lb_on_initial_request_sent_, OnInitialRequestSentLocked, + this, grpc_combiner_scheduler(xdslb_policy()->combiner())); + GRPC_CLOSURE_INIT(&lb_on_balancer_message_received_, + OnBalancerMessageReceivedLocked, this, + grpc_combiner_scheduler(xdslb_policy()->combiner())); + GRPC_CLOSURE_INIT(&lb_on_balancer_status_received_, + OnBalancerStatusReceivedLocked, this, + grpc_combiner_scheduler(xdslb_policy()->combiner())); +} + +XdsLb::BalancerCallState::~BalancerCallState() { + GPR_ASSERT(lb_call_ != nullptr); + grpc_call_unref(lb_call_); + grpc_metadata_array_destroy(&lb_initial_metadata_recv_); + grpc_metadata_array_destroy(&lb_trailing_metadata_recv_); + grpc_byte_buffer_destroy(send_message_payload_); + grpc_byte_buffer_destroy(recv_message_payload_); + grpc_slice_unref_internal(lb_call_status_details_); +} + +void XdsLb::BalancerCallState::Orphan() { + GPR_ASSERT(lb_call_ != nullptr); + // If we are here because xdslb_policy wants to cancel the call, + // lb_on_balancer_status_received_ will complete the cancellation and clean + // up. Otherwise, we are here because xdslb_policy has to orphan a failed + // call, then the following cancellation will be a no-op. + grpc_call_cancel(lb_call_, nullptr); + if (client_load_report_timer_callback_pending_) { + grpc_timer_cancel(&client_load_report_timer_); + } + // Note that the initial ref is hold by lb_on_balancer_status_received_ + // instead of the caller of this function. So the corresponding unref happens + // in lb_on_balancer_status_received_ instead of here. +} + +void XdsLb::BalancerCallState::StartQuery() { + GPR_ASSERT(lb_call_ != nullptr); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] Starting LB call (lb_calld: %p, lb_call: %p)", + xdslb_policy_.get(), this, lb_call_); + } + // Create the ops. + grpc_call_error call_error; + grpc_op ops[3]; + memset(ops, 0, sizeof(ops)); + // Op: send initial metadata. + grpc_op* op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + // Op: send request message. + GPR_ASSERT(send_message_payload_ != nullptr); + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = send_message_payload_; + op->flags = 0; + op->reserved = nullptr; + op++; + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = Ref(DEBUG_LOCATION, "on_initial_request_sent"); + self.release(); + call_error = grpc_call_start_batch_and_execute( + lb_call_, ops, (size_t)(op - ops), &lb_on_initial_request_sent_); + GPR_ASSERT(GRPC_CALL_OK == call_error); + // Op: recv initial metadata. + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &lb_initial_metadata_recv_; + op->flags = 0; + op->reserved = nullptr; + op++; + // Op: recv response. + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &recv_message_payload_; + op->flags = 0; + op->reserved = nullptr; + op++; + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + self = Ref(DEBUG_LOCATION, "on_message_received"); + self.release(); + call_error = grpc_call_start_batch_and_execute( + lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_message_received_); + GPR_ASSERT(GRPC_CALL_OK == call_error); + // Op: recv server status. + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &lb_trailing_metadata_recv_; + op->data.recv_status_on_client.status = &lb_call_status_; + op->data.recv_status_on_client.status_details = &lb_call_status_details_; + op->flags = 0; + op->reserved = nullptr; + op++; + // This callback signals the end of the LB call, so it relies on the initial + // ref instead of a new ref. When it's invoked, it's the initial ref that is + // unreffed. + call_error = grpc_call_start_batch_and_execute( + lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_status_received_); + GPR_ASSERT(GRPC_CALL_OK == call_error); +} + +void XdsLb::BalancerCallState::ScheduleNextClientLoadReportLocked() { + const grpc_millis next_client_load_report_time = + ExecCtx::Get()->Now() + client_stats_report_interval_; + GRPC_CLOSURE_INIT(&client_load_report_closure_, + MaybeSendClientLoadReportLocked, this, + grpc_combiner_scheduler(xdslb_policy()->combiner())); + grpc_timer_init(&client_load_report_timer_, next_client_load_report_time, + &client_load_report_closure_); + client_load_report_timer_callback_pending_ = true; +} + +void XdsLb::BalancerCallState::MaybeSendClientLoadReportLocked( + void* arg, grpc_error* error) { + BalancerCallState* lb_calld = static_cast(arg); + XdsLb* xdslb_policy = lb_calld->xdslb_policy(); + lb_calld->client_load_report_timer_callback_pending_ = false; + if (error != GRPC_ERROR_NONE || lb_calld != xdslb_policy->lb_calld_.get()) { + lb_calld->Unref(DEBUG_LOCATION, "client_load_report"); + return; + } + // If we've already sent the initial request, then we can go ahead and send + // the load report. Otherwise, we need to wait until the initial request has + // been sent to send this (see OnInitialRequestSentLocked()). + if (lb_calld->send_message_payload_ == nullptr) { + lb_calld->SendClientLoadReportLocked(); + } else { + lb_calld->client_load_report_is_due_ = true; + } +} + +bool XdsLb::BalancerCallState::LoadReportCountersAreZero( + xds_grpclb_request* request) { + XdsLbClientStats::DroppedCallCounts* drop_entries = + static_cast( + request->client_stats.calls_finished_with_drop.arg); + return request->client_stats.num_calls_started == 0 && + request->client_stats.num_calls_finished == 0 && + request->client_stats.num_calls_finished_with_client_failed_to_send == + 0 && + request->client_stats.num_calls_finished_known_received == 0 && + (drop_entries == nullptr || drop_entries->empty()); +} + +// TODO(vpowar): Use LRS to send the client Load Report. +void XdsLb::BalancerCallState::SendClientLoadReportLocked() { + // Construct message payload. + GPR_ASSERT(send_message_payload_ == nullptr); + xds_grpclb_request* request = + xds_grpclb_load_report_request_create_locked(client_stats_.get()); + // Skip client load report if the counters were all zero in the last + // report and they are still zero in this one. + if (LoadReportCountersAreZero(request)) { + if (last_client_load_report_counters_were_zero_) { + xds_grpclb_request_destroy(request); + ScheduleNextClientLoadReportLocked(); + return; + } + last_client_load_report_counters_were_zero_ = true; + } else { + last_client_load_report_counters_were_zero_ = false; + } + // TODO(vpowar): Send the report on LRS stream. + xds_grpclb_request_destroy(request); +} + +void XdsLb::BalancerCallState::OnInitialRequestSentLocked(void* arg, + grpc_error* error) { + BalancerCallState* lb_calld = static_cast(arg); + grpc_byte_buffer_destroy(lb_calld->send_message_payload_); + lb_calld->send_message_payload_ = nullptr; + // If we attempted to send a client load report before the initial request was + // sent (and this lb_calld is still in use), send the load report now. + if (lb_calld->client_load_report_is_due_ && + lb_calld == lb_calld->xdslb_policy()->lb_calld_.get()) { + lb_calld->SendClientLoadReportLocked(); + lb_calld->client_load_report_is_due_ = false; + } + lb_calld->Unref(DEBUG_LOCATION, "on_initial_request_sent"); +} + +void XdsLb::BalancerCallState::OnBalancerMessageReceivedLocked( + void* arg, grpc_error* error) { + BalancerCallState* lb_calld = static_cast(arg); + XdsLb* xdslb_policy = lb_calld->xdslb_policy(); + // Empty payload means the LB call was cancelled. + if (lb_calld != xdslb_policy->lb_calld_.get() || + lb_calld->recv_message_payload_ == nullptr) { + lb_calld->Unref(DEBUG_LOCATION, "on_message_received"); + return; + } + grpc_byte_buffer_reader bbr; + grpc_byte_buffer_reader_init(&bbr, lb_calld->recv_message_payload_); + grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr); + grpc_byte_buffer_reader_destroy(&bbr); + grpc_byte_buffer_destroy(lb_calld->recv_message_payload_); + lb_calld->recv_message_payload_ = nullptr; + xds_grpclb_initial_response* initial_response; + xds_grpclb_serverlist* serverlist; + if (!lb_calld->seen_initial_response_ && + (initial_response = xds_grpclb_initial_response_parse(response_slice)) != + nullptr) { + // Have NOT seen initial response, look for initial response. + if (initial_response->has_client_stats_report_interval) { + lb_calld->client_stats_report_interval_ = GPR_MAX( + GPR_MS_PER_SEC, xds_grpclb_duration_to_millis( + &initial_response->client_stats_report_interval)); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Received initial LB response message; " + "client load reporting interval = %" PRId64 " milliseconds", + xdslb_policy, lb_calld->client_stats_report_interval_); + } + } else if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Received initial LB response message; client load " + "reporting NOT enabled", + xdslb_policy); + } + xds_grpclb_initial_response_destroy(initial_response); + lb_calld->seen_initial_response_ = true; + } else if ((serverlist = xds_grpclb_response_parse_serverlist( + response_slice)) != nullptr) { + // Have seen initial response, look for serverlist. + GPR_ASSERT(lb_calld->lb_call_ != nullptr); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Serverlist with %" PRIuPTR " servers received", + xdslb_policy, serverlist->num_servers); + for (size_t i = 0; i < serverlist->num_servers; ++i) { + grpc_resolved_address addr; + ParseServer(serverlist->servers[i], &addr); + char* ipport; + grpc_sockaddr_to_string(&ipport, &addr, false); + gpr_log(GPR_INFO, "[xdslb %p] Serverlist[%" PRIuPTR "]: %s", + xdslb_policy, i, ipport); + gpr_free(ipport); + } + } + /* update serverlist */ + if (serverlist->num_servers > 0) { + // Start sending client load report only after we start using the + // serverlist returned from the current LB call. + if (lb_calld->client_stats_report_interval_ > 0 && + lb_calld->client_stats_ == nullptr) { + lb_calld->client_stats_.reset(New()); + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = lb_calld->Ref(DEBUG_LOCATION, "client_load_report"); + self.release(); + lb_calld->ScheduleNextClientLoadReportLocked(); + } + if (xds_grpclb_serverlist_equals(xdslb_policy->serverlist_, serverlist)) { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Incoming server list identical to current, " + "ignoring.", + xdslb_policy); + } + xds_grpclb_destroy_serverlist(serverlist); + } else { /* new serverlist */ + if (xdslb_policy->serverlist_ != nullptr) { + /* dispose of the old serverlist */ + xds_grpclb_destroy_serverlist(xdslb_policy->serverlist_); + } else { + /* or dispose of the fallback */ + xdslb_policy->fallback_backend_addresses_.reset(); + if (xdslb_policy->fallback_timer_callback_pending_) { + grpc_timer_cancel(&xdslb_policy->lb_fallback_timer_); + } + } + // and update the copy in the XdsLb instance. This + // serverlist instance will be destroyed either upon the next + // update or when the XdsLb instance is destroyed. + xdslb_policy->serverlist_ = serverlist; + xdslb_policy->CreateOrUpdateChildPolicyLocked(); + } + } else { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] Received empty server list, ignoring.", + xdslb_policy); + } + xds_grpclb_destroy_serverlist(serverlist); + } + } else { + // No valid initial response or serverlist found. + char* response_slice_str = + grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX); + gpr_log(GPR_ERROR, + "[xdslb %p] Invalid LB response received: '%s'. Ignoring.", + xdslb_policy, response_slice_str); + gpr_free(response_slice_str); + } + grpc_slice_unref_internal(response_slice); + if (!xdslb_policy->shutting_down_) { + // Keep listening for serverlist updates. + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_RECV_MESSAGE; + op.data.recv_message.recv_message = &lb_calld->recv_message_payload_; + op.flags = 0; + op.reserved = nullptr; + // Reuse the "OnBalancerMessageReceivedLocked" ref taken in StartQuery(). + const grpc_call_error call_error = grpc_call_start_batch_and_execute( + lb_calld->lb_call_, &op, 1, + &lb_calld->lb_on_balancer_message_received_); + GPR_ASSERT(GRPC_CALL_OK == call_error); + } else { + lb_calld->Unref(DEBUG_LOCATION, "on_message_received+xds_shutdown"); + } +} + +void XdsLb::BalancerCallState::OnBalancerStatusReceivedLocked( + void* arg, grpc_error* error) { + BalancerCallState* lb_calld = static_cast(arg); + XdsLb* xdslb_policy = lb_calld->xdslb_policy(); + GPR_ASSERT(lb_calld->lb_call_ != nullptr); + if (grpc_lb_xds_trace.enabled()) { + char* status_details = + grpc_slice_to_c_string(lb_calld->lb_call_status_details_); + gpr_log(GPR_INFO, + "[xdslb %p] Status from LB server received. Status = %d, details " + "= '%s', (lb_calld: %p, lb_call: %p), error '%s'", + xdslb_policy, lb_calld->lb_call_status_, status_details, lb_calld, + lb_calld->lb_call_, grpc_error_string(error)); + gpr_free(status_details); + } + xdslb_policy->TryReresolutionLocked(&grpc_lb_xds_trace, GRPC_ERROR_NONE); + // If this lb_calld is still in use, this call ended because of a failure so + // we want to retry connecting. Otherwise, we have deliberately ended this + // call and no further action is required. + if (lb_calld == xdslb_policy->lb_calld_.get()) { + xdslb_policy->lb_calld_.reset(); + GPR_ASSERT(!xdslb_policy->shutting_down_); + if (lb_calld->seen_initial_response_) { + // If we lose connection to the LB server, reset the backoff and restart + // the LB call immediately. + xdslb_policy->lb_call_backoff_.Reset(); + xdslb_policy->StartBalancerCallLocked(); + } else { + // If this LB call fails establishing any connection to the LB server, + // retry later. + xdslb_policy->StartBalancerCallRetryTimerLocked(); + } + } + lb_calld->Unref(DEBUG_LOCATION, "lb_call_ended"); +} + +// +// helper code for creating balancer channel +// + +UniquePtr ExtractBalancerAddresses( + const ServerAddressList& addresses) { + auto balancer_addresses = MakeUnique(); + for (size_t i = 0; i < addresses.size(); ++i) { + if (addresses[i].IsBalancer()) { + balancer_addresses->emplace_back(addresses[i]); + } + } + return balancer_addresses; +} + +/* Returns the channel args for the LB channel, used to create a bidirectional + * stream for the reception of load balancing updates. + * + * Inputs: + * - \a addresses: corresponding to the balancers. + * - \a response_generator: in order to propagate updates from the resolver + * above the grpclb policy. + * - \a args: other args inherited from the xds policy. */ +grpc_channel_args* BuildBalancerChannelArgs( + const ServerAddressList& addresses, + FakeResolverResponseGenerator* response_generator, + const grpc_channel_args* args) { + UniquePtr balancer_addresses = + ExtractBalancerAddresses(addresses); + // Channel args to remove. + static const char* args_to_remove[] = { + // LB policy name, since we want to use the default (pick_first) in + // the LB channel. + GRPC_ARG_LB_POLICY_NAME, + // The channel arg for the server URI, since that will be different for + // the LB channel than for the parent channel. The client channel + // factory will re-add this arg with the right value. + GRPC_ARG_SERVER_URI, + // The resolved addresses, which will be generated by the name resolver + // used in the LB channel. Note that the LB channel will use the fake + // resolver, so this won't actually generate a query to DNS (or some + // other name service). However, the addresses returned by the fake + // resolver will have is_balancer=false, whereas our own addresses have + // is_balancer=true. We need the LB channel to return addresses with + // is_balancer=false so that it does not wind up recursively using the + // xds LB policy, as per the special case logic in client_channel.c. + GRPC_ARG_SERVER_ADDRESS_LIST, + // The fake resolver response generator, because we are replacing it + // with the one from the xds policy, used to propagate updates to + // the LB channel. + GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, + // The LB channel should use the authority indicated by the target + // authority table (see \a grpc_lb_policy_xds_modify_lb_channel_args), + // as opposed to the authority from the parent channel. + GRPC_ARG_DEFAULT_AUTHORITY, + // Just as for \a GRPC_ARG_DEFAULT_AUTHORITY, the LB channel should be + // treated as a stand-alone channel and not inherit this argument from the + // args of the parent channel. + GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, + }; + // Channel args to add. + const grpc_arg args_to_add[] = { + // New server address list. + // Note that we pass these in both when creating the LB channel + // and via the fake resolver. The latter is what actually gets used. + CreateServerAddressListChannelArg(balancer_addresses.get()), + // The fake resolver response generator, which we use to inject + // address updates into the LB channel. + grpc_core::FakeResolverResponseGenerator::MakeChannelArg( + response_generator), + // A channel arg indicating the target is a xds load balancer. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ADDRESS_IS_XDS_LOAD_BALANCER), 1), + // A channel arg indicating this is an internal channels, aka it is + // owned by components in Core, not by the user application. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), 1), + }; + // Construct channel args. + grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove( + args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add, + GPR_ARRAY_SIZE(args_to_add)); + // Make any necessary modifications for security. + return grpc_lb_policy_xds_modify_lb_channel_args(new_args); +} + +// +// ctor and dtor +// + +// TODO(vishalpowar): Use lb_config in args to configure LB policy. +XdsLb::XdsLb(LoadBalancingPolicy::Args args) + : LoadBalancingPolicy(std::move(args)), + response_generator_(MakeRefCounted()), + lb_call_backoff_( + BackOff::Options() + .set_initial_backoff(GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS * + 1000) + .set_multiplier(GRPC_XDS_RECONNECT_BACKOFF_MULTIPLIER) + .set_jitter(GRPC_XDS_RECONNECT_JITTER) + .set_max_backoff(GRPC_XDS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)) { + // Initialization. + gpr_mu_init(&lb_channel_mu_); + GRPC_CLOSURE_INIT(&lb_channel_on_connectivity_changed_, + &XdsLb::OnBalancerChannelConnectivityChangedLocked, this, + grpc_combiner_scheduler(args.combiner)); + GRPC_CLOSURE_INIT(&on_child_connectivity_changed_, + &XdsLb::OnChildPolicyConnectivityChangedLocked, this, + grpc_combiner_scheduler(args.combiner)); + GRPC_CLOSURE_INIT(&on_child_request_reresolution_, + &XdsLb::OnChildPolicyRequestReresolutionLocked, this, + grpc_combiner_scheduler(args.combiner)); + grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "xds"); + // Record server name. + const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI); + const char* server_uri = grpc_channel_arg_get_string(arg); + GPR_ASSERT(server_uri != nullptr); + grpc_uri* uri = grpc_uri_parse(server_uri, true); + GPR_ASSERT(uri->path[0] != '\0'); + server_name_ = gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Will use '%s' as the server name for LB request.", this, + server_name_); + } + grpc_uri_destroy(uri); + // Record LB call timeout. + arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS); + lb_call_timeout_ms_ = grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX}); + // Record fallback timeout. + arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS); + lb_fallback_timeout_ms_ = grpc_channel_arg_get_integer( + arg, {GRPC_XDS_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX}); + // Parse the LB config. + ParseLbConfig(args.lb_config); + // Process channel args. + ProcessChannelArgsLocked(*args.args); +} + +XdsLb::~XdsLb() { + GPR_ASSERT(pending_picks_ == nullptr); + gpr_mu_destroy(&lb_channel_mu_); + gpr_free((void*)server_name_); + grpc_channel_args_destroy(args_); + grpc_connectivity_state_destroy(&state_tracker_); + if (serverlist_ != nullptr) { + xds_grpclb_destroy_serverlist(serverlist_); + } +} + +void XdsLb::ShutdownLocked() { + grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"); + shutting_down_ = true; + lb_calld_.reset(); + if (retry_timer_callback_pending_) { + grpc_timer_cancel(&lb_call_retry_timer_); + } + if (fallback_timer_callback_pending_) { + grpc_timer_cancel(&lb_fallback_timer_); + } + child_policy_.reset(); + TryReresolutionLocked(&grpc_lb_xds_trace, GRPC_ERROR_CANCELLED); + // We destroy the LB channel here instead of in our destructor because + // destroying the channel triggers a last callback to + // OnBalancerChannelConnectivityChangedLocked(), and we need to be + // alive when that callback is invoked. + if (lb_channel_ != nullptr) { + gpr_mu_lock(&lb_channel_mu_); + grpc_channel_destroy(lb_channel_); + lb_channel_ = nullptr; + gpr_mu_unlock(&lb_channel_mu_); + } + grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN, + GRPC_ERROR_REF(error), "xds_shutdown"); + // Clear pending picks. + PendingPick* pp; + while ((pp = pending_picks_) != nullptr) { + pending_picks_ = pp->next; + pp->pick->connected_subchannel.reset(); + // Note: pp is deleted in this callback. + GRPC_CLOSURE_SCHED(&pp->on_complete, GRPC_ERROR_REF(error)); + } + GRPC_ERROR_UNREF(error); +} + +// +// public methods +// + +void XdsLb::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) { + PendingPick* pp; + while ((pp = pending_picks_) != nullptr) { + pending_picks_ = pp->next; + pp->pick->on_complete = pp->original_on_complete; + grpc_error* error = GRPC_ERROR_NONE; + if (new_policy->PickLocked(pp->pick, &error)) { + // Synchronous return; schedule closure. + GRPC_CLOSURE_SCHED(pp->pick->on_complete, error); + } + Delete(pp); + } +} + +// Cancel a specific pending pick. +// +// A pick progresses as follows: +// - If there's a child policy available, it'll be handed over to child policy +// (in CreateChildPolicyLocked()). From that point onwards, it'll be the +// child policy's responsibility. For cancellations, that implies the pick +// needs to be also cancelled by the child policy instance. +// - Otherwise, without a child policy instance, picks stay pending at this +// policy's level (xds), inside the pending_picks_ list. To cancel these, +// we invoke the completion closure and set the pick's connected +// subchannel to nullptr right here. +void XdsLb::CancelPickLocked(PickState* pick, grpc_error* error) { + PendingPick* pp = pending_picks_; + pending_picks_ = nullptr; + while (pp != nullptr) { + PendingPick* next = pp->next; + if (pp->pick == pick) { + pick->connected_subchannel.reset(); + // Note: pp is deleted in this callback. + GRPC_CLOSURE_SCHED(&pp->on_complete, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Pick Cancelled", &error, 1)); + } else { + pp->next = pending_picks_; + pending_picks_ = pp; + } + pp = next; + } + if (child_policy_ != nullptr) { + child_policy_->CancelPickLocked(pick, GRPC_ERROR_REF(error)); + } + GRPC_ERROR_UNREF(error); +} + +// Cancel all pending picks. +// +// A pick progresses as follows: +// - If there's a child policy available, it'll be handed over to child policy +// (in CreateChildPolicyLocked()). From that point onwards, it'll be the +// child policy's responsibility. For cancellations, that implies the pick +// needs to be also cancelled by the child policy instance. +// - Otherwise, without a child policy instance, picks stay pending at this +// policy's level (xds), inside the pending_picks_ list. To cancel these, +// we invoke the completion closure and set the pick's connected +// subchannel to nullptr right here. +void XdsLb::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq, + grpc_error* error) { + PendingPick* pp = pending_picks_; + pending_picks_ = nullptr; + while (pp != nullptr) { + PendingPick* next = pp->next; + if ((*pp->pick->initial_metadata_flags & initial_metadata_flags_mask) == + initial_metadata_flags_eq) { + // Note: pp is deleted in this callback. + GRPC_CLOSURE_SCHED(&pp->on_complete, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Pick Cancelled", &error, 1)); + } else { + pp->next = pending_picks_; + pending_picks_ = pp; + } + pp = next; + } + if (child_policy_ != nullptr) { + child_policy_->CancelMatchingPicksLocked(initial_metadata_flags_mask, + initial_metadata_flags_eq, + GRPC_ERROR_REF(error)); + } + GRPC_ERROR_UNREF(error); +} + +void XdsLb::ExitIdleLocked() { + if (!started_picking_) { + StartPickingLocked(); + } +} + +void XdsLb::ResetBackoffLocked() { + if (lb_channel_ != nullptr) { + grpc_channel_reset_connect_backoff(lb_channel_); + } + if (child_policy_ != nullptr) { + child_policy_->ResetBackoffLocked(); + } +} + +bool XdsLb::PickLocked(PickState* pick, grpc_error** error) { + PendingPick* pp = PendingPickCreate(pick); + bool pick_done = false; + if (child_policy_ != nullptr) { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] about to PICK from policy %p", this, + child_policy_.get()); + } + pick_done = PickFromChildPolicyLocked(false /* force_async */, pp, error); + } else { // child_policy_ == NULL + if (pick->on_complete == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No pick result available but synchronous result required."); + pick_done = true; + } else { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] No child policy. Adding to xds's pending picks", + this); + } + AddPendingPick(pp); + if (!started_picking_) { + StartPickingLocked(); + } + pick_done = false; + } + } + return pick_done; +} + +void XdsLb::FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) { + // delegate to the child_policy_ to fill the children subchannels. + child_policy_->FillChildRefsForChannelz(child_subchannels, child_channels); + MutexLock lock(&lb_channel_mu_); + if (lb_channel_ != nullptr) { + grpc_core::channelz::ChannelNode* channel_node = + grpc_channel_get_channelz_node(lb_channel_); + if (channel_node != nullptr) { + child_channels->push_back(channel_node->uuid()); + } + } +} + +grpc_connectivity_state XdsLb::CheckConnectivityLocked( + grpc_error** connectivity_error) { + return grpc_connectivity_state_get(&state_tracker_, connectivity_error); +} + +void XdsLb::NotifyOnStateChangeLocked(grpc_connectivity_state* current, + grpc_closure* closure) { + grpc_connectivity_state_notify_on_state_change(&state_tracker_, current, + closure); +} + +void XdsLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { + const ServerAddressList* addresses = FindServerAddressListChannelArg(&args); + if (addresses == nullptr) { + // Ignore this update. + gpr_log(GPR_ERROR, + "[xdslb %p] No valid LB addresses channel arg in update, ignoring.", + this); + return; + } + // Update fallback address list. + fallback_backend_addresses_ = ExtractBackendAddresses(*addresses); + // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args, + // since we use this to trigger the client_load_reporting filter. + static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME}; + grpc_arg new_arg = grpc_channel_arg_string_create( + (char*)GRPC_ARG_LB_POLICY_NAME, (char*)"xds"); + grpc_channel_args_destroy(args_); + args_ = grpc_channel_args_copy_and_add_and_remove( + &args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1); + // Construct args for balancer channel. + grpc_channel_args* lb_channel_args = + BuildBalancerChannelArgs(*addresses, response_generator_.get(), &args); + // Create balancer channel if needed. + if (lb_channel_ == nullptr) { + char* uri_str; + gpr_asprintf(&uri_str, "fake:///%s", server_name_); + gpr_mu_lock(&lb_channel_mu_); + lb_channel_ = grpc_client_channel_factory_create_channel( + client_channel_factory(), uri_str, + GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, lb_channel_args); + gpr_mu_unlock(&lb_channel_mu_); + GPR_ASSERT(lb_channel_ != nullptr); + gpr_free(uri_str); + } + // Propagate updates to the LB channel (pick_first) through the fake + // resolver. + response_generator_->SetResponse(lb_channel_args); + grpc_channel_args_destroy(lb_channel_args); +} + +void XdsLb::ParseLbConfig(grpc_json* xds_config_json) { + const char* balancer_name = nullptr; + grpc_json* child_policy = nullptr; + grpc_json* fallback_policy = nullptr; + for (grpc_json* field = xds_config_json; field != nullptr; + field = field->next) { + if (field->key == nullptr) return; + if (strcmp(field->key, "balancerName") == 0) { + if (balancer_name != nullptr) return; // Duplicate. + if (field->type != GRPC_JSON_STRING) return; + balancer_name = field->value; + } else if (strcmp(field->key, "childPolicy") == 0) { + if (child_policy != nullptr) return; // Duplicate. + child_policy = ParseLoadBalancingConfig(field); + } else if (strcmp(field->key, "fallbackPolicy") == 0) { + if (fallback_policy != nullptr) return; // Duplicate. + fallback_policy = ParseLoadBalancingConfig(field); + } + } + if (balancer_name == nullptr) return; // Required field. + if (child_policy != nullptr) { + child_policy_json_string_ = + UniquePtr(grpc_json_dump_to_string(child_policy, 0 /* indent */)); + } + if (fallback_policy != nullptr) { + fallback_policy_json_string_ = UniquePtr( + grpc_json_dump_to_string(fallback_policy, 0 /* indent */)); + } + balancer_name_ = UniquePtr(gpr_strdup(balancer_name)); +} + +void XdsLb::UpdateLocked(const grpc_channel_args& args, grpc_json* lb_config) { + ParseLbConfig(lb_config); + // TODO(juanlishen): Pass fallback policy config update after fallback policy + // is added. + if (balancer_name_ == nullptr) { + gpr_log(GPR_ERROR, "[xdslb %p] LB config parsing fails.", this); + } + ProcessChannelArgsLocked(args); + // Update the existing child policy. + // Note: We have disabled fallback mode in the code, so this child policy must + // have been created from a serverlist. + // TODO(vpowar): Handle the fallback_address changes when we add support for + // fallback in xDS. + if (child_policy_ != nullptr) CreateOrUpdateChildPolicyLocked(); + // Start watching the LB channel connectivity for connection, if not + // already doing so. + if (!watching_lb_channel_) { + lb_channel_connectivity_ = grpc_channel_check_connectivity_state( + lb_channel_, true /* try to connect */); + grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( + grpc_channel_get_channel_stack(lb_channel_)); + GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter); + watching_lb_channel_ = true; + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = Ref(DEBUG_LOCATION, "watch_lb_channel_connectivity"); + self.release(); + grpc_client_channel_watch_connectivity_state( + client_channel_elem, + grpc_polling_entity_create_from_pollset_set(interested_parties()), + &lb_channel_connectivity_, &lb_channel_on_connectivity_changed_, + nullptr); + } +} + +// +// code for balancer channel and call +// + +void XdsLb::StartPickingLocked() { + // Start a timer to fall back. + if (lb_fallback_timeout_ms_ > 0 && serverlist_ == nullptr && + !fallback_timer_callback_pending_) { + grpc_millis deadline = ExecCtx::Get()->Now() + lb_fallback_timeout_ms_; + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = Ref(DEBUG_LOCATION, "on_fallback_timer"); + self.release(); + GRPC_CLOSURE_INIT(&lb_on_fallback_, &XdsLb::OnFallbackTimerLocked, this, + grpc_combiner_scheduler(combiner())); + fallback_timer_callback_pending_ = true; + grpc_timer_init(&lb_fallback_timer_, deadline, &lb_on_fallback_); + } + started_picking_ = true; + StartBalancerCallLocked(); +} + +void XdsLb::StartBalancerCallLocked() { + GPR_ASSERT(lb_channel_ != nullptr); + if (shutting_down_) return; + // Init the LB call data. + GPR_ASSERT(lb_calld_ == nullptr); + lb_calld_ = MakeOrphanable(Ref()); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Query for backends (lb_channel: %p, lb_calld: %p)", + this, lb_channel_, lb_calld_.get()); + } + lb_calld_->StartQuery(); +} + +void XdsLb::OnFallbackTimerLocked(void* arg, grpc_error* error) { + XdsLb* xdslb_policy = static_cast(arg); + xdslb_policy->fallback_timer_callback_pending_ = false; + // If we receive a serverlist after the timer fires but before this callback + // actually runs, don't fall back. + if (xdslb_policy->serverlist_ == nullptr && !xdslb_policy->shutting_down_ && + error == GRPC_ERROR_NONE) { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Fallback timer fired. Not using fallback backends", + xdslb_policy); + } + } + xdslb_policy->Unref(DEBUG_LOCATION, "on_fallback_timer"); +} + +void XdsLb::StartBalancerCallRetryTimerLocked() { + grpc_millis next_try = lb_call_backoff_.NextAttemptTime(); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] Connection to LB server lost...", this); + grpc_millis timeout = next_try - ExecCtx::Get()->Now(); + if (timeout > 0) { + gpr_log(GPR_INFO, "[xdslb %p] ... retry_timer_active in %" PRId64 "ms.", + this, timeout); + } else { + gpr_log(GPR_INFO, "[xdslb %p] ... retry_timer_active immediately.", this); + } + } + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = Ref(DEBUG_LOCATION, "on_balancer_call_retry_timer"); + self.release(); + GRPC_CLOSURE_INIT(&lb_on_call_retry_, &XdsLb::OnBalancerCallRetryTimerLocked, + this, grpc_combiner_scheduler(combiner())); + retry_timer_callback_pending_ = true; + grpc_timer_init(&lb_call_retry_timer_, next_try, &lb_on_call_retry_); +} + +void XdsLb::OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error) { + XdsLb* xdslb_policy = static_cast(arg); + xdslb_policy->retry_timer_callback_pending_ = false; + if (!xdslb_policy->shutting_down_ && error == GRPC_ERROR_NONE && + xdslb_policy->lb_calld_ == nullptr) { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] Restarting call to LB server", + xdslb_policy); + } + xdslb_policy->StartBalancerCallLocked(); + } + xdslb_policy->Unref(DEBUG_LOCATION, "on_balancer_call_retry_timer"); +} + +// Invoked as part of the update process. It continues watching the LB channel +// until it shuts down or becomes READY. It's invoked even if the LB channel +// stayed READY throughout the update (for example if the update is identical). +void XdsLb::OnBalancerChannelConnectivityChangedLocked(void* arg, + grpc_error* error) { + XdsLb* xdslb_policy = static_cast(arg); + if (xdslb_policy->shutting_down_) goto done; + // Re-initialize the lb_call. This should also take care of updating the + // child policy. Note that the current child policy, if any, will + // stay in effect until an update from the new lb_call is received. + switch (xdslb_policy->lb_channel_connectivity_) { + case GRPC_CHANNEL_CONNECTING: + case GRPC_CHANNEL_TRANSIENT_FAILURE: { + // Keep watching the LB channel. + grpc_channel_element* client_channel_elem = + grpc_channel_stack_last_element( + grpc_channel_get_channel_stack(xdslb_policy->lb_channel_)); + GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter); + grpc_client_channel_watch_connectivity_state( + client_channel_elem, + grpc_polling_entity_create_from_pollset_set( + xdslb_policy->interested_parties()), + &xdslb_policy->lb_channel_connectivity_, + &xdslb_policy->lb_channel_on_connectivity_changed_, nullptr); + break; + } + // The LB channel may be IDLE because it's shut down before the update. + // Restart the LB call to kick the LB channel into gear. + case GRPC_CHANNEL_IDLE: + case GRPC_CHANNEL_READY: + xdslb_policy->lb_calld_.reset(); + if (xdslb_policy->started_picking_) { + if (xdslb_policy->retry_timer_callback_pending_) { + grpc_timer_cancel(&xdslb_policy->lb_call_retry_timer_); + } + xdslb_policy->lb_call_backoff_.Reset(); + xdslb_policy->StartBalancerCallLocked(); + } + // Fall through. + case GRPC_CHANNEL_SHUTDOWN: + done: + xdslb_policy->watching_lb_channel_ = false; + xdslb_policy->Unref(DEBUG_LOCATION, + "watch_lb_channel_connectivity_cb_shutdown"); + } +} + +// +// PendingPick +// + +// Destroy function used when embedding client stats in call context. +void DestroyClientStats(void* arg) { + static_cast(arg)->Unref(); +} + +void XdsLb::PendingPickCleanup(PendingPick* pp) { + // If connected_subchannel is nullptr, no pick has been made by the + // child policy (e.g., all addresses failed to connect). + if (pp->pick->connected_subchannel != nullptr) { + // Pass on client stats via context. Passes ownership of the reference. + if (pp->client_stats != nullptr) { + pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].value = + pp->client_stats.release(); + pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].destroy = + DestroyClientStats; + } + } else { + pp->client_stats.reset(); + } +} + +/* The \a on_complete closure passed as part of the pick requires keeping a + * reference to its associated child policy instance. We wrap this closure in + * order to unref the child policy instance upon its invocation */ +void XdsLb::OnPendingPickComplete(void* arg, grpc_error* error) { + PendingPick* pp = static_cast(arg); + PendingPickCleanup(pp); + GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_REF(error)); + Delete(pp); +} + +XdsLb::PendingPick* XdsLb::PendingPickCreate(PickState* pick) { + PendingPick* pp = New(); + pp->xdslb_policy = this; + pp->pick = pick; + GRPC_CLOSURE_INIT(&pp->on_complete, &XdsLb::OnPendingPickComplete, pp, + grpc_schedule_on_exec_ctx); + pp->original_on_complete = pick->on_complete; + pick->on_complete = &pp->on_complete; + return pp; +} + +void XdsLb::AddPendingPick(PendingPick* pp) { + pp->next = pending_picks_; + pending_picks_ = pp; +} + +// +// code for interacting with the child policy +// + +// Performs a pick over \a child_policy_. Given that a pick can return +// immediately (ignoring its completion callback), we need to perform the +// cleanups this callback would otherwise be responsible for. +// If \a force_async is true, then we will manually schedule the +// completion callback even if the pick is available immediately. +bool XdsLb::PickFromChildPolicyLocked(bool force_async, PendingPick* pp, + grpc_error** error) { + // Set client_stats. + if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) { + pp->client_stats = lb_calld_->client_stats()->Ref(); + } + // Pick via the child policy. + bool pick_done = child_policy_->PickLocked(pp->pick, error); + if (pick_done) { + PendingPickCleanup(pp); + if (force_async) { + GRPC_CLOSURE_SCHED(pp->original_on_complete, *error); + *error = GRPC_ERROR_NONE; + pick_done = false; + } + Delete(pp); + } + // else, the pending pick will be registered and taken care of by the + // pending pick list inside the child policy. Eventually, + // OnPendingPickComplete() will be called, which will (among other + // things) add the LB token to the call's initial metadata. + return pick_done; +} + +void XdsLb::CreateChildPolicyLocked(const char* name, Args args) { + GPR_ASSERT(child_policy_ == nullptr); + child_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( + name, std::move(args)); + if (GPR_UNLIKELY(child_policy_ == nullptr)) { + gpr_log(GPR_ERROR, "[xdslb %p] Failure creating a child policy", this); + return; + } + // TODO(roth): We currently track this ref manually. Once the new + // ClosureRef API is done, pass the RefCountedPtr<> along with the closure. + auto self = Ref(DEBUG_LOCATION, "on_child_reresolution_requested"); + self.release(); + child_policy_->SetReresolutionClosureLocked(&on_child_request_reresolution_); + grpc_error* child_state_error = nullptr; + child_connectivity_state_ = + child_policy_->CheckConnectivityLocked(&child_state_error); + // Connectivity state is a function of the child policy updated/created. + UpdateConnectivityStateFromChildPolicyLocked(child_state_error); + // Add the xDS's interested_parties pollset_set to that of the newly created + // child policy. This will make the child policy progress upon activity on + // xDS LB, which in turn is tied to the application's call. + grpc_pollset_set_add_pollset_set(child_policy_->interested_parties(), + interested_parties()); + // Subscribe to changes to the connectivity of the new child policy. + // TODO(roth): We currently track this ref manually. Once the new + // ClosureRef API is done, pass the RefCountedPtr<> along with the closure. + self = Ref(DEBUG_LOCATION, "on_child_connectivity_changed"); + self.release(); + child_policy_->NotifyOnStateChangeLocked(&child_connectivity_state_, + &on_child_connectivity_changed_); + child_policy_->ExitIdleLocked(); + // Send pending picks to child policy. + PendingPick* pp; + while ((pp = pending_picks_)) { + pending_picks_ = pp->next; + if (grpc_lb_xds_trace.enabled()) { + gpr_log( + GPR_INFO, + "[xdslb %p] Pending pick about to (async) PICK from child policy %p", + this, child_policy_.get()); + } + grpc_error* error = GRPC_ERROR_NONE; + PickFromChildPolicyLocked(true /* force_async */, pp, &error); + } +} + +grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() { + bool is_backend_from_grpclb_load_balancer = false; + // This should never be invoked if we do not have serverlist_, as fallback + // mode is disabled for xDS plugin. + GPR_ASSERT(serverlist_ != nullptr); + GPR_ASSERT(serverlist_->num_servers > 0); + UniquePtr addresses = ProcessServerlist(serverlist_); + GPR_ASSERT(addresses != nullptr); + is_backend_from_grpclb_load_balancer = true; + // Replace the server address list in the channel args that we pass down to + // the subchannel. + static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST}; + const grpc_arg args_to_add[] = { + CreateServerAddressListChannelArg(addresses.get()), + // A channel arg indicating if the target is a backend inferred from a + // grpclb load balancer. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ADDRESS_IS_BACKEND_FROM_XDS_LOAD_BALANCER), + is_backend_from_grpclb_load_balancer), + }; + grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove( + args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add, + GPR_ARRAY_SIZE(args_to_add)); + return args; +} + +void XdsLb::CreateOrUpdateChildPolicyLocked() { + if (shutting_down_) return; + grpc_channel_args* args = CreateChildPolicyArgsLocked(); + GPR_ASSERT(args != nullptr); + const char* child_policy_name = nullptr; + grpc_json* child_policy_config = nullptr; + grpc_json* child_policy_json = + grpc_json_parse_string(child_policy_json_string_.get()); + // TODO(juanlishen): If the child policy is not configured via service config, + // use whatever algorithm is specified by the balancer. + if (child_policy_json != nullptr) { + child_policy_name = child_policy_json->key; + child_policy_config = child_policy_json->child; + } else { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] No valid child policy LB config", this); + } + child_policy_name = "round_robin"; + } + // TODO(juanlishen): Switch policy according to child_policy_config->key. + if (child_policy_ != nullptr) { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] Updating the child policy %p", this, + child_policy_.get()); + } + child_policy_->UpdateLocked(*args, child_policy_config); + } else { + LoadBalancingPolicy::Args lb_policy_args; + lb_policy_args.combiner = combiner(); + lb_policy_args.client_channel_factory = client_channel_factory(); + lb_policy_args.subchannel_pool = subchannel_pool()->Ref(); + lb_policy_args.args = args; + lb_policy_args.lb_config = child_policy_config; + CreateChildPolicyLocked(child_policy_name, std::move(lb_policy_args)); + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] Created a new child policy %p", this, + child_policy_.get()); + } + } + grpc_channel_args_destroy(args); + grpc_json_destroy(child_policy_json); +} + +void XdsLb::OnChildPolicyRequestReresolutionLocked(void* arg, + grpc_error* error) { + XdsLb* xdslb_policy = static_cast(arg); + if (xdslb_policy->shutting_down_ || error != GRPC_ERROR_NONE) { + xdslb_policy->Unref(DEBUG_LOCATION, "on_child_reresolution_requested"); + return; + } + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Re-resolution requested from child policy " + "(%p).", + xdslb_policy, xdslb_policy->child_policy_.get()); + } + // If we are talking to a balancer, we expect to get updated addresses form + // the balancer, so we can ignore the re-resolution request from the child + // policy. + // Otherwise, handle the re-resolution request using the xds policy's + // original re-resolution closure. + if (xdslb_policy->lb_calld_ == nullptr || + !xdslb_policy->lb_calld_->seen_initial_response()) { + xdslb_policy->TryReresolutionLocked(&grpc_lb_xds_trace, GRPC_ERROR_NONE); + } + // Give back the wrapper closure to the child policy. + xdslb_policy->child_policy_->SetReresolutionClosureLocked( + &xdslb_policy->on_child_request_reresolution_); +} + +void XdsLb::UpdateConnectivityStateFromChildPolicyLocked( + grpc_error* child_state_error) { + const grpc_connectivity_state curr_glb_state = + grpc_connectivity_state_check(&state_tracker_); + /* The new connectivity status is a function of the previous one and the new + * input coming from the status of the child policy. + * + * current state (xds's) + * | + * v || I | C | R | TF | SD | <- new state (child policy's) + * ===++====+=====+=====+======+======+ + * I || I | C | R | [I] | [I] | + * ---++----+-----+-----+------+------+ + * C || I | C | R | [C] | [C] | + * ---++----+-----+-----+------+------+ + * R || I | C | R | [R] | [R] | + * ---++----+-----+-----+------+------+ + * TF || I | C | R | [TF] | [TF] | + * ---++----+-----+-----+------+------+ + * SD || NA | NA | NA | NA | NA | (*) + * ---++----+-----+-----+------+------+ + * + * A [STATE] indicates that the old child policy is kept. In those cases, + * STATE is the current state of xds, which is left untouched. + * + * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to + * the previous child policy instance. + * + * Note that the status is never updated to SHUTDOWN as a result of calling + * this function. Only glb_shutdown() has the power to set that state. + * + * (*) This function mustn't be called during shutting down. */ + GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN); + switch (child_connectivity_state_) { + case GRPC_CHANNEL_TRANSIENT_FAILURE: + case GRPC_CHANNEL_SHUTDOWN: + GPR_ASSERT(child_state_error != GRPC_ERROR_NONE); + break; + case GRPC_CHANNEL_IDLE: + case GRPC_CHANNEL_CONNECTING: + case GRPC_CHANNEL_READY: + GPR_ASSERT(child_state_error == GRPC_ERROR_NONE); + } + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Setting xds's state to %s from child policy %p state.", + this, grpc_connectivity_state_name(child_connectivity_state_), + child_policy_.get()); + } + grpc_connectivity_state_set(&state_tracker_, child_connectivity_state_, + child_state_error, + "update_lb_connectivity_status_locked"); +} + +void XdsLb::OnChildPolicyConnectivityChangedLocked(void* arg, + grpc_error* error) { + XdsLb* xdslb_policy = static_cast(arg); + if (xdslb_policy->shutting_down_) { + xdslb_policy->Unref(DEBUG_LOCATION, "on_child_connectivity_changed"); + return; + } + xdslb_policy->UpdateConnectivityStateFromChildPolicyLocked( + GRPC_ERROR_REF(error)); + // Resubscribe. Reuse the "on_child_connectivity_changed" ref. + xdslb_policy->child_policy_->NotifyOnStateChangeLocked( + &xdslb_policy->child_connectivity_state_, + &xdslb_policy->on_child_connectivity_changed_); +} + +// +// factory +// + +class XdsFactory : public LoadBalancingPolicyFactory { + public: + OrphanablePtr CreateLoadBalancingPolicy( + LoadBalancingPolicy::Args args) const override { + /* Count the number of gRPC-LB addresses. There must be at least one. */ + const ServerAddressList* addresses = + FindServerAddressListChannelArg(args.args); + if (addresses == nullptr) return nullptr; + bool found_balancer_address = false; + for (size_t i = 0; i < addresses->size(); ++i) { + if ((*addresses)[i].IsBalancer()) { + found_balancer_address = true; + break; + } + } + if (!found_balancer_address) return nullptr; + return OrphanablePtr(New(std::move(args))); + } + + const char* name() const override { return kXds; } +}; + +} // namespace + +} // namespace grpc_core + +// +// Plugin registration +// + +void grpc_lb_policy_xds_init() { + grpc_core::LoadBalancingPolicyRegistry::Builder:: + RegisterLoadBalancingPolicyFactory( + grpc_core::UniquePtr( + grpc_core::New())); +} + +void grpc_lb_policy_xds_shutdown() {} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds.h new file mode 100644 index 000000000..8b20680f2 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_H + +#include + +/** Channel arg indicating if a target corresponding to the address is grpclb + * loadbalancer. The type of this arg is an integer and the value is treated as + * a bool. */ +#define GRPC_ARG_ADDRESS_IS_XDS_LOAD_BALANCER \ + "grpc.address_is_xds_load_balancer" +/** Channel arg indicating if a target corresponding to the address is a backend + * received from a balancer. The type of this arg is an integer and the value is + * treated as a bool. */ +#define GRPC_ARG_ADDRESS_IS_BACKEND_FROM_XDS_LOAD_BALANCER \ + "grpc.address_is_backend_from_xds_load_balancer" + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_H \ + */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h new file mode 100644 index 000000000..f713b7f56 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CHANNEL_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CHANNEL_H + +#include + +#include + +/// Makes any necessary modifications to \a args for use in the xds +/// balancer channel. +/// +/// Takes ownership of \a args. +/// +/// Caller takes ownership of the returned args. +grpc_channel_args* grpc_lb_policy_xds_modify_lb_channel_args( + grpc_channel_args* args); + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CHANNEL_H \ + */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc new file mode 100644 index 000000000..55c646e6e --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc @@ -0,0 +1,104 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h" + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/target_authority_table.h" +#include "src/core/lib/slice/slice_internal.h" + +namespace grpc_core { +namespace { + +int BalancerNameCmp(const grpc_core::UniquePtr& a, + const grpc_core::UniquePtr& b) { + return strcmp(a.get(), b.get()); +} + +RefCountedPtr CreateTargetAuthorityTable( + const ServerAddressList& addresses) { + TargetAuthorityTable::Entry* target_authority_entries = + static_cast( + gpr_zalloc(sizeof(*target_authority_entries) * addresses.size())); + for (size_t i = 0; i < addresses.size(); ++i) { + char* addr_str; + GPR_ASSERT( + grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true) > 0); + target_authority_entries[i].key = grpc_slice_from_copied_string(addr_str); + gpr_free(addr_str); + char* balancer_name = grpc_channel_arg_get_string(grpc_channel_args_find( + addresses[i].args(), GRPC_ARG_ADDRESS_BALANCER_NAME)); + target_authority_entries[i].value.reset(gpr_strdup(balancer_name)); + } + RefCountedPtr target_authority_table = + TargetAuthorityTable::Create(addresses.size(), target_authority_entries, + BalancerNameCmp); + gpr_free(target_authority_entries); + return target_authority_table; +} + +} // namespace +} // namespace grpc_core + +grpc_channel_args* grpc_lb_policy_xds_modify_lb_channel_args( + grpc_channel_args* args) { + const char* args_to_remove[1]; + size_t num_args_to_remove = 0; + grpc_arg args_to_add[2]; + size_t num_args_to_add = 0; + // Add arg for targets info table. + grpc_core::ServerAddressList* addresses = + grpc_core::FindServerAddressListChannelArg(args); + GPR_ASSERT(addresses != nullptr); + grpc_core::RefCountedPtr + target_authority_table = + grpc_core::CreateTargetAuthorityTable(*addresses); + args_to_add[num_args_to_add++] = + grpc_core::CreateTargetAuthorityTableChannelArg( + target_authority_table.get()); + // Substitute the channel credentials with a version without call + // credentials: the load balancer is not necessarily trusted to handle + // bearer token credentials. + grpc_channel_credentials* channel_credentials = + grpc_channel_credentials_find_in_args(args); + grpc_core::RefCountedPtr creds_sans_call_creds; + if (channel_credentials != nullptr) { + creds_sans_call_creds = + channel_credentials->duplicate_without_call_credentials(); + GPR_ASSERT(creds_sans_call_creds != nullptr); + args_to_remove[num_args_to_remove++] = GRPC_ARG_CHANNEL_CREDENTIALS; + args_to_add[num_args_to_add++] = + grpc_channel_credentials_to_arg(creds_sans_call_creds.get()); + } + grpc_channel_args* result = grpc_channel_args_copy_and_add_and_remove( + args, args_to_remove, num_args_to_remove, args_to_add, num_args_to_add); + // Clean up. + grpc_channel_args_destroy(args); + return result; +} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.cc new file mode 100644 index 000000000..cdf5408be --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.cc @@ -0,0 +1,85 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h" + +#include +#include +#include + +namespace grpc_core { + +void XdsLbClientStats::AddCallStarted() { + gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1); +} + +void XdsLbClientStats::AddCallFinished(bool finished_with_client_failed_to_send, + bool finished_known_received) { + gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1); + if (finished_with_client_failed_to_send) { + gpr_atm_full_fetch_add(&num_calls_finished_with_client_failed_to_send_, + (gpr_atm)1); + } + if (finished_known_received) { + gpr_atm_full_fetch_add(&num_calls_finished_known_received_, (gpr_atm)1); + } +} + +void XdsLbClientStats::AddCallDroppedLocked(char* token) { + // Increment num_calls_started and num_calls_finished. + gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1); + gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1); + // Record the drop. + if (drop_token_counts_ == nullptr) { + drop_token_counts_.reset(New()); + } + for (size_t i = 0; i < drop_token_counts_->size(); ++i) { + if (strcmp((*drop_token_counts_)[i].token.get(), token) == 0) { + ++(*drop_token_counts_)[i].count; + return; + } + } + // Not found, so add a new entry. + drop_token_counts_->emplace_back(UniquePtr(gpr_strdup(token)), 1); +} + +namespace { + +void AtomicGetAndResetCounter(int64_t* value, gpr_atm* counter) { + *value = static_cast(gpr_atm_full_xchg(counter, (gpr_atm)0)); +} + +} // namespace + +void XdsLbClientStats::GetLocked( + int64_t* num_calls_started, int64_t* num_calls_finished, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received, + UniquePtr* drop_token_counts) { + AtomicGetAndResetCounter(num_calls_started, &num_calls_started_); + AtomicGetAndResetCounter(num_calls_finished, &num_calls_finished_); + AtomicGetAndResetCounter(num_calls_finished_with_client_failed_to_send, + &num_calls_finished_with_client_failed_to_send_); + AtomicGetAndResetCounter(num_calls_finished_known_received, + &num_calls_finished_known_received_); + *drop_token_counts = std::move(drop_token_counts_); +} + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h new file mode 100644 index 000000000..fa0b9f4b6 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h @@ -0,0 +1,72 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CLIENT_STATS_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CLIENT_STATS_H + +#include + +#include + +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/ref_counted.h" + +namespace grpc_core { + +class XdsLbClientStats : public RefCounted { + public: + struct DropTokenCount { + UniquePtr token; + int64_t count; + + DropTokenCount(UniquePtr token, int64_t count) + : token(std::move(token)), count(count) {} + }; + + typedef InlinedVector DroppedCallCounts; + + XdsLbClientStats() {} + + void AddCallStarted(); + void AddCallFinished(bool finished_with_client_failed_to_send, + bool finished_known_received); + + // This method is not thread-safe; caller must synchronize. + void AddCallDroppedLocked(char* token); + + // This method is not thread-safe; caller must synchronize. + void GetLocked(int64_t* num_calls_started, int64_t* num_calls_finished, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received, + UniquePtr* drop_token_counts); + + private: + // This field must only be accessed via *_locked() methods. + UniquePtr drop_token_counts_; + // These fields may be accessed from multiple threads at a time. + gpr_atm num_calls_started_ = 0; + gpr_atm num_calls_finished_ = 0; + gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; + gpr_atm num_calls_finished_known_received_ = 0; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_CLIENT_STATS_H \ + */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc new file mode 100644 index 000000000..79b7bdbe3 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc @@ -0,0 +1,307 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "pb_decode.h" +#include "pb_encode.h" +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h" + +#include + +/* invoked once for every Server in ServerList */ +static bool count_serverlist(pb_istream_t* stream, const pb_field_t* field, + void** arg) { + xds_grpclb_serverlist* sl = static_cast(*arg); + xds_grpclb_server server; + if (GPR_UNLIKELY(!pb_decode(stream, grpc_lb_v1_Server_fields, &server))) { + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream)); + return false; + } + ++sl->num_servers; + return true; +} + +typedef struct decode_serverlist_arg { + /* The decoding callback is invoked once per server in serverlist. Remember + * which index of the serverlist are we currently decoding */ + size_t decoding_idx; + /* The decoded serverlist */ + xds_grpclb_serverlist* serverlist; +} decode_serverlist_arg; + +/* invoked once for every Server in ServerList */ +static bool decode_serverlist(pb_istream_t* stream, const pb_field_t* field, + void** arg) { + decode_serverlist_arg* dec_arg = static_cast(*arg); + GPR_ASSERT(dec_arg->serverlist->num_servers >= dec_arg->decoding_idx); + xds_grpclb_server* server = + static_cast(gpr_zalloc(sizeof(xds_grpclb_server))); + if (GPR_UNLIKELY(!pb_decode(stream, grpc_lb_v1_Server_fields, server))) { + gpr_free(server); + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream)); + return false; + } + dec_arg->serverlist->servers[dec_arg->decoding_idx++] = server; + return true; +} + +xds_grpclb_request* xds_grpclb_request_create(const char* lb_service_name) { + xds_grpclb_request* req = + static_cast(gpr_malloc(sizeof(xds_grpclb_request))); + req->has_client_stats = false; + req->has_initial_request = true; + req->initial_request.has_name = true; + strncpy(req->initial_request.name, lb_service_name, + XDS_SERVICE_NAME_MAX_LENGTH); + return req; +} + +static void populate_timestamp(gpr_timespec timestamp, + xds_grpclb_timestamp* timestamp_pb) { + timestamp_pb->has_seconds = true; + timestamp_pb->seconds = timestamp.tv_sec; + timestamp_pb->has_nanos = true; + timestamp_pb->nanos = timestamp.tv_nsec; +} + +static bool encode_string(pb_ostream_t* stream, const pb_field_t* field, + void* const* arg) { + char* str = static_cast(*arg); + if (!pb_encode_tag_for_field(stream, field)) return false; + return pb_encode_string(stream, reinterpret_cast(str), strlen(str)); +} + +static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field, + void* const* arg) { + grpc_core::XdsLbClientStats::DroppedCallCounts* drop_entries = + static_cast(*arg); + if (drop_entries == nullptr) return true; + for (size_t i = 0; i < drop_entries->size(); ++i) { + if (!pb_encode_tag_for_field(stream, field)) return false; + grpc_lb_v1_ClientStatsPerToken drop_message; + drop_message.load_balance_token.funcs.encode = encode_string; + drop_message.load_balance_token.arg = (*drop_entries)[i].token.get(); + drop_message.has_num_calls = true; + drop_message.num_calls = (*drop_entries)[i].count; + if (!pb_encode_submessage(stream, grpc_lb_v1_ClientStatsPerToken_fields, + &drop_message)) { + return false; + } + } + return true; +} + +xds_grpclb_request* xds_grpclb_load_report_request_create_locked( + grpc_core::XdsLbClientStats* client_stats) { + xds_grpclb_request* req = + static_cast(gpr_zalloc(sizeof(xds_grpclb_request))); + req->has_client_stats = true; + req->client_stats.has_timestamp = true; + populate_timestamp(gpr_now(GPR_CLOCK_REALTIME), &req->client_stats.timestamp); + req->client_stats.has_num_calls_started = true; + req->client_stats.has_num_calls_finished = true; + req->client_stats.has_num_calls_finished_with_client_failed_to_send = true; + req->client_stats.has_num_calls_finished_with_client_failed_to_send = true; + req->client_stats.has_num_calls_finished_known_received = true; + req->client_stats.calls_finished_with_drop.funcs.encode = encode_drops; + grpc_core::UniquePtr + drop_counts; + client_stats->GetLocked( + &req->client_stats.num_calls_started, + &req->client_stats.num_calls_finished, + &req->client_stats.num_calls_finished_with_client_failed_to_send, + &req->client_stats.num_calls_finished_known_received, &drop_counts); + // Will be deleted in xds_grpclb_request_destroy(). + req->client_stats.calls_finished_with_drop.arg = drop_counts.release(); + return req; +} + +grpc_slice xds_grpclb_request_encode(const xds_grpclb_request* request) { + size_t encoded_length; + pb_ostream_t sizestream; + pb_ostream_t outputstream; + grpc_slice slice; + memset(&sizestream, 0, sizeof(pb_ostream_t)); + pb_encode(&sizestream, grpc_lb_v1_LoadBalanceRequest_fields, request); + encoded_length = sizestream.bytes_written; + + slice = GRPC_SLICE_MALLOC(encoded_length); + outputstream = + pb_ostream_from_buffer(GRPC_SLICE_START_PTR(slice), encoded_length); + GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v1_LoadBalanceRequest_fields, + request) != 0); + return slice; +} + +void xds_grpclb_request_destroy(xds_grpclb_request* request) { + if (request->has_client_stats) { + grpc_core::XdsLbClientStats::DroppedCallCounts* drop_entries = + static_cast( + request->client_stats.calls_finished_with_drop.arg); + grpc_core::Delete(drop_entries); + } + gpr_free(request); +} + +typedef grpc_lb_v1_LoadBalanceResponse xds_grpclb_response; +xds_grpclb_initial_response* xds_grpclb_initial_response_parse( + grpc_slice encoded_xds_grpclb_response) { + pb_istream_t stream = + pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_xds_grpclb_response), + GRPC_SLICE_LENGTH(encoded_xds_grpclb_response)); + xds_grpclb_response res; + memset(&res, 0, sizeof(xds_grpclb_response)); + if (GPR_UNLIKELY( + !pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res))) { + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); + return nullptr; + } + + if (!res.has_initial_response) return nullptr; + + xds_grpclb_initial_response* initial_res = + static_cast( + gpr_malloc(sizeof(xds_grpclb_initial_response))); + memcpy(initial_res, &res.initial_response, + sizeof(xds_grpclb_initial_response)); + + return initial_res; +} + +xds_grpclb_serverlist* xds_grpclb_response_parse_serverlist( + grpc_slice encoded_xds_grpclb_response) { + pb_istream_t stream = + pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_xds_grpclb_response), + GRPC_SLICE_LENGTH(encoded_xds_grpclb_response)); + pb_istream_t stream_at_start = stream; + xds_grpclb_serverlist* sl = static_cast( + gpr_zalloc(sizeof(xds_grpclb_serverlist))); + xds_grpclb_response res; + memset(&res, 0, sizeof(xds_grpclb_response)); + // First pass: count number of servers. + res.server_list.servers.funcs.decode = count_serverlist; + res.server_list.servers.arg = sl; + bool status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res); + if (GPR_UNLIKELY(!status)) { + gpr_free(sl); + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); + return nullptr; + } + // Second pass: populate servers. + if (sl->num_servers > 0) { + sl->servers = static_cast( + gpr_zalloc(sizeof(xds_grpclb_server*) * sl->num_servers)); + decode_serverlist_arg decode_arg; + memset(&decode_arg, 0, sizeof(decode_arg)); + decode_arg.serverlist = sl; + res.server_list.servers.funcs.decode = decode_serverlist; + res.server_list.servers.arg = &decode_arg; + status = pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, + &res); + if (GPR_UNLIKELY(!status)) { + xds_grpclb_destroy_serverlist(sl); + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); + return nullptr; + } + } + return sl; +} + +void xds_grpclb_destroy_serverlist(xds_grpclb_serverlist* serverlist) { + if (serverlist == nullptr) { + return; + } + for (size_t i = 0; i < serverlist->num_servers; i++) { + gpr_free(serverlist->servers[i]); + } + gpr_free(serverlist->servers); + gpr_free(serverlist); +} + +xds_grpclb_serverlist* xds_grpclb_serverlist_copy( + const xds_grpclb_serverlist* sl) { + xds_grpclb_serverlist* copy = static_cast( + gpr_zalloc(sizeof(xds_grpclb_serverlist))); + copy->num_servers = sl->num_servers; + copy->servers = static_cast( + gpr_malloc(sizeof(xds_grpclb_server*) * sl->num_servers)); + for (size_t i = 0; i < sl->num_servers; i++) { + copy->servers[i] = + static_cast(gpr_malloc(sizeof(xds_grpclb_server))); + memcpy(copy->servers[i], sl->servers[i], sizeof(xds_grpclb_server)); + } + return copy; +} + +bool xds_grpclb_serverlist_equals(const xds_grpclb_serverlist* lhs, + const xds_grpclb_serverlist* rhs) { + if (lhs == nullptr || rhs == nullptr) { + return false; + } + if (lhs->num_servers != rhs->num_servers) { + return false; + } + for (size_t i = 0; i < lhs->num_servers; i++) { + if (!xds_grpclb_server_equals(lhs->servers[i], rhs->servers[i])) { + return false; + } + } + return true; +} + +bool xds_grpclb_server_equals(const xds_grpclb_server* lhs, + const xds_grpclb_server* rhs) { + return memcmp(lhs, rhs, sizeof(xds_grpclb_server)) == 0; +} + +int xds_grpclb_duration_compare(const xds_grpclb_duration* lhs, + const xds_grpclb_duration* rhs) { + GPR_ASSERT(lhs && rhs); + if (lhs->has_seconds && rhs->has_seconds) { + if (lhs->seconds < rhs->seconds) return -1; + if (lhs->seconds > rhs->seconds) return 1; + } else if (lhs->has_seconds) { + return 1; + } else if (rhs->has_seconds) { + return -1; + } + + GPR_ASSERT(lhs->seconds == rhs->seconds); + if (lhs->has_nanos && rhs->has_nanos) { + if (lhs->nanos < rhs->nanos) return -1; + if (lhs->nanos > rhs->nanos) return 1; + } else if (lhs->has_nanos) { + return 1; + } else if (rhs->has_nanos) { + return -1; + } + + return 0; +} + +grpc_millis xds_grpclb_duration_to_millis(xds_grpclb_duration* duration_pb) { + return static_cast( + (duration_pb->has_seconds ? duration_pb->seconds : 0) * GPR_MS_PER_SEC + + (duration_pb->has_nanos ? duration_pb->nanos : 0) / GPR_NS_PER_MS); +} + +void xds_grpclb_initial_response_destroy( + xds_grpclb_initial_response* response) { + gpr_free(response); +} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h new file mode 100644 index 000000000..670499564 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h @@ -0,0 +1,89 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_LOAD_BALANCER_API_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_LOAD_BALANCER_API_H + +#include + +#include + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" +#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h" +#include "src/core/lib/iomgr/exec_ctx.h" + +#define XDS_SERVICE_NAME_MAX_LENGTH 128 + +typedef grpc_lb_v1_Server_ip_address_t xds_grpclb_ip_address; +typedef grpc_lb_v1_LoadBalanceRequest xds_grpclb_request; +typedef grpc_lb_v1_InitialLoadBalanceResponse xds_grpclb_initial_response; +typedef grpc_lb_v1_Server xds_grpclb_server; +typedef google_protobuf_Duration xds_grpclb_duration; +typedef google_protobuf_Timestamp xds_grpclb_timestamp; + +typedef struct { + xds_grpclb_server** servers; + size_t num_servers; +} xds_grpclb_serverlist; + +/** Create a request for a gRPC LB service under \a lb_service_name */ +xds_grpclb_request* xds_grpclb_request_create(const char* lb_service_name); +xds_grpclb_request* xds_grpclb_load_report_request_create_locked( + grpc_core::XdsLbClientStats* client_stats); + +/** Protocol Buffers v3-encode \a request */ +grpc_slice xds_grpclb_request_encode(const xds_grpclb_request* request); + +/** Destroy \a request */ +void xds_grpclb_request_destroy(xds_grpclb_request* request); + +/** Parse (ie, decode) the bytes in \a encoded_xds_grpclb_response as a \a + * xds_grpclb_initial_response */ +xds_grpclb_initial_response* xds_grpclb_initial_response_parse( + grpc_slice encoded_xds_grpclb_response); + +/** Parse the list of servers from an encoded \a xds_grpclb_response */ +xds_grpclb_serverlist* xds_grpclb_response_parse_serverlist( + grpc_slice encoded_xds_grpclb_response); + +/** Return a copy of \a sl. The caller is responsible for calling \a + * xds_grpclb_destroy_serverlist on the returned copy. */ +xds_grpclb_serverlist* xds_grpclb_serverlist_copy( + const xds_grpclb_serverlist* sl); + +bool xds_grpclb_serverlist_equals(const xds_grpclb_serverlist* lhs, + const xds_grpclb_serverlist* rhs); + +bool xds_grpclb_server_equals(const xds_grpclb_server* lhs, + const xds_grpclb_server* rhs); + +/** Destroy \a serverlist */ +void xds_grpclb_destroy_serverlist(xds_grpclb_serverlist* serverlist); + +/** Compare \a lhs against \a rhs and return 0 if \a lhs and \a rhs are equal, + * < 0 if \a lhs represents a duration shorter than \a rhs and > 0 otherwise */ +int xds_grpclb_duration_compare(const xds_grpclb_duration* lhs, + const xds_grpclb_duration* rhs); + +grpc_millis xds_grpclb_duration_to_millis(xds_grpclb_duration* duration_pb); + +/** Destroy \a initial_response */ +void xds_grpclb_initial_response_destroy(xds_grpclb_initial_response* response); + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_LOAD_BALANCER_API_H \ + */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.cc deleted file mode 100644 index 7c8cba55b..000000000 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.cc +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -#include -#include - -#include "src/core/lib/channel/channel_args.h" - -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" -#include "src/core/ext/filters/client_channel/parse_address.h" - -grpc_lb_addresses* grpc_lb_addresses_create( - size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) { - grpc_lb_addresses* addresses = - static_cast(gpr_zalloc(sizeof(grpc_lb_addresses))); - addresses->num_addresses = num_addresses; - addresses->user_data_vtable = user_data_vtable; - const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses; - addresses->addresses = - static_cast(gpr_zalloc(addresses_size)); - return addresses; -} - -grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) { - grpc_lb_addresses* new_addresses = grpc_lb_addresses_create( - addresses->num_addresses, addresses->user_data_vtable); - memcpy(new_addresses->addresses, addresses->addresses, - sizeof(grpc_lb_address) * addresses->num_addresses); - for (size_t i = 0; i < addresses->num_addresses; ++i) { - if (new_addresses->addresses[i].balancer_name != nullptr) { - new_addresses->addresses[i].balancer_name = - gpr_strdup(new_addresses->addresses[i].balancer_name); - } - if (new_addresses->addresses[i].user_data != nullptr) { - new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy( - new_addresses->addresses[i].user_data); - } - } - return new_addresses; -} - -void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, - const void* address, size_t address_len, - bool is_balancer, const char* balancer_name, - void* user_data) { - GPR_ASSERT(index < addresses->num_addresses); - if (user_data != nullptr) GPR_ASSERT(addresses->user_data_vtable != nullptr); - grpc_lb_address* target = &addresses->addresses[index]; - memcpy(target->address.addr, address, address_len); - target->address.len = static_cast(address_len); - target->is_balancer = is_balancer; - target->balancer_name = gpr_strdup(balancer_name); - target->user_data = user_data; -} - -bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses, - size_t index, const grpc_uri* uri, - bool is_balancer, - const char* balancer_name, - void* user_data) { - grpc_resolved_address address; - if (!grpc_parse_uri(uri, &address)) return false; - grpc_lb_addresses_set_address(addresses, index, address.addr, address.len, - is_balancer, balancer_name, user_data); - return true; -} - -int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1, - const grpc_lb_addresses* addresses2) { - if (addresses1->num_addresses > addresses2->num_addresses) return 1; - if (addresses1->num_addresses < addresses2->num_addresses) return -1; - if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1; - if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1; - for (size_t i = 0; i < addresses1->num_addresses; ++i) { - const grpc_lb_address* target1 = &addresses1->addresses[i]; - const grpc_lb_address* target2 = &addresses2->addresses[i]; - if (target1->address.len > target2->address.len) return 1; - if (target1->address.len < target2->address.len) return -1; - int retval = memcmp(target1->address.addr, target2->address.addr, - target1->address.len); - if (retval != 0) return retval; - if (target1->is_balancer > target2->is_balancer) return 1; - if (target1->is_balancer < target2->is_balancer) return -1; - const char* balancer_name1 = - target1->balancer_name != nullptr ? target1->balancer_name : ""; - const char* balancer_name2 = - target2->balancer_name != nullptr ? target2->balancer_name : ""; - retval = strcmp(balancer_name1, balancer_name2); - if (retval != 0) return retval; - if (addresses1->user_data_vtable != nullptr) { - retval = addresses1->user_data_vtable->cmp(target1->user_data, - target2->user_data); - if (retval != 0) return retval; - } - } - return 0; -} - -void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) { - for (size_t i = 0; i < addresses->num_addresses; ++i) { - gpr_free(addresses->addresses[i].balancer_name); - if (addresses->addresses[i].user_data != nullptr) { - addresses->user_data_vtable->destroy(addresses->addresses[i].user_data); - } - } - gpr_free(addresses->addresses); - gpr_free(addresses); -} - -static void* lb_addresses_copy(void* addresses) { - return grpc_lb_addresses_copy(static_cast(addresses)); -} -static void lb_addresses_destroy(void* addresses) { - grpc_lb_addresses_destroy(static_cast(addresses)); -} -static int lb_addresses_cmp(void* addresses1, void* addresses2) { - return grpc_lb_addresses_cmp(static_cast(addresses1), - static_cast(addresses2)); -} -static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = { - lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp}; - -grpc_arg grpc_lb_addresses_create_channel_arg( - const grpc_lb_addresses* addresses) { - return grpc_channel_arg_pointer_create( - (char*)GRPC_ARG_LB_ADDRESSES, (void*)addresses, &lb_addresses_arg_vtable); -} - -grpc_lb_addresses* grpc_lb_addresses_find_channel_arg( - const grpc_channel_args* channel_args) { - const grpc_arg* lb_addresses_arg = - grpc_channel_args_find(channel_args, GRPC_ARG_LB_ADDRESSES); - if (lb_addresses_arg == nullptr || lb_addresses_arg->type != GRPC_ARG_POINTER) - return nullptr; - return static_cast(lb_addresses_arg->value.pointer.p); -} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.h index 644025815..770bcbeee 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_factory.h @@ -21,89 +21,9 @@ #include -#include "src/core/lib/iomgr/resolve_address.h" - -#include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/lb_policy.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" - -// -// representation of an LB address -// - -// Channel arg key for grpc_lb_addresses. -#define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses" - -/** A resolved address alongside any LB related information associated with it. - * \a user_data, if not NULL, contains opaque data meant to be consumed by the - * gRPC LB policy. Note that no all LB policies support \a user_data as input. - * Those who don't will simply ignore it and will correspondingly return NULL in - * their namesake pick() output argument. */ -// TODO(roth): Once we figure out a better way of handling user_data in -// LB policies, convert these structs to C++ classes. -typedef struct grpc_lb_address { - grpc_resolved_address address; - bool is_balancer; - char* balancer_name; /* For secure naming. */ - void* user_data; -} grpc_lb_address; - -typedef struct grpc_lb_user_data_vtable { - void* (*copy)(void*); - void (*destroy)(void*); - int (*cmp)(void*, void*); -} grpc_lb_user_data_vtable; - -typedef struct grpc_lb_addresses { - size_t num_addresses; - grpc_lb_address* addresses; - const grpc_lb_user_data_vtable* user_data_vtable; -} grpc_lb_addresses; - -/** Returns a grpc_addresses struct with enough space for - \a num_addresses addresses. The \a user_data_vtable argument may be - NULL if no user data will be added. */ -grpc_lb_addresses* grpc_lb_addresses_create( - size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable); - -/** Creates a copy of \a addresses. */ -grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses); - -/** Sets the value of the address at index \a index of \a addresses. - * \a address is a socket address of length \a address_len. - * Takes ownership of \a balancer_name. */ -void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, - const void* address, size_t address_len, - bool is_balancer, const char* balancer_name, - void* user_data); - -/** Sets the value of the address at index \a index of \a addresses from \a uri. - * Returns true upon success, false otherwise. Takes ownership of \a - * balancer_name. */ -bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses, - size_t index, const grpc_uri* uri, - bool is_balancer, - const char* balancer_name, - void* user_data); - -/** Compares \a addresses1 and \a addresses2. */ -int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1, - const grpc_lb_addresses* addresses2); - -/** Destroys \a addresses. */ -void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses); - -/** Returns a channel arg containing \a addresses. */ -grpc_arg grpc_lb_addresses_create_channel_arg( - const grpc_lb_addresses* addresses); - -/** Returns the \a grpc_lb_addresses instance in \a channel_args or NULL */ -grpc_lb_addresses* grpc_lb_addresses_find_channel_arg( - const grpc_channel_args* channel_args); - -// -// LB policy factory -// +#include "src/core/lib/gprpp/abstract.h" +#include "src/core/lib/gprpp/orphanable.h" namespace grpc_core { @@ -111,7 +31,12 @@ class LoadBalancingPolicyFactory { public: /// Returns a new LB policy instance. virtual OrphanablePtr CreateLoadBalancingPolicy( - const LoadBalancingPolicy::Args& args) const GRPC_ABSTRACT; + LoadBalancingPolicy::Args args) const { + std::move(args); // Suppress clang-tidy complaint. + // The rest of this is copied from the GRPC_ABSTRACT macro. + gpr_log(GPR_ERROR, "Function marked GRPC_ABSTRACT was not implemented"); + GPR_ASSERT(false); + } /// Returns the LB policy name that this factory provides. /// Caller does NOT take ownership of result. diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.cc index d651b1120..99980d550 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.cc @@ -84,14 +84,19 @@ void LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory( OrphanablePtr LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( - const char* name, const LoadBalancingPolicy::Args& args) { + const char* name, LoadBalancingPolicy::Args args) { GPR_ASSERT(g_state != nullptr); // Find factory. LoadBalancingPolicyFactory* factory = g_state->GetLoadBalancingPolicyFactory(name); if (factory == nullptr) return nullptr; // Specified name not found. // Create policy via factory. - return factory->CreateLoadBalancingPolicy(args); + return factory->CreateLoadBalancingPolicy(std::move(args)); +} + +bool LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(const char* name) { + GPR_ASSERT(g_state != nullptr); + return g_state->GetLoadBalancingPolicyFactory(name) != nullptr; } } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.h b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.h index 2e9bb061e..7472ba9f8 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/lb_policy_registry.h @@ -46,7 +46,11 @@ class LoadBalancingPolicyRegistry { /// Creates an LB policy of the type specified by \a name. static OrphanablePtr CreateLoadBalancingPolicy( - const char* name, const LoadBalancingPolicy::Args& args); + const char* name, LoadBalancingPolicy::Args args); + + /// Returns true if the LB policy factory specified by \a name exists in this + /// registry. + static bool LoadBalancingPolicyExists(const char* name); }; } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/local_subchannel_pool.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/local_subchannel_pool.cc new file mode 100644 index 000000000..d1c1cacb4 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/local_subchannel_pool.cc @@ -0,0 +1,96 @@ +// +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include + +#include "src/core/ext/filters/client_channel/local_subchannel_pool.h" + +#include "src/core/ext/filters/client_channel/subchannel.h" + +namespace grpc_core { + +LocalSubchannelPool::LocalSubchannelPool() { + subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_); +} + +LocalSubchannelPool::~LocalSubchannelPool() { + grpc_avl_unref(subchannel_map_, nullptr); +} + +Subchannel* LocalSubchannelPool::RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) { + // Check to see if a subchannel already exists. + Subchannel* c = + static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); + if (c != nullptr) { + // The subchannel already exists. Reuse it. + c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse"); + GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing"); + } else { + // There hasn't been such subchannel. Add one. + subchannel_map_ = grpc_avl_add(subchannel_map_, New(*key), + constructed, nullptr); + c = constructed; + } + return c; +} + +void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { + subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr); +} + +Subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { + Subchannel* c = + static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); + return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool"); +} + +namespace { + +void sck_avl_destroy(void* p, void* user_data) { + SubchannelKey* key = static_cast(p); + Delete(key); +} + +void* sck_avl_copy(void* p, void* unused) { + const SubchannelKey* key = static_cast(p); + auto new_key = New(*key); + return static_cast(new_key); +} + +long sck_avl_compare(void* a, void* b, void* unused) { + const SubchannelKey* key_a = static_cast(a); + const SubchannelKey* key_b = static_cast(b); + return key_a->Cmp(*key_b); +} + +void scv_avl_destroy(void* p, void* user_data) {} + +void* scv_avl_copy(void* p, void* unused) { return p; } + +} // namespace + +const grpc_avl_vtable LocalSubchannelPool::subchannel_avl_vtable_ = { + sck_avl_destroy, // destroy_key + sck_avl_copy, // copy_key + sck_avl_compare, // compare_keys + scv_avl_destroy, // destroy_value + scv_avl_copy // copy_value +}; + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/local_subchannel_pool.h b/Sources/CgRPC/src/core/ext/filters/client_channel/local_subchannel_pool.h new file mode 100644 index 000000000..a6b7e259f --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/local_subchannel_pool.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H + +#include + +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" + +namespace grpc_core { + +// The local subchannel pool that is owned by a single channel. It doesn't +// support subchannel sharing with other channels by nature. Nor does it support +// subchannel retention when a subchannel is not used. The only real purpose of +// using this subchannel pool is to allow subchannel reuse within the channel +// when an incoming resolver update contains some addresses for which the +// channel has already created subchannels. +// Thread-unsafe. +class LocalSubchannelPool final : public SubchannelPoolInterface { + public: + LocalSubchannelPool(); + ~LocalSubchannelPool() override; + + // Implements interface methods. + // Thread-unsafe. Intended to be invoked within the client_channel combiner. + Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) override; + void UnregisterSubchannel(SubchannelKey* key) override; + Subchannel* FindSubchannel(SubchannelKey* key) override; + + private: + // The vtable for subchannel operations in an AVL tree. + static const grpc_avl_vtable subchannel_avl_vtable_; + // A map from subchannel key to subchannel. + grpc_avl subchannel_map_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/method_params.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/method_params.cc deleted file mode 100644 index 1f116bb67..000000000 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/method_params.cc +++ /dev/null @@ -1,178 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include -#include -#include - -#include "src/core/ext/filters/client_channel/method_params.h" -#include "src/core/lib/channel/status_util.h" -#include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/memory.h" - -// As per the retry design, we do not allow more than 5 retry attempts. -#define MAX_MAX_RETRY_ATTEMPTS 5 - -namespace grpc_core { -namespace internal { - -namespace { - -bool ParseWaitForReady( - grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) { - if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) { - return false; - } - *wait_for_ready = field->type == GRPC_JSON_TRUE - ? ClientChannelMethodParams::WAIT_FOR_READY_TRUE - : ClientChannelMethodParams::WAIT_FOR_READY_FALSE; - return true; -} - -// Parses a JSON field of the form generated for a google.proto.Duration -// proto message, as per: -// https://developers.google.com/protocol-buffers/docs/proto3#json -bool ParseDuration(grpc_json* field, grpc_millis* duration) { - if (field->type != GRPC_JSON_STRING) return false; - size_t len = strlen(field->value); - if (field->value[len - 1] != 's') return false; - UniquePtr buf(gpr_strdup(field->value)); - *(buf.get() + len - 1) = '\0'; // Remove trailing 's'. - char* decimal_point = strchr(buf.get(), '.'); - int nanos = 0; - if (decimal_point != nullptr) { - *decimal_point = '\0'; - nanos = gpr_parse_nonnegative_int(decimal_point + 1); - if (nanos == -1) { - return false; - } - int num_digits = static_cast(strlen(decimal_point + 1)); - if (num_digits > 9) { // We don't accept greater precision than nanos. - return false; - } - for (int i = 0; i < (9 - num_digits); ++i) { - nanos *= 10; - } - } - int seconds = - decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get()); - if (seconds == -1) return false; - *duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS; - return true; -} - -UniquePtr ParseRetryPolicy( - grpc_json* field) { - auto retry_policy = MakeUnique(); - if (field->type != GRPC_JSON_OBJECT) return nullptr; - for (grpc_json* sub_field = field->child; sub_field != nullptr; - sub_field = sub_field->next) { - if (sub_field->key == nullptr) return nullptr; - if (strcmp(sub_field->key, "maxAttempts") == 0) { - if (retry_policy->max_attempts != 0) return nullptr; // Duplicate. - if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; - retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value); - if (retry_policy->max_attempts <= 1) return nullptr; - if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) { - gpr_log(GPR_ERROR, - "service config: clamped retryPolicy.maxAttempts at %d", - MAX_MAX_RETRY_ATTEMPTS); - retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS; - } - } else if (strcmp(sub_field->key, "initialBackoff") == 0) { - if (retry_policy->initial_backoff > 0) return nullptr; // Duplicate. - if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) { - return nullptr; - } - if (retry_policy->initial_backoff == 0) return nullptr; - } else if (strcmp(sub_field->key, "maxBackoff") == 0) { - if (retry_policy->max_backoff > 0) return nullptr; // Duplicate. - if (!ParseDuration(sub_field, &retry_policy->max_backoff)) { - return nullptr; - } - if (retry_policy->max_backoff == 0) return nullptr; - } else if (strcmp(sub_field->key, "backoffMultiplier") == 0) { - if (retry_policy->backoff_multiplier != 0) return nullptr; // Duplicate. - if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; - if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) != - 1) { - return nullptr; - } - if (retry_policy->backoff_multiplier <= 0) return nullptr; - } else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) { - if (!retry_policy->retryable_status_codes.Empty()) { - return nullptr; // Duplicate. - } - if (sub_field->type != GRPC_JSON_ARRAY) return nullptr; - for (grpc_json* element = sub_field->child; element != nullptr; - element = element->next) { - if (element->type != GRPC_JSON_STRING) return nullptr; - grpc_status_code status; - if (!grpc_status_code_from_string(element->value, &status)) { - return nullptr; - } - retry_policy->retryable_status_codes.Add(status); - } - if (retry_policy->retryable_status_codes.Empty()) return nullptr; - } - } - // Make sure required fields are set. - if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 || - retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 || - retry_policy->retryable_status_codes.Empty()) { - return nullptr; - } - return retry_policy; -} - -} // namespace - -RefCountedPtr -ClientChannelMethodParams::CreateFromJson(const grpc_json* json) { - RefCountedPtr method_params = - MakeRefCounted(); - for (grpc_json* field = json->child; field != nullptr; field = field->next) { - if (field->key == nullptr) continue; - if (strcmp(field->key, "waitForReady") == 0) { - if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) { - return nullptr; // Duplicate. - } - if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) { - return nullptr; - } - } else if (strcmp(field->key, "timeout") == 0) { - if (method_params->timeout_ > 0) return nullptr; // Duplicate. - if (!ParseDuration(field, &method_params->timeout_)) return nullptr; - } else if (strcmp(field->key, "retryPolicy") == 0) { - if (method_params->retry_policy_ != nullptr) { - return nullptr; // Duplicate. - } - method_params->retry_policy_ = ParseRetryPolicy(field); - if (method_params->retry_policy_ == nullptr) return nullptr; - } - } - return method_params; -} - -} // namespace internal -} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/method_params.h b/Sources/CgRPC/src/core/ext/filters/client_channel/method_params.h deleted file mode 100644 index a31d360f1..000000000 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/method_params.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H - -#include - -#include "src/core/lib/channel/status_util.h" -#include "src/core/lib/gprpp/ref_counted.h" -#include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis -#include "src/core/lib/json/json.h" - -namespace grpc_core { -namespace internal { - -class ClientChannelMethodParams : public RefCounted { - public: - enum WaitForReady { - WAIT_FOR_READY_UNSET = 0, - WAIT_FOR_READY_FALSE, - WAIT_FOR_READY_TRUE - }; - - struct RetryPolicy { - int max_attempts = 0; - grpc_millis initial_backoff = 0; - grpc_millis max_backoff = 0; - float backoff_multiplier = 0; - StatusCodeSet retryable_status_codes; - }; - - /// Creates a method_parameters object from \a json. - /// Intended for use with ServiceConfig::CreateMethodConfigTable(). - static RefCountedPtr CreateFromJson( - const grpc_json* json); - - grpc_millis timeout() const { return timeout_; } - WaitForReady wait_for_ready() const { return wait_for_ready_; } - const RetryPolicy* retry_policy() const { return retry_policy_.get(); } - - private: - // So New() can call our private ctor. - template - friend T* grpc_core::New(Args&&... args); - - // So Delete() can call our private dtor. - template - friend void grpc_core::Delete(T*); - - ClientChannelMethodParams() {} - virtual ~ClientChannelMethodParams() {} - - grpc_millis timeout_ = 0; - WaitForReady wait_for_ready_ = WAIT_FOR_READY_UNSET; - UniquePtr retry_policy_; -}; - -} // namespace internal -} // namespace grpc_core - -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.cc index b3900114a..c5e1ed811 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.cc @@ -19,6 +19,7 @@ #include #include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/lib/iomgr/grpc_if_nametoindex.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" @@ -35,6 +36,11 @@ #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" +#ifdef GRPC_POSIX_SOCKET +#include +#include +#endif + #ifdef GRPC_HAVE_UNIX_SOCKET bool grpc_parse_unix(const grpc_uri* uri, @@ -69,7 +75,12 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr, // Split host and port. char* host; char* port; - if (!gpr_split_host_port(hostport, &host, &port)) return false; + if (!gpr_split_host_port(hostport, &host, &port)) { + if (log_errors) { + gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport); + } + return false; + } // Parse IP address. memset(addr, 0, sizeof(*addr)); addr->len = static_cast(sizeof(grpc_sockaddr_in)); @@ -115,7 +126,12 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, // Split host and port. char* host; char* port; - if (!gpr_split_host_port(hostport, &host, &port)) return false; + if (!gpr_split_host_port(hostport, &host, &port)) { + if (log_errors) { + gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport); + } + return false; + } // Parse IP address. memset(addr, 0, sizeof(*addr)); addr->len = static_cast(sizeof(grpc_sockaddr_in6)); @@ -125,27 +141,44 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, char* host_end = static_cast(gpr_memrchr(host, '%', strlen(host))); if (host_end != nullptr) { GPR_ASSERT(host_end >= host); - char host_without_scope[GRPC_INET6_ADDRSTRLEN]; + char host_without_scope[GRPC_INET6_ADDRSTRLEN + 1]; size_t host_without_scope_len = static_cast(host_end - host); uint32_t sin6_scope_id = 0; + if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) { + if (log_errors) { + gpr_log( + GPR_ERROR, + "invalid ipv6 address length %zu. Length cannot be greater than " + "GRPC_INET6_ADDRSTRLEN i.e %d)", + host_without_scope_len, GRPC_INET6_ADDRSTRLEN); + } + goto done; + } strncpy(host_without_scope, host, host_without_scope_len); host_without_scope[host_without_scope_len] = '\0'; if (grpc_inet_pton(GRPC_AF_INET6, host_without_scope, &in6->sin6_addr) == 0) { - gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope); + if (log_errors) { + gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope); + } goto done; } if (gpr_parse_bytes_to_uint32(host_end + 1, strlen(host) - host_without_scope_len - 1, &sin6_scope_id) == 0) { - gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1); - goto done; + if ((sin6_scope_id = grpc_if_nametoindex(host_end + 1)) == 0) { + gpr_log(GPR_ERROR, + "Invalid interface name: '%s'. " + "Non-numeric and failed if_nametoindex.", + host_end + 1); + goto done; + } } // Handle "sin6_scope_id" being type "u_long". See grpc issue #10027. in6->sin6_scope_id = sin6_scope_id; } else { if (grpc_inet_pton(GRPC_AF_INET6, host, &in6->sin6_addr) == 0) { - gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host); + if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host); goto done; } } @@ -190,3 +223,12 @@ bool grpc_parse_uri(const grpc_uri* uri, grpc_resolved_address* resolved_addr) { gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri->scheme); return false; } + +uint16_t grpc_strhtons(const char* port) { + if (strcmp(port, "http") == 0) { + return htons(80); + } else if (strcmp(port, "https") == 0) { + return htons(443); + } + return htons(static_cast(atoi(port))); +} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.h b/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.h index 9a88b66ed..5c050a233 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/parse_address.h @@ -23,8 +23,8 @@ #include -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/uri/uri_parser.h" /** Populate \a resolved_addr from \a uri, whose path is expected to contain a * unix socket path. Returns true upon success. */ @@ -47,4 +47,7 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr, bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, bool log_errors); +/* Converts named or numeric port to a uint16 suitable for use in a sockaddr. */ +uint16_t grpc_strhtons(const char* port); + #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/request_routing.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/request_routing.cc new file mode 100644 index 000000000..d6ff34c99 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/request_routing.cc @@ -0,0 +1,946 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/filters/client_channel/request_routing.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/ext/filters/client_channel/backup_poller.h" +#include "src/core/ext/filters/client_channel/global_subchannel_pool.h" +#include "src/core/ext/filters/client_channel/http_connect_handshaker.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/local_subchannel_pool.h" +#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/retry_throttle.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/ext/filters/client_channel/subchannel.h" +#include "src/core/ext/filters/deadline/deadline_filter.h" +#include "src/core/lib/backoff/backoff.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/profiling/timers.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/connectivity_state.h" +#include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/metadata_batch.h" +#include "src/core/lib/transport/service_config.h" +#include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/transport/status_metadata.h" + +namespace grpc_core { + +// +// RequestRouter::Request::ResolverResultWaiter +// + +// Handles waiting for a resolver result. +// Used only for the first call on an idle channel. +class RequestRouter::Request::ResolverResultWaiter { + public: + explicit ResolverResultWaiter(Request* request) + : request_router_(request->request_router_), + request_(request), + tracer_enabled_(request_router_->tracer_->enabled()) { + if (tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: deferring pick pending resolver " + "result", + request_router_, request); + } + // Add closure to be run when a resolver result is available. + GRPC_CLOSURE_INIT(&done_closure_, &DoneLocked, this, + grpc_combiner_scheduler(request_router_->combiner_)); + AddToWaitingList(); + // Set cancellation closure, so that we abort if the call is cancelled. + GRPC_CLOSURE_INIT(&cancel_closure_, &CancelLocked, this, + grpc_combiner_scheduler(request_router_->combiner_)); + grpc_call_combiner_set_notify_on_cancel(request->call_combiner_, + &cancel_closure_); + } + + private: + // Adds done_closure_ to + // request_router_->waiting_for_resolver_result_closures_. + void AddToWaitingList() { + grpc_closure_list_append( + &request_router_->waiting_for_resolver_result_closures_, &done_closure_, + GRPC_ERROR_NONE); + } + + // Invoked when a resolver result is available. + static void DoneLocked(void* arg, grpc_error* error) { + ResolverResultWaiter* self = static_cast(arg); + RequestRouter* request_router = self->request_router_; + // If CancelLocked() has already run, delete ourselves without doing + // anything. Note that the call stack may have already been destroyed, + // so it's not safe to access anything in state_. + if (GPR_UNLIKELY(self->finished_)) { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p: call cancelled before resolver result", + request_router); + } + Delete(self); + return; + } + // Otherwise, process the resolver result. + Request* request = self->request_; + if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: resolver failed to return data", + request_router, request); + } + GRPC_CLOSURE_RUN(request->on_route_done_, GRPC_ERROR_REF(error)); + } else if (GPR_UNLIKELY(request_router->resolver_ == nullptr)) { + // Shutting down. + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, "request_router=%p request=%p: resolver disconnected", + request_router, request); + } + GRPC_CLOSURE_RUN(request->on_route_done_, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); + } else if (GPR_UNLIKELY(request_router->lb_policy_ == nullptr)) { + // Transient resolver failure. + // If call has wait_for_ready=true, try again; otherwise, fail. + if (*request->pick_.initial_metadata_flags & + GRPC_INITIAL_METADATA_WAIT_FOR_READY) { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: resolver returned but no LB " + "policy; wait_for_ready=true; trying again", + request_router, request); + } + // Re-add ourselves to the waiting list. + self->AddToWaitingList(); + // Return early so that we don't set finished_ to true below. + return; + } else { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: resolver returned but no LB " + "policy; wait_for_ready=false; failing", + request_router, request); + } + GRPC_CLOSURE_RUN( + request->on_route_done_, + grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); + } + } else { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: resolver returned, doing LB " + "pick", + request_router, request); + } + request->ProcessServiceConfigAndStartLbPickLocked(); + } + self->finished_ = true; + } + + // Invoked when the call is cancelled. + // Note: This runs under the client_channel combiner, but will NOT be + // holding the call combiner. + static void CancelLocked(void* arg, grpc_error* error) { + ResolverResultWaiter* self = static_cast(arg); + RequestRouter* request_router = self->request_router_; + // If DoneLocked() has already run, delete ourselves without doing anything. + if (self->finished_) { + Delete(self); + return; + } + Request* request = self->request_; + // If we are being cancelled, immediately invoke on_route_done_ + // to propagate the error back to the caller. + if (error != GRPC_ERROR_NONE) { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: cancelling call waiting for " + "name resolution", + request_router, request); + } + // Note: Although we are not in the call combiner here, we are + // basically stealing the call combiner from the pending pick, so + // it's safe to run on_route_done_ here -- we are essentially + // calling it here instead of calling it in DoneLocked(). + GRPC_CLOSURE_RUN(request->on_route_done_, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Pick cancelled", &error, 1)); + } + self->finished_ = true; + } + + RequestRouter* request_router_; + Request* request_; + const bool tracer_enabled_; + grpc_closure done_closure_; + grpc_closure cancel_closure_; + bool finished_ = false; +}; + +// +// RequestRouter::Request::AsyncPickCanceller +// + +// Handles the call combiner cancellation callback for an async LB pick. +class RequestRouter::Request::AsyncPickCanceller { + public: + explicit AsyncPickCanceller(Request* request) + : request_router_(request->request_router_), + request_(request), + tracer_enabled_(request_router_->tracer_->enabled()) { + GRPC_CALL_STACK_REF(request->owning_call_, "pick_callback_cancel"); + // Set cancellation closure, so that we abort if the call is cancelled. + GRPC_CLOSURE_INIT(&cancel_closure_, &CancelLocked, this, + grpc_combiner_scheduler(request_router_->combiner_)); + grpc_call_combiner_set_notify_on_cancel(request->call_combiner_, + &cancel_closure_); + } + + void MarkFinishedLocked() { + finished_ = true; + GRPC_CALL_STACK_UNREF(request_->owning_call_, "pick_callback_cancel"); + } + + private: + // Invoked when the call is cancelled. + // Note: This runs under the client_channel combiner, but will NOT be + // holding the call combiner. + static void CancelLocked(void* arg, grpc_error* error) { + AsyncPickCanceller* self = static_cast(arg); + Request* request = self->request_; + RequestRouter* request_router = self->request_router_; + if (!self->finished_) { + // Note: request_router->lb_policy_ may have changed since we started our + // pick, in which case we will be cancelling the pick on a policy other + // than the one we started it on. However, this will just be a no-op. + if (error != GRPC_ERROR_NONE && request_router->lb_policy_ != nullptr) { + if (self->tracer_enabled_) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: cancelling pick from LB " + "policy %p", + request_router, request, request_router->lb_policy_.get()); + } + request_router->lb_policy_->CancelPickLocked(&request->pick_, + GRPC_ERROR_REF(error)); + } + request->pick_canceller_ = nullptr; + GRPC_CALL_STACK_UNREF(request->owning_call_, "pick_callback_cancel"); + } + Delete(self); + } + + RequestRouter* request_router_; + Request* request_; + const bool tracer_enabled_; + grpc_closure cancel_closure_; + bool finished_ = false; +}; + +// +// RequestRouter::Request +// + +RequestRouter::Request::Request(grpc_call_stack* owning_call, + grpc_call_combiner* call_combiner, + grpc_polling_entity* pollent, + grpc_metadata_batch* send_initial_metadata, + uint32_t* send_initial_metadata_flags, + ApplyServiceConfigCallback apply_service_config, + void* apply_service_config_user_data, + grpc_closure* on_route_done) + : owning_call_(owning_call), + call_combiner_(call_combiner), + pollent_(pollent), + apply_service_config_(apply_service_config), + apply_service_config_user_data_(apply_service_config_user_data), + on_route_done_(on_route_done) { + pick_.initial_metadata = send_initial_metadata; + pick_.initial_metadata_flags = send_initial_metadata_flags; +} + +RequestRouter::Request::~Request() { + if (pick_.connected_subchannel != nullptr) { + pick_.connected_subchannel.reset(); + } + for (size_t i = 0; i < GRPC_CONTEXT_COUNT; ++i) { + if (pick_.subchannel_call_context[i].destroy != nullptr) { + pick_.subchannel_call_context[i].destroy( + pick_.subchannel_call_context[i].value); + } + } +} + +// Invoked once resolver results are available. +void RequestRouter::Request::ProcessServiceConfigAndStartLbPickLocked() { + // Get service config data if needed. + if (!apply_service_config_(apply_service_config_user_data_)) return; + // Start LB pick. + StartLbPickLocked(); +} + +void RequestRouter::Request::MaybeAddCallToInterestedPartiesLocked() { + if (!pollent_added_to_interested_parties_) { + pollent_added_to_interested_parties_ = true; + grpc_polling_entity_add_to_pollset_set( + pollent_, request_router_->interested_parties_); + } +} + +void RequestRouter::Request::MaybeRemoveCallFromInterestedPartiesLocked() { + if (pollent_added_to_interested_parties_) { + pollent_added_to_interested_parties_ = false; + grpc_polling_entity_del_from_pollset_set( + pollent_, request_router_->interested_parties_); + } +} + +// Starts a pick on the LB policy. +void RequestRouter::Request::StartLbPickLocked() { + if (request_router_->tracer_->enabled()) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: starting pick on lb_policy=%p", + request_router_, this, request_router_->lb_policy_.get()); + } + GRPC_CLOSURE_INIT(&on_pick_done_, &LbPickDoneLocked, this, + grpc_combiner_scheduler(request_router_->combiner_)); + pick_.on_complete = &on_pick_done_; + GRPC_CALL_STACK_REF(owning_call_, "pick_callback"); + grpc_error* error = GRPC_ERROR_NONE; + const bool pick_done = + request_router_->lb_policy_->PickLocked(&pick_, &error); + if (pick_done) { + // Pick completed synchronously. + if (request_router_->tracer_->enabled()) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: pick completed synchronously", + request_router_, this); + } + GRPC_CLOSURE_RUN(on_route_done_, error); + GRPC_CALL_STACK_UNREF(owning_call_, "pick_callback"); + } else { + // Pick will be returned asynchronously. + // Add the request's polling entity to the request_router's + // interested_parties, so that the I/O of the LB policy can be done + // under it. It will be removed in LbPickDoneLocked(). + MaybeAddCallToInterestedPartiesLocked(); + // Request notification on call cancellation. + // We allocate a separate object to track cancellation, since the + // cancellation closure might still be pending when we need to reuse + // the memory in which this Request object is stored for a subsequent + // retry attempt. + pick_canceller_ = New(this); + } +} + +// Callback invoked by LoadBalancingPolicy::PickLocked() for async picks. +// Unrefs the LB policy and invokes on_route_done_. +void RequestRouter::Request::LbPickDoneLocked(void* arg, grpc_error* error) { + Request* self = static_cast(arg); + RequestRouter* request_router = self->request_router_; + if (request_router->tracer_->enabled()) { + gpr_log(GPR_INFO, + "request_router=%p request=%p: pick completed asynchronously", + request_router, self); + } + self->MaybeRemoveCallFromInterestedPartiesLocked(); + if (self->pick_canceller_ != nullptr) { + self->pick_canceller_->MarkFinishedLocked(); + } + GRPC_CLOSURE_RUN(self->on_route_done_, GRPC_ERROR_REF(error)); + GRPC_CALL_STACK_UNREF(self->owning_call_, "pick_callback"); +} + +// +// RequestRouter::LbConnectivityWatcher +// + +class RequestRouter::LbConnectivityWatcher { + public: + LbConnectivityWatcher(RequestRouter* request_router, + grpc_connectivity_state state, + LoadBalancingPolicy* lb_policy, + grpc_channel_stack* owning_stack, + grpc_combiner* combiner) + : request_router_(request_router), + state_(state), + lb_policy_(lb_policy), + owning_stack_(owning_stack) { + GRPC_CHANNEL_STACK_REF(owning_stack_, "LbConnectivityWatcher"); + GRPC_CLOSURE_INIT(&on_changed_, &OnLbPolicyStateChangedLocked, this, + grpc_combiner_scheduler(combiner)); + lb_policy_->NotifyOnStateChangeLocked(&state_, &on_changed_); + } + + ~LbConnectivityWatcher() { + GRPC_CHANNEL_STACK_UNREF(owning_stack_, "LbConnectivityWatcher"); + } + + private: + static void OnLbPolicyStateChangedLocked(void* arg, grpc_error* error) { + LbConnectivityWatcher* self = static_cast(arg); + // If the notification is not for the current policy, we're stale, + // so delete ourselves. + if (self->lb_policy_ != self->request_router_->lb_policy_.get()) { + Delete(self); + return; + } + // Otherwise, process notification. + if (self->request_router_->tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: lb_policy=%p state changed to %s", + self->request_router_, self->lb_policy_, + grpc_connectivity_state_name(self->state_)); + } + self->request_router_->SetConnectivityStateLocked( + self->state_, GRPC_ERROR_REF(error), "lb_changed"); + // If shutting down, terminate watch. + if (self->state_ == GRPC_CHANNEL_SHUTDOWN) { + Delete(self); + return; + } + // Renew watch. + self->lb_policy_->NotifyOnStateChangeLocked(&self->state_, + &self->on_changed_); + } + + RequestRouter* request_router_; + grpc_connectivity_state state_; + // LB policy address. No ref held, so not safe to dereference unless + // it happens to match request_router->lb_policy_. + LoadBalancingPolicy* lb_policy_; + grpc_channel_stack* owning_stack_; + grpc_closure on_changed_; +}; + +// +// RequestRounter::ReresolutionRequestHandler +// + +class RequestRouter::ReresolutionRequestHandler { + public: + ReresolutionRequestHandler(RequestRouter* request_router, + LoadBalancingPolicy* lb_policy, + grpc_channel_stack* owning_stack, + grpc_combiner* combiner) + : request_router_(request_router), + lb_policy_(lb_policy), + owning_stack_(owning_stack) { + GRPC_CHANNEL_STACK_REF(owning_stack_, "ReresolutionRequestHandler"); + GRPC_CLOSURE_INIT(&closure_, &OnRequestReresolutionLocked, this, + grpc_combiner_scheduler(combiner)); + lb_policy_->SetReresolutionClosureLocked(&closure_); + } + + private: + static void OnRequestReresolutionLocked(void* arg, grpc_error* error) { + ReresolutionRequestHandler* self = + static_cast(arg); + RequestRouter* request_router = self->request_router_; + // If this invocation is for a stale LB policy, treat it as an LB shutdown + // signal. + if (self->lb_policy_ != request_router->lb_policy_.get() || + error != GRPC_ERROR_NONE || request_router->resolver_ == nullptr) { + GRPC_CHANNEL_STACK_UNREF(request_router->owning_stack_, + "ReresolutionRequestHandler"); + Delete(self); + return; + } + if (request_router->tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: started name re-resolving", + request_router); + } + request_router->resolver_->RequestReresolutionLocked(); + // Give back the closure to the LB policy. + self->lb_policy_->SetReresolutionClosureLocked(&self->closure_); + } + + RequestRouter* request_router_; + // LB policy address. No ref held, so not safe to dereference unless + // it happens to match request_router->lb_policy_. + LoadBalancingPolicy* lb_policy_; + grpc_channel_stack* owning_stack_; + grpc_closure closure_; +}; + +// +// RequestRouter +// + +RequestRouter::RequestRouter( + grpc_channel_stack* owning_stack, grpc_combiner* combiner, + grpc_client_channel_factory* client_channel_factory, + grpc_pollset_set* interested_parties, TraceFlag* tracer, + ProcessResolverResultCallback process_resolver_result, + void* process_resolver_result_user_data, const char* target_uri, + const grpc_channel_args* args, grpc_error** error) + : owning_stack_(owning_stack), + combiner_(combiner), + client_channel_factory_(client_channel_factory), + interested_parties_(interested_parties), + tracer_(tracer), + process_resolver_result_(process_resolver_result), + process_resolver_result_user_data_(process_resolver_result_user_data) { + // Get subchannel pool. + const grpc_arg* arg = + grpc_channel_args_find(args, GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL); + if (grpc_channel_arg_get_bool(arg, false)) { + subchannel_pool_ = MakeRefCounted(); + } else { + subchannel_pool_ = GlobalSubchannelPool::instance(); + } + GRPC_CLOSURE_INIT(&on_resolver_result_changed_, + &RequestRouter::OnResolverResultChangedLocked, this, + grpc_combiner_scheduler(combiner)); + grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, + "request_router"); + grpc_channel_args* new_args = nullptr; + if (process_resolver_result == nullptr) { + grpc_arg arg = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION), 0); + new_args = grpc_channel_args_copy_and_add(args, &arg, 1); + } + resolver_ = ResolverRegistry::CreateResolver( + target_uri, (new_args == nullptr ? args : new_args), interested_parties_, + combiner_); + grpc_channel_args_destroy(new_args); + if (resolver_ == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed"); + } +} + +RequestRouter::~RequestRouter() { + if (resolver_ != nullptr) { + // The only way we can get here is if we never started resolving, + // because we take a ref to the channel stack when we start + // resolving and do not release it until the resolver callback is + // invoked after the resolver shuts down. + resolver_.reset(); + } + if (lb_policy_ != nullptr) { + grpc_pollset_set_del_pollset_set(lb_policy_->interested_parties(), + interested_parties_); + lb_policy_.reset(); + } + if (client_channel_factory_ != nullptr) { + grpc_client_channel_factory_unref(client_channel_factory_); + } + grpc_connectivity_state_destroy(&state_tracker_); +} + +namespace { + +const char* GetChannelConnectivityStateChangeString( + grpc_connectivity_state state) { + switch (state) { + case GRPC_CHANNEL_IDLE: + return "Channel state change to IDLE"; + case GRPC_CHANNEL_CONNECTING: + return "Channel state change to CONNECTING"; + case GRPC_CHANNEL_READY: + return "Channel state change to READY"; + case GRPC_CHANNEL_TRANSIENT_FAILURE: + return "Channel state change to TRANSIENT_FAILURE"; + case GRPC_CHANNEL_SHUTDOWN: + return "Channel state change to SHUTDOWN"; + } + GPR_UNREACHABLE_CODE(return "UNKNOWN"); +} + +} // namespace + +void RequestRouter::SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, + const char* reason) { + if (lb_policy_ != nullptr) { + if (state == GRPC_CHANNEL_TRANSIENT_FAILURE) { + // Cancel picks with wait_for_ready=false. + lb_policy_->CancelMatchingPicksLocked( + /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY, + /* check= */ 0, GRPC_ERROR_REF(error)); + } else if (state == GRPC_CHANNEL_SHUTDOWN) { + // Cancel all picks. + lb_policy_->CancelMatchingPicksLocked(/* mask= */ 0, /* check= */ 0, + GRPC_ERROR_REF(error)); + } + } + if (tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: setting connectivity state to %s", + this, grpc_connectivity_state_name(state)); + } + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + GetChannelConnectivityStateChangeString(state))); + } + grpc_connectivity_state_set(&state_tracker_, state, error, reason); +} + +void RequestRouter::StartResolvingLocked() { + if (tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: starting name resolution", this); + } + GPR_ASSERT(!started_resolving_); + started_resolving_ = true; + GRPC_CHANNEL_STACK_REF(owning_stack_, "resolver"); + resolver_->NextLocked(&resolver_result_, &on_resolver_result_changed_); +} + +// Invoked from the resolver NextLocked() callback when the resolver +// is shutting down. +void RequestRouter::OnResolverShutdownLocked(grpc_error* error) { + if (tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: shutting down", this); + } + if (lb_policy_ != nullptr) { + if (tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: shutting down lb_policy=%p", this, + lb_policy_.get()); + } + grpc_pollset_set_del_pollset_set(lb_policy_->interested_parties(), + interested_parties_); + lb_policy_.reset(); + } + if (resolver_ != nullptr) { + // This should never happen; it can only be triggered by a resolver + // implementation spotaneously deciding to report shutdown without + // being orphaned. This code is included just to be defensive. + if (tracer_->enabled()) { + gpr_log(GPR_INFO, + "request_router=%p: spontaneous shutdown from resolver %p", this, + resolver_.get()); + } + resolver_.reset(); + SetConnectivityStateLocked(GRPC_CHANNEL_SHUTDOWN, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Resolver spontaneous shutdown", &error, 1), + "resolver_spontaneous_shutdown"); + } + grpc_closure_list_fail_all(&waiting_for_resolver_result_closures_, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Channel disconnected", &error, 1)); + GRPC_CLOSURE_LIST_SCHED(&waiting_for_resolver_result_closures_); + GRPC_CHANNEL_STACK_UNREF(owning_stack_, "resolver"); + grpc_channel_args_destroy(resolver_result_); + resolver_result_ = nullptr; + GRPC_ERROR_UNREF(error); +} + +// Creates a new LB policy, replacing any previous one. +// If the new policy is created successfully, sets *connectivity_state and +// *connectivity_error to its initial connectivity state; otherwise, +// leaves them unchanged. +void RequestRouter::CreateNewLbPolicyLocked( + const char* lb_policy_name, grpc_json* lb_config, + grpc_connectivity_state* connectivity_state, + grpc_error** connectivity_error, TraceStringVector* trace_strings) { + LoadBalancingPolicy::Args lb_policy_args; + lb_policy_args.combiner = combiner_; + lb_policy_args.client_channel_factory = client_channel_factory_; + lb_policy_args.subchannel_pool = subchannel_pool_; + lb_policy_args.args = resolver_result_; + lb_policy_args.lb_config = lb_config; + OrphanablePtr new_lb_policy = + LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(lb_policy_name, + lb_policy_args); + if (GPR_UNLIKELY(new_lb_policy == nullptr)) { + gpr_log(GPR_ERROR, "could not create LB policy \"%s\"", lb_policy_name); + if (channelz_node_ != nullptr) { + char* str; + gpr_asprintf(&str, "Could not create LB policy \'%s\'", lb_policy_name); + trace_strings->push_back(str); + } + } else { + if (tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: created new LB policy \"%s\" (%p)", + this, lb_policy_name, new_lb_policy.get()); + } + if (channelz_node_ != nullptr) { + char* str; + gpr_asprintf(&str, "Created new LB policy \'%s\'", lb_policy_name); + trace_strings->push_back(str); + } + // Swap out the LB policy and update the fds in interested_parties_. + if (lb_policy_ != nullptr) { + if (tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: shutting down lb_policy=%p", this, + lb_policy_.get()); + } + grpc_pollset_set_del_pollset_set(lb_policy_->interested_parties(), + interested_parties_); + lb_policy_->HandOffPendingPicksLocked(new_lb_policy.get()); + } + lb_policy_ = std::move(new_lb_policy); + grpc_pollset_set_add_pollset_set(lb_policy_->interested_parties(), + interested_parties_); + // Create re-resolution request handler for the new LB policy. It + // will delete itself when no longer needed. + New(this, lb_policy_.get(), owning_stack_, + combiner_); + // Get the new LB policy's initial connectivity state and start a + // connectivity watch. + GRPC_ERROR_UNREF(*connectivity_error); + *connectivity_state = + lb_policy_->CheckConnectivityLocked(connectivity_error); + if (exit_idle_when_lb_policy_arrives_) { + lb_policy_->ExitIdleLocked(); + exit_idle_when_lb_policy_arrives_ = false; + } + // Create new watcher. It will delete itself when done. + New(this, *connectivity_state, lb_policy_.get(), + owning_stack_, combiner_); + } +} + +void RequestRouter::MaybeAddTraceMessagesForAddressChangesLocked( + TraceStringVector* trace_strings) { + const ServerAddressList* addresses = + FindServerAddressListChannelArg(resolver_result_); + const bool resolution_contains_addresses = + addresses != nullptr && addresses->size() > 0; + if (!resolution_contains_addresses && + previous_resolution_contained_addresses_) { + trace_strings->push_back(gpr_strdup("Address list became empty")); + } else if (resolution_contains_addresses && + !previous_resolution_contained_addresses_) { + trace_strings->push_back(gpr_strdup("Address list became non-empty")); + } + previous_resolution_contained_addresses_ = resolution_contains_addresses; +} + +void RequestRouter::ConcatenateAndAddChannelTraceLocked( + TraceStringVector* trace_strings) const { + if (!trace_strings->empty()) { + gpr_strvec v; + gpr_strvec_init(&v); + gpr_strvec_add(&v, gpr_strdup("Resolution event: ")); + bool is_first = 1; + for (size_t i = 0; i < trace_strings->size(); ++i) { + if (!is_first) gpr_strvec_add(&v, gpr_strdup(", ")); + is_first = false; + gpr_strvec_add(&v, (*trace_strings)[i]); + } + char* flat; + size_t flat_len = 0; + flat = gpr_strvec_flatten(&v, &flat_len); + channelz_node_->AddTraceEvent(channelz::ChannelTrace::Severity::Info, + grpc_slice_new(flat, flat_len, gpr_free)); + gpr_strvec_destroy(&v); + } +} + +// Callback invoked when a resolver result is available. +void RequestRouter::OnResolverResultChangedLocked(void* arg, + grpc_error* error) { + RequestRouter* self = static_cast(arg); + if (self->tracer_->enabled()) { + const char* disposition = + self->resolver_result_ != nullptr + ? "" + : (error == GRPC_ERROR_NONE ? " (transient error)" + : " (resolver shutdown)"); + gpr_log(GPR_INFO, + "request_router=%p: got resolver result: resolver_result=%p " + "error=%s%s", + self, self->resolver_result_, grpc_error_string(error), + disposition); + } + // Handle shutdown. + if (error != GRPC_ERROR_NONE || self->resolver_ == nullptr) { + self->OnResolverShutdownLocked(GRPC_ERROR_REF(error)); + return; + } + // Data used to set the channel's connectivity state. + bool set_connectivity_state = true; + // We only want to trace the address resolution in the follow cases: + // (a) Address resolution resulted in service config change. + // (b) Address resolution that causes number of backends to go from + // zero to non-zero. + // (c) Address resolution that causes number of backends to go from + // non-zero to zero. + // (d) Address resolution that causes a new LB policy to be created. + // + // we track a list of strings to eventually be concatenated and traced. + TraceStringVector trace_strings; + grpc_connectivity_state connectivity_state = GRPC_CHANNEL_TRANSIENT_FAILURE; + grpc_error* connectivity_error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy"); + // resolver_result_ will be null in the case of a transient + // resolution error. In that case, we don't have any new result to + // process, which means that we keep using the previous result (if any). + if (self->resolver_result_ == nullptr) { + if (self->tracer_->enabled()) { + gpr_log(GPR_INFO, "request_router=%p: resolver transient failure", self); + } + // Don't override connectivity state if we already have an LB policy. + if (self->lb_policy_ != nullptr) set_connectivity_state = false; + } else { + // Parse the resolver result. + const char* lb_policy_name = nullptr; + grpc_json* lb_policy_config = nullptr; + const bool service_config_changed = self->process_resolver_result_( + self->process_resolver_result_user_data_, *self->resolver_result_, + &lb_policy_name, &lb_policy_config); + GPR_ASSERT(lb_policy_name != nullptr); + // Check to see if we're already using the right LB policy. + const bool lb_policy_name_changed = + self->lb_policy_ == nullptr || + strcmp(self->lb_policy_->name(), lb_policy_name) != 0; + if (self->lb_policy_ != nullptr && !lb_policy_name_changed) { + // Continue using the same LB policy. Update with new addresses. + if (self->tracer_->enabled()) { + gpr_log(GPR_INFO, + "request_router=%p: updating existing LB policy \"%s\" (%p)", + self, lb_policy_name, self->lb_policy_.get()); + } + self->lb_policy_->UpdateLocked(*self->resolver_result_, lb_policy_config); + // No need to set the channel's connectivity state; the existing + // watch on the LB policy will take care of that. + set_connectivity_state = false; + } else { + // Instantiate new LB policy. + self->CreateNewLbPolicyLocked(lb_policy_name, lb_policy_config, + &connectivity_state, &connectivity_error, + &trace_strings); + } + // Add channel trace event. + if (self->channelz_node_ != nullptr) { + if (service_config_changed) { + // TODO(ncteisen): might be worth somehow including a snippet of the + // config in the trace, at the risk of bloating the trace logs. + trace_strings.push_back(gpr_strdup("Service config changed")); + } + self->MaybeAddTraceMessagesForAddressChangesLocked(&trace_strings); + self->ConcatenateAndAddChannelTraceLocked(&trace_strings); + } + // Clean up. + grpc_channel_args_destroy(self->resolver_result_); + self->resolver_result_ = nullptr; + } + // Set the channel's connectivity state if needed. + if (set_connectivity_state) { + self->SetConnectivityStateLocked(connectivity_state, connectivity_error, + "resolver_result"); + } else { + GRPC_ERROR_UNREF(connectivity_error); + } + // Invoke closures that were waiting for results and renew the watch. + GRPC_CLOSURE_LIST_SCHED(&self->waiting_for_resolver_result_closures_); + self->resolver_->NextLocked(&self->resolver_result_, + &self->on_resolver_result_changed_); +} + +void RequestRouter::RouteCallLocked(Request* request) { + GPR_ASSERT(request->pick_.connected_subchannel == nullptr); + request->request_router_ = this; + if (lb_policy_ != nullptr) { + // We already have resolver results, so process the service config + // and start an LB pick. + request->ProcessServiceConfigAndStartLbPickLocked(); + } else if (resolver_ == nullptr) { + GRPC_CLOSURE_RUN(request->on_route_done_, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); + } else { + // We do not yet have an LB policy, so wait for a resolver result. + if (!started_resolving_) { + StartResolvingLocked(); + } + // Create a new waiter, which will delete itself when done. + New(request); + // Add the request's polling entity to the request_router's + // interested_parties, so that the I/O of the resolver can be done + // under it. It will be removed in LbPickDoneLocked(). + request->MaybeAddCallToInterestedPartiesLocked(); + } +} + +void RequestRouter::ShutdownLocked(grpc_error* error) { + if (resolver_ != nullptr) { + SetConnectivityStateLocked(GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), + "disconnect"); + resolver_.reset(); + if (!started_resolving_) { + grpc_closure_list_fail_all(&waiting_for_resolver_result_closures_, + GRPC_ERROR_REF(error)); + GRPC_CLOSURE_LIST_SCHED(&waiting_for_resolver_result_closures_); + } + if (lb_policy_ != nullptr) { + grpc_pollset_set_del_pollset_set(lb_policy_->interested_parties(), + interested_parties_); + lb_policy_.reset(); + } + } + GRPC_ERROR_UNREF(error); +} + +grpc_connectivity_state RequestRouter::GetConnectivityState() { + return grpc_connectivity_state_check(&state_tracker_); +} + +void RequestRouter::NotifyOnConnectivityStateChange( + grpc_connectivity_state* state, grpc_closure* closure) { + grpc_connectivity_state_notify_on_state_change(&state_tracker_, state, + closure); +} + +void RequestRouter::ExitIdleLocked() { + if (lb_policy_ != nullptr) { + lb_policy_->ExitIdleLocked(); + } else { + exit_idle_when_lb_policy_arrives_ = true; + if (!started_resolving_ && resolver_ != nullptr) { + StartResolvingLocked(); + } + } +} + +void RequestRouter::ResetConnectionBackoffLocked() { + if (resolver_ != nullptr) { + resolver_->ResetBackoffLocked(); + resolver_->RequestReresolutionLocked(); + } + if (lb_policy_ != nullptr) { + lb_policy_->ResetBackoffLocked(); + } +} + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/request_routing.h b/Sources/CgRPC/src/core/ext/filters/client_channel/request_routing.h new file mode 100644 index 000000000..002716386 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/request_routing.h @@ -0,0 +1,181 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_REQUEST_ROUTING_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_REQUEST_ROUTING_H + +#include + +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include "src/core/ext/filters/client_channel/client_channel_factory.h" +#include "src/core/ext/filters/client_channel/lb_policy.h" +#include "src/core/ext/filters/client_channel/resolver.h" +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/orphanable.h" +#include "src/core/lib/iomgr/call_combiner.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/transport/connectivity_state.h" +#include "src/core/lib/transport/metadata_batch.h" + +namespace grpc_core { + +class RequestRouter { + public: + class Request { + public: + // Synchronous callback that applies the service config to a call. + // Returns false if the call should be failed. + typedef bool (*ApplyServiceConfigCallback)(void* user_data); + + Request(grpc_call_stack* owning_call, grpc_call_combiner* call_combiner, + grpc_polling_entity* pollent, + grpc_metadata_batch* send_initial_metadata, + uint32_t* send_initial_metadata_flags, + ApplyServiceConfigCallback apply_service_config, + void* apply_service_config_user_data, grpc_closure* on_route_done); + + ~Request(); + + // TODO(roth): It seems a bit ugly to expose this member in a + // non-const way. Find a better API to avoid this. + LoadBalancingPolicy::PickState* pick() { return &pick_; } + + private: + friend class RequestRouter; + + class ResolverResultWaiter; + class AsyncPickCanceller; + + void ProcessServiceConfigAndStartLbPickLocked(); + void StartLbPickLocked(); + static void LbPickDoneLocked(void* arg, grpc_error* error); + + void MaybeAddCallToInterestedPartiesLocked(); + void MaybeRemoveCallFromInterestedPartiesLocked(); + + // Populated by caller. + grpc_call_stack* owning_call_; + grpc_call_combiner* call_combiner_; + grpc_polling_entity* pollent_; + ApplyServiceConfigCallback apply_service_config_; + void* apply_service_config_user_data_; + grpc_closure* on_route_done_; + LoadBalancingPolicy::PickState pick_; + + // Internal state. + RequestRouter* request_router_ = nullptr; + bool pollent_added_to_interested_parties_ = false; + grpc_closure on_pick_done_; + AsyncPickCanceller* pick_canceller_ = nullptr; + }; + + // Synchronous callback that takes the service config JSON string and + // LB policy name. + // Returns true if the service config has changed since the last result. + typedef bool (*ProcessResolverResultCallback)(void* user_data, + const grpc_channel_args& args, + const char** lb_policy_name, + grpc_json** lb_policy_config); + + RequestRouter(grpc_channel_stack* owning_stack, grpc_combiner* combiner, + grpc_client_channel_factory* client_channel_factory, + grpc_pollset_set* interested_parties, TraceFlag* tracer, + ProcessResolverResultCallback process_resolver_result, + void* process_resolver_result_user_data, const char* target_uri, + const grpc_channel_args* args, grpc_error** error); + + ~RequestRouter(); + + void set_channelz_node(channelz::ClientChannelNode* channelz_node) { + channelz_node_ = channelz_node; + } + + void RouteCallLocked(Request* request); + + // TODO(roth): Add methods to cancel picks. + + void ShutdownLocked(grpc_error* error); + + void ExitIdleLocked(); + void ResetConnectionBackoffLocked(); + + grpc_connectivity_state GetConnectivityState(); + void NotifyOnConnectivityStateChange(grpc_connectivity_state* state, + grpc_closure* closure); + + LoadBalancingPolicy* lb_policy() const { return lb_policy_.get(); } + + private: + using TraceStringVector = InlinedVector; + + class ReresolutionRequestHandler; + class LbConnectivityWatcher; + + void StartResolvingLocked(); + void OnResolverShutdownLocked(grpc_error* error); + void CreateNewLbPolicyLocked(const char* lb_policy_name, grpc_json* lb_config, + grpc_connectivity_state* connectivity_state, + grpc_error** connectivity_error, + TraceStringVector* trace_strings); + void MaybeAddTraceMessagesForAddressChangesLocked( + TraceStringVector* trace_strings); + void ConcatenateAndAddChannelTraceLocked( + TraceStringVector* trace_strings) const; + static void OnResolverResultChangedLocked(void* arg, grpc_error* error); + + void SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, const char* reason); + + // Passed in from caller at construction time. + grpc_channel_stack* owning_stack_; + grpc_combiner* combiner_; + grpc_client_channel_factory* client_channel_factory_; + grpc_pollset_set* interested_parties_; + TraceFlag* tracer_; + + channelz::ClientChannelNode* channelz_node_ = nullptr; + + // Resolver and associated state. + OrphanablePtr resolver_; + ProcessResolverResultCallback process_resolver_result_; + void* process_resolver_result_user_data_; + bool started_resolving_ = false; + grpc_channel_args* resolver_result_ = nullptr; + bool previous_resolution_contained_addresses_ = false; + grpc_closure_list waiting_for_resolver_result_closures_; + grpc_closure on_resolver_result_changed_; + + // LB policy and associated state. + OrphanablePtr lb_policy_; + bool exit_idle_when_lb_policy_arrives_ = false; + + // Subchannel pool to pass to LB policy. + RefCountedPtr subchannel_pool_; + + grpc_connectivity_state_tracker state_tracker_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_REQUEST_ROUTING_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.cc index cd11eeb9e..601b08be2 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.cc @@ -27,7 +27,7 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount(false, namespace grpc_core { Resolver::Resolver(grpc_combiner* combiner) - : InternallyRefCountedWithTracing(&grpc_trace_resolver_refcount), + : InternallyRefCounted(&grpc_trace_resolver_refcount), combiner_(GRPC_COMBINER_REF(combiner, "resolver")) {} Resolver::~Resolver() { GRPC_COMBINER_UNREF(combiner_, "resolver"); } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.h b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.h index 02380314d..9da849a10 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver.h @@ -44,7 +44,7 @@ namespace grpc_core { /// /// Note: All methods with a "Locked" suffix must be called from the /// combiner passed to the constructor. -class Resolver : public InternallyRefCountedWithTracing { +class Resolver : public InternallyRefCounted { public: // Not copyable nor movable. Resolver(const Resolver&) = delete; @@ -81,18 +81,15 @@ class Resolver : public InternallyRefCountedWithTracing { /// /// If this causes new data to become available, then the currently /// pending call to \a NextLocked() will return the new result. - /// - /// Note: Currently, all resolvers are required to return a new result - /// shortly after this method is called. For pull-based mechanisms, if - /// the implementation decides to delay querying the name service, it - /// should immediately return a new copy of the previously returned - /// result (and it can then return the updated data later, when it - /// actually does query the name service). For push-based mechanisms, - /// the implementation should immediately return a new copy of the - /// last-seen result. - /// TODO(roth): Remove this requirement once we fix pick_first to not - /// throw away unselected subchannels. - virtual void RequestReresolutionLocked() GRPC_ABSTRACT; + virtual void RequestReresolutionLocked() {} + + /// Resets the re-resolution backoff, if any. + /// This needs to be implemented only by pull-based implementations; + /// for push-based implementations, it will be a no-op. + /// TODO(roth): Pull the backoff code out of resolver and into + /// client_channel, so that it can be shared across resolver + /// implementations. At that point, this method can go away. + virtual void ResetBackoffLocked() {} void Orphan() override { // Invoke ShutdownAndUnrefLocked() inside of the combiner. @@ -105,9 +102,7 @@ class Resolver : public InternallyRefCountedWithTracing { GRPC_ABSTRACT_BASE_CLASS protected: - // So Delete() can access our protected dtor. - template - friend void Delete(T*); + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE /// Does NOT take ownership of the reference to \a combiner. // TODO(roth): Once we have a C++-like interface for combiners, this diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index c3c62b60b..69d4ee243 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -34,6 +33,7 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" @@ -67,6 +67,8 @@ class AresDnsResolver : public Resolver { void RequestReresolutionLocked() override; + void ResetBackoffLocked() override; + void ShutdownLocked() override; private: @@ -116,9 +118,15 @@ class AresDnsResolver : public Resolver { /// retry backoff state BackOff backoff_; /// currently resolving addresses - grpc_lb_addresses* lb_addresses_ = nullptr; + UniquePtr addresses_; /// currently resolving service config char* service_config_json_ = nullptr; + // has shutdown been initiated + bool shutdown_initiated_ = false; + // timeout in milliseconds for active DNS queries + int query_timeout_ms_; + // whether or not to enable SRV DNS queries + bool enable_srv_queries_; }; AresDnsResolver::AresDnsResolver(const ResolverArgs& args) @@ -140,14 +148,18 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) dns_server_ = gpr_strdup(args.uri->authority); } channel_args_ = grpc_channel_args_copy(args.args); + // Disable service config option const grpc_arg* arg = grpc_channel_args_find( channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION); - request_service_config_ = !grpc_channel_arg_get_integer( - arg, (grpc_integer_options){false, false, true}); + request_service_config_ = !grpc_channel_arg_get_bool(arg, true); + // Min time b/t resolutions option arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS); min_time_between_resolutions_ = grpc_channel_arg_get_integer(arg, {1000, 0, INT_MAX}); + // Enable SRV queries option + arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_ENABLE_SRV_QUERIES); + enable_srv_queries_ = grpc_channel_arg_get_bool(arg, false); interested_parties_ = grpc_pollset_set_create(); if (args.pollset_set != nullptr) { grpc_pollset_set_add_pollset_set(interested_parties_, args.pollset_set); @@ -156,10 +168,15 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) grpc_combiner_scheduler(combiner())); GRPC_CLOSURE_INIT(&on_resolved_, OnResolvedLocked, this, grpc_combiner_scheduler(combiner())); + const grpc_arg* query_timeout_ms_arg = + grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS); + query_timeout_ms_ = grpc_channel_arg_get_integer( + query_timeout_ms_arg, + {GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, 0, INT_MAX}); } AresDnsResolver::~AresDnsResolver() { - gpr_log(GPR_DEBUG, "destroying AresDnsResolver"); + GRPC_CARES_TRACE_LOG("resolver:%p destroying AresDnsResolver", this); if (resolved_result_ != nullptr) { grpc_channel_args_destroy(resolved_result_); } @@ -171,7 +188,8 @@ AresDnsResolver::~AresDnsResolver() { void AresDnsResolver::NextLocked(grpc_channel_args** target_result, grpc_closure* on_complete) { - gpr_log(GPR_DEBUG, "AresDnsResolver::NextLocked() is called."); + GRPC_CARES_TRACE_LOG("resolver:%p AresDnsResolver::NextLocked() is called.", + this); GPR_ASSERT(next_completion_ == nullptr); next_completion_ = on_complete; target_result_ = target_result; @@ -188,12 +206,20 @@ void AresDnsResolver::RequestReresolutionLocked() { } } +void AresDnsResolver::ResetBackoffLocked() { + if (have_next_resolution_timer_) { + grpc_timer_cancel(&next_resolution_timer_); + } + backoff_.Reset(); +} + void AresDnsResolver::ShutdownLocked() { + shutdown_initiated_ = true; if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); } if (pending_request_ != nullptr) { - grpc_cancel_ares_request(pending_request_); + grpc_cancel_ares_request_locked(pending_request_); } if (next_completion_ != nullptr) { *target_result_ = nullptr; @@ -205,9 +231,15 @@ void AresDnsResolver::ShutdownLocked() { void AresDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) { AresDnsResolver* r = static_cast(arg); + GRPC_CARES_TRACE_LOG( + "resolver:%p re-resolution timer fired. error: %s. shutdown_initiated_: " + "%d", + r, grpc_error_string(error), r->shutdown_initiated_); r->have_next_resolution_timer_ = false; - if (error == GRPC_ERROR_NONE) { + if (error == GRPC_ERROR_NONE && !r->shutdown_initiated_) { if (!r->resolving_) { + GRPC_CARES_TRACE_LOG( + "resolver:%p start resolving due to re-resolution timer", r); r->StartResolvingLocked(); } } @@ -290,54 +322,42 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { grpc_channel_args* result = nullptr; GPR_ASSERT(r->resolving_); r->resolving_ = false; + gpr_free(r->pending_request_); r->pending_request_ = nullptr; - if (r->lb_addresses_ != nullptr) { - static const char* args_to_remove[2]; + if (r->addresses_ != nullptr) { + static const char* args_to_remove[1]; size_t num_args_to_remove = 0; - grpc_arg new_args[3]; + grpc_arg args_to_add[2]; size_t num_args_to_add = 0; - new_args[num_args_to_add++] = - grpc_lb_addresses_create_channel_arg(r->lb_addresses_); - grpc_core::UniquePtr service_config; + args_to_add[num_args_to_add++] = + CreateServerAddressListChannelArg(r->addresses_.get()); char* service_config_string = nullptr; if (r->service_config_json_ != nullptr) { service_config_string = ChooseServiceConfig(r->service_config_json_); gpr_free(r->service_config_json_); if (service_config_string != nullptr) { - gpr_log(GPR_INFO, "selected service config choice: %s", - service_config_string); + GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", + r, service_config_string); args_to_remove[num_args_to_remove++] = GRPC_ARG_SERVICE_CONFIG; - new_args[num_args_to_add++] = grpc_channel_arg_string_create( + args_to_add[num_args_to_add++] = grpc_channel_arg_string_create( (char*)GRPC_ARG_SERVICE_CONFIG, service_config_string); - service_config = - grpc_core::ServiceConfig::Create(service_config_string); - if (service_config != nullptr) { - const char* lb_policy_name = - service_config->GetLoadBalancingPolicyName(); - if (lb_policy_name != nullptr) { - args_to_remove[num_args_to_remove++] = GRPC_ARG_LB_POLICY_NAME; - new_args[num_args_to_add++] = grpc_channel_arg_string_create( - (char*)GRPC_ARG_LB_POLICY_NAME, - const_cast(lb_policy_name)); - } - } } } result = grpc_channel_args_copy_and_add_and_remove( - r->channel_args_, args_to_remove, num_args_to_remove, new_args, + r->channel_args_, args_to_remove, num_args_to_remove, args_to_add, num_args_to_add); gpr_free(service_config_string); - grpc_lb_addresses_destroy(r->lb_addresses_); + r->addresses_.reset(); // Reset backoff state so that we start from the beginning when the // next request gets triggered. r->backoff_.Reset(); - } else { + } else if (!r->shutdown_initiated_) { const char* msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg); + GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", r, msg); grpc_millis next_try = r->backoff_.NextAttemptTime(); grpc_millis timeout = next_try - ExecCtx::Get()->Now(); - gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", - grpc_error_string(error)); + GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed (will retry): %s", + r, grpc_error_string(error)); GPR_ASSERT(!r->have_next_resolution_timer_); r->have_next_resolution_timer_ = true; // TODO(roth): We currently deal with this ref manually. Once the @@ -346,9 +366,10 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { RefCountedPtr self = r->Ref(DEBUG_LOCATION, "retry-timer"); self.release(); if (timeout > 0) { - gpr_log(GPR_DEBUG, "retrying in %" PRIdPTR " milliseconds", timeout); + GRPC_CARES_TRACE_LOG("resolver:%p retrying in %" PRId64 " milliseconds", + r, timeout); } else { - gpr_log(GPR_DEBUG, "retrying immediately"); + GRPC_CARES_TRACE_LOG("resolver:%p retrying immediately", r); } grpc_timer_init(&r->next_resolution_timer_, next_try, &r->on_next_resolution_); @@ -365,13 +386,7 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { void AresDnsResolver::MaybeStartResolvingLocked() { // If there is an existing timer, the time it fires is the earliest time we // can start the next resolution. - if (have_next_resolution_timer_) { - // TODO(dgq): remove the following two lines once Pick First stops - // discarding subchannels after selecting. - ++resolved_version_; - MaybeFinishNextLocked(); - return; - } + if (have_next_resolution_timer_) return; if (last_resolution_timestamp_ >= 0) { const grpc_millis earliest_next_resolution = last_resolution_timestamp_ + min_time_between_resolutions_; @@ -380,10 +395,10 @@ void AresDnsResolver::MaybeStartResolvingLocked() { if (ms_until_next_resolution > 0) { const grpc_millis last_resolution_ago = grpc_core::ExecCtx::Get()->Now() - last_resolution_timestamp_; - gpr_log(GPR_DEBUG, - "In cooldown from last resolution (from %" PRIdPTR - " ms ago). Will resolve again in %" PRIdPTR " ms", - last_resolution_ago, ms_until_next_resolution); + GRPC_CARES_TRACE_LOG( + "resolver:%p In cooldown from last resolution (from %" PRId64 + " ms ago). Will resolve again in %" PRId64 " ms", + this, last_resolution_ago, ms_until_next_resolution); have_next_resolution_timer_ = true; // TODO(roth): We currently deal with this ref manually. Once the // new closure API is done, find a way to track this ref with the timer @@ -393,10 +408,6 @@ void AresDnsResolver::MaybeStartResolvingLocked() { self.release(); grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution, &on_next_resolution_); - // TODO(dgq): remove the following two lines once Pick First stops - // discarding subchannels after selecting. - ++resolved_version_; - MaybeFinishNextLocked(); return; } } @@ -404,7 +415,6 @@ void AresDnsResolver::MaybeStartResolvingLocked() { } void AresDnsResolver::StartResolvingLocked() { - gpr_log(GPR_DEBUG, "Start resolving."); // TODO(roth): We currently deal with this ref manually. Once the // new closure API is done, find a way to track this ref with the timer // callback as part of the type system. @@ -412,13 +422,15 @@ void AresDnsResolver::StartResolvingLocked() { self.release(); GPR_ASSERT(!resolving_); resolving_ = true; - lb_addresses_ = nullptr; service_config_json_ = nullptr; - pending_request_ = grpc_dns_lookup_ares( + pending_request_ = grpc_dns_lookup_ares_locked( dns_server_, name_to_resolve_, kDefaultPort, interested_parties_, - &on_resolved_, &lb_addresses_, true /* check_grpclb */, - request_service_config_ ? &service_config_json_ : nullptr); + &on_resolved_, &addresses_, enable_srv_queries_ /* check_grpclb */, + request_service_config_ ? &service_config_json_ : nullptr, + query_timeout_ms_, combiner()); last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now(); + GRPC_CARES_TRACE_LOG("resolver:%p Started resolving. pending_request_:%p", + this, pending_request_); } void AresDnsResolver::MaybeFinishNextLocked() { @@ -426,7 +438,8 @@ void AresDnsResolver::MaybeFinishNextLocked() { *target_result_ = resolved_result_ == nullptr ? nullptr : grpc_channel_args_copy(resolved_result_); - gpr_log(GPR_DEBUG, "AresDnsResolver::MaybeFinishNextLocked()"); + GRPC_CARES_TRACE_LOG("resolver:%p AresDnsResolver::MaybeFinishNextLocked()", + this); GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE); next_completion_ = nullptr; published_version_ = resolved_version_; @@ -464,18 +477,24 @@ static grpc_error* blocking_resolve_address_ares( static grpc_address_resolver_vtable ares_resolver = { grpc_resolve_address_ares, blocking_resolve_address_ares}; +static bool should_use_ares(const char* resolver_env) { + return resolver_env == nullptr || strlen(resolver_env) == 0 || + gpr_stricmp(resolver_env, "ares") == 0; +} + void grpc_resolver_dns_ares_init() { char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER"); - /* TODO(zyc): Turn on c-ares based resolver by default after the address - sorter and the CNAME support are added. */ - if (resolver_env != nullptr && gpr_stricmp(resolver_env, "ares") == 0) { + if (should_use_ares(resolver_env)) { + gpr_log(GPR_DEBUG, "Using ares dns resolver"); address_sorting_init(); grpc_error* error = grpc_ares_init(); if (error != GRPC_ERROR_NONE) { GRPC_LOG_IF_ERROR("ares_library_init() failed", error); return; } - default_resolver = grpc_resolve_address_impl; + if (default_resolver == nullptr) { + default_resolver = grpc_resolve_address_impl; + } grpc_set_resolver_impl(&ares_resolver); grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( grpc_core::UniquePtr( @@ -486,7 +505,7 @@ void grpc_resolver_dns_ares_init() { void grpc_resolver_dns_ares_shutdown() { char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER"); - if (resolver_env != nullptr && gpr_stricmp(resolver_env, "ares") == 0) { + if (should_use_ares(resolver_env)) { address_sorting_shutdown(); grpc_ares_cleanup(); } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc new file mode 100644 index 000000000..d99c2e300 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc @@ -0,0 +1,368 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && !defined(GRPC_UV) + +#include +#include + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" + +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/timer.h" + +typedef struct fd_node { + /** the owner of this fd node */ + grpc_ares_ev_driver* ev_driver; + /** a closure wrapping on_readable_locked, which should be + invoked when the grpc_fd in this node becomes readable. */ + grpc_closure read_closure; + /** a closure wrapping on_writable_locked, which should be + invoked when the grpc_fd in this node becomes writable. */ + grpc_closure write_closure; + /** next fd node in the list */ + struct fd_node* next; + + /** wrapped fd that's polled by grpc's poller for the current platform */ + grpc_core::GrpcPolledFd* grpc_polled_fd; + /** if the readable closure has been registered */ + bool readable_registered; + /** if the writable closure has been registered */ + bool writable_registered; + /** if the fd has been shutdown yet from grpc iomgr perspective */ + bool already_shutdown; +} fd_node; + +struct grpc_ares_ev_driver { + /** the ares_channel owned by this event driver */ + ares_channel channel; + /** pollset set for driving the IO events of the channel */ + grpc_pollset_set* pollset_set; + /** refcount of the event driver */ + gpr_refcount refs; + + /** combiner to synchronize c-ares and I/O callbacks on */ + grpc_combiner* combiner; + /** a list of grpc_fd that this event driver is currently using. */ + fd_node* fds; + /** is this event driver currently working? */ + bool working; + /** is this event driver being shut down */ + bool shutting_down; + /** request object that's using this ev driver */ + grpc_ares_request* request; + /** Owned by the ev_driver. Creates new GrpcPolledFd's */ + grpc_core::UniquePtr polled_fd_factory; + /** query timeout in milliseconds */ + int query_timeout_ms; + /** alarm to cancel active queries */ + grpc_timer query_timeout; + /** cancels queries on a timeout */ + grpc_closure on_timeout_locked; +}; + +static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver); + +static grpc_ares_ev_driver* grpc_ares_ev_driver_ref( + grpc_ares_ev_driver* ev_driver) { + GRPC_CARES_TRACE_LOG("request:%p Ref ev_driver %p", ev_driver->request, + ev_driver); + gpr_ref(&ev_driver->refs); + return ev_driver; +} + +static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) { + GRPC_CARES_TRACE_LOG("request:%p Unref ev_driver %p", ev_driver->request, + ev_driver); + if (gpr_unref(&ev_driver->refs)) { + GRPC_CARES_TRACE_LOG("request:%p destroy ev_driver %p", ev_driver->request, + ev_driver); + GPR_ASSERT(ev_driver->fds == nullptr); + GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver"); + ares_destroy(ev_driver->channel); + grpc_ares_complete_request_locked(ev_driver->request); + grpc_core::Delete(ev_driver); + } +} + +static void fd_node_destroy_locked(fd_node* fdn) { + GRPC_CARES_TRACE_LOG("request:%p delete fd: %s", fdn->ev_driver->request, + fdn->grpc_polled_fd->GetName()); + GPR_ASSERT(!fdn->readable_registered); + GPR_ASSERT(!fdn->writable_registered); + GPR_ASSERT(fdn->already_shutdown); + grpc_core::Delete(fdn->grpc_polled_fd); + gpr_free(fdn); +} + +static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) { + if (!fdn->already_shutdown) { + fdn->already_shutdown = true; + fdn->grpc_polled_fd->ShutdownLocked( + GRPC_ERROR_CREATE_FROM_STATIC_STRING(reason)); + } +} + +static void on_timeout_locked(void* arg, grpc_error* error); + +grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver, + grpc_pollset_set* pollset_set, + int query_timeout_ms, + grpc_combiner* combiner, + grpc_ares_request* request) { + *ev_driver = grpc_core::New(); + ares_options opts; + memset(&opts, 0, sizeof(opts)); + opts.flags |= ARES_FLAG_STAYOPEN; + int status = ares_init_options(&(*ev_driver)->channel, &opts, ARES_OPT_FLAGS); + GRPC_CARES_TRACE_LOG("request:%p grpc_ares_ev_driver_create_locked", request); + if (status != ARES_SUCCESS) { + char* err_msg; + gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", + ares_strerror(status)); + grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg); + gpr_free(err_msg); + gpr_free(*ev_driver); + return err; + } + (*ev_driver)->combiner = GRPC_COMBINER_REF(combiner, "ares event driver"); + gpr_ref_init(&(*ev_driver)->refs, 1); + (*ev_driver)->pollset_set = pollset_set; + (*ev_driver)->fds = nullptr; + (*ev_driver)->working = false; + (*ev_driver)->shutting_down = false; + (*ev_driver)->request = request; + (*ev_driver)->polled_fd_factory = + grpc_core::NewGrpcPolledFdFactory((*ev_driver)->combiner); + (*ev_driver) + ->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel); + GRPC_CLOSURE_INIT(&(*ev_driver)->on_timeout_locked, on_timeout_locked, + *ev_driver, grpc_combiner_scheduler(combiner)); + (*ev_driver)->query_timeout_ms = query_timeout_ms; + return GRPC_ERROR_NONE; +} + +void grpc_ares_ev_driver_on_queries_complete_locked( + grpc_ares_ev_driver* ev_driver) { + // We mark the event driver as being shut down. If the event driver + // is working, grpc_ares_notify_on_event_locked will shut down the + // fds; if it's not working, there are no fds to shut down. + ev_driver->shutting_down = true; + grpc_timer_cancel(&ev_driver->query_timeout); + grpc_ares_ev_driver_unref(ev_driver); +} + +void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) { + ev_driver->shutting_down = true; + fd_node* fn = ev_driver->fds; + while (fn != nullptr) { + fd_node_shutdown_locked(fn, "grpc_ares_ev_driver_shutdown"); + fn = fn->next; + } +} + +// Search fd in the fd_node list head. This is an O(n) search, the max possible +// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests. +static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) { + fd_node dummy_head; + dummy_head.next = *head; + fd_node* node = &dummy_head; + while (node->next != nullptr) { + if (node->next->grpc_polled_fd->GetWrappedAresSocketLocked() == as) { + fd_node* ret = node->next; + node->next = node->next->next; + *head = dummy_head.next; + return ret; + } + node = node->next; + } + return nullptr; +} + +static void on_timeout_locked(void* arg, grpc_error* error) { + grpc_ares_ev_driver* driver = static_cast(arg); + GRPC_CARES_TRACE_LOG( + "request:%p ev_driver=%p on_timeout_locked. driver->shutting_down=%d. " + "err=%s", + driver->request, driver, driver->shutting_down, grpc_error_string(error)); + if (!driver->shutting_down && error == GRPC_ERROR_NONE) { + grpc_ares_ev_driver_shutdown_locked(driver); + } + grpc_ares_ev_driver_unref(driver); +} + +static void on_readable_locked(void* arg, grpc_error* error) { + fd_node* fdn = static_cast(arg); + grpc_ares_ev_driver* ev_driver = fdn->ev_driver; + const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); + fdn->readable_registered = false; + GRPC_CARES_TRACE_LOG("request:%p readable on %s", fdn->ev_driver->request, + fdn->grpc_polled_fd->GetName()); + if (error == GRPC_ERROR_NONE) { + do { + ares_process_fd(ev_driver->channel, as, ARES_SOCKET_BAD); + } while (fdn->grpc_polled_fd->IsFdStillReadableLocked()); + } else { + // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or + // timed out. The pending lookups made on this ev_driver will be cancelled + // by the following ares_cancel() and the on_done callbacks will be invoked + // with a status of ARES_ECANCELLED. The remaining file descriptors in this + // ev_driver will be cleaned up in the follwing + // grpc_ares_notify_on_event_locked(). + ares_cancel(ev_driver->channel); + } + grpc_ares_notify_on_event_locked(ev_driver); + grpc_ares_ev_driver_unref(ev_driver); +} + +static void on_writable_locked(void* arg, grpc_error* error) { + fd_node* fdn = static_cast(arg); + grpc_ares_ev_driver* ev_driver = fdn->ev_driver; + const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); + fdn->writable_registered = false; + GRPC_CARES_TRACE_LOG("request:%p writable on %s", ev_driver->request, + fdn->grpc_polled_fd->GetName()); + if (error == GRPC_ERROR_NONE) { + ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, as); + } else { + // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or + // timed out. The pending lookups made on this ev_driver will be cancelled + // by the following ares_cancel() and the on_done callbacks will be invoked + // with a status of ARES_ECANCELLED. The remaining file descriptors in this + // ev_driver will be cleaned up in the follwing + // grpc_ares_notify_on_event_locked(). + ares_cancel(ev_driver->channel); + } + grpc_ares_notify_on_event_locked(ev_driver); + grpc_ares_ev_driver_unref(ev_driver); +} + +ares_channel* grpc_ares_ev_driver_get_channel_locked( + grpc_ares_ev_driver* ev_driver) { + return &ev_driver->channel; +} + +// Get the file descriptors used by the ev_driver's ares channel, register +// driver_closure with these filedescriptors. +static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) { + fd_node* new_list = nullptr; + if (!ev_driver->shutting_down) { + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; + int socks_bitmask = + ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM); + for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) { + if (ARES_GETSOCK_READABLE(socks_bitmask, i) || + ARES_GETSOCK_WRITABLE(socks_bitmask, i)) { + fd_node* fdn = pop_fd_node_locked(&ev_driver->fds, socks[i]); + // Create a new fd_node if sock[i] is not in the fd_node list. + if (fdn == nullptr) { + fdn = static_cast(gpr_malloc(sizeof(fd_node))); + fdn->grpc_polled_fd = + ev_driver->polled_fd_factory->NewGrpcPolledFdLocked( + socks[i], ev_driver->pollset_set, ev_driver->combiner); + GRPC_CARES_TRACE_LOG("request:%p new fd: %s", ev_driver->request, + fdn->grpc_polled_fd->GetName()); + fdn->ev_driver = ev_driver; + fdn->readable_registered = false; + fdn->writable_registered = false; + fdn->already_shutdown = false; + GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_locked, fdn, + grpc_combiner_scheduler(ev_driver->combiner)); + GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_locked, fdn, + grpc_combiner_scheduler(ev_driver->combiner)); + } + fdn->next = new_list; + new_list = fdn; + // Register read_closure if the socket is readable and read_closure has + // not been registered with this socket. + if (ARES_GETSOCK_READABLE(socks_bitmask, i) && + !fdn->readable_registered) { + grpc_ares_ev_driver_ref(ev_driver); + GRPC_CARES_TRACE_LOG("request:%p notify read on: %s", + ev_driver->request, + fdn->grpc_polled_fd->GetName()); + fdn->grpc_polled_fd->RegisterForOnReadableLocked(&fdn->read_closure); + fdn->readable_registered = true; + } + // Register write_closure if the socket is writable and write_closure + // has not been registered with this socket. + if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) && + !fdn->writable_registered) { + GRPC_CARES_TRACE_LOG("request:%p notify write on: %s", + ev_driver->request, + fdn->grpc_polled_fd->GetName()); + grpc_ares_ev_driver_ref(ev_driver); + fdn->grpc_polled_fd->RegisterForOnWriteableLocked( + &fdn->write_closure); + fdn->writable_registered = true; + } + } + } + } + // Any remaining fds in ev_driver->fds were not returned by ares_getsock() and + // are therefore no longer in use, so they can be shut down and removed from + // the list. + while (ev_driver->fds != nullptr) { + fd_node* cur = ev_driver->fds; + ev_driver->fds = ev_driver->fds->next; + fd_node_shutdown_locked(cur, "c-ares fd shutdown"); + if (!cur->readable_registered && !cur->writable_registered) { + fd_node_destroy_locked(cur); + } else { + cur->next = new_list; + new_list = cur; + } + } + ev_driver->fds = new_list; + // If the ev driver has no working fd, all the tasks are done. + if (new_list == nullptr) { + ev_driver->working = false; + GRPC_CARES_TRACE_LOG("request:%p ev driver stop working", + ev_driver->request); + } +} + +void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { + if (!ev_driver->working) { + ev_driver->working = true; + grpc_ares_notify_on_event_locked(ev_driver); + grpc_millis timeout = + ev_driver->query_timeout_ms == 0 + ? GRPC_MILLIS_INF_FUTURE + : ev_driver->query_timeout_ms + grpc_core::ExecCtx::Get()->Now(); + GRPC_CARES_TRACE_LOG( + "request:%p ev_driver=%p grpc_ares_ev_driver_start_locked. timeout in " + "%" PRId64 " ms", + ev_driver->request, ev_driver, timeout); + grpc_ares_ev_driver_ref(ev_driver); + grpc_timer_init(&ev_driver->query_timeout, timeout, + &ev_driver->on_timeout_locked); + } +} + +#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h index 623954953..b8cefd947 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h @@ -22,6 +22,8 @@ #include #include +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/iomgr/pollset_set.h" typedef struct grpc_ares_ev_driver grpc_ares_ev_driver; @@ -29,25 +31,77 @@ typedef struct grpc_ares_ev_driver grpc_ares_ev_driver; /* Start \a ev_driver. It will keep working until all IO on its ares_channel is done, or grpc_ares_ev_driver_destroy() is called. It may notify the callbacks bound to its ares_channel when necessary. */ -void grpc_ares_ev_driver_start(grpc_ares_ev_driver* ev_driver); +void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver); /* Returns the ares_channel owned by \a ev_driver. To bind a c-ares query to \a ev_driver, use the ares_channel owned by \a ev_driver as the arg of the query. */ -ares_channel* grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver* ev_driver); +ares_channel* grpc_ares_ev_driver_get_channel_locked( + grpc_ares_ev_driver* ev_driver); /* Creates a new grpc_ares_ev_driver. Returns GRPC_ERROR_NONE if \a ev_driver is created successfully. */ -grpc_error* grpc_ares_ev_driver_create(grpc_ares_ev_driver** ev_driver, - grpc_pollset_set* pollset_set); +grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver, + grpc_pollset_set* pollset_set, + int query_timeout_ms, + grpc_combiner* combiner, + grpc_ares_request* request); -/* Destroys \a ev_driver asynchronously. Pending lookups made on \a ev_driver - will be cancelled and their on_done callbacks will be invoked with a status - of ARES_ECANCELLED. */ -void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver* ev_driver); +/* Called back when all DNS lookups have completed. */ +void grpc_ares_ev_driver_on_queries_complete_locked( + grpc_ares_ev_driver* ev_driver); /* Shutdown all the grpc_fds used by \a ev_driver */ -void grpc_ares_ev_driver_shutdown(grpc_ares_ev_driver* ev_driver); +void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver); + +namespace grpc_core { + +/* A wrapped fd that integrates with the grpc iomgr of the current platform. + * A GrpcPolledFd knows how to create grpc platform-specific iomgr endpoints + * from "ares_socket_t" sockets, and then sign up for readability/writeability + * with that poller, and do shutdown and destruction. */ +class GrpcPolledFd { + public: + virtual ~GrpcPolledFd() {} + /* Called when c-ares library is interested and there's no pending callback */ + virtual void RegisterForOnReadableLocked(grpc_closure* read_closure) + GRPC_ABSTRACT; + /* Called when c-ares library is interested and there's no pending callback */ + virtual void RegisterForOnWriteableLocked(grpc_closure* write_closure) + GRPC_ABSTRACT; + /* Indicates if there is data left even after just being read from */ + virtual bool IsFdStillReadableLocked() GRPC_ABSTRACT; + /* Called once and only once. Must cause cancellation of any pending + * read/write callbacks. */ + virtual void ShutdownLocked(grpc_error* error) GRPC_ABSTRACT; + /* Get the underlying ares_socket_t that this was created from */ + virtual ares_socket_t GetWrappedAresSocketLocked() GRPC_ABSTRACT; + /* A unique name, for logging */ + virtual const char* GetName() GRPC_ABSTRACT; + + GRPC_ABSTRACT_BASE_CLASS +}; + +/* A GrpcPolledFdFactory is 1-to-1 with and owned by the + * ares event driver. It knows how to create GrpcPolledFd's + * for the current platform, and the ares driver uses it for all of + * its fd's. */ +class GrpcPolledFdFactory { + public: + virtual ~GrpcPolledFdFactory() {} + /* Creates a new wrapped fd for the current platform */ + virtual GrpcPolledFd* NewGrpcPolledFdLocked( + ares_socket_t as, grpc_pollset_set* driver_pollset_set, + grpc_combiner* combiner) GRPC_ABSTRACT; + /* Optionally configures the ares channel after creation */ + virtual void ConfigureAresChannelLocked(ares_channel channel) GRPC_ABSTRACT; + + GRPC_ABSTRACT_BASE_CLASS +}; + +UniquePtr NewGrpcPolledFdFactory(grpc_combiner* combiner); + +} // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H \ */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc index b604f2bf1..aa58e1aaf 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -18,9 +18,10 @@ #include #include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) +#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) #include +#include #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" @@ -35,317 +36,71 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" -typedef struct fd_node { - /** the owner of this fd node */ - grpc_ares_ev_driver* ev_driver; - /** a closure wrapping on_readable_cb, which should be invoked when the - grpc_fd in this node becomes readable. */ - grpc_closure read_closure; - /** a closure wrapping on_writable_cb, which should be invoked when the - grpc_fd in this node becomes writable. */ - grpc_closure write_closure; - /** next fd node in the list */ - struct fd_node* next; +namespace grpc_core { - /** mutex guarding the rest of the state */ - gpr_mu mu; - /** the grpc_fd owned by this fd node */ - grpc_fd* fd; - /** if the readable closure has been registered */ - bool readable_registered; - /** if the writable closure has been registered */ - bool writable_registered; - /** if the fd is being shut down */ - bool shutting_down; -} fd_node; - -struct grpc_ares_ev_driver { - /** the ares_channel owned by this event driver */ - ares_channel channel; - /** pollset set for driving the IO events of the channel */ - grpc_pollset_set* pollset_set; - /** refcount of the event driver */ - gpr_refcount refs; - - /** mutex guarding the rest of the state */ - gpr_mu mu; - /** a list of grpc_fd that this event driver is currently using. */ - fd_node* fds; - /** is this event driver currently working? */ - bool working; - /** is this event driver being shut down */ - bool shutting_down; -}; - -static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver); - -static grpc_ares_ev_driver* grpc_ares_ev_driver_ref( - grpc_ares_ev_driver* ev_driver) { - gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); - gpr_ref(&ev_driver->refs); - return ev_driver; -} - -static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) { - gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); - if (gpr_unref(&ev_driver->refs)) { - gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver); - GPR_ASSERT(ev_driver->fds == nullptr); - gpr_mu_destroy(&ev_driver->mu); - ares_destroy(ev_driver->channel); - gpr_free(ev_driver); +class GrpcPolledFdPosix : public GrpcPolledFd { + public: + GrpcPolledFdPosix(ares_socket_t as, grpc_pollset_set* driver_pollset_set) + : as_(as) { + gpr_asprintf(&name_, "c-ares fd: %d", (int)as); + fd_ = grpc_fd_create((int)as, name_, false); + driver_pollset_set_ = driver_pollset_set; + grpc_pollset_set_add_fd(driver_pollset_set_, fd_); } -} -static void fd_node_destroy(fd_node* fdn) { - gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->fd)); - GPR_ASSERT(!fdn->readable_registered); - GPR_ASSERT(!fdn->writable_registered); - gpr_mu_destroy(&fdn->mu); - /* c-ares library has closed the fd inside grpc_fd. This fd may be picked up - immediately by another thread, and should not be closed by the following - grpc_fd_orphan. */ - grpc_fd_orphan(fdn->fd, nullptr, nullptr, true /* already_closed */, - "c-ares query finished"); - gpr_free(fdn); -} - -static void fd_node_shutdown(fd_node* fdn) { - gpr_mu_lock(&fdn->mu); - fdn->shutting_down = true; - if (!fdn->readable_registered && !fdn->writable_registered) { - gpr_mu_unlock(&fdn->mu); - fd_node_destroy(fdn); - } else { - grpc_fd_shutdown( - fdn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING("c-ares fd shutdown")); - gpr_mu_unlock(&fdn->mu); + ~GrpcPolledFdPosix() { + gpr_free(name_); + grpc_pollset_set_del_fd(driver_pollset_set_, fd_); + /* c-ares library will close the fd inside grpc_fd. This fd may be picked up + immediately by another thread, and should not be closed by the following + grpc_fd_orphan. */ + int dummy_release_fd; + grpc_fd_orphan(fd_, nullptr, &dummy_release_fd, "c-ares query finished"); } -} -grpc_error* grpc_ares_ev_driver_create(grpc_ares_ev_driver** ev_driver, - grpc_pollset_set* pollset_set) { - *ev_driver = static_cast( - gpr_malloc(sizeof(grpc_ares_ev_driver))); - int status = ares_init(&(*ev_driver)->channel); - gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create"); - if (status != ARES_SUCCESS) { - char* err_msg; - gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", - ares_strerror(status)); - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg); - gpr_free(err_msg); - gpr_free(*ev_driver); - return err; + void RegisterForOnReadableLocked(grpc_closure* read_closure) override { + grpc_fd_notify_on_read(fd_, read_closure); } - gpr_mu_init(&(*ev_driver)->mu); - gpr_ref_init(&(*ev_driver)->refs, 1); - (*ev_driver)->pollset_set = pollset_set; - (*ev_driver)->fds = nullptr; - (*ev_driver)->working = false; - (*ev_driver)->shutting_down = false; - return GRPC_ERROR_NONE; -} -void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver* ev_driver) { - // It's not safe to shut down remaining fds here directly, becauses - // ares_host_callback does not provide an exec_ctx. We mark the event driver - // as being shut down. If the event driver is working, - // grpc_ares_notify_on_event_locked will shut down the fds; if it's not - // working, there are no fds to shut down. - gpr_mu_lock(&ev_driver->mu); - ev_driver->shutting_down = true; - gpr_mu_unlock(&ev_driver->mu); - grpc_ares_ev_driver_unref(ev_driver); -} - -void grpc_ares_ev_driver_shutdown(grpc_ares_ev_driver* ev_driver) { - gpr_mu_lock(&ev_driver->mu); - ev_driver->shutting_down = true; - fd_node* fn = ev_driver->fds; - while (fn != nullptr) { - grpc_fd_shutdown(fn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "grpc_ares_ev_driver_shutdown")); - fn = fn->next; + void RegisterForOnWriteableLocked(grpc_closure* write_closure) override { + grpc_fd_notify_on_write(fd_, write_closure); } - gpr_mu_unlock(&ev_driver->mu); -} -// Search fd in the fd_node list head. This is an O(n) search, the max possible -// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests. -static fd_node* pop_fd_node(fd_node** head, int fd) { - fd_node dummy_head; - dummy_head.next = *head; - fd_node* node = &dummy_head; - while (node->next != nullptr) { - if (grpc_fd_wrapped_fd(node->next->fd) == fd) { - fd_node* ret = node->next; - node->next = node->next->next; - *head = dummy_head.next; - return ret; - } - node = node->next; + bool IsFdStillReadableLocked() override { + size_t bytes_available = 0; + return ioctl(grpc_fd_wrapped_fd(fd_), FIONREAD, &bytes_available) == 0 && + bytes_available > 0; } - return nullptr; -} -/* Check if \a fd is still readable */ -static bool grpc_ares_is_fd_still_readable(grpc_ares_ev_driver* ev_driver, - int fd) { - size_t bytes_available = 0; - return ioctl(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0; -} - -static void on_readable_cb(void* arg, grpc_error* error) { - fd_node* fdn = static_cast(arg); - grpc_ares_ev_driver* ev_driver = fdn->ev_driver; - gpr_mu_lock(&fdn->mu); - const int fd = grpc_fd_wrapped_fd(fdn->fd); - fdn->readable_registered = false; - if (fdn->shutting_down && !fdn->writable_registered) { - gpr_mu_unlock(&fdn->mu); - fd_node_destroy(fdn); - grpc_ares_ev_driver_unref(ev_driver); - return; + void ShutdownLocked(grpc_error* error) override { + grpc_fd_shutdown(fd_, error); } - gpr_mu_unlock(&fdn->mu); - gpr_log(GPR_DEBUG, "readable on %d", fd); - if (error == GRPC_ERROR_NONE) { - do { - ares_process_fd(ev_driver->channel, fd, ARES_SOCKET_BAD); - } while (grpc_ares_is_fd_still_readable(ev_driver, fd)); - } else { - // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or - // timed out. The pending lookups made on this ev_driver will be cancelled - // by the following ares_cancel() and the on_done callbacks will be invoked - // with a status of ARES_ECANCELLED. The remaining file descriptors in this - // ev_driver will be cleaned up in the follwing - // grpc_ares_notify_on_event_locked(). - ares_cancel(ev_driver->channel); - } - gpr_mu_lock(&ev_driver->mu); - grpc_ares_notify_on_event_locked(ev_driver); - gpr_mu_unlock(&ev_driver->mu); - grpc_ares_ev_driver_unref(ev_driver); -} + ares_socket_t GetWrappedAresSocketLocked() override { return as_; } -static void on_writable_cb(void* arg, grpc_error* error) { - fd_node* fdn = static_cast(arg); - grpc_ares_ev_driver* ev_driver = fdn->ev_driver; - gpr_mu_lock(&fdn->mu); - const int fd = grpc_fd_wrapped_fd(fdn->fd); - fdn->writable_registered = false; - if (fdn->shutting_down && !fdn->readable_registered) { - gpr_mu_unlock(&fdn->mu); - fd_node_destroy(fdn); - grpc_ares_ev_driver_unref(ev_driver); - return; - } - gpr_mu_unlock(&fdn->mu); + const char* GetName() override { return name_; } + + char* name_; + ares_socket_t as_; + grpc_fd* fd_; + grpc_pollset_set* driver_pollset_set_; +}; - gpr_log(GPR_DEBUG, "writable on %d", fd); - if (error == GRPC_ERROR_NONE) { - ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, fd); - } else { - // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or - // timed out. The pending lookups made on this ev_driver will be cancelled - // by the following ares_cancel() and the on_done callbacks will be invoked - // with a status of ARES_ECANCELLED. The remaining file descriptors in this - // ev_driver will be cleaned up in the follwing - // grpc_ares_notify_on_event_locked(). - ares_cancel(ev_driver->channel); +class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory { + public: + GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as, + grpc_pollset_set* driver_pollset_set, + grpc_combiner* combiner) override { + return New(as, driver_pollset_set); } - gpr_mu_lock(&ev_driver->mu); - grpc_ares_notify_on_event_locked(ev_driver); - gpr_mu_unlock(&ev_driver->mu); - grpc_ares_ev_driver_unref(ev_driver); -} -ares_channel* grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver* ev_driver) { - return &ev_driver->channel; -} + void ConfigureAresChannelLocked(ares_channel channel) override {} +}; -// Get the file descriptors used by the ev_driver's ares channel, register -// driver_closure with these filedescriptors. -static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) { - fd_node* new_list = nullptr; - if (!ev_driver->shutting_down) { - ares_socket_t socks[ARES_GETSOCK_MAXNUM]; - int socks_bitmask = - ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM); - for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) { - if (ARES_GETSOCK_READABLE(socks_bitmask, i) || - ARES_GETSOCK_WRITABLE(socks_bitmask, i)) { - fd_node* fdn = pop_fd_node(&ev_driver->fds, socks[i]); - // Create a new fd_node if sock[i] is not in the fd_node list. - if (fdn == nullptr) { - char* fd_name; - gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i); - fdn = static_cast(gpr_malloc(sizeof(fd_node))); - gpr_log(GPR_DEBUG, "new fd: %d", socks[i]); - fdn->fd = grpc_fd_create(socks[i], fd_name); - fdn->ev_driver = ev_driver; - fdn->readable_registered = false; - fdn->writable_registered = false; - fdn->shutting_down = false; - gpr_mu_init(&fdn->mu); - GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_cb, fdn, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_cb, fdn, - grpc_schedule_on_exec_ctx); - grpc_pollset_set_add_fd(ev_driver->pollset_set, fdn->fd); - gpr_free(fd_name); - } - fdn->next = new_list; - new_list = fdn; - gpr_mu_lock(&fdn->mu); - // Register read_closure if the socket is readable and read_closure has - // not been registered with this socket. - if (ARES_GETSOCK_READABLE(socks_bitmask, i) && - !fdn->readable_registered) { - grpc_ares_ev_driver_ref(ev_driver); - gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->fd)); - grpc_fd_notify_on_read(fdn->fd, &fdn->read_closure); - fdn->readable_registered = true; - } - // Register write_closure if the socket is writable and write_closure - // has not been registered with this socket. - if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) && - !fdn->writable_registered) { - gpr_log(GPR_DEBUG, "notify write on: %d", - grpc_fd_wrapped_fd(fdn->fd)); - grpc_ares_ev_driver_ref(ev_driver); - grpc_fd_notify_on_write(fdn->fd, &fdn->write_closure); - fdn->writable_registered = true; - } - gpr_mu_unlock(&fdn->mu); - } - } - } - // Any remaining fds in ev_driver->fds were not returned by ares_getsock() and - // are therefore no longer in use, so they can be shut down and removed from - // the list. - while (ev_driver->fds != nullptr) { - fd_node* cur = ev_driver->fds; - ev_driver->fds = ev_driver->fds->next; - fd_node_shutdown(cur); - } - ev_driver->fds = new_list; - // If the ev driver has no working fd, all the tasks are done. - if (new_list == nullptr) { - ev_driver->working = false; - gpr_log(GPR_DEBUG, "ev driver stop working"); - } +UniquePtr NewGrpcPolledFdFactory(grpc_combiner* combiner) { + return UniquePtr(New()); } -void grpc_ares_ev_driver_start(grpc_ares_ev_driver* ev_driver) { - gpr_mu_lock(&ev_driver->mu); - if (!ev_driver->working) { - ev_driver->working = true; - grpc_ares_notify_on_event_locked(ev_driver); - } - gpr_mu_unlock(&ev_driver->mu); -} +} // namespace grpc_core -#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) */ +#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc new file mode 100644 index 000000000..9570e32c1 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc @@ -0,0 +1,540 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GPR_WINDOWS) + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/socket_windows.h" +#include "src/core/lib/iomgr/tcp_windows.h" +#include "src/core/lib/slice/slice_internal.h" + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" + +/* TODO(apolcyn): remove this hack after fixing upstream. + * Our grpc/c-ares code on Windows uses the ares_set_socket_functions API, + * which uses "struct iovec" type, which on Windows is defined inside of + * a c-ares header that is not public. + * See https://github.com/c-ares/c-ares/issues/206. */ +struct iovec { + void* iov_base; + size_t iov_len; +}; + +namespace grpc_core { + +/* c-ares creates its own sockets and is meant to read them when readable and + * write them when writeable. To fit this socket usage model into the grpc + * windows poller (which gives notifications when attempted reads and writes are + * actually fulfilled rather than possible), this GrpcPolledFdWindows class + * takes advantage of the ares_set_socket_functions API and acts as a virtual + * socket. It holds its own read and write buffers which are written to and read + * from c-ares and are used with the grpc windows poller, and it, e.g., + * manufactures virtual socket error codes when it e.g. needs to tell the c-ares + * library to wait for an async read. */ +class GrpcPolledFdWindows : public GrpcPolledFd { + public: + enum WriteState { + WRITE_IDLE, + WRITE_REQUESTED, + WRITE_PENDING, + WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY, + }; + + GrpcPolledFdWindows(ares_socket_t as, grpc_combiner* combiner) + : read_buf_(grpc_empty_slice()), + write_buf_(grpc_empty_slice()), + write_state_(WRITE_IDLE), + gotten_into_driver_list_(false) { + gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, as); + winsocket_ = grpc_winsocket_create(as, name_); + combiner_ = GRPC_COMBINER_REF(combiner, name_); + GRPC_CLOSURE_INIT(&outer_read_closure_, + &GrpcPolledFdWindows::OnIocpReadable, this, + grpc_combiner_scheduler(combiner_)); + GRPC_CLOSURE_INIT(&outer_write_closure_, + &GrpcPolledFdWindows::OnIocpWriteable, this, + grpc_combiner_scheduler(combiner_)); + } + + ~GrpcPolledFdWindows() { + GRPC_COMBINER_UNREF(combiner_, name_); + grpc_slice_unref_internal(read_buf_); + grpc_slice_unref_internal(write_buf_); + GPR_ASSERT(read_closure_ == nullptr); + GPR_ASSERT(write_closure_ == nullptr); + grpc_winsocket_destroy(winsocket_); + gpr_free(name_); + } + + void ScheduleAndNullReadClosure(grpc_error* error) { + GRPC_CLOSURE_SCHED(read_closure_, error); + read_closure_ = nullptr; + } + + void ScheduleAndNullWriteClosure(grpc_error* error) { + GRPC_CLOSURE_SCHED(write_closure_, error); + write_closure_ = nullptr; + } + + void RegisterForOnReadableLocked(grpc_closure* read_closure) override { + GPR_ASSERT(read_closure_ == nullptr); + read_closure_ = read_closure; + GPR_ASSERT(GRPC_SLICE_LENGTH(read_buf_) == 0); + grpc_slice_unref_internal(read_buf_); + read_buf_ = GRPC_SLICE_MALLOC(4192); + WSABUF buffer; + buffer.buf = (char*)GRPC_SLICE_START_PTR(read_buf_); + buffer.len = GRPC_SLICE_LENGTH(read_buf_); + memset(&winsocket_->read_info.overlapped, 0, sizeof(OVERLAPPED)); + recv_from_source_addr_len_ = sizeof(recv_from_source_addr_); + DWORD flags = 0; + if (WSARecvFrom(grpc_winsocket_wrapped_socket(winsocket_), &buffer, 1, + nullptr, &flags, (sockaddr*)recv_from_source_addr_, + &recv_from_source_addr_len_, + &winsocket_->read_info.overlapped, nullptr)) { + int wsa_last_error = WSAGetLastError(); + char* msg = gpr_format_message(wsa_last_error); + grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + GRPC_CARES_TRACE_LOG( + "RegisterForOnReadableLocked: WSARecvFrom error:|%s|. fd:|%s|", msg, + GetName()); + gpr_free(msg); + if (wsa_last_error != WSA_IO_PENDING) { + ScheduleAndNullReadClosure(error); + return; + } + } + grpc_socket_notify_on_read(winsocket_, &outer_read_closure_); + } + + void RegisterForOnWriteableLocked(grpc_closure* write_closure) override { + GRPC_CARES_TRACE_LOG( + "RegisterForOnWriteableLocked. fd:|%s|. Current write state: %d", + GetName(), write_state_); + GPR_ASSERT(write_closure_ == nullptr); + write_closure_ = write_closure; + switch (write_state_) { + case WRITE_IDLE: + ScheduleAndNullWriteClosure(GRPC_ERROR_NONE); + break; + case WRITE_REQUESTED: + write_state_ = WRITE_PENDING; + SendWriteBuf(nullptr, &winsocket_->write_info.overlapped); + grpc_socket_notify_on_write(winsocket_, &outer_write_closure_); + break; + case WRITE_PENDING: + case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY: + abort(); + } + } + + bool IsFdStillReadableLocked() override { + return GRPC_SLICE_LENGTH(read_buf_) > 0; + } + + void ShutdownLocked(grpc_error* error) override { + grpc_winsocket_shutdown(winsocket_); + } + + ares_socket_t GetWrappedAresSocketLocked() override { + return grpc_winsocket_wrapped_socket(winsocket_); + } + + const char* GetName() override { return name_; } + + ares_ssize_t RecvFrom(void* data, ares_socket_t data_len, int flags, + struct sockaddr* from, ares_socklen_t* from_len) { + GRPC_CARES_TRACE_LOG( + "RecvFrom called on fd:|%s|. Current read buf length:|%d|", GetName(), + GRPC_SLICE_LENGTH(read_buf_)); + if (GRPC_SLICE_LENGTH(read_buf_) == 0) { + WSASetLastError(WSAEWOULDBLOCK); + return -1; + } + ares_ssize_t bytes_read = 0; + for (size_t i = 0; i < GRPC_SLICE_LENGTH(read_buf_) && i < data_len; i++) { + ((char*)data)[i] = GRPC_SLICE_START_PTR(read_buf_)[i]; + bytes_read++; + } + read_buf_ = grpc_slice_sub_no_ref(read_buf_, bytes_read, + GRPC_SLICE_LENGTH(read_buf_)); + /* c-ares overloads this recv_from virtual socket function to receive + * data on both UDP and TCP sockets, and from is nullptr for TCP. */ + if (from != nullptr) { + GPR_ASSERT(*from_len <= recv_from_source_addr_len_); + memcpy(from, &recv_from_source_addr_, recv_from_source_addr_len_); + *from_len = recv_from_source_addr_len_; + } + return bytes_read; + } + + grpc_slice FlattenIovec(const struct iovec* iov, int iov_count) { + int total = 0; + for (int i = 0; i < iov_count; i++) { + total += iov[i].iov_len; + } + grpc_slice out = GRPC_SLICE_MALLOC(total); + size_t cur = 0; + for (int i = 0; i < iov_count; i++) { + for (int k = 0; k < iov[i].iov_len; k++) { + GRPC_SLICE_START_PTR(out)[cur++] = ((char*)iov[i].iov_base)[k]; + } + } + return out; + } + + int SendWriteBuf(LPDWORD bytes_sent_ptr, LPWSAOVERLAPPED overlapped) { + WSABUF buf; + buf.len = GRPC_SLICE_LENGTH(write_buf_); + buf.buf = (char*)GRPC_SLICE_START_PTR(write_buf_); + DWORD flags = 0; + int out = WSASend(grpc_winsocket_wrapped_socket(winsocket_), &buf, 1, + bytes_sent_ptr, flags, overlapped, nullptr); + GRPC_CARES_TRACE_LOG( + "WSASend: name:%s. buf len:%d. bytes sent: %d. overlapped %p. return " + "val: %d", + GetName(), buf.len, *bytes_sent_ptr, overlapped, out); + return out; + } + + ares_ssize_t TrySendWriteBufSyncNonBlocking() { + GPR_ASSERT(write_state_ == WRITE_IDLE); + ares_ssize_t total_sent; + DWORD bytes_sent = 0; + if (SendWriteBuf(&bytes_sent, nullptr) != 0) { + int wsa_last_error = WSAGetLastError(); + char* msg = gpr_format_message(wsa_last_error); + GRPC_CARES_TRACE_LOG( + "TrySendWriteBufSyncNonBlocking: SendWriteBuf error:|%s|. fd:|%s|", + msg, GetName()); + gpr_free(msg); + if (wsa_last_error == WSA_IO_PENDING) { + WSASetLastError(WSAEWOULDBLOCK); + write_state_ = WRITE_REQUESTED; + } + } + write_buf_ = grpc_slice_sub_no_ref(write_buf_, bytes_sent, + GRPC_SLICE_LENGTH(write_buf_)); + return bytes_sent; + } + + ares_ssize_t SendV(const struct iovec* iov, int iov_count) { + GRPC_CARES_TRACE_LOG("SendV called on fd:|%s|. Current write state: %d", + GetName(), write_state_); + switch (write_state_) { + case WRITE_IDLE: + GPR_ASSERT(GRPC_SLICE_LENGTH(write_buf_) == 0); + grpc_slice_unref_internal(write_buf_); + write_buf_ = FlattenIovec(iov, iov_count); + return TrySendWriteBufSyncNonBlocking(); + case WRITE_REQUESTED: + case WRITE_PENDING: + WSASetLastError(WSAEWOULDBLOCK); + return -1; + case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY: + grpc_slice currently_attempted = FlattenIovec(iov, iov_count); + GPR_ASSERT(GRPC_SLICE_LENGTH(currently_attempted) >= + GRPC_SLICE_LENGTH(write_buf_)); + ares_ssize_t total_sent = 0; + for (size_t i = 0; i < GRPC_SLICE_LENGTH(write_buf_); i++) { + GPR_ASSERT(GRPC_SLICE_START_PTR(currently_attempted)[i] == + GRPC_SLICE_START_PTR(write_buf_)[i]); + total_sent++; + } + grpc_slice_unref_internal(write_buf_); + write_buf_ = + grpc_slice_sub_no_ref(currently_attempted, total_sent, + GRPC_SLICE_LENGTH(currently_attempted)); + write_state_ = WRITE_IDLE; + total_sent += TrySendWriteBufSyncNonBlocking(); + return total_sent; + } + abort(); + } + + int Connect(const struct sockaddr* target, ares_socklen_t target_len) { + SOCKET s = grpc_winsocket_wrapped_socket(winsocket_); + GRPC_CARES_TRACE_LOG("Connect: fd:|%s|", GetName()); + int out = + WSAConnect(s, target, target_len, nullptr, nullptr, nullptr, nullptr); + if (out != 0) { + int wsa_last_error = WSAGetLastError(); + char* msg = gpr_format_message(wsa_last_error); + GRPC_CARES_TRACE_LOG("Connect error code:|%d|, msg:|%s|. fd:|%s|", + wsa_last_error, msg, GetName()); + gpr_free(msg); + // c-ares expects a posix-style connect API + out = -1; + } + return out; + } + + static void OnIocpReadable(void* arg, grpc_error* error) { + GrpcPolledFdWindows* polled_fd = static_cast(arg); + polled_fd->OnIocpReadableInner(error); + } + + void OnIocpReadableInner(grpc_error* error) { + if (error == GRPC_ERROR_NONE) { + if (winsocket_->read_info.wsa_error != 0) { + /* WSAEMSGSIZE would be due to receiving more data + * than our read buffer's fixed capacity. Assume that + * the connection is TCP and read the leftovers + * in subsequent c-ares reads. */ + if (winsocket_->read_info.wsa_error != WSAEMSGSIZE) { + GRPC_ERROR_UNREF(error); + char* msg = gpr_format_message(winsocket_->read_info.wsa_error); + GRPC_CARES_TRACE_LOG( + "OnIocpReadableInner. winsocket error:|%s|. fd:|%s|", msg, + GetName()); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + } + } + } + if (error == GRPC_ERROR_NONE) { + read_buf_ = grpc_slice_sub_no_ref(read_buf_, 0, + winsocket_->read_info.bytes_transfered); + } else { + grpc_slice_unref_internal(read_buf_); + read_buf_ = grpc_empty_slice(); + } + GRPC_CARES_TRACE_LOG( + "OnIocpReadable finishing. read buf length now:|%d|. :fd:|%s|", + GRPC_SLICE_LENGTH(read_buf_), GetName()); + ScheduleAndNullReadClosure(error); + } + + static void OnIocpWriteable(void* arg, grpc_error* error) { + GrpcPolledFdWindows* polled_fd = static_cast(arg); + polled_fd->OnIocpWriteableInner(error); + } + + void OnIocpWriteableInner(grpc_error* error) { + GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName()); + if (error == GRPC_ERROR_NONE) { + if (winsocket_->write_info.wsa_error != 0) { + char* msg = gpr_format_message(winsocket_->write_info.wsa_error); + GRPC_CARES_TRACE_LOG( + "OnIocpWriteableInner. winsocket error:|%s|. fd:|%s|", msg, + GetName()); + GRPC_ERROR_UNREF(error); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + } + } + GPR_ASSERT(write_state_ == WRITE_PENDING); + if (error == GRPC_ERROR_NONE) { + write_state_ = WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY; + write_buf_ = grpc_slice_sub_no_ref( + write_buf_, 0, winsocket_->write_info.bytes_transfered); + } else { + grpc_slice_unref_internal(write_buf_); + write_buf_ = grpc_empty_slice(); + } + ScheduleAndNullWriteClosure(error); + } + + bool gotten_into_driver_list() const { return gotten_into_driver_list_; } + void set_gotten_into_driver_list() { gotten_into_driver_list_ = true; } + + grpc_combiner* combiner_; + char recv_from_source_addr_[200]; + ares_socklen_t recv_from_source_addr_len_; + grpc_slice read_buf_; + grpc_slice write_buf_; + grpc_closure* read_closure_ = nullptr; + grpc_closure* write_closure_ = nullptr; + grpc_closure outer_read_closure_; + grpc_closure outer_write_closure_; + grpc_winsocket* winsocket_; + WriteState write_state_; + char* name_ = nullptr; + bool gotten_into_driver_list_; +}; + +struct SockToPolledFdEntry { + SockToPolledFdEntry(SOCKET s, GrpcPolledFdWindows* fd) + : socket(s), polled_fd(fd) {} + SOCKET socket; + GrpcPolledFdWindows* polled_fd; + SockToPolledFdEntry* next = nullptr; +}; + +/* A SockToPolledFdMap can make ares_socket_t types (SOCKET's on windows) + * to GrpcPolledFdWindow's, and is used to find the appropriate + * GrpcPolledFdWindows to handle a virtual socket call when c-ares makes that + * socket call on the ares_socket_t type. Instances are owned by and one-to-one + * with a GrpcPolledFdWindows factory and event driver */ +class SockToPolledFdMap { + public: + SockToPolledFdMap(grpc_combiner* combiner) { + combiner_ = GRPC_COMBINER_REF(combiner, "sock to polled fd map"); + } + + ~SockToPolledFdMap() { + GPR_ASSERT(head_ == nullptr); + GRPC_COMBINER_UNREF(combiner_, "sock to polled fd map"); + } + + void AddNewSocket(SOCKET s, GrpcPolledFdWindows* polled_fd) { + SockToPolledFdEntry* new_node = New(s, polled_fd); + new_node->next = head_; + head_ = new_node; + } + + GrpcPolledFdWindows* LookupPolledFd(SOCKET s) { + for (SockToPolledFdEntry* node = head_; node != nullptr; + node = node->next) { + if (node->socket == s) { + GPR_ASSERT(node->polled_fd != nullptr); + return node->polled_fd; + } + } + abort(); + } + + void RemoveEntry(SOCKET s) { + GPR_ASSERT(head_ != nullptr); + SockToPolledFdEntry** prev = &head_; + for (SockToPolledFdEntry* node = head_; node != nullptr; + node = node->next) { + if (node->socket == s) { + *prev = node->next; + Delete(node); + return; + } + prev = &node->next; + } + abort(); + } + + /* These virtual socket functions are called from within the c-ares + * library. These methods generally dispatch those socket calls to the + * appropriate methods. The virtual "socket" and "close" methods are + * special and instead create/add and remove/destroy GrpcPolledFdWindows + * objects. + */ + static ares_socket_t Socket(int af, int type, int protocol, void* user_data) { + SockToPolledFdMap* map = static_cast(user_data); + SOCKET s = WSASocket(af, type, protocol, nullptr, 0, WSA_FLAG_OVERLAPPED); + if (s == INVALID_SOCKET) { + return s; + } + grpc_tcp_set_non_block(s); + GrpcPolledFdWindows* polled_fd = + New(s, map->combiner_); + map->AddNewSocket(s, polled_fd); + return s; + } + + static int Connect(ares_socket_t as, const struct sockaddr* target, + ares_socklen_t target_len, void* user_data) { + SockToPolledFdMap* map = static_cast(user_data); + GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as); + return polled_fd->Connect(target, target_len); + } + + static ares_ssize_t SendV(ares_socket_t as, const struct iovec* iov, + int iovec_count, void* user_data) { + SockToPolledFdMap* map = static_cast(user_data); + GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as); + return polled_fd->SendV(iov, iovec_count); + } + + static ares_ssize_t RecvFrom(ares_socket_t as, void* data, size_t data_len, + int flags, struct sockaddr* from, + ares_socklen_t* from_len, void* user_data) { + SockToPolledFdMap* map = static_cast(user_data); + GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as); + return polled_fd->RecvFrom(data, data_len, flags, from, from_len); + } + + static int CloseSocket(SOCKET s, void* user_data) { + SockToPolledFdMap* map = static_cast(user_data); + GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(s); + map->RemoveEntry(s); + // If a gRPC polled fd has not made it in to the driver's list yet, then + // the driver has not and will never see this socket. + if (!polled_fd->gotten_into_driver_list()) { + polled_fd->ShutdownLocked(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Shut down c-ares fd before without it ever having made it into the " + "driver's list")); + return 0; + } + return 0; + } + + private: + SockToPolledFdEntry* head_ = nullptr; + grpc_combiner* combiner_; +}; + +const struct ares_socket_functions custom_ares_sock_funcs = { + &SockToPolledFdMap::Socket /* socket */, + &SockToPolledFdMap::CloseSocket /* close */, + &SockToPolledFdMap::Connect /* connect */, + &SockToPolledFdMap::RecvFrom /* recvfrom */, + &SockToPolledFdMap::SendV /* sendv */, +}; + +class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory { + public: + GrpcPolledFdFactoryWindows(grpc_combiner* combiner) + : sock_to_polled_fd_map_(combiner) {} + + GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as, + grpc_pollset_set* driver_pollset_set, + grpc_combiner* combiner) override { + GrpcPolledFdWindows* polled_fd = sock_to_polled_fd_map_.LookupPolledFd(as); + // Set a flag so that the virtual socket "close" method knows it + // doesn't need to call ShutdownLocked, since now the driver will. + polled_fd->set_gotten_into_driver_list(); + return polled_fd; + } + + void ConfigureAresChannelLocked(ares_channel channel) override { + ares_set_socket_functions(channel, &custom_ares_sock_funcs, + &sock_to_polled_fd_map_); + } + + private: + SockToPolledFdMap sock_to_polled_fd_map_; +}; + +UniquePtr NewGrpcPolledFdFactory(grpc_combiner* combiner) { + return UniquePtr( + New(combiner)); +} + +} // namespace grpc_core + +#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index e86ab5a37..d41c8238f 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -22,7 +22,6 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" #include #include @@ -38,18 +37,24 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/nameser.h" #include "src/core/lib/iomgr/sockaddr_utils.h" +using grpc_core::ServerAddress; +using grpc_core::ServerAddressList; + static gpr_once g_basic_init = GPR_ONCE_INIT; static gpr_mu g_init_mu; grpc_core::TraceFlag grpc_trace_cares_address_sorting(false, "cares_address_sorting"); +grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver"); + struct grpc_ares_request { /** indicates the DNS server to use, if specified */ struct ares_addr_port_node dns_server_addr; @@ -57,16 +62,14 @@ struct grpc_ares_request { /** closure to call when the request completes */ grpc_closure* on_done; /** the pointer to receive the resolved addresses */ - grpc_lb_addresses** lb_addrs_out; + grpc_core::UniquePtr* addresses_out; /** the pointer to receive the service config in JSON */ char** service_config_json_out; /** the evernt driver used by this request */ grpc_ares_ev_driver* ev_driver; /** number of ongoing queries */ - gpr_refcount pending_queries; + size_t pending_queries; - /** mutex guarding the rest of the state */ - gpr_mu mu; /** is there at least one successful query, set in on_done_cb */ bool success; /** the errors explaining the request failure, set in on_done_cb */ @@ -74,7 +77,8 @@ struct grpc_ares_request { }; typedef struct grpc_ares_hostbyname_request { - /** following members are set in create_hostbyname_request */ + /** following members are set in create_hostbyname_request_locked + */ /** the top-level request instance */ grpc_ares_request* parent_request; /** host to resolve, parsed from the name to resolve */ @@ -87,84 +91,70 @@ typedef struct grpc_ares_hostbyname_request { static void do_basic_init(void) { gpr_mu_init(&g_init_mu); } -static uint16_t strhtons(const char* port) { - if (strcmp(port, "http") == 0) { - return htons(80); - } else if (strcmp(port, "https") == 0) { - return htons(443); - } - return htons(static_cast(atoi(port))); -} - -static void grpc_ares_request_ref(grpc_ares_request* r) { - gpr_ref(&r->pending_queries); -} - -static void log_address_sorting_list(grpc_lb_addresses* lb_addrs, +static void log_address_sorting_list(const ServerAddressList& addresses, const char* input_output_str) { - for (size_t i = 0; i < lb_addrs->num_addresses; i++) { + for (size_t i = 0; i < addresses.size(); i++) { char* addr_str; - if (grpc_sockaddr_to_string(&addr_str, &lb_addrs->addresses[i].address, - true)) { - gpr_log(GPR_DEBUG, "c-ares address sorting: %s[%" PRIuPTR "]=%s", + if (grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true)) { + gpr_log(GPR_INFO, "c-ares address sorting: %s[%" PRIuPTR "]=%s", input_output_str, i, addr_str); gpr_free(addr_str); } else { - gpr_log(GPR_DEBUG, + gpr_log(GPR_INFO, "c-ares address sorting: %s[%" PRIuPTR "]=", input_output_str, i); } } } -void grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses* lb_addrs) { +void grpc_cares_wrapper_address_sorting_sort(ServerAddressList* addresses) { if (grpc_trace_cares_address_sorting.enabled()) { - log_address_sorting_list(lb_addrs, "input"); + log_address_sorting_list(*addresses, "input"); } address_sorting_sortable* sortables = (address_sorting_sortable*)gpr_zalloc( - sizeof(address_sorting_sortable) * lb_addrs->num_addresses); - for (size_t i = 0; i < lb_addrs->num_addresses; i++) { - sortables[i].user_data = &lb_addrs->addresses[i]; - memcpy(&sortables[i].dest_addr.addr, &lb_addrs->addresses[i].address.addr, - lb_addrs->addresses[i].address.len); - sortables[i].dest_addr.len = lb_addrs->addresses[i].address.len; + sizeof(address_sorting_sortable) * addresses->size()); + for (size_t i = 0; i < addresses->size(); ++i) { + sortables[i].user_data = &(*addresses)[i]; + memcpy(&sortables[i].dest_addr.addr, &(*addresses)[i].address().addr, + (*addresses)[i].address().len); + sortables[i].dest_addr.len = (*addresses)[i].address().len; } - address_sorting_rfc_6724_sort(sortables, lb_addrs->num_addresses); - grpc_lb_address* sorted_lb_addrs = (grpc_lb_address*)gpr_zalloc( - sizeof(grpc_lb_address) * lb_addrs->num_addresses); - for (size_t i = 0; i < lb_addrs->num_addresses; i++) { - sorted_lb_addrs[i] = *(grpc_lb_address*)sortables[i].user_data; + address_sorting_rfc_6724_sort(sortables, addresses->size()); + ServerAddressList sorted; + sorted.reserve(addresses->size()); + for (size_t i = 0; i < addresses->size(); ++i) { + sorted.emplace_back(*static_cast(sortables[i].user_data)); } gpr_free(sortables); - gpr_free(lb_addrs->addresses); - lb_addrs->addresses = sorted_lb_addrs; + *addresses = std::move(sorted); if (grpc_trace_cares_address_sorting.enabled()) { - log_address_sorting_list(lb_addrs, "output"); + log_address_sorting_list(*addresses, "output"); } } -/* Allow tests to access grpc_ares_wrapper_address_sorting_sort */ -void grpc_cares_wrapper_test_only_address_sorting_sort( - grpc_lb_addresses* lb_addrs) { - grpc_cares_wrapper_address_sorting_sort(lb_addrs); +static void grpc_ares_request_ref_locked(grpc_ares_request* r) { + r->pending_queries++; +} + +static void grpc_ares_request_unref_locked(grpc_ares_request* r) { + r->pending_queries--; + if (r->pending_queries == 0u) { + grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver); + } } -static void grpc_ares_request_unref(grpc_ares_request* r) { - /* If there are no pending queries, invoke on_done callback and destroy the +void grpc_ares_complete_request_locked(grpc_ares_request* r) { + /* Invoke on_done callback and destroy the request */ - if (gpr_unref(&r->pending_queries)) { - grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out); - if (lb_addrs != nullptr) { - grpc_cares_wrapper_address_sorting_sort(lb_addrs); - } - GRPC_CLOSURE_SCHED(r->on_done, r->error); - gpr_mu_destroy(&r->mu); - grpc_ares_ev_driver_destroy(r->ev_driver); - gpr_free(r); + r->ev_driver = nullptr; + ServerAddressList* addresses = r->addresses_out->get(); + if (addresses != nullptr) { + grpc_cares_wrapper_address_sorting_sort(addresses); } + GRPC_CLOSURE_SCHED(r->on_done, r->error); } -static grpc_ares_hostbyname_request* create_hostbyname_request( +static grpc_ares_hostbyname_request* create_hostbyname_request_locked( grpc_ares_request* parent_request, char* host, uint16_t port, bool is_balancer) { grpc_ares_hostbyname_request* hr = static_cast( @@ -173,80 +163,73 @@ static grpc_ares_hostbyname_request* create_hostbyname_request( hr->host = gpr_strdup(host); hr->port = port; hr->is_balancer = is_balancer; - grpc_ares_request_ref(parent_request); + grpc_ares_request_ref_locked(parent_request); return hr; } -static void destroy_hostbyname_request(grpc_ares_hostbyname_request* hr) { - grpc_ares_request_unref(hr->parent_request); +static void destroy_hostbyname_request_locked( + grpc_ares_hostbyname_request* hr) { + grpc_ares_request_unref_locked(hr->parent_request); gpr_free(hr->host); gpr_free(hr); } -static void on_hostbyname_done_cb(void* arg, int status, int timeouts, - struct hostent* hostent) { +static void on_hostbyname_done_locked(void* arg, int status, int timeouts, + struct hostent* hostent) { grpc_ares_hostbyname_request* hr = static_cast(arg); grpc_ares_request* r = hr->parent_request; - gpr_mu_lock(&r->mu); if (status == ARES_SUCCESS) { GRPC_ERROR_UNREF(r->error); r->error = GRPC_ERROR_NONE; r->success = true; - grpc_lb_addresses** lb_addresses = r->lb_addrs_out; - if (*lb_addresses == nullptr) { - *lb_addresses = grpc_lb_addresses_create(0, nullptr); - } - size_t prev_naddr = (*lb_addresses)->num_addresses; - size_t i; - for (i = 0; hostent->h_addr_list[i] != nullptr; i++) { + if (*r->addresses_out == nullptr) { + *r->addresses_out = grpc_core::MakeUnique(); } - (*lb_addresses)->num_addresses += i; - (*lb_addresses)->addresses = static_cast( - gpr_realloc((*lb_addresses)->addresses, - sizeof(grpc_lb_address) * (*lb_addresses)->num_addresses)); - for (i = prev_naddr; i < (*lb_addresses)->num_addresses; i++) { + ServerAddressList& addresses = **r->addresses_out; + for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) { + grpc_core::InlinedVector args_to_add; + if (hr->is_balancer) { + args_to_add.emplace_back(grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ADDRESS_IS_BALANCER), 1)); + args_to_add.emplace_back(grpc_channel_arg_string_create( + const_cast(GRPC_ARG_ADDRESS_BALANCER_NAME), hr->host)); + } + grpc_channel_args* args = grpc_channel_args_copy_and_add( + nullptr, args_to_add.data(), args_to_add.size()); switch (hostent->h_addrtype) { case AF_INET6: { size_t addr_len = sizeof(struct sockaddr_in6); struct sockaddr_in6 addr; memset(&addr, 0, addr_len); - memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr], + memcpy(&addr.sin6_addr, hostent->h_addr_list[i], sizeof(struct in6_addr)); - addr.sin6_family = static_cast(hostent->h_addrtype); + addr.sin6_family = static_cast(hostent->h_addrtype); addr.sin6_port = hr->port; - grpc_lb_addresses_set_address( - *lb_addresses, i, &addr, addr_len, - hr->is_balancer /* is_balancer */, - hr->is_balancer ? hr->host : nullptr /* balancer_name */, - nullptr /* user_data */); + addresses.emplace_back(&addr, addr_len, args); char output[INET6_ADDRSTRLEN]; ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN); - gpr_log(GPR_DEBUG, - "c-ares resolver gets a AF_INET6 result: \n" - " addr: %s\n port: %d\n sin6_scope_id: %d\n", - output, ntohs(hr->port), addr.sin6_scope_id); + GRPC_CARES_TRACE_LOG( + "request:%p c-ares resolver gets a AF_INET6 result: \n" + " addr: %s\n port: %d\n sin6_scope_id: %d\n", + r, output, ntohs(hr->port), addr.sin6_scope_id); break; } case AF_INET: { size_t addr_len = sizeof(struct sockaddr_in); struct sockaddr_in addr; memset(&addr, 0, addr_len); - memcpy(&addr.sin_addr, hostent->h_addr_list[i - prev_naddr], + memcpy(&addr.sin_addr, hostent->h_addr_list[i], sizeof(struct in_addr)); - addr.sin_family = static_cast(hostent->h_addrtype); + addr.sin_family = static_cast(hostent->h_addrtype); addr.sin_port = hr->port; - grpc_lb_addresses_set_address( - *lb_addresses, i, &addr, addr_len, - hr->is_balancer /* is_balancer */, - hr->is_balancer ? hr->host : nullptr /* balancer_name */, - nullptr /* user_data */); + addresses.emplace_back(&addr, addr_len, args); char output[INET_ADDRSTRLEN]; ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN); - gpr_log(GPR_DEBUG, - "c-ares resolver gets a AF_INET result: \n" - " addr: %s\n port: %d\n", - output, ntohs(hr->port)); + GRPC_CARES_TRACE_LOG( + "request:%p c-ares resolver gets a AF_INET result: \n" + " addr: %s\n port: %d\n", + r, output, ntohs(hr->port)); break; } } @@ -263,34 +246,33 @@ static void on_hostbyname_done_cb(void* arg, int status, int timeouts, r->error = grpc_error_add_child(error, r->error); } } - gpr_mu_unlock(&r->mu); - destroy_hostbyname_request(hr); + destroy_hostbyname_request_locked(hr); } -static void on_srv_query_done_cb(void* arg, int status, int timeouts, - unsigned char* abuf, int alen) { +static void on_srv_query_done_locked(void* arg, int status, int timeouts, + unsigned char* abuf, int alen) { grpc_ares_request* r = static_cast(arg); - grpc_core::ExecCtx exec_ctx; - gpr_log(GPR_DEBUG, "on_query_srv_done_cb"); + GRPC_CARES_TRACE_LOG("request:%p on_query_srv_done_locked", r); if (status == ARES_SUCCESS) { - gpr_log(GPR_DEBUG, "on_query_srv_done_cb ARES_SUCCESS"); + GRPC_CARES_TRACE_LOG("request:%p on_query_srv_done_locked ARES_SUCCESS", r); struct ares_srv_reply* reply; const int parse_status = ares_parse_srv_reply(abuf, alen, &reply); if (parse_status == ARES_SUCCESS) { - ares_channel* channel = grpc_ares_ev_driver_get_channel(r->ev_driver); + ares_channel* channel = + grpc_ares_ev_driver_get_channel_locked(r->ev_driver); for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr; srv_it = srv_it->next) { - if (grpc_ipv6_loopback_available()) { - grpc_ares_hostbyname_request* hr = create_hostbyname_request( + if (grpc_ares_query_ipv6()) { + grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked( r, srv_it->host, htons(srv_it->port), true /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, - on_hostbyname_done_cb, hr); + on_hostbyname_done_locked, hr); } - grpc_ares_hostbyname_request* hr = create_hostbyname_request( + grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked( r, srv_it->host, htons(srv_it->port), true /* is_balancer */); - ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, - hr); - grpc_ares_ev_driver_start(r->ev_driver); + ares_gethostbyname(*channel, hr->host, AF_INET, + on_hostbyname_done_locked, hr); + grpc_ares_ev_driver_start_locked(r->ev_driver); } } if (reply != nullptr) { @@ -308,21 +290,20 @@ static void on_srv_query_done_cb(void* arg, int status, int timeouts, r->error = grpc_error_add_child(error, r->error); } } - grpc_ares_request_unref(r); + grpc_ares_request_unref_locked(r); } static const char g_service_config_attribute_prefix[] = "grpc_config="; -static void on_txt_done_cb(void* arg, int status, int timeouts, - unsigned char* buf, int len) { - gpr_log(GPR_DEBUG, "on_txt_done_cb"); +static void on_txt_done_locked(void* arg, int status, int timeouts, + unsigned char* buf, int len) { char* error_msg; grpc_ares_request* r = static_cast(arg); + GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked", r); const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1; struct ares_txt_ext* result = nullptr; struct ares_txt_ext* reply = nullptr; grpc_error* error = GRPC_ERROR_NONE; - gpr_mu_lock(&r->mu); if (status != ARES_SUCCESS) goto fail; status = ares_parse_txt_reply_ext(buf, len, &reply); if (status != ARES_SUCCESS) goto fail; @@ -351,7 +332,8 @@ static void on_txt_done_cb(void* arg, int status, int timeouts, service_config_len += result->length; } (*r->service_config_json_out)[service_config_len] = '\0'; - gpr_log(GPR_INFO, "found service config: %s", *r->service_config_json_out); + GRPC_CARES_TRACE_LOG("request:%p found service config: %s", r, + *r->service_config_json_out); } // Clean up. ares_free_data(reply); @@ -367,24 +349,16 @@ static void on_txt_done_cb(void* arg, int status, int timeouts, r->error = grpc_error_add_child(error, r->error); } done: - gpr_mu_unlock(&r->mu); - grpc_ares_request_unref(r); + grpc_ares_request_unref_locked(r); } -static grpc_ares_request* grpc_dns_lookup_ares_impl( - const char* dns_server, const char* name, const char* default_port, - grpc_pollset_set* interested_parties, grpc_closure* on_done, - grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json) { +void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( + grpc_ares_request* r, const char* dns_server, const char* name, + const char* default_port, grpc_pollset_set* interested_parties, + bool check_grpclb, int query_timeout_ms, grpc_combiner* combiner) { grpc_error* error = GRPC_ERROR_NONE; grpc_ares_hostbyname_request* hr = nullptr; - grpc_ares_request* r = nullptr; ares_channel* channel = nullptr; - /* TODO(zyc): Enable tracing after #9603 is checked in */ - /* if (grpc_dns_trace) { - gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s", - name, default_port); - } */ - /* parse name, splitting it into host and port parts */ char* host; char* port; @@ -403,24 +377,13 @@ static grpc_ares_request* grpc_dns_lookup_ares_impl( } port = gpr_strdup(default_port); } - - grpc_ares_ev_driver* ev_driver; - error = grpc_ares_ev_driver_create(&ev_driver, interested_parties); + error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties, + query_timeout_ms, combiner, r); if (error != GRPC_ERROR_NONE) goto error_cleanup; - - r = static_cast(gpr_zalloc(sizeof(grpc_ares_request))); - gpr_mu_init(&r->mu); - r->ev_driver = ev_driver; - r->on_done = on_done; - r->lb_addrs_out = addrs; - r->service_config_json_out = service_config_json; - r->success = false; - r->error = GRPC_ERROR_NONE; - channel = grpc_ares_ev_driver_get_channel(r->ev_driver); - + channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver); // If dns_server is specified, use it. if (dns_server != nullptr) { - gpr_log(GPR_INFO, "Using DNS server %s", dns_server); + GRPC_CARES_TRACE_LOG("request:%p Using DNS server %s", r, dns_server); grpc_resolved_address addr; if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) { r->dns_server_addr.family = AF_INET; @@ -442,7 +405,6 @@ static grpc_ares_request* grpc_dns_lookup_ares_impl( error = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name)); - gpr_free(r); goto error_cleanup; } int status = ares_set_servers_ports(*channel, &r->dns_server_addr); @@ -452,61 +414,180 @@ static grpc_ares_request* grpc_dns_lookup_ares_impl( ares_strerror(status)); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg); gpr_free(error_msg); - gpr_free(r); goto error_cleanup; } } - gpr_ref_init(&r->pending_queries, 1); - if (grpc_ipv6_loopback_available()) { - hr = create_hostbyname_request(r, host, strhtons(port), - false /* is_balancer */); - ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_cb, hr); + r->pending_queries = 1; + if (grpc_ares_query_ipv6()) { + hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port), + false /* is_balancer */); + ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked, + hr); } - hr = create_hostbyname_request(r, host, strhtons(port), - false /* is_balancer */); - ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, hr); + hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port), + false /* is_balancer */); + ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked, + hr); if (check_grpclb) { /* Query the SRV record */ - grpc_ares_request_ref(r); + grpc_ares_request_ref_locked(r); char* service_name; gpr_asprintf(&service_name, "_grpclb._tcp.%s", host); - ares_query(*channel, service_name, ns_c_in, ns_t_srv, on_srv_query_done_cb, - r); + ares_query(*channel, service_name, ns_c_in, ns_t_srv, + on_srv_query_done_locked, r); gpr_free(service_name); } - if (service_config_json != nullptr) { - grpc_ares_request_ref(r); + if (r->service_config_json_out != nullptr) { + grpc_ares_request_ref_locked(r); char* config_name; gpr_asprintf(&config_name, "_grpc_config.%s", host); - ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_cb, r); + ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked, + r); gpr_free(config_name); } - /* TODO(zyc): Handle CNAME records here. */ - grpc_ares_ev_driver_start(r->ev_driver); - grpc_ares_request_unref(r); + grpc_ares_ev_driver_start_locked(r->ev_driver); + grpc_ares_request_unref_locked(r); gpr_free(host); gpr_free(port); - return r; + return; error_cleanup: - GRPC_CLOSURE_SCHED(on_done, error); + GRPC_CLOSURE_SCHED(r->on_done, error); gpr_free(host); gpr_free(port); - return nullptr; } -grpc_ares_request* (*grpc_dns_lookup_ares)( +static bool inner_resolve_as_ip_literal_locked( + const char* name, const char* default_port, + grpc_core::UniquePtr* addrs, char** host, + char** port, char** hostport) { + gpr_split_host_port(name, host, port); + if (*host == nullptr) { + gpr_log(GPR_ERROR, + "Failed to parse %s to host:port while attempting to resolve as ip " + "literal.", + name); + return false; + } + if (*port == nullptr) { + if (default_port == nullptr) { + gpr_log(GPR_ERROR, + "No port or default port for %s while attempting to resolve as " + "ip literal.", + name); + return false; + } + *port = gpr_strdup(default_port); + } + grpc_resolved_address addr; + GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port))); + if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) || + grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) { + GPR_ASSERT(*addrs == nullptr); + *addrs = grpc_core::MakeUnique(); + (*addrs)->emplace_back(addr.addr, addr.len, nullptr /* args */); + return true; + } + return false; +} + +static bool resolve_as_ip_literal_locked( + const char* name, const char* default_port, + grpc_core::UniquePtr* addrs) { + char* host = nullptr; + char* port = nullptr; + char* hostport = nullptr; + bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs, + &host, &port, &hostport); + gpr_free(host); + gpr_free(port); + gpr_free(hostport); + return out; +} + +static bool target_matches_localhost_inner(const char* name, char** host, + char** port) { + if (!gpr_split_host_port(name, host, port)) { + gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name); + return false; + } + if (gpr_stricmp(*host, "localhost") == 0) { + return true; + } else { + return false; + } +} + +static bool target_matches_localhost(const char* name) { + char* host = nullptr; + char* port = nullptr; + bool out = target_matches_localhost_inner(name, &host, &port); + gpr_free(host); + gpr_free(port); + return out; +} + +static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, - grpc_lb_addresses** addrs, bool check_grpclb, - char** service_config_json) = grpc_dns_lookup_ares_impl; + grpc_core::UniquePtr* addrs, + bool check_grpclb, char** service_config_json, int query_timeout_ms, + grpc_combiner* combiner) { + grpc_ares_request* r = + static_cast(gpr_zalloc(sizeof(grpc_ares_request))); + r->ev_driver = nullptr; + r->on_done = on_done; + r->addresses_out = addrs; + r->service_config_json_out = service_config_json; + r->success = false; + r->error = GRPC_ERROR_NONE; + r->pending_queries = 0; + GRPC_CARES_TRACE_LOG( + "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, " + "default_port=%s", + r, name, default_port); + // Early out if the target is an ipv4 or ipv6 literal. + if (resolve_as_ip_literal_locked(name, default_port, addrs)) { + grpc_ares_complete_request_locked(r); + return r; + } + // Early out if the target is localhost and we're on Windows. + if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port, + addrs)) { + grpc_ares_complete_request_locked(r); + return r; + } + // Don't query for SRV and TXT records if the target is "localhost", so + // as to cut down on lookups over the network, especially in tests: + // https://github.com/grpc/proposal/pull/79 + if (target_matches_localhost(name)) { + check_grpclb = false; + r->service_config_json_out = nullptr; + } + // Look up name using c-ares lib. + grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( + r, dns_server, name, default_port, interested_parties, check_grpclb, + query_timeout_ms, combiner); + return r; +} -void grpc_cancel_ares_request(grpc_ares_request* r) { - if (grpc_dns_lookup_ares == grpc_dns_lookup_ares_impl) { - grpc_ares_ev_driver_shutdown(r->ev_driver); +grpc_ares_request* (*grpc_dns_lookup_ares_locked)( + const char* dns_server, const char* name, const char* default_port, + grpc_pollset_set* interested_parties, grpc_closure* on_done, + grpc_core::UniquePtr* addrs, + bool check_grpclb, char** service_config_json, int query_timeout_ms, + grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl; + +static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) { + GPR_ASSERT(r != nullptr); + if (r->ev_driver != nullptr) { + grpc_ares_ev_driver_shutdown_locked(r->ev_driver); } } +void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) = + grpc_cancel_ares_request_locked_impl; + grpc_error* grpc_ares_init(void) { gpr_once_init(&g_basic_init, do_basic_init); gpr_mu_lock(&g_init_mu); @@ -535,39 +616,61 @@ void grpc_ares_cleanup(void) { */ typedef struct grpc_resolve_address_ares_request { + /* combiner that queries and related callbacks run under */ + grpc_combiner* combiner; /** the pointer to receive the resolved addresses */ grpc_resolved_addresses** addrs_out; - /** currently resolving lb addresses */ - grpc_lb_addresses* lb_addrs; + /** currently resolving addresses */ + grpc_core::UniquePtr addresses; /** closure to call when the resolve_address_ares request completes */ grpc_closure* on_resolve_address_done; - /** a closure wrapping on_dns_lookup_done_cb, which should be invoked when the - grpc_dns_lookup_ares operation is done. */ - grpc_closure on_dns_lookup_done; + /** a closure wrapping on_resolve_address_done, which should be invoked when + the grpc_dns_lookup_ares_locked operation is done. */ + grpc_closure on_dns_lookup_done_locked; + /* target name */ + const char* name; + /* default port to use if none is specified */ + const char* default_port; + /* pollset_set to be driven by */ + grpc_pollset_set* interested_parties; + /* underlying ares_request that the query is performed on */ + grpc_ares_request* ares_request = nullptr; } grpc_resolve_address_ares_request; -static void on_dns_lookup_done_cb(void* arg, grpc_error* error) { +static void on_dns_lookup_done_locked(void* arg, grpc_error* error) { grpc_resolve_address_ares_request* r = static_cast(arg); + gpr_free(r->ares_request); grpc_resolved_addresses** resolved_addresses = r->addrs_out; - if (r->lb_addrs == nullptr || r->lb_addrs->num_addresses == 0) { + if (r->addresses == nullptr || r->addresses->empty()) { *resolved_addresses = nullptr; } else { *resolved_addresses = static_cast( gpr_zalloc(sizeof(grpc_resolved_addresses))); - (*resolved_addresses)->naddrs = r->lb_addrs->num_addresses; + (*resolved_addresses)->naddrs = r->addresses->size(); (*resolved_addresses)->addrs = static_cast(gpr_zalloc( sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs)); - for (size_t i = 0; i < (*resolved_addresses)->naddrs; i++) { - GPR_ASSERT(!r->lb_addrs->addresses[i].is_balancer); - memcpy(&(*resolved_addresses)->addrs[i], - &r->lb_addrs->addresses[i].address, sizeof(grpc_resolved_address)); + for (size_t i = 0; i < (*resolved_addresses)->naddrs; ++i) { + GPR_ASSERT(!(*r->addresses)[i].IsBalancer()); + memcpy(&(*resolved_addresses)->addrs[i], &(*r->addresses)[i].address(), + sizeof(grpc_resolved_address)); } } GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error)); - if (r->lb_addrs != nullptr) grpc_lb_addresses_destroy(r->lb_addrs); - gpr_free(r); + GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb"); + grpc_core::Delete(r); +} + +static void grpc_resolve_address_invoke_dns_lookup_ares_locked( + void* arg, grpc_error* unused_error) { + grpc_resolve_address_ares_request* r = + static_cast(arg); + r->ares_request = grpc_dns_lookup_ares_locked( + nullptr /* dns_server */, r->name, r->default_port, r->interested_parties, + &r->on_dns_lookup_done_locked, &r->addresses, false /* check_grpclb */, + nullptr /* service_config_json */, GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, + r->combiner); } static void grpc_resolve_address_ares_impl(const char* name, @@ -576,16 +679,19 @@ static void grpc_resolve_address_ares_impl(const char* name, grpc_closure* on_done, grpc_resolved_addresses** addrs) { grpc_resolve_address_ares_request* r = - static_cast( - gpr_zalloc(sizeof(grpc_resolve_address_ares_request))); + grpc_core::New(); + r->combiner = grpc_combiner_create(); r->addrs_out = addrs; r->on_resolve_address_done = on_done; - GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r, - grpc_schedule_on_exec_ctx); - grpc_dns_lookup_ares(nullptr /* dns_server */, name, default_port, - interested_parties, &r->on_dns_lookup_done, &r->lb_addrs, - false /* check_grpclb */, - nullptr /* service_config_json */); + GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done_locked, r, + grpc_combiner_scheduler(r->combiner)); + r->name = name; + r->default_port = default_port; + r->interested_parties = interested_parties; + GRPC_CLOSURE_SCHED( + GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r, + grpc_combiner_scheduler(r->combiner)), + GRPC_ERROR_NONE); } void (*grpc_resolve_address_ares)( diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index 2d84a038d..280825045 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -21,13 +21,22 @@ #include -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/resolve_address.h" +#define GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS 10000 + extern grpc_core::TraceFlag grpc_trace_cares_address_sorting; +extern grpc_core::TraceFlag grpc_trace_cares_resolver; + +#define GRPC_CARES_TRACE_LOG(format, ...) \ + if (grpc_trace_cares_resolver.enabled()) { \ + gpr_log(GPR_DEBUG, "(c-ares resolver) " format, __VA_ARGS__); \ + } + typedef struct grpc_ares_request grpc_ares_request; /* Asynchronously resolve \a name. Use \a default_port if a port isn't @@ -47,15 +56,17 @@ extern void (*grpc_resolve_address_ares)(const char* name, port in \a name. grpc_ares_init() must be called at least once before this function. \a on_done may be called directly in this function without being scheduled with \a exec_ctx, so it must not try to acquire locks that are - being held by the caller. */ -extern grpc_ares_request* (*grpc_dns_lookup_ares)( + being held by the caller. The returned grpc_ares_request object is owned + by the caller and it is safe to free after on_done is called back. */ +extern grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, - grpc_lb_addresses** addresses, bool check_grpclb, - char** service_config_json); + grpc_core::UniquePtr* addresses, + bool check_grpclb, char** service_config_json, int query_timeout_ms, + grpc_combiner* combiner); /* Cancel the pending grpc_ares_request \a request */ -void grpc_cancel_ares_request(grpc_ares_request* request); +extern void (*grpc_cancel_ares_request_locked)(grpc_ares_request* request); /* Initialize gRPC ares wrapper. Must be called at least once before grpc_resolve_address_ares(). */ @@ -66,9 +77,25 @@ grpc_error* grpc_ares_init(void); it has been called the same number of times as grpc_ares_init(). */ void grpc_ares_cleanup(void); -/* Exposed only for testing */ -void grpc_cares_wrapper_test_only_address_sorting_sort( - grpc_lb_addresses* lb_addrs); +/** Schedules the desired callback for request completion + * and destroys the grpc_ares_request */ +void grpc_ares_complete_request_locked(grpc_ares_request* request); + +/* Indicates whether or not AAAA queries should be attempted. */ +/* E.g., return false if ipv6 is known to not be available. */ +bool grpc_ares_query_ipv6(); + +/* Maybe (depending on the current platform) checks if "name" matches + * "localhost" and if so fills in addrs with the correct sockaddr structures. + * Returns a bool indicating whether or not such an action was performed. + * See https://github.com/grpc/grpc/issues/15158. */ +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, + grpc_core::UniquePtr* addrs); + +/* Sorts destinations in lb_addrs according to RFC 6724. */ +void grpc_cares_wrapper_address_sorting_sort( + grpc_core::ServerAddressList* addresses); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H \ */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc index 5096e480b..1f4701c99 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc @@ -26,20 +26,26 @@ struct grpc_ares_request { char val; }; -static grpc_ares_request* grpc_dns_lookup_ares_impl( +static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, - grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json) { + grpc_core::UniquePtr* addrs, + bool check_grpclb, char** service_config_json, int query_timeout_ms, + grpc_combiner* combiner) { return NULL; } -grpc_ares_request* (*grpc_dns_lookup_ares)( +grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, - grpc_lb_addresses** addrs, bool check_grpclb, - char** service_config_json) = grpc_dns_lookup_ares_impl; + grpc_core::UniquePtr* addrs, + bool check_grpclb, char** service_config_json, int query_timeout_ms, + grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl; -void grpc_cancel_ares_request(grpc_ares_request* r) {} +static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {} + +void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) = + grpc_cancel_ares_request_locked_impl; grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc new file mode 100644 index 000000000..028d84421 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc @@ -0,0 +1,35 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" + +bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } + +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, + grpc_core::UniquePtr* addrs) { + return false; +} + +#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc new file mode 100644 index 000000000..202452f1b --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -0,0 +1,97 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GPR_WINDOWS) + +#include + +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/socket_windows.h" + +bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } + +static bool inner_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, + grpc_core::UniquePtr* addrs, char** host, + char** port) { + gpr_split_host_port(name, host, port); + if (*host == nullptr) { + gpr_log(GPR_ERROR, + "Failed to parse %s into host:port during Windows localhost " + "resolution check.", + name); + return false; + } + if (*port == nullptr) { + if (default_port == nullptr) { + gpr_log(GPR_ERROR, + "No port or default port for %s during Windows localhost " + "resolution check.", + name); + return false; + } + *port = gpr_strdup(default_port); + } + if (gpr_stricmp(*host, "localhost") == 0) { + GPR_ASSERT(*addrs == nullptr); + *addrs = grpc_core::MakeUnique(); + uint16_t numeric_port = grpc_strhtons(*port); + // Append the ipv6 loopback address. + struct sockaddr_in6 ipv6_loopback_addr; + memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr)); + ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1; + ipv6_loopback_addr.sin6_family = AF_INET6; + ipv6_loopback_addr.sin6_port = numeric_port; + (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr), + nullptr /* args */); + // Append the ipv4 loopback address. + struct sockaddr_in ipv4_loopback_addr; + memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr)); + ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f; + ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01; + ipv4_loopback_addr.sin_family = AF_INET; + ipv4_loopback_addr.sin_port = numeric_port; + (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr), + nullptr /* args */); + // Let the address sorter figure out which one should be tried first. + grpc_cares_wrapper_address_sorting_sort(addrs->get()); + return true; + } + return false; +} + +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, + grpc_core::UniquePtr* addrs) { + char* host = nullptr; + char* port = nullptr; + bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port, + addrs, &host, &port); + gpr_free(host); + gpr_free(port); + return out; +} + +#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc index e7842a795..c365f1abf 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc @@ -26,8 +26,8 @@ #include #include -#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" @@ -58,6 +58,8 @@ class NativeDnsResolver : public Resolver { void RequestReresolutionLocked() override; + void ResetBackoffLocked() override; + void ShutdownLocked() override; private: @@ -158,6 +160,13 @@ void NativeDnsResolver::RequestReresolutionLocked() { } } +void NativeDnsResolver::ResetBackoffLocked() { + if (have_next_resolution_timer_) { + grpc_timer_cancel(&next_resolution_timer_); + } + backoff_.Reset(); +} + void NativeDnsResolver::ShutdownLocked() { if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); @@ -189,18 +198,14 @@ void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(r->name_to_resolve_)); if (r->addresses_ != nullptr) { - grpc_lb_addresses* addresses = grpc_lb_addresses_create( - r->addresses_->naddrs, nullptr /* user_data_vtable */); + ServerAddressList addresses; for (size_t i = 0; i < r->addresses_->naddrs; ++i) { - grpc_lb_addresses_set_address( - addresses, i, &r->addresses_->addrs[i].addr, - r->addresses_->addrs[i].len, false /* is_balancer */, - nullptr /* balancer_name */, nullptr /* user_data */); + addresses.emplace_back(&r->addresses_->addrs[i].addr, + r->addresses_->addrs[i].len, nullptr /* args */); } - grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses); + grpc_arg new_arg = CreateServerAddressListChannelArg(&addresses); result = grpc_channel_args_copy_and_add(r->channel_args_, &new_arg, 1); grpc_resolved_addresses_destroy(r->addresses_); - grpc_lb_addresses_destroy(addresses); // Reset backoff state so that we start from the beginning when the // next request gets triggered. r->backoff_.Reset(); @@ -218,7 +223,7 @@ void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { r->Ref(DEBUG_LOCATION, "next_resolution_timer"); self.release(); if (timeout > 0) { - gpr_log(GPR_DEBUG, "retrying in %" PRIdPTR " milliseconds", timeout); + gpr_log(GPR_DEBUG, "retrying in %" PRId64 " milliseconds", timeout); } else { gpr_log(GPR_DEBUG, "retrying immediately"); } @@ -238,13 +243,7 @@ void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { void NativeDnsResolver::MaybeStartResolvingLocked() { // If there is an existing timer, the time it fires is the earliest time we // can start the next resolution. - if (have_next_resolution_timer_) { - // TODO(dgq): remove the following two lines once Pick First stops - // discarding subchannels after selecting. - ++resolved_version_; - MaybeFinishNextLocked(); - return; - } + if (have_next_resolution_timer_) return; if (last_resolution_timestamp_ >= 0) { const grpc_millis earliest_next_resolution = last_resolution_timestamp_ + min_time_between_resolutions_; @@ -254,8 +253,8 @@ void NativeDnsResolver::MaybeStartResolvingLocked() { const grpc_millis last_resolution_ago = grpc_core::ExecCtx::Get()->Now() - last_resolution_timestamp_; gpr_log(GPR_DEBUG, - "In cooldown from last resolution (from %" PRIdPTR - " ms ago). Will resolve again in %" PRIdPTR " ms", + "In cooldown from last resolution (from %" PRId64 + " ms ago). Will resolve again in %" PRId64 " ms", last_resolution_ago, ms_until_next_resolution); have_next_resolution_timer_ = true; // TODO(roth): We currently deal with this ref manually. Once the @@ -266,10 +265,6 @@ void NativeDnsResolver::MaybeStartResolvingLocked() { self.release(); grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution, &on_next_resolution_); - // TODO(dgq): remove the following two lines once Pick First stops - // discarding subchannels after selecting. - ++resolved_version_; - MaybeFinishNextLocked(); return; } } @@ -310,7 +305,7 @@ class NativeDnsResolverFactory : public ResolverFactory { public: OrphanablePtr CreateResolver( const ResolverArgs& args) const override { - if (0 != strcmp(args.uri->authority, "")) { + if (GPR_UNLIKELY(0 != strcmp(args.uri->authority, ""))) { gpr_log(GPR_ERROR, "authority based dns uri's not supported"); return OrphanablePtr(nullptr); } diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc index 99a33f227..258339491 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc @@ -28,12 +28,13 @@ #include #include -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/useful.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/resolve_address.h" @@ -73,11 +74,6 @@ class FakeResolver : public Resolver { // Results to use for the pretended re-resolution in // RequestReresolutionLocked(). grpc_channel_args* reresolution_results_ = nullptr; - // TODO(juanlishen): This can go away once pick_first is changed to not throw - // away its subchannels, since that will eliminate its dependence on - // channel_saw_error_locked() causing an immediate resolver return. - // A copy of the most-recently used resolution results. - grpc_channel_args* last_used_results_ = nullptr; // pending next completion, or NULL grpc_closure* next_completion_ = nullptr; // target result address for next completion @@ -96,7 +92,6 @@ FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) { FakeResolver::~FakeResolver() { grpc_channel_args_destroy(next_results_); grpc_channel_args_destroy(reresolution_results_); - grpc_channel_args_destroy(last_used_results_); grpc_channel_args_destroy(channel_args_); } @@ -109,17 +104,11 @@ void FakeResolver::NextLocked(grpc_channel_args** target_result, } void FakeResolver::RequestReresolutionLocked() { - // A resolution must have been returned before an error is seen. - GPR_ASSERT(last_used_results_ != nullptr); - grpc_channel_args_destroy(next_results_); - if (reresolution_results_ != nullptr) { + if (reresolution_results_ != nullptr || return_failure_) { + grpc_channel_args_destroy(next_results_); next_results_ = grpc_channel_args_copy(reresolution_results_); - } else { - // If reresolution_results is unavailable, re-resolve with the most-recently - // used results to avoid a no-op re-resolution. - next_results_ = grpc_channel_args_copy(last_used_results_); + MaybeFinishNextLocked(); } - MaybeFinishNextLocked(); } void FakeResolver::MaybeFinishNextLocked() { @@ -153,6 +142,7 @@ struct SetResponseClosureArg { grpc_closure set_response_closure; FakeResolverResponseGenerator* generator; grpc_channel_args* response; + bool immediate = true; }; void FakeResolverResponseGenerator::SetResponseLocked(void* arg, @@ -161,8 +151,6 @@ void FakeResolverResponseGenerator::SetResponseLocked(void* arg, FakeResolver* resolver = closure_arg->generator->resolver_; grpc_channel_args_destroy(resolver->next_results_); resolver->next_results_ = closure_arg->response; - grpc_channel_args_destroy(resolver->last_used_results_); - resolver->last_used_results_ = grpc_channel_args_copy(closure_arg->response); resolver->MaybeFinishNextLocked(); Delete(closure_arg); } @@ -208,7 +196,7 @@ void FakeResolverResponseGenerator::SetFailureLocked(void* arg, SetResponseClosureArg* closure_arg = static_cast(arg); FakeResolver* resolver = closure_arg->generator->resolver_; resolver->return_failure_ = true; - resolver->MaybeFinishNextLocked(); + if (closure_arg->immediate) resolver->MaybeFinishNextLocked(); Delete(closure_arg); } @@ -223,6 +211,18 @@ void FakeResolverResponseGenerator::SetFailure() { GRPC_ERROR_NONE); } +void FakeResolverResponseGenerator::SetFailureOnReresolution() { + GPR_ASSERT(resolver_ != nullptr); + SetResponseClosureArg* closure_arg = New(); + closure_arg->generator = this; + closure_arg->immediate = false; + GRPC_CLOSURE_SCHED( + GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked, + closure_arg, + grpc_combiner_scheduler(resolver_->combiner())), + GRPC_ERROR_NONE); +} + namespace { static void* response_generator_arg_copy(void* p) { diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h index e5175f9b7..d86111c38 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h @@ -19,10 +19,9 @@ #include -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/iomgr/error.h" #define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \ "grpc.fake_resolver.response_generator" @@ -53,13 +52,18 @@ class FakeResolverResponseGenerator // The new re-resolution response replaces any previous re-resolution // response that may have been set by a previous call. // If the re-resolution response is set to NULL, then the fake - // resolver will return the last value set via \a SetResponse(). + // resolver will not return anything when \a RequestReresolutionLocked() + // is called. void SetReresolutionResponse(grpc_channel_args* response); // Tells the resolver to return a transient failure (signalled by // returning a null result with no error). void SetFailure(); + // Same as SetFailure(), but instead of returning the error + // immediately, waits for the next call to RequestReresolutionLocked(). + void SetFailureOnReresolution(); + // Returns a channel arg containing \a generator. static grpc_arg MakeChannelArg(FakeResolverResponseGenerator* generator); diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc index f74ac5aeb..1654747a7 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc @@ -26,9 +26,9 @@ #include #include -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" @@ -45,13 +45,12 @@ namespace { class SockaddrResolver : public Resolver { public: /// Takes ownership of \a addresses. - SockaddrResolver(const ResolverArgs& args, grpc_lb_addresses* addresses); + SockaddrResolver(const ResolverArgs& args, + UniquePtr addresses); void NextLocked(grpc_channel_args** result, grpc_closure* on_complete) override; - void RequestReresolutionLocked() override; - void ShutdownLocked() override; private: @@ -60,7 +59,7 @@ class SockaddrResolver : public Resolver { void MaybeFinishNextLocked(); /// the addresses that we've "resolved" - grpc_lb_addresses* addresses_ = nullptr; + UniquePtr addresses_; /// channel args grpc_channel_args* channel_args_ = nullptr; /// have we published? @@ -72,13 +71,12 @@ class SockaddrResolver : public Resolver { }; SockaddrResolver::SockaddrResolver(const ResolverArgs& args, - grpc_lb_addresses* addresses) + UniquePtr addresses) : Resolver(args.combiner), - addresses_(addresses), + addresses_(std::move(addresses)), channel_args_(grpc_channel_args_copy(args.args)) {} SockaddrResolver::~SockaddrResolver() { - grpc_lb_addresses_destroy(addresses_); grpc_channel_args_destroy(channel_args_); } @@ -90,11 +88,6 @@ void SockaddrResolver::NextLocked(grpc_channel_args** target_result, MaybeFinishNextLocked(); } -void SockaddrResolver::RequestReresolutionLocked() { - published_ = false; - MaybeFinishNextLocked(); -} - void SockaddrResolver::ShutdownLocked() { if (next_completion_ != nullptr) { *target_result_ = nullptr; @@ -107,7 +100,7 @@ void SockaddrResolver::ShutdownLocked() { void SockaddrResolver::MaybeFinishNextLocked() { if (next_completion_ != nullptr && !published_) { published_ = true; - grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses_); + grpc_arg arg = CreateServerAddressListChannelArg(addresses_.get()); *target_result_ = grpc_channel_args_copy_and_add(channel_args_, &arg, 1); GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE); next_completion_ = nullptr; @@ -134,27 +127,27 @@ OrphanablePtr CreateSockaddrResolver( grpc_slice_buffer path_parts; grpc_slice_buffer_init(&path_parts); grpc_slice_split(path_slice, ",", &path_parts); - grpc_lb_addresses* addresses = grpc_lb_addresses_create( - path_parts.count, nullptr /* user_data_vtable */); + auto addresses = MakeUnique(); bool errors_found = false; - for (size_t i = 0; i < addresses->num_addresses; i++) { + for (size_t i = 0; i < path_parts.count; i++) { grpc_uri ith_uri = *args.uri; - char* part_str = grpc_slice_to_c_string(path_parts.slices[i]); - ith_uri.path = part_str; - if (!parse(&ith_uri, &addresses->addresses[i].address)) { + UniquePtr part_str(grpc_slice_to_c_string(path_parts.slices[i])); + ith_uri.path = part_str.get(); + grpc_resolved_address addr; + if (!parse(&ith_uri, &addr)) { errors_found = true; /* GPR_TRUE */ + break; } - gpr_free(part_str); - if (errors_found) break; + addresses->emplace_back(addr, nullptr /* args */); } grpc_slice_buffer_destroy_internal(&path_parts); grpc_slice_unref_internal(path_slice); if (errors_found) { - grpc_lb_addresses_destroy(addresses); return OrphanablePtr(nullptr); } // Instantiate resolver. - return OrphanablePtr(New(args, addresses)); + return OrphanablePtr( + New(args, std::move(addresses))); } class IPv4ResolverFactory : public ResolverFactory { diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_factory.h b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_factory.h index ee3cfeeb9..d891ef62e 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_factory.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_factory.h @@ -24,11 +24,11 @@ #include #include "src/core/ext/filters/client_channel/resolver.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/uri/uri_parser.h" namespace grpc_core { diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_result_parsing.cc new file mode 100644 index 000000000..0af07dc4e --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -0,0 +1,349 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/filters/client_channel/resolver_result_parsing.h" + +#include +#include +#include + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/uri/uri_parser.h" + +// As per the retry design, we do not allow more than 5 retry attempts. +#define MAX_MAX_RETRY_ATTEMPTS 5 + +namespace grpc_core { +namespace internal { + +ProcessedResolverResult::ProcessedResolverResult( + const grpc_channel_args& resolver_result, bool parse_retry) { + ProcessServiceConfig(resolver_result, parse_retry); + // If no LB config was found above, just find the LB policy name then. + if (lb_policy_name_ == nullptr) ProcessLbPolicyName(resolver_result); +} + +void ProcessedResolverResult::ProcessServiceConfig( + const grpc_channel_args& resolver_result, bool parse_retry) { + const grpc_arg* channel_arg = + grpc_channel_args_find(&resolver_result, GRPC_ARG_SERVICE_CONFIG); + const char* service_config_json = grpc_channel_arg_get_string(channel_arg); + if (service_config_json != nullptr) { + service_config_json_.reset(gpr_strdup(service_config_json)); + service_config_ = grpc_core::ServiceConfig::Create(service_config_json); + if (service_config_ != nullptr) { + if (parse_retry) { + channel_arg = + grpc_channel_args_find(&resolver_result, GRPC_ARG_SERVER_URI); + const char* server_uri = grpc_channel_arg_get_string(channel_arg); + GPR_ASSERT(server_uri != nullptr); + grpc_uri* uri = grpc_uri_parse(server_uri, true); + GPR_ASSERT(uri->path[0] != '\0'); + server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path; + service_config_->ParseGlobalParams(ParseServiceConfig, this); + grpc_uri_destroy(uri); + } else { + service_config_->ParseGlobalParams(ParseServiceConfig, this); + } + method_params_table_ = service_config_->CreateMethodConfigTable( + ClientChannelMethodParams::CreateFromJson); + } + } +} + +void ProcessedResolverResult::ProcessLbPolicyName( + const grpc_channel_args& resolver_result) { + // Prefer the LB policy name found in the service config. Note that this is + // checking the deprecated loadBalancingPolicy field, rather than the new + // loadBalancingConfig field. + if (service_config_ != nullptr) { + lb_policy_name_.reset( + gpr_strdup(service_config_->GetLoadBalancingPolicyName())); + // Convert to lower-case. + if (lb_policy_name_ != nullptr) { + char* lb_policy_name = lb_policy_name_.get(); + for (size_t i = 0; i < strlen(lb_policy_name); ++i) { + lb_policy_name[i] = tolower(lb_policy_name[i]); + } + } + } + // Otherwise, find the LB policy name set by the client API. + if (lb_policy_name_ == nullptr) { + const grpc_arg* channel_arg = + grpc_channel_args_find(&resolver_result, GRPC_ARG_LB_POLICY_NAME); + lb_policy_name_.reset(gpr_strdup(grpc_channel_arg_get_string(channel_arg))); + } + // Special case: If at least one balancer address is present, we use + // the grpclb policy, regardless of what the resolver has returned. + const ServerAddressList* addresses = + FindServerAddressListChannelArg(&resolver_result); + if (addresses != nullptr) { + bool found_balancer_address = false; + for (size_t i = 0; i < addresses->size(); ++i) { + const ServerAddress& address = (*addresses)[i]; + if (address.IsBalancer()) { + found_balancer_address = true; + break; + } + } + if (found_balancer_address) { + if (lb_policy_name_ != nullptr && + strcmp(lb_policy_name_.get(), "grpclb") != 0) { + gpr_log(GPR_INFO, + "resolver requested LB policy %s but provided at least one " + "balancer address -- forcing use of grpclb LB policy", + lb_policy_name_.get()); + } + lb_policy_name_.reset(gpr_strdup("grpclb")); + } + } + // Use pick_first if nothing was specified and we didn't select grpclb + // above. + if (lb_policy_name_ == nullptr) { + lb_policy_name_.reset(gpr_strdup("pick_first")); + } +} + +void ProcessedResolverResult::ParseServiceConfig( + const grpc_json* field, ProcessedResolverResult* parsing_state) { + parsing_state->ParseLbConfigFromServiceConfig(field); + if (parsing_state->server_name_ != nullptr) { + parsing_state->ParseRetryThrottleParamsFromServiceConfig(field); + } +} + +void ProcessedResolverResult::ParseLbConfigFromServiceConfig( + const grpc_json* field) { + if (lb_policy_config_ != nullptr) return; // Already found. + if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0) { + return; // Not the LB config global parameter. + } + const grpc_json* policy = + LoadBalancingPolicy::ParseLoadBalancingConfig(field); + if (policy != nullptr) { + lb_policy_name_.reset(gpr_strdup(policy->key)); + lb_policy_config_ = policy->child; + } +} + +void ProcessedResolverResult::ParseRetryThrottleParamsFromServiceConfig( + const grpc_json* field) { + if (strcmp(field->key, "retryThrottling") == 0) { + if (retry_throttle_data_ != nullptr) return; // Duplicate. + if (field->type != GRPC_JSON_OBJECT) return; + int max_milli_tokens = 0; + int milli_token_ratio = 0; + for (grpc_json* sub_field = field->child; sub_field != nullptr; + sub_field = sub_field->next) { + if (sub_field->key == nullptr) return; + if (strcmp(sub_field->key, "maxTokens") == 0) { + if (max_milli_tokens != 0) return; // Duplicate. + if (sub_field->type != GRPC_JSON_NUMBER) return; + max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value); + if (max_milli_tokens == -1) return; + max_milli_tokens *= 1000; + } else if (strcmp(sub_field->key, "tokenRatio") == 0) { + if (milli_token_ratio != 0) return; // Duplicate. + if (sub_field->type != GRPC_JSON_NUMBER) return; + // We support up to 3 decimal digits. + size_t whole_len = strlen(sub_field->value); + uint32_t multiplier = 1; + uint32_t decimal_value = 0; + const char* decimal_point = strchr(sub_field->value, '.'); + if (decimal_point != nullptr) { + whole_len = static_cast(decimal_point - sub_field->value); + multiplier = 1000; + size_t decimal_len = strlen(decimal_point + 1); + if (decimal_len > 3) decimal_len = 3; + if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len, + &decimal_value)) { + return; + } + uint32_t decimal_multiplier = 1; + for (size_t i = 0; i < (3 - decimal_len); ++i) { + decimal_multiplier *= 10; + } + decimal_value *= decimal_multiplier; + } + uint32_t whole_value; + if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len, + &whole_value)) { + return; + } + milli_token_ratio = + static_cast((whole_value * multiplier) + decimal_value); + if (milli_token_ratio <= 0) return; + } + } + retry_throttle_data_ = + grpc_core::internal::ServerRetryThrottleMap::GetDataForServer( + server_name_, max_milli_tokens, milli_token_ratio); + } +} + +namespace { + +bool ParseWaitForReady( + grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) { + if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) { + return false; + } + *wait_for_ready = field->type == GRPC_JSON_TRUE + ? ClientChannelMethodParams::WAIT_FOR_READY_TRUE + : ClientChannelMethodParams::WAIT_FOR_READY_FALSE; + return true; +} + +// Parses a JSON field of the form generated for a google.proto.Duration +// proto message, as per: +// https://developers.google.com/protocol-buffers/docs/proto3#json +bool ParseDuration(grpc_json* field, grpc_millis* duration) { + if (field->type != GRPC_JSON_STRING) return false; + size_t len = strlen(field->value); + if (field->value[len - 1] != 's') return false; + UniquePtr buf(gpr_strdup(field->value)); + *(buf.get() + len - 1) = '\0'; // Remove trailing 's'. + char* decimal_point = strchr(buf.get(), '.'); + int nanos = 0; + if (decimal_point != nullptr) { + *decimal_point = '\0'; + nanos = gpr_parse_nonnegative_int(decimal_point + 1); + if (nanos == -1) { + return false; + } + int num_digits = static_cast(strlen(decimal_point + 1)); + if (num_digits > 9) { // We don't accept greater precision than nanos. + return false; + } + for (int i = 0; i < (9 - num_digits); ++i) { + nanos *= 10; + } + } + int seconds = + decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get()); + if (seconds == -1) return false; + *duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS; + return true; +} + +UniquePtr ParseRetryPolicy( + grpc_json* field) { + auto retry_policy = MakeUnique(); + if (field->type != GRPC_JSON_OBJECT) return nullptr; + for (grpc_json* sub_field = field->child; sub_field != nullptr; + sub_field = sub_field->next) { + if (sub_field->key == nullptr) return nullptr; + if (strcmp(sub_field->key, "maxAttempts") == 0) { + if (retry_policy->max_attempts != 0) return nullptr; // Duplicate. + if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; + retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value); + if (retry_policy->max_attempts <= 1) return nullptr; + if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) { + gpr_log(GPR_ERROR, + "service config: clamped retryPolicy.maxAttempts at %d", + MAX_MAX_RETRY_ATTEMPTS); + retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS; + } + } else if (strcmp(sub_field->key, "initialBackoff") == 0) { + if (retry_policy->initial_backoff > 0) return nullptr; // Duplicate. + if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) { + return nullptr; + } + if (retry_policy->initial_backoff == 0) return nullptr; + } else if (strcmp(sub_field->key, "maxBackoff") == 0) { + if (retry_policy->max_backoff > 0) return nullptr; // Duplicate. + if (!ParseDuration(sub_field, &retry_policy->max_backoff)) { + return nullptr; + } + if (retry_policy->max_backoff == 0) return nullptr; + } else if (strcmp(sub_field->key, "backoffMultiplier") == 0) { + if (retry_policy->backoff_multiplier != 0) return nullptr; // Duplicate. + if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; + if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) != + 1) { + return nullptr; + } + if (retry_policy->backoff_multiplier <= 0) return nullptr; + } else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) { + if (!retry_policy->retryable_status_codes.Empty()) { + return nullptr; // Duplicate. + } + if (sub_field->type != GRPC_JSON_ARRAY) return nullptr; + for (grpc_json* element = sub_field->child; element != nullptr; + element = element->next) { + if (element->type != GRPC_JSON_STRING) return nullptr; + grpc_status_code status; + if (!grpc_status_code_from_string(element->value, &status)) { + return nullptr; + } + retry_policy->retryable_status_codes.Add(status); + } + if (retry_policy->retryable_status_codes.Empty()) return nullptr; + } + } + // Make sure required fields are set. + if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 || + retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 || + retry_policy->retryable_status_codes.Empty()) { + return nullptr; + } + return retry_policy; +} + +} // namespace + +RefCountedPtr +ClientChannelMethodParams::CreateFromJson(const grpc_json* json) { + RefCountedPtr method_params = + MakeRefCounted(); + for (grpc_json* field = json->child; field != nullptr; field = field->next) { + if (field->key == nullptr) continue; + if (strcmp(field->key, "waitForReady") == 0) { + if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) { + return nullptr; // Duplicate. + } + if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) { + return nullptr; + } + } else if (strcmp(field->key, "timeout") == 0) { + if (method_params->timeout_ > 0) return nullptr; // Duplicate. + if (!ParseDuration(field, &method_params->timeout_)) return nullptr; + } else if (strcmp(field->key, "retryPolicy") == 0) { + if (method_params->retry_policy_ != nullptr) { + return nullptr; // Duplicate. + } + method_params->retry_policy_ = ParseRetryPolicy(field); + if (method_params->retry_policy_ == nullptr) return nullptr; + } + } + return method_params; +} + +} // namespace internal +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_result_parsing.h b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_result_parsing.h new file mode 100644 index 000000000..98a9d26c4 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/resolver_result_parsing.h @@ -0,0 +1,142 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H + +#include + +#include "src/core/ext/filters/client_channel/retry_throttle.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis +#include "src/core/lib/json/json.h" +#include "src/core/lib/slice/slice_hash_table.h" +#include "src/core/lib/transport/service_config.h" + +namespace grpc_core { +namespace internal { + +class ClientChannelMethodParams; + +// A table mapping from a method name to its method parameters. +typedef SliceHashTable> + ClientChannelMethodParamsTable; + +// A container of processed fields from the resolver result. Simplifies the +// usage of resolver result. +class ProcessedResolverResult { + public: + // Processes the resolver result and populates the relative members + // for later consumption. Tries to parse retry parameters only if parse_retry + // is true. + ProcessedResolverResult(const grpc_channel_args& resolver_result, + bool parse_retry); + + // Getters. Any managed object's ownership is transferred. + UniquePtr service_config_json() { + return std::move(service_config_json_); + } + RefCountedPtr retry_throttle_data() { + return std::move(retry_throttle_data_); + } + RefCountedPtr method_params_table() { + return std::move(method_params_table_); + } + UniquePtr lb_policy_name() { return std::move(lb_policy_name_); } + grpc_json* lb_policy_config() { return lb_policy_config_; } + + private: + // Finds the service config; extracts LB config and (maybe) retry throttle + // params from it. + void ProcessServiceConfig(const grpc_channel_args& resolver_result, + bool parse_retry); + + // Finds the LB policy name (when no LB config was found). + void ProcessLbPolicyName(const grpc_channel_args& resolver_result); + + // Parses the service config. Intended to be used by + // ServiceConfig::ParseGlobalParams. + static void ParseServiceConfig(const grpc_json* field, + ProcessedResolverResult* parsing_state); + // Parses the LB config from service config. + void ParseLbConfigFromServiceConfig(const grpc_json* field); + // Parses the retry throttle parameters from service config. + void ParseRetryThrottleParamsFromServiceConfig(const grpc_json* field); + + // Service config. + UniquePtr service_config_json_; + UniquePtr service_config_; + // LB policy. + grpc_json* lb_policy_config_ = nullptr; + UniquePtr lb_policy_name_; + // Retry throttle data. + char* server_name_ = nullptr; + RefCountedPtr retry_throttle_data_; + // Method params table. + RefCountedPtr method_params_table_; +}; + +// The parameters of a method. +class ClientChannelMethodParams : public RefCounted { + public: + enum WaitForReady { + WAIT_FOR_READY_UNSET = 0, + WAIT_FOR_READY_FALSE, + WAIT_FOR_READY_TRUE + }; + + struct RetryPolicy { + int max_attempts = 0; + grpc_millis initial_backoff = 0; + grpc_millis max_backoff = 0; + float backoff_multiplier = 0; + StatusCodeSet retryable_status_codes; + }; + + /// Creates a method_parameters object from \a json. + /// Intended for use with ServiceConfig::CreateMethodConfigTable(). + static RefCountedPtr CreateFromJson( + const grpc_json* json); + + grpc_millis timeout() const { return timeout_; } + WaitForReady wait_for_ready() const { return wait_for_ready_; } + const RetryPolicy* retry_policy() const { return retry_policy_.get(); } + + private: + // So New() can call our private ctor. + template + friend T* grpc_core::New(Args&&... args); + + // So Delete() can call our private dtor. + template + friend void grpc_core::Delete(T*); + + ClientChannelMethodParams() {} + virtual ~ClientChannelMethodParams() {} + + grpc_millis timeout_ = 0; + WaitForReady wait_for_ready_ = WAIT_FOR_READY_UNSET; + UniquePtr retry_policy_; +}; + +} // namespace internal +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/server_address.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/server_address.cc new file mode 100644 index 000000000..ec33cbbd9 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/server_address.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/filters/client_channel/server_address.h" + +#include + +namespace grpc_core { + +// +// ServerAddress +// + +ServerAddress::ServerAddress(const grpc_resolved_address& address, + grpc_channel_args* args) + : address_(address), args_(args) {} + +ServerAddress::ServerAddress(const void* address, size_t address_len, + grpc_channel_args* args) + : args_(args) { + memcpy(address_.addr, address, address_len); + address_.len = static_cast(address_len); +} + +int ServerAddress::Cmp(const ServerAddress& other) const { + if (address_.len > other.address_.len) return 1; + if (address_.len < other.address_.len) return -1; + int retval = memcmp(address_.addr, other.address_.addr, address_.len); + if (retval != 0) return retval; + return grpc_channel_args_compare(args_, other.args_); +} + +bool ServerAddress::IsBalancer() const { + return grpc_channel_arg_get_bool( + grpc_channel_args_find(args_, GRPC_ARG_ADDRESS_IS_BALANCER), false); +} + +// +// ServerAddressList +// + +namespace { + +void* ServerAddressListCopy(void* addresses) { + ServerAddressList* a = static_cast(addresses); + return New(*a); +} + +void ServerAddressListDestroy(void* addresses) { + ServerAddressList* a = static_cast(addresses); + Delete(a); +} + +int ServerAddressListCompare(void* addresses1, void* addresses2) { + ServerAddressList* a1 = static_cast(addresses1); + ServerAddressList* a2 = static_cast(addresses2); + if (a1->size() > a2->size()) return 1; + if (a1->size() < a2->size()) return -1; + for (size_t i = 0; i < a1->size(); ++i) { + int retval = (*a1)[i].Cmp((*a2)[i]); + if (retval != 0) return retval; + } + return 0; +} + +const grpc_arg_pointer_vtable server_addresses_arg_vtable = { + ServerAddressListCopy, ServerAddressListDestroy, ServerAddressListCompare}; + +} // namespace + +grpc_arg CreateServerAddressListChannelArg(const ServerAddressList* addresses) { + return grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_SERVER_ADDRESS_LIST), + const_cast(addresses), &server_addresses_arg_vtable); +} + +ServerAddressList* FindServerAddressListChannelArg( + const grpc_channel_args* channel_args) { + const grpc_arg* lb_addresses_arg = + grpc_channel_args_find(channel_args, GRPC_ARG_SERVER_ADDRESS_LIST); + if (lb_addresses_arg == nullptr || lb_addresses_arg->type != GRPC_ARG_POINTER) + return nullptr; + return static_cast(lb_addresses_arg->value.pointer.p); +} + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/server_address.h b/Sources/CgRPC/src/core/ext/filters/client_channel/server_address.h new file mode 100644 index 000000000..3a1bf1df6 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/server_address.h @@ -0,0 +1,108 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H + +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/uri/uri_parser.h" + +// Channel arg key for ServerAddressList. +#define GRPC_ARG_SERVER_ADDRESS_LIST "grpc.server_address_list" + +// Channel arg key for a bool indicating whether an address is a grpclb +// load balancer (as opposed to a backend). +#define GRPC_ARG_ADDRESS_IS_BALANCER "grpc.address_is_balancer" + +// Channel arg key for a string indicating an address's balancer name. +#define GRPC_ARG_ADDRESS_BALANCER_NAME "grpc.address_balancer_name" + +namespace grpc_core { + +// +// ServerAddress +// + +// A server address is a grpc_resolved_address with an associated set of +// channel args. Any args present here will be merged into the channel +// args when a subchannel is created for this address. +class ServerAddress { + public: + // Takes ownership of args. + ServerAddress(const grpc_resolved_address& address, grpc_channel_args* args); + ServerAddress(const void* address, size_t address_len, + grpc_channel_args* args); + + ~ServerAddress() { grpc_channel_args_destroy(args_); } + + // Copyable. + ServerAddress(const ServerAddress& other) + : address_(other.address_), args_(grpc_channel_args_copy(other.args_)) {} + ServerAddress& operator=(const ServerAddress& other) { + address_ = other.address_; + grpc_channel_args_destroy(args_); + args_ = grpc_channel_args_copy(other.args_); + return *this; + } + + // Movable. + ServerAddress(ServerAddress&& other) + : address_(other.address_), args_(other.args_) { + other.args_ = nullptr; + } + ServerAddress& operator=(ServerAddress&& other) { + address_ = other.address_; + args_ = other.args_; + other.args_ = nullptr; + return *this; + } + + bool operator==(const ServerAddress& other) const { return Cmp(other) == 0; } + + int Cmp(const ServerAddress& other) const; + + const grpc_resolved_address& address() const { return address_; } + const grpc_channel_args* args() const { return args_; } + + bool IsBalancer() const; + + private: + grpc_resolved_address address_; + grpc_channel_args* args_; +}; + +// +// ServerAddressList +// + +typedef InlinedVector ServerAddressList; + +// Returns a channel arg containing \a addresses. +grpc_arg CreateServerAddressListChannelArg(const ServerAddressList* addresses); + +// Returns the ServerListAddress instance in channel_args or NULL. +ServerAddressList* FindServerAddressListChannelArg( + const grpc_channel_args* channel_args); + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.cc index d7815fb7e..1a07edad0 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.cc +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.cc @@ -30,244 +30,461 @@ #include #include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/health/health_check_client.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" -#include "src/core/ext/filters/client_channel/subchannel_index.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/debug/stats.h" +#include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" -#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/connectivity_state.h" +#include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/transport/service_config.h" +#include "src/core/lib/transport/status_metadata.h" +#include "src/core/lib/uri/uri_parser.h" +// Strong and weak refs. #define INTERNAL_REF_BITS 16 #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1)) +// Backoff parameters. #define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_SUBCHANNEL_RECONNECT_MIN_TIMEOUT_SECONDS 20 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 -namespace { -struct state_watcher { - grpc_closure closure; - grpc_subchannel* subchannel; - grpc_connectivity_state connectivity_state; -}; -} // namespace +// Conversion between subchannel call and call stack. +#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ + (grpc_call_stack*)((char*)(call) + \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) +#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \ + (SubchannelCall*)(((char*)(call_stack)) - \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) -typedef struct external_state_watcher { - grpc_subchannel* subchannel; - grpc_pollset_set* pollset_set; - grpc_closure* notify; - grpc_closure closure; - struct external_state_watcher* next; - struct external_state_watcher* prev; -} external_state_watcher; - -struct grpc_subchannel { - grpc_connector* connector; +namespace grpc_core { - /** refcount - - lower INTERNAL_REF_BITS bits are for internal references: - these do not keep the subchannel open. - - upper remaining bits are for public references: these do - keep the subchannel open */ - gpr_atm ref_pair; +// +// ConnectedSubchannel +// - /** non-transport related channel filters */ - const grpc_channel_filter** filters; - size_t num_filters; - /** channel arguments */ - grpc_channel_args* args; +ConnectedSubchannel::ConnectedSubchannel( + grpc_channel_stack* channel_stack, const grpc_channel_args* args, + RefCountedPtr channelz_subchannel, + intptr_t socket_uuid) + : RefCounted(&grpc_trace_stream_refcount), + channel_stack_(channel_stack), + args_(grpc_channel_args_copy(args)), + channelz_subchannel_(std::move(channelz_subchannel)), + socket_uuid_(socket_uuid) {} - grpc_subchannel_key* key; +ConnectedSubchannel::~ConnectedSubchannel() { + grpc_channel_args_destroy(args_); + GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); +} - /** set during connection */ - grpc_connect_out_args connecting_result; +void ConnectedSubchannel::NotifyOnStateChange( + grpc_pollset_set* interested_parties, grpc_connectivity_state* state, + grpc_closure* closure) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->connectivity_state = state; + op->on_connectivity_state_change = closure; + op->bind_pollset_set = interested_parties; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} - /** callback for connection finishing */ - grpc_closure on_connected; +void ConnectedSubchannel::Ping(grpc_closure* on_initiate, + grpc_closure* on_ack) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->send_ping.on_initiate = on_initiate; + op->send_ping.on_ack = on_ack; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} - /** callback for our alarm */ - grpc_closure on_alarm; +RefCountedPtr ConnectedSubchannel::CreateCall( + const CallArgs& args, grpc_error** error) { + const size_t allocation_size = + GetInitialCallSizeEstimate(args.parent_data_size); + RefCountedPtr call( + new (gpr_arena_alloc(args.arena, allocation_size)) + SubchannelCall(Ref(DEBUG_LOCATION, "subchannel_call"), args)); + grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call.get()); + const grpc_call_element_args call_args = { + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner /* call_combiner */ + }; + *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCall::Destroy, + call.get(), &call_args); + if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { + const char* error_string = grpc_error_string(*error); + gpr_log(GPR_ERROR, "error: %s", error_string); + return call; + } + grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + } + return call; +} - /** pollset_set tracking who's interested in a connection - being setup */ - grpc_pollset_set* pollset_set; +size_t ConnectedSubchannel::GetInitialCallSizeEstimate( + size_t parent_data_size) const { + size_t allocation_size = + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)); + if (parent_data_size > 0) { + allocation_size += + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + + parent_data_size; + } else { + allocation_size += channel_stack_->call_stack_size; + } + return allocation_size; +} - /** mutex protecting remaining elements */ - gpr_mu mu; - - /** active connection, or null; of type grpc_core::ConnectedSubchannel - */ - grpc_core::RefCountedPtr connected_subchannel; - - /** have we seen a disconnection? */ - bool disconnected; - /** are we connecting */ - bool connecting; - /** connectivity state tracking */ - grpc_connectivity_state_tracker state_tracker; - - external_state_watcher root_external_state_watcher; - - /** backoff state */ - grpc_core::ManualConstructor backoff; - grpc_millis next_attempt_deadline; - grpc_millis min_connect_timeout_ms; - - /** do we have an active alarm? */ - bool have_alarm; - /** have we started the backoff loop */ - bool backoff_begun; - /** our alarm */ - grpc_timer alarm; -}; +// +// SubchannelCall +// -struct grpc_subchannel_call { - grpc_core::ConnectedSubchannel* connection; - grpc_closure* schedule_closure_after_destroy; -}; +void SubchannelCall::StartTransportStreamOpBatch( + grpc_transport_stream_op_batch* batch) { + GPR_TIMER_SCOPE("subchannel_call_process_op", 0); + MaybeInterceptRecvTrailingMetadata(batch); + grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this); + grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); + GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); + top_elem->filter->start_transport_stream_op_batch(top_elem, batch); +} -#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack*)((call) + 1)) -#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ - (((grpc_subchannel_call*)(callstack)) - 1) +void* SubchannelCall::GetParentData() { + grpc_channel_stack* chanstk = connected_subchannel_->channel_stack(); + return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); +} -static void on_subchannel_connected(void* subchannel, grpc_error* error); +grpc_call_stack* SubchannelCall::GetCallStack() { + return SUBCHANNEL_CALL_TO_CALL_STACK(this); +} -#ifndef NDEBUG -#define REF_REASON reason -#define REF_MUTATE_EXTRA_ARGS \ - GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose -#define REF_MUTATE_PURPOSE(x) , file, line, reason, x -#else -#define REF_REASON "" -#define REF_MUTATE_EXTRA_ARGS -#define REF_MUTATE_PURPOSE(x) -#endif +void SubchannelCall::SetAfterCallStackDestroy(grpc_closure* closure) { + GPR_ASSERT(after_call_stack_destroy_ == nullptr); + GPR_ASSERT(closure != nullptr); + after_call_stack_destroy_ = closure; +} -/* - * connection implementation - */ +RefCountedPtr SubchannelCall::Ref() { + IncrementRefCount(); + return RefCountedPtr(this); +} -static void connection_destroy(void* arg, grpc_error* error) { - grpc_channel_stack* stk = static_cast(arg); - grpc_channel_stack_destroy(stk); - gpr_free(stk); +RefCountedPtr SubchannelCall::Ref( + const grpc_core::DebugLocation& location, const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr(this); } -/* - * grpc_subchannel implementation - */ +void SubchannelCall::Unref() { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); +} -static void subchannel_destroy(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - gpr_free((void*)c->filters); - grpc_channel_args_destroy(c->args); - grpc_connectivity_state_destroy(&c->state_tracker); - grpc_connector_unref(c->connector); - grpc_pollset_set_destroy(c->pollset_set); - grpc_subchannel_key_destroy(c->key); - gpr_mu_destroy(&c->mu); - gpr_free(c); -} - -static gpr_atm ref_mutate(grpc_subchannel* c, gpr_atm delta, - int barrier REF_MUTATE_EXTRA_ARGS) { - gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) - : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); -#ifndef NDEBUG - if (grpc_trace_stream_refcount.enabled()) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c, - purpose, old_val, old_val + delta, reason); - } -#endif - return old_val; +void SubchannelCall::Unref(const DebugLocation& location, const char* reason) { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); } -grpc_subchannel* grpc_subchannel_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS), - 0 REF_MUTATE_PURPOSE("STRONG_REF")); - GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); - return c; +void SubchannelCall::Destroy(void* arg, grpc_error* error) { + GPR_TIMER_SCOPE("subchannel_call_destroy", 0); + SubchannelCall* self = static_cast(arg); + // Keep some members before destroying the subchannel call. + grpc_closure* after_call_stack_destroy = self->after_call_stack_destroy_; + RefCountedPtr connected_subchannel = + std::move(self->connected_subchannel_); + // Destroy the subchannel call. + self->~SubchannelCall(); + // Destroy the call stack. This should be after destroying the subchannel + // call, because call->after_call_stack_destroy(), if not null, will free the + // call arena. + grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(self), nullptr, + after_call_stack_destroy); + // Automatically reset connected_subchannel. This should be after destroying + // the call stack, because destroying call stack needs access to the channel + // stack. } -grpc_subchannel* grpc_subchannel_weak_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF")); - GPR_ASSERT(old_refs != 0); - return c; +void SubchannelCall::MaybeInterceptRecvTrailingMetadata( + grpc_transport_stream_op_batch* batch) { + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (connected_subchannel_->channelz_subchannel() == nullptr) { + return; + } + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady, + this, grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(recv_trailing_metadata_ == nullptr); + recv_trailing_metadata_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + original_recv_trailing_metadata_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &recv_trailing_metadata_ready_; } -grpc_subchannel* grpc_subchannel_ref_from_weak_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - if (!c) return nullptr; - for (;;) { - gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair); - if (old_refs >= (1 << INTERNAL_REF_BITS)) { - gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); - if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) { - return c; - } +namespace { + +// Sets *status based on the rest of the parameters. +void GetCallStatus(grpc_status_code* status, grpc_millis deadline, + grpc_metadata_batch* md_batch, grpc_error* error) { + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); + } else { + if (md_batch->idx.named.grpc_status != nullptr) { + *status = grpc_get_status_code_from_metadata( + md_batch->idx.named.grpc_status->md); } else { - return nullptr; + *status = GRPC_STATUS_UNKNOWN; } } + GRPC_ERROR_UNREF(error); } -static void disconnect(grpc_subchannel* c) { - grpc_subchannel_index_unregister(c->key, c); - gpr_mu_lock(&c->mu); - GPR_ASSERT(!c->disconnected); - c->disconnected = true; - grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Subchannel disconnected")); - c->connected_subchannel.reset(); - gpr_mu_unlock(&c->mu); -} +} // namespace -void grpc_subchannel_unref(grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - // add a weak ref and subtract a strong ref (atomically) - old_refs = ref_mutate( - c, static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), - 1 REF_MUTATE_PURPOSE("STRONG_UNREF")); - if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { - disconnect(c); +void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) { + SubchannelCall* call = static_cast(arg); + GPR_ASSERT(call->recv_trailing_metadata_ != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + GetCallStatus(&status, call->deadline_, call->recv_trailing_metadata_, + GRPC_ERROR_REF(error)); + channelz::SubchannelNode* channelz_subchannel = + call->connected_subchannel_->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); } - GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref"); + GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_, + GRPC_ERROR_REF(error)); } -void grpc_subchannel_weak_unref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, -static_cast(1), - 1 REF_MUTATE_PURPOSE("WEAK_UNREF")); - if (old_refs == 1) { - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx), - GRPC_ERROR_NONE); - } +void SubchannelCall::IncrementRefCount() { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); } -static void parse_args_for_backoff_values( - const grpc_channel_args* args, grpc_core::BackOff::Options* backoff_options, - grpc_millis* min_connect_timeout_ms) { +void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location, + const char* reason) { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); +} + +// +// Subchannel::ConnectedSubchannelStateWatcher +// + +class Subchannel::ConnectedSubchannelStateWatcher + : public InternallyRefCounted { + public: + // Must be instantiated while holding c->mu. + explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) { + // Steal subchannel ref for connecting. + GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); + GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); + // Start watching for connectivity state changes. + // Callback uses initial ref to this. + GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this, + grpc_schedule_on_exec_ctx); + c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_, + &pending_connectivity_state_, + &on_connectivity_changed_); + // Start health check if needed. + grpc_connectivity_state health_state = GRPC_CHANNEL_READY; + if (c->health_check_service_name_ != nullptr) { + health_check_client_ = MakeOrphanable( + c->health_check_service_name_.get(), c->connected_subchannel_, + c->pollset_set_, c->channelz_node_); + GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this, + grpc_schedule_on_exec_ctx); + Ref().release(); // Ref for health callback tracked manually. + health_check_client_->NotifyOnHealthChange(&health_state_, + &on_health_changed_); + health_state = GRPC_CHANNEL_CONNECTING; + } + // Report initial state. + c->SetConnectivityStateLocked(GRPC_CHANNEL_READY, GRPC_ERROR_NONE, + "subchannel_connected"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, health_state, + GRPC_ERROR_NONE, "subchannel_connected"); + } + + ~ConnectedSubchannelStateWatcher() { + GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher"); + } + + // Must be called while holding subchannel_->mu. + void Orphan() override { health_check_client_.reset(); } + + private: + static void OnConnectivityChanged(void* arg, grpc_error* error) { + auto* self = static_cast(arg); + Subchannel* c = self->subchannel_; + { + MutexLock lock(&c->mu_); + switch (self->pending_connectivity_state_) { + case GRPC_CHANNEL_TRANSIENT_FAILURE: + case GRPC_CHANNEL_SHUTDOWN: { + if (!c->disconnected_ && c->connected_subchannel_ != nullptr) { + if (grpc_trace_stream_refcount.enabled()) { + gpr_log(GPR_INFO, + "Connected subchannel %p of subchannel %p has gone into " + "%s. Attempting to reconnect.", + c->connected_subchannel_.get(), c, + grpc_connectivity_state_name( + self->pending_connectivity_state_)); + } + c->connected_subchannel_.reset(); + c->connected_subchannel_watcher_.reset(); + self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE; + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), + "reflect_child"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, + GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), "reflect_child"); + c->backoff_begun_ = false; + c->backoff_.Reset(); + c->MaybeStartConnectingLocked(); + } else { + self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN; + } + self->health_check_client_.reset(); + break; + } + default: { + // In principle, this should never happen. We should not get + // a callback for READY, because that was the state we started + // this watch from. And a connected subchannel should never go + // from READY to CONNECTING or IDLE. + self->last_connectivity_state_ = self->pending_connectivity_state_; + c->SetConnectivityStateLocked(self->pending_connectivity_state_, + GRPC_ERROR_REF(error), "reflect_child"); + if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) { + grpc_connectivity_state_set(&c->state_and_health_tracker_, + self->pending_connectivity_state_, + GRPC_ERROR_REF(error), "reflect_child"); + } + c->connected_subchannel_->NotifyOnStateChange( + nullptr, &self->pending_connectivity_state_, + &self->on_connectivity_changed_); + self = nullptr; // So we don't unref below. + } + } + } + // Don't unref until we've released the lock, because this might + // cause the subchannel (which contains the lock) to be destroyed. + if (self != nullptr) self->Unref(); + } + + static void OnHealthChanged(void* arg, grpc_error* error) { + auto* self = static_cast(arg); + Subchannel* c = self->subchannel_; + { + MutexLock lock(&c->mu_); + if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN && + self->health_check_client_ != nullptr) { + if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { + grpc_connectivity_state_set(&c->state_and_health_tracker_, + self->health_state_, + GRPC_ERROR_REF(error), "health_changed"); + } + self->health_check_client_->NotifyOnHealthChange( + &self->health_state_, &self->on_health_changed_); + self = nullptr; // So we don't unref below. + } + } + // Don't unref until we've released the lock, because this might + // cause the subchannel (which contains the lock) to be destroyed. + if (self != nullptr) self->Unref(); + } + + Subchannel* subchannel_; + grpc_closure on_connectivity_changed_; + grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY; + grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY; + OrphanablePtr health_check_client_; + grpc_closure on_health_changed_; + grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING; +}; + +// +// Subchannel::ExternalStateWatcher +// + +struct Subchannel::ExternalStateWatcher { + ExternalStateWatcher(Subchannel* subchannel, grpc_pollset_set* pollset_set, + grpc_closure* notify) + : subchannel(subchannel), pollset_set(pollset_set), notify(notify) { + GRPC_SUBCHANNEL_WEAK_REF(subchannel, "external_state_watcher+init"); + GRPC_CLOSURE_INIT(&on_state_changed, OnStateChanged, this, + grpc_schedule_on_exec_ctx); + } + + static void OnStateChanged(void* arg, grpc_error* error) { + ExternalStateWatcher* w = static_cast(arg); + grpc_closure* follow_up = w->notify; + if (w->pollset_set != nullptr) { + grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, + w->pollset_set); + } + gpr_mu_lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; + } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; + gpr_mu_unlock(&w->subchannel->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); + Delete(w); + GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); + } + + Subchannel* subchannel; + grpc_pollset_set* pollset_set; + grpc_closure* notify; + grpc_closure on_state_changed; + ExternalStateWatcher* next = nullptr; + ExternalStateWatcher* prev = nullptr; +}; + +// +// Subchannel +// + +namespace { + +BackOff::Options ParseArgsForBackoffValues( + const grpc_channel_args* args, grpc_millis* min_connect_timeout_ms) { grpc_millis initial_backoff_ms = GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000; *min_connect_timeout_ms = @@ -304,7 +521,8 @@ static void parse_args_for_backoff_values( } } } - backoff_options->set_initial_backoff(initial_backoff_ms) + return BackOff::Options() + .set_initial_backoff(initial_backoff_ms) .set_multiplier(fixed_reconnect_backoff ? 1.0 : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER) @@ -313,330 +531,439 @@ static void parse_args_for_backoff_values( .set_max_backoff(max_backoff_ms); } -grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_subchannel_args* args) { - grpc_subchannel_key* key = grpc_subchannel_key_create(args); - grpc_subchannel* c = grpc_subchannel_index_find(key); - if (c) { - grpc_subchannel_key_destroy(key); - return c; +struct HealthCheckParams { + UniquePtr service_name; + + static void Parse(const grpc_json* field, HealthCheckParams* params) { + if (strcmp(field->key, "healthCheckConfig") == 0) { + if (field->type != GRPC_JSON_OBJECT) return; + for (grpc_json* sub_field = field->child; sub_field != nullptr; + sub_field = sub_field->next) { + if (sub_field->key == nullptr) return; + if (strcmp(sub_field->key, "serviceName") == 0) { + if (params->service_name != nullptr) return; // Duplicate. + if (sub_field->type != GRPC_JSON_STRING) return; + params->service_name.reset(gpr_strdup(sub_field->value)); + } + } + } } +}; + +} // namespace +Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, + const grpc_channel_args* args) + : key_(key), + connector_(connector), + backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) { GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(); - c = static_cast(gpr_zalloc(sizeof(*c))); - c->key = key; - gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); - c->connector = connector; - grpc_connector_ref(c->connector); - c->num_filters = args->filter_count; - if (c->num_filters > 0) { - c->filters = static_cast( - gpr_malloc(sizeof(grpc_channel_filter*) * c->num_filters)); - memcpy((void*)c->filters, args->filters, - sizeof(grpc_channel_filter*) * c->num_filters); - } else { - c->filters = nullptr; - } - c->pollset_set = grpc_pollset_set_create(); + gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS); + grpc_connector_ref(connector_); + pollset_set_ = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); - grpc_get_subchannel_address_arg(args->args, addr); + GetAddressFromSubchannelAddressArg(args, addr); grpc_resolved_address* new_address = nullptr; grpc_channel_args* new_args = nullptr; - if (grpc_proxy_mappers_map_address(addr, args->args, &new_address, - &new_args)) { + if (grpc_proxy_mappers_map_address(addr, args, &new_address, &new_args)) { GPR_ASSERT(new_address != nullptr); gpr_free(addr); addr = new_address; } static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; - grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); + grpc_arg new_arg = CreateSubchannelAddressArg(addr); gpr_free(addr); - c->args = grpc_channel_args_copy_and_add_and_remove( - new_args != nullptr ? new_args : args->args, keys_to_remove, + args_ = grpc_channel_args_copy_and_add_and_remove( + new_args != nullptr ? new_args : args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); gpr_free(new_arg.value.string); if (new_args != nullptr) grpc_channel_args_destroy(new_args); - c->root_external_state_watcher.next = c->root_external_state_watcher.prev = - &c->root_external_state_watcher; - GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c, + GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this, grpc_schedule_on_exec_ctx); - grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - grpc_core::BackOff::Options backoff_options; - parse_args_for_backoff_values(args->args, &backoff_options, - &c->min_connect_timeout_ms); - c->backoff.Init(backoff_options); - gpr_mu_init(&c->mu); - - return grpc_subchannel_index_register(key, c); + grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, + "subchannel"); + gpr_mu_init(&mu_); + // Check whether we should enable health checking. + const char* service_config_json = grpc_channel_arg_get_string( + grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); + if (service_config_json != nullptr) { + UniquePtr service_config = + ServiceConfig::Create(service_config_json); + if (service_config != nullptr) { + HealthCheckParams params; + service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); + health_check_service_name_ = std::move(params.service_name); + } + } + const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ); + const bool channelz_enabled = + grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT); + arg = grpc_channel_args_find( + args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); + const grpc_integer_options options = { + GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX}; + size_t channel_tracer_max_memory = + (size_t)grpc_channel_arg_get_integer(arg, options); + if (channelz_enabled) { + channelz_node_ = MakeRefCounted( + this, channel_tracer_max_memory); + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel created")); + } } -static void continue_connect_locked(grpc_subchannel* c) { - grpc_connect_in_args args; - args.interested_parties = c->pollset_set; - const grpc_millis min_deadline = - c->min_connect_timeout_ms + grpc_core::ExecCtx::Get()->Now(); - c->next_attempt_deadline = c->backoff->NextAttemptTime(); - args.deadline = std::max(c->next_attempt_deadline, min_deadline); - args.channel_args = c->args; - grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_CONNECTING, - GRPC_ERROR_NONE, "state_change"); - grpc_connector_connect(c->connector, &args, &c->connecting_result, - &c->on_connected); -} - -grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel* c, - grpc_error** error) { - grpc_connectivity_state state; - gpr_mu_lock(&c->mu); - state = grpc_connectivity_state_get(&c->state_tracker, error); - gpr_mu_unlock(&c->mu); - return state; +Subchannel::~Subchannel() { + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel destroyed")); + channelz_node_->MarkSubchannelDestroyed(); + } + grpc_channel_args_destroy(args_); + grpc_connectivity_state_destroy(&state_tracker_); + grpc_connectivity_state_destroy(&state_and_health_tracker_); + grpc_connector_unref(connector_); + grpc_pollset_set_destroy(pollset_set_); + Delete(key_); + gpr_mu_destroy(&mu_); } -static void on_external_state_watcher_done(void* arg, grpc_error* error) { - external_state_watcher* w = static_cast(arg); - grpc_closure* follow_up = w->notify; - if (w->pollset_set != nullptr) { - grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set, - w->pollset_set); +Subchannel* Subchannel::Create(grpc_connector* connector, + const grpc_channel_args* args) { + SubchannelKey* key = New(args); + SubchannelPoolInterface* subchannel_pool = + SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args); + GPR_ASSERT(subchannel_pool != nullptr); + Subchannel* c = subchannel_pool->FindSubchannel(key); + if (c != nullptr) { + Delete(key); + return c; } - gpr_mu_lock(&w->subchannel->mu); - w->next->prev = w->prev; - w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher"); - gpr_free(w); - GRPC_CLOSURE_RUN(follow_up, GRPC_ERROR_REF(error)); + c = New(key, connector, args); + // Try to register the subchannel before setting the subchannel pool. + // Otherwise, in case of a registration race, unreffing c in + // RegisterSubchannel() will cause c to be tried to be unregistered, while + // its key maps to a different subchannel. + Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); + if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref(); + return registered; } -static void on_alarm(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu); - c->have_alarm = false; - if (c->disconnected) { - error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", - &error, 1); - } else { - GRPC_ERROR_REF(error); - } - if (error == GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); - continue_connect_locked(c); - gpr_mu_unlock(&c->mu); - } else { - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } - GRPC_ERROR_UNREF(error); +Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate((1 << INTERNAL_REF_BITS), + 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF")); + GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); + return this; } -static void maybe_start_connecting_locked(grpc_subchannel* c) { - if (c->disconnected) { - /* Don't try to connect if we're already disconnected */ - return; +void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + // add a weak ref and subtract a strong ref (atomically) + old_refs = RefMutate( + static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), + 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF")); + if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { + Disconnect(); } + GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref"); +} - if (c->connecting) { - /* Already connecting: don't restart */ - return; - } +Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF")); + GPR_ASSERT(old_refs != 0); + return this; +} - if (c->connected_subchannel != nullptr) { - /* Already connected: don't restart */ - return; - } +namespace { - if (!grpc_connectivity_state_has_watchers(&c->state_tracker)) { - /* Nobody is interested in connecting: so don't just yet */ - return; - } +void subchannel_destroy(void* arg, grpc_error* error) { + Subchannel* self = static_cast(arg); + Delete(self); +} - c->connecting = true; - GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); +} // namespace - if (!c->backoff_begun) { - c->backoff_begun = true; - continue_connect_locked(c); - } else { - GPR_ASSERT(!c->have_alarm); - c->have_alarm = true; - const grpc_millis time_til_next = - c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now(); - if (time_til_next <= 0) { - gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c); +void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate(-static_cast(1), + 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF")); + if (old_refs == 1) { + GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(subchannel_destroy, this, + grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); + } +} + +Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + for (;;) { + gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_); + if (old_refs >= (1 << INTERNAL_REF_BITS)) { + gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); + if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) { + return this; + } } else { - gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRIdPTR " milliseconds", c, - time_til_next); + return nullptr; } - GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); - grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm); } } -void grpc_subchannel_notify_on_state_change( - grpc_subchannel* c, grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify) { - external_state_watcher* w; +intptr_t Subchannel::GetChildSocketUuid() { + if (connected_subchannel_ != nullptr) { + return connected_subchannel_->socket_uuid(); + } else { + return 0; + } +} + +const char* Subchannel::GetTargetAddress() { + const grpc_arg* addr_arg = + grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; +} + +RefCountedPtr Subchannel::connected_subchannel() { + MutexLock lock(&mu_); + return connected_subchannel_; +} +channelz::SubchannelNode* Subchannel::channelz_node() { + return channelz_node_.get(); +} + +grpc_connectivity_state Subchannel::CheckConnectivity( + grpc_error** error, bool inhibit_health_checking) { + MutexLock lock(&mu_); + grpc_connectivity_state_tracker* tracker = + inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_; + grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); + return state; +} + +void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, + grpc_closure* notify, + bool inhibit_health_checking) { + grpc_connectivity_state_tracker* tracker = + inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_; + ExternalStateWatcher* w; if (state == nullptr) { - gpr_mu_lock(&c->mu); - for (w = c->root_external_state_watcher.next; - w != &c->root_external_state_watcher; w = w->next) { + MutexLock lock(&mu_); + for (w = external_state_watcher_list_; w != nullptr; w = w->next) { if (w->notify == notify) { - grpc_connectivity_state_notify_on_state_change(&c->state_tracker, - nullptr, &w->closure); + grpc_connectivity_state_notify_on_state_change(tracker, nullptr, + &w->on_state_changed); } } - gpr_mu_unlock(&c->mu); } else { - w = static_cast(gpr_malloc(sizeof(*w))); - w->subchannel = c; - w->pollset_set = interested_parties; - w->notify = notify; - GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w, - grpc_schedule_on_exec_ctx); + w = New(this, interested_parties, notify); if (interested_parties != nullptr) { - grpc_pollset_set_add_pollset_set(c->pollset_set, interested_parties); + grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties); + } + MutexLock lock(&mu_); + if (external_state_watcher_list_ != nullptr) { + w->next = external_state_watcher_list_; + w->next->prev = w; } - GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher"); - gpr_mu_lock(&c->mu); - w->next = &c->root_external_state_watcher; - w->prev = w->next->prev; - w->next->prev = w->prev->next = w; - grpc_connectivity_state_notify_on_state_change(&c->state_tracker, state, - &w->closure); - maybe_start_connecting_locked(c); - gpr_mu_unlock(&c->mu); + external_state_watcher_list_ = w; + grpc_connectivity_state_notify_on_state_change(tracker, state, + &w->on_state_changed); + MaybeStartConnectingLocked(); } } -static void on_connected_subchannel_connectivity_changed(void* p, - grpc_error* error) { - state_watcher* connected_subchannel_watcher = static_cast(p); - grpc_subchannel* c = connected_subchannel_watcher->subchannel; - gpr_mu* mu = &c->mu; +void Subchannel::ResetBackoff() { + MutexLock lock(&mu_); + backoff_.Reset(); + if (have_retry_alarm_) { + retry_immediately_ = true; + grpc_timer_cancel(&retry_alarm_); + } else { + backoff_begun_ = false; + MaybeStartConnectingLocked(); + } +} - gpr_mu_lock(mu); +grpc_arg Subchannel::CreateSubchannelAddressArg( + const grpc_resolved_address* addr) { + return grpc_channel_arg_string_create( + (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, + addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); +} - switch (connected_subchannel_watcher->connectivity_state) { - case GRPC_CHANNEL_TRANSIENT_FAILURE: - case GRPC_CHANNEL_SHUTDOWN: { - if (!c->disconnected && c->connected_subchannel != nullptr) { - if (grpc_trace_stream_refcount.enabled()) { - gpr_log(GPR_INFO, - "Connected subchannel %p of subchannel %p has gone into %s. " - "Attempting to reconnect.", - c->connected_subchannel.get(), c, - grpc_connectivity_state_name( - connected_subchannel_watcher->connectivity_state)); - } - c->connected_subchannel.reset(); - grpc_connectivity_state_set(&c->state_tracker, - GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), "reflect_child"); - c->backoff_begun = false; - c->backoff->Reset(); - maybe_start_connecting_locked(c); - } else { - connected_subchannel_watcher->connectivity_state = - GRPC_CHANNEL_SHUTDOWN; - } - break; - } - default: { - grpc_connectivity_state_set( - &c->state_tracker, connected_subchannel_watcher->connectivity_state, - GRPC_ERROR_REF(error), "reflect_child"); - GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); - c->connected_subchannel->NotifyOnStateChange( - nullptr, &connected_subchannel_watcher->connectivity_state, - &connected_subchannel_watcher->closure); - connected_subchannel_watcher = nullptr; - } - } - gpr_mu_unlock(mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "state_watcher"); - gpr_free(connected_subchannel_watcher); +const char* Subchannel::GetUriFromSubchannelAddressArg( + const grpc_channel_args* args) { + const grpc_arg* addr_arg = + grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; } -static bool publish_transport_locked(grpc_subchannel* c) { - /* construct channel stack */ - grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); - grpc_channel_stack_builder_set_channel_arguments( - builder, c->connecting_result.channel_args); - grpc_channel_stack_builder_set_transport(builder, - c->connecting_result.transport); +namespace { - if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { - grpc_channel_stack_builder_destroy(builder); - return false; +void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) { + grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); + GPR_ASSERT(uri != nullptr); + if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); + grpc_uri_destroy(uri); +} + +} // namespace + +void Subchannel::GetAddressFromSubchannelAddressArg( + const grpc_channel_args* args, grpc_resolved_address* addr) { + const char* addr_uri_str = GetUriFromSubchannelAddressArg(args); + memset(addr, 0, sizeof(*addr)); + if (*addr_uri_str != '\0') { + UriToSockaddr(addr_uri_str, addr); } - grpc_channel_stack* stk; - grpc_error* error = grpc_channel_stack_builder_finish( - builder, 0, 1, connection_destroy, nullptr, - reinterpret_cast(&stk)); - if (error != GRPC_ERROR_NONE) { - grpc_transport_destroy(c->connecting_result.transport); - gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); - return false; +} + +namespace { + +// Returns a string indicating the subchannel's connectivity state change to +// \a state. +const char* SubchannelConnectivityStateChangeString( + grpc_connectivity_state state) { + switch (state) { + case GRPC_CHANNEL_IDLE: + return "Subchannel state change to IDLE"; + case GRPC_CHANNEL_CONNECTING: + return "Subchannel state change to CONNECTING"; + case GRPC_CHANNEL_READY: + return "Subchannel state change to READY"; + case GRPC_CHANNEL_TRANSIENT_FAILURE: + return "Subchannel state change to TRANSIENT_FAILURE"; + case GRPC_CHANNEL_SHUTDOWN: + return "Subchannel state change to SHUTDOWN"; } - memset(&c->connecting_result, 0, sizeof(c->connecting_result)); + GPR_UNREACHABLE_CODE(return "UNKNOWN"); +} - /* initialize state watcher */ - state_watcher* connected_subchannel_watcher = static_cast( - gpr_zalloc(sizeof(*connected_subchannel_watcher))); - connected_subchannel_watcher->subchannel = c; - connected_subchannel_watcher->connectivity_state = GRPC_CHANNEL_READY; - GRPC_CLOSURE_INIT(&connected_subchannel_watcher->closure, - on_connected_subchannel_connectivity_changed, - connected_subchannel_watcher, grpc_schedule_on_exec_ctx); +} // namespace - if (c->disconnected) { - gpr_free(connected_subchannel_watcher); - grpc_channel_stack_destroy(stk); - gpr_free(stk); - return false; +void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, + const char* reason) { + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + SubchannelConnectivityStateChangeString(state))); } + grpc_connectivity_state_set(&state_tracker_, state, error, reason); +} - /* publish */ - c->connected_subchannel.reset( - grpc_core::New(stk)); - gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", - c->connected_subchannel.get(), c); - - /* setup subchannel watching connected subchannel for changes; subchannel - ref for connecting is donated to the state watcher */ - GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - c->connected_subchannel->NotifyOnStateChange( - c->pollset_set, &connected_subchannel_watcher->connectivity_state, - &connected_subchannel_watcher->closure); - - /* signal completion */ - grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_READY, - GRPC_ERROR_NONE, "connected"); - return true; +void Subchannel::MaybeStartConnectingLocked() { + if (disconnected_) { + // Don't try to connect if we're already disconnected. + return; + } + if (connecting_) { + // Already connecting: don't restart. + return; + } + if (connected_subchannel_ != nullptr) { + // Already connected: don't restart. + return; + } + if (!grpc_connectivity_state_has_watchers(&state_tracker_) && + !grpc_connectivity_state_has_watchers(&state_and_health_tracker_)) { + // Nobody is interested in connecting: so don't just yet. + return; + } + connecting_ = true; + GRPC_SUBCHANNEL_WEAK_REF(this, "connecting"); + if (!backoff_begun_) { + backoff_begun_ = true; + ContinueConnectingLocked(); + } else { + GPR_ASSERT(!have_retry_alarm_); + have_retry_alarm_ = true; + const grpc_millis time_til_next = + next_attempt_deadline_ - ExecCtx::Get()->Now(); + if (time_til_next <= 0) { + gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this); + } else { + gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", + this, time_til_next); + } + GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&retry_alarm_, next_attempt_deadline_, &on_retry_alarm_); + } } -static void on_subchannel_connected(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - grpc_channel_args* delete_channel_args = c->connecting_result.channel_args; +void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { + Subchannel* c = static_cast(arg); + gpr_mu_lock(&c->mu_); + c->have_retry_alarm_ = false; + if (c->disconnected_) { + error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", + &error, 1); + } else if (c->retry_immediately_) { + c->retry_immediately_ = false; + error = GRPC_ERROR_NONE; + } else { + GRPC_ERROR_REF(error); + } + if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); + c->ContinueConnectingLocked(); + gpr_mu_unlock(&c->mu_); + } else { + gpr_mu_unlock(&c->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } + GRPC_ERROR_UNREF(error); +} + +void Subchannel::ContinueConnectingLocked() { + grpc_connect_in_args args; + args.interested_parties = pollset_set_; + const grpc_millis min_deadline = + min_connect_timeout_ms_ + ExecCtx::Get()->Now(); + next_attempt_deadline_ = backoff_.NextAttemptTime(); + args.deadline = std::max(next_attempt_deadline_, min_deadline); + args.channel_args = args_; + SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connectivity_state_set(&state_and_health_tracker_, + GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connector_connect(connector_, &args, &connecting_result_, + &on_connecting_finished_); +} - GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected"); - gpr_mu_lock(&c->mu); - c->connecting = false; - if (c->connecting_result.transport != nullptr && - publish_transport_locked(c)) { - /* do nothing, transport was published */ - } else if (c->disconnected) { +void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { + auto* c = static_cast(arg); + grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; + GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); + gpr_mu_lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } else { + c->SetConnectivityStateLocked( + GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); grpc_connectivity_state_set( - &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, + &c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Connect Failed", &error, 1), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), @@ -645,171 +972,92 @@ static void on_subchannel_connected(void* arg, grpc_error* error) { const char* errmsg = grpc_error_string(error); gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - maybe_start_connecting_locked(c); + c->MaybeStartConnectingLocked(); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected"); + gpr_mu_unlock(&c->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); grpc_channel_args_destroy(delete_channel_args); } -/* - * grpc_subchannel_call implementation - */ - -static void subchannel_call_destroy(void* call, grpc_error* error) { - GPR_TIMER_SCOPE("grpc_subchannel_call_unref.destroy", 0); - grpc_subchannel_call* c = static_cast(call); - grpc_core::ConnectedSubchannel* connection = c->connection; - grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr, - c->schedule_closure_after_destroy); - connection->Unref(DEBUG_LOCATION, "subchannel_call"); -} - -void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call* call, - grpc_closure* closure) { - GPR_ASSERT(call->schedule_closure_after_destroy == nullptr); - GPR_ASSERT(closure != nullptr); - call->schedule_closure_after_destroy = closure; -} - -grpc_subchannel_call* grpc_subchannel_call_ref( - grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); - return c; -} - -void grpc_subchannel_call_unref( - grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); -} - -void grpc_subchannel_call_process_op(grpc_subchannel_call* call, - grpc_transport_stream_op_batch* batch) { - GPR_TIMER_SCOPE("grpc_subchannel_call_process_op", 0); - grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); - grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); - GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); - top_elem->filter->start_transport_stream_op_batch(top_elem, batch); -} - -grpc_core::RefCountedPtr -grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) { - gpr_mu_lock(&c->mu); - auto copy = c->connected_subchannel; - gpr_mu_unlock(&c->mu); - return copy; -} - -const grpc_subchannel_key* grpc_subchannel_get_key( - const grpc_subchannel* subchannel) { - return subchannel->key; -} - -void* grpc_connected_subchannel_call_get_parent_data( - grpc_subchannel_call* subchannel_call) { - grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack(); - return (char*)subchannel_call + sizeof(grpc_subchannel_call) + - chanstk->call_stack_size; -} +namespace { -grpc_call_stack* grpc_subchannel_call_get_call_stack( - grpc_subchannel_call* subchannel_call) { - return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); +void ConnectionDestroy(void* arg, grpc_error* error) { + grpc_channel_stack* stk = static_cast(arg); + grpc_channel_stack_destroy(stk); + gpr_free(stk); } -static void grpc_uri_to_sockaddr(const char* uri_str, - grpc_resolved_address* addr) { - grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); - GPR_ASSERT(uri != nullptr); - if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); - grpc_uri_destroy(uri); -} +} // namespace -void grpc_get_subchannel_address_arg(const grpc_channel_args* args, - grpc_resolved_address* addr) { - const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args); - memset(addr, 0, sizeof(*addr)); - if (*addr_uri_str != '\0') { - grpc_uri_to_sockaddr(addr_uri_str, addr); +bool Subchannel::PublishTransportLocked() { + // Construct channel stack. + grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); + grpc_channel_stack_builder_set_channel_arguments( + builder, connecting_result_.channel_args); + grpc_channel_stack_builder_set_transport(builder, + connecting_result_.transport); + if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { + grpc_channel_stack_builder_destroy(builder); + return false; } + grpc_channel_stack* stk; + grpc_error* error = grpc_channel_stack_builder_finish( + builder, 0, 1, ConnectionDestroy, nullptr, + reinterpret_cast(&stk)); + if (error != GRPC_ERROR_NONE) { + grpc_transport_destroy(connecting_result_.transport); + gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", + grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + return false; + } + intptr_t socket_uuid = connecting_result_.socket_uuid; + memset(&connecting_result_, 0, sizeof(connecting_result_)); + if (disconnected_) { + grpc_channel_stack_destroy(stk); + gpr_free(stk); + return false; + } + // Publish. + connected_subchannel_.reset( + New(stk, args_, channelz_node_, socket_uuid)); + gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", + connected_subchannel_.get(), this); + // Instantiate state watcher. Will clean itself up. + connected_subchannel_watcher_ = + MakeOrphanable(this); + return true; } -const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) { - const grpc_arg* addr_arg = - grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} - -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { - return grpc_channel_arg_string_create( - (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, - addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); -} - -namespace grpc_core { - -ConnectedSubchannel::ConnectedSubchannel(grpc_channel_stack* channel_stack) - : RefCountedWithTracing(&grpc_trace_stream_refcount), - channel_stack_(channel_stack) {} - -ConnectedSubchannel::~ConnectedSubchannel() { - GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); -} - -void ConnectedSubchannel::NotifyOnStateChange( - grpc_pollset_set* interested_parties, grpc_connectivity_state* state, - grpc_closure* closure) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->connectivity_state = state; - op->on_connectivity_state_change = closure; - op->bind_pollset_set = interested_parties; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} - -void ConnectedSubchannel::Ping(grpc_closure* on_initiate, - grpc_closure* on_ack) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->send_ping.on_initiate = on_initiate; - op->send_ping.on_ack = on_ack; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); +void Subchannel::Disconnect() { + // The subchannel_pool is only used once here in this subchannel, so the + // access can be outside of the lock. + if (subchannel_pool_ != nullptr) { + subchannel_pool_->UnregisterSubchannel(key_); + subchannel_pool_.reset(); + } + MutexLock lock(&mu_); + GPR_ASSERT(!disconnected_); + disconnected_ = true; + grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Subchannel disconnected")); + connected_subchannel_.reset(); + connected_subchannel_watcher_.reset(); } -grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, - grpc_subchannel_call** call) { - *call = static_cast(gpr_arena_alloc( - args.arena, sizeof(grpc_subchannel_call) + - channel_stack_->call_stack_size + args.parent_data_size)); - grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); - RefCountedPtr connection = - Ref(DEBUG_LOCATION, "subchannel_call"); - connection.release(); // Ref is passed to the grpc_subchannel_call object. - (*call)->connection = this; - const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ - }; - grpc_error* error = grpc_call_stack_init( - channel_stack_, 1, subchannel_call_destroy, *call, &call_args); - if (error != GRPC_ERROR_NONE) { - const char* error_string = grpc_error_string(error); - gpr_log(GPR_ERROR, "error: %s", error_string); - return error; +gpr_atm Subchannel::RefMutate( + gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) { + gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta) + : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta); +#ifndef NDEBUG + if (grpc_trace_stream_refcount.enabled()) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this, + purpose, old_val, old_val + delta, reason); } - grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); - return GRPC_ERROR_NONE; +#endif + return old_val; } } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.h b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.h index e23aec12d..bb8e45bf9 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.h +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel.h @@ -21,57 +21,53 @@ #include +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/connector.h" +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" // Channel arg containing a grpc_resolved_address to connect to. #define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" -/** A (sub-)channel that knows how to connect to exactly one target - address. Provides a target for load balancing. */ -typedef struct grpc_subchannel grpc_subchannel; -typedef struct grpc_subchannel_call grpc_subchannel_call; -typedef struct grpc_subchannel_args grpc_subchannel_args; -typedef struct grpc_subchannel_key grpc_subchannel_key; - +// For debugging refcounting. #ifndef NDEBUG -#define GRPC_SUBCHANNEL_REF(p, r) \ - grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref(__FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_UNREF(p, r) \ - grpc_subchannel_unref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \ - grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) \ - grpc_subchannel_weak_unref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_CALL_REF(p, r) \ - grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \ - grpc_subchannel_call_unref((p), __FILE__, __LINE__, (r)) + (p)->RefFromWeakRef(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref(__FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ - , const char *file, int line, const char *reason + const char *file, int line, const char *reason +#define GRPC_SUBCHANNEL_REF_REASON reason +#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS \ + , GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose +#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) , file, line, reason, x #else -#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p)) -#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - grpc_subchannel_ref_from_weak_ref((p)) -#define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) grpc_subchannel_weak_unref((p)) -#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p)) -#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p)) +#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref() +#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) (p)->RefFromWeakRef() +#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref() +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef() +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref() #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS +#define GRPC_SUBCHANNEL_REF_REASON "" +#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS +#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) #endif namespace grpc_core { -class ConnectedSubchannel : public RefCountedWithTracing { +class SubchannelCall; + +class ConnectedSubchannel : public RefCounted { public: struct CallArgs { grpc_polling_entity* pollent; @@ -84,100 +80,229 @@ class ConnectedSubchannel : public RefCountedWithTracing { size_t parent_data_size; }; - explicit ConnectedSubchannel(grpc_channel_stack* channel_stack); + ConnectedSubchannel( + grpc_channel_stack* channel_stack, const grpc_channel_args* args, + RefCountedPtr channelz_subchannel, + intptr_t socket_uuid); ~ConnectedSubchannel(); - grpc_channel_stack* channel_stack() { return channel_stack_; } void NotifyOnStateChange(grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_closure* closure); void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); - grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call); + RefCountedPtr CreateCall(const CallArgs& args, + grpc_error** error); + + grpc_channel_stack* channel_stack() const { return channel_stack_; } + const grpc_channel_args* args() const { return args_; } + channelz::SubchannelNode* channelz_subchannel() const { + return channelz_subchannel_.get(); + } + intptr_t socket_uuid() const { return socket_uuid_; } + + size_t GetInitialCallSizeEstimate(size_t parent_data_size) const; private: grpc_channel_stack* channel_stack_; + grpc_channel_args* args_; + // ref counted pointer to the channelz node in this connected subchannel's + // owning subchannel. + RefCountedPtr channelz_subchannel_; + // uuid of this subchannel's socket. 0 if this subchannel is not connected. + const intptr_t socket_uuid_; }; -} // namespace grpc_core +// Implements the interface of RefCounted<>. +class SubchannelCall { + public: + SubchannelCall(RefCountedPtr connected_subchannel, + const ConnectedSubchannel::CallArgs& args) + : connected_subchannel_(std::move(connected_subchannel)), + deadline_(args.deadline) {} + + // Continues processing a transport stream op batch. + void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); + + // Returns a pointer to the parent data associated with the subchannel call. + // The data will be of the size specified in \a parent_data_size field of + // the args passed to \a ConnectedSubchannel::CreateCall(). + void* GetParentData(); + + // Returns the call stack of the subchannel call. + grpc_call_stack* GetCallStack(); + + // Sets the 'then_schedule_closure' argument for call stack destruction. + // Must be called once per call. + void SetAfterCallStackDestroy(grpc_closure* closure); -grpc_subchannel* grpc_subchannel_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel* grpc_subchannel_ref_from_weak_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_unref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel* grpc_subchannel_weak_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_weak_unref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel_call* grpc_subchannel_call_ref( - grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_call_unref( - grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - -/** Returns a pointer to the parent data associated with \a subchannel_call. - The data will be of the size specified in \a parent_data_size - field of the args passed to \a grpc_connected_subchannel_create_call(). */ -void* grpc_connected_subchannel_call_get_parent_data( - grpc_subchannel_call* subchannel_call); - -/** poll the current connectivity state of a channel */ -grpc_connectivity_state grpc_subchannel_check_connectivity( - grpc_subchannel* channel, grpc_error** error); - -/** Calls notify when the connectivity state of a channel becomes different - from *state. Updates *state with the new state of the channel. */ -void grpc_subchannel_notify_on_state_change( - grpc_subchannel* channel, grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify); - -/** retrieve the grpc_core::ConnectedSubchannel - or nullptr if not connected - * (which may happen before it initially connects or during transient failures) - * */ -grpc_core::RefCountedPtr -grpc_subchannel_get_connected_subchannel(grpc_subchannel* c); - -/** return the subchannel index key for \a subchannel */ -const grpc_subchannel_key* grpc_subchannel_get_key( - const grpc_subchannel* subchannel); - -/** continue processing a transport op */ -void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call, - grpc_transport_stream_op_batch* op); - -/** Must be called once per call. Sets the 'then_schedule_closure' argument for - call stack destruction. */ -void grpc_subchannel_call_set_cleanup_closure( - grpc_subchannel_call* subchannel_call, grpc_closure* closure); - -grpc_call_stack* grpc_subchannel_call_get_call_stack( - grpc_subchannel_call* subchannel_call); - -struct grpc_subchannel_args { - /* When updating this struct, also update subchannel_index.c */ - - /** Channel filters for this channel - wrapped factories will likely - want to mutate this */ - const grpc_channel_filter** filters; - /** The number of filters in the above array */ - size_t filter_count; - /** Channel arguments to be supplied to the newly created channel */ - const grpc_channel_args* args; + // Interface of RefCounted<>. + RefCountedPtr Ref() GRPC_MUST_USE_RESULT; + RefCountedPtr Ref(const DebugLocation& location, + const char* reason) GRPC_MUST_USE_RESULT; + // When refcount drops to 0, destroys itself and the associated call stack, + // but does NOT free the memory because it's in the call arena. + void Unref(); + void Unref(const DebugLocation& location, const char* reason); + + static void Destroy(void* arg, grpc_error* error); + + private: + // Allow RefCountedPtr<> to access IncrementRefCount(). + template + friend class RefCountedPtr; + + // If channelz is enabled, intercepts recv_trailing so that we may check the + // status and associate it to a subchannel. + void MaybeInterceptRecvTrailingMetadata( + grpc_transport_stream_op_batch* batch); + + static void RecvTrailingMetadataReady(void* arg, grpc_error* error); + + // Interface of RefCounted<>. + void IncrementRefCount(); + void IncrementRefCount(const DebugLocation& location, const char* reason); + + RefCountedPtr connected_subchannel_; + grpc_closure* after_call_stack_destroy_ = nullptr; + // State needed to support channelz interception of recv trailing metadata. + grpc_closure recv_trailing_metadata_ready_; + grpc_closure* original_recv_trailing_metadata_ = nullptr; + grpc_metadata_batch* recv_trailing_metadata_ = nullptr; + grpc_millis deadline_; }; -/** create a subchannel given a connector */ -grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_subchannel_args* args); +// A subchannel that knows how to connect to exactly one target address. It +// provides a target for load balancing. +class Subchannel { + public: + // The ctor and dtor are not intended to use directly. + Subchannel(SubchannelKey* key, grpc_connector* connector, + const grpc_channel_args* args); + ~Subchannel(); + + // Creates a subchannel given \a connector and \a args. + static Subchannel* Create(grpc_connector* connector, + const grpc_channel_args* args); + + // Strong and weak refcounting. + Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + Subchannel* WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + void WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + Subchannel* RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + + intptr_t GetChildSocketUuid(); -/// Sets \a addr from \a args. -void grpc_get_subchannel_address_arg(const grpc_channel_args* args, - grpc_resolved_address* addr); + // Gets the string representing the subchannel address. + // Caller doesn't take ownership. + const char* GetTargetAddress(); -/// Returns the URI string for the address to connect to. -const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args); + // Gets the connected subchannel - or nullptr if not connected (which may + // happen before it initially connects or during transient failures). + RefCountedPtr connected_subchannel(); -/// Returns a new channel arg encoding the subchannel address as a string. -/// Caller is responsible for freeing the string. -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr); + channelz::SubchannelNode* channelz_node(); + + // Polls the current connectivity state of the subchannel. + grpc_connectivity_state CheckConnectivity(grpc_error** error, + bool inhibit_health_checking); + + // When the connectivity state of the subchannel changes from \a *state, + // invokes \a notify and updates \a *state with the new state. + void NotifyOnStateChange(grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, grpc_closure* notify, + bool inhibit_health_checking); + + // Resets the connection backoff of the subchannel. + // TODO(roth): Move connection backoff out of subchannels and up into LB + // policy code (probably by adding a SubchannelGroup between + // SubchannelList and SubchannelData), at which point this method can + // go away. + void ResetBackoff(); + + // Returns a new channel arg encoding the subchannel address as a URI + // string. Caller is responsible for freeing the string. + static grpc_arg CreateSubchannelAddressArg(const grpc_resolved_address* addr); + + // Returns the URI string from the subchannel address arg in \a args. + static const char* GetUriFromSubchannelAddressArg( + const grpc_channel_args* args); + + // Sets \a addr from the subchannel address arg in \a args. + static void GetAddressFromSubchannelAddressArg(const grpc_channel_args* args, + grpc_resolved_address* addr); + + private: + struct ExternalStateWatcher; + class ConnectedSubchannelStateWatcher; + + // Sets the subchannel's connectivity state to \a state. + void SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, const char* reason); + + // Methods for connection. + void MaybeStartConnectingLocked(); + static void OnRetryAlarm(void* arg, grpc_error* error); + void ContinueConnectingLocked(); + static void OnConnectingFinished(void* arg, grpc_error* error); + bool PublishTransportLocked(); + void Disconnect(); + + gpr_atm RefMutate(gpr_atm delta, + int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS); + + // The subchannel pool this subchannel is in. + RefCountedPtr subchannel_pool_; + // TODO(juanlishen): Consider using args_ as key_ directly. + // Subchannel key that identifies this subchannel in the subchannel pool. + SubchannelKey* key_; + // Channel args. + grpc_channel_args* args_; + // pollset_set tracking who's interested in a connection being setup. + grpc_pollset_set* pollset_set_; + // Protects the other members. + gpr_mu mu_; + // Refcount + // - lower INTERNAL_REF_BITS bits are for internal references: + // these do not keep the subchannel open. + // - upper remaining bits are for public references: these do + // keep the subchannel open + gpr_atm ref_pair_; + + // Connection states. + grpc_connector* connector_ = nullptr; + // Set during connection. + grpc_connect_out_args connecting_result_; + grpc_closure on_connecting_finished_; + // Active connection, or null. + RefCountedPtr connected_subchannel_; + OrphanablePtr connected_subchannel_watcher_; + bool connecting_ = false; + bool disconnected_ = false; + + // Connectivity state tracking. + grpc_connectivity_state_tracker state_tracker_; + grpc_connectivity_state_tracker state_and_health_tracker_; + UniquePtr health_check_service_name_; + ExternalStateWatcher* external_state_watcher_list_ = nullptr; + + // Backoff state. + BackOff backoff_; + grpc_millis next_attempt_deadline_; + grpc_millis min_connect_timeout_ms_; + bool backoff_begun_ = false; + + // Retry alarm. + grpc_timer retry_alarm_; + grpc_closure on_retry_alarm_; + bool have_retry_alarm_ = false; + // reset_backoff() was called while alarm was pending. + bool retry_immediately_ = false; + + // Channelz tracking. + RefCountedPtr channelz_node_; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_index.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_index.cc deleted file mode 100644 index cb02b1a74..000000000 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_index.cc +++ /dev/null @@ -1,254 +0,0 @@ -// -// -// Copyright 2016 gRPC authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// - -#include - -#include "src/core/ext/filters/client_channel/subchannel_index.h" - -#include -#include - -#include -#include - -#include "src/core/lib/avl/avl.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/tls.h" - -// a map of subchannel_key --> subchannel, used for detecting connections -// to the same destination in order to share them -static grpc_avl g_subchannel_index; - -static gpr_mu g_mu; - -static gpr_refcount g_refcount; - -struct grpc_subchannel_key { - grpc_subchannel_args args; -}; - -static bool g_force_creation = false; - -static grpc_subchannel_key* create_key( - const grpc_subchannel_args* args, - grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) { - grpc_subchannel_key* k = - static_cast(gpr_malloc(sizeof(*k))); - k->args.filter_count = args->filter_count; - if (k->args.filter_count > 0) { - k->args.filters = static_cast( - gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count)); - memcpy(reinterpret_cast(k->args.filters), - args->filters, sizeof(*k->args.filters) * k->args.filter_count); - } else { - k->args.filters = nullptr; - } - k->args.args = copy_channel_args(args->args); - return k; -} - -grpc_subchannel_key* grpc_subchannel_key_create( - const grpc_subchannel_args* args) { - return create_key(args, grpc_channel_args_normalize); -} - -static grpc_subchannel_key* subchannel_key_copy(grpc_subchannel_key* k) { - return create_key(&k->args, grpc_channel_args_copy); -} - -int grpc_subchannel_key_compare(const grpc_subchannel_key* a, - const grpc_subchannel_key* b) { - if (g_force_creation) return false; - int c = GPR_ICMP(a->args.filter_count, b->args.filter_count); - if (c != 0) return c; - if (a->args.filter_count > 0) { - c = memcmp(a->args.filters, b->args.filters, - a->args.filter_count * sizeof(*a->args.filters)); - if (c != 0) return c; - } - return grpc_channel_args_compare(a->args.args, b->args.args); -} - -void grpc_subchannel_key_destroy(grpc_subchannel_key* k) { - gpr_free(reinterpret_cast(k->args.filters)); - grpc_channel_args_destroy(const_cast(k->args.args)); - gpr_free(k); -} - -static void sck_avl_destroy(void* p, void* user_data) { - grpc_subchannel_key_destroy(static_cast(p)); -} - -static void* sck_avl_copy(void* p, void* unused) { - return subchannel_key_copy(static_cast(p)); -} - -static long sck_avl_compare(void* a, void* b, void* unused) { - return grpc_subchannel_key_compare(static_cast(a), - static_cast(b)); -} - -static void scv_avl_destroy(void* p, void* user_data) { - GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "subchannel_index"); -} - -static void* scv_avl_copy(void* p, void* unused) { - GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel*)p, "subchannel_index"); - return p; -} - -static const grpc_avl_vtable subchannel_avl_vtable = { - sck_avl_destroy, // destroy_key - sck_avl_copy, // copy_key - sck_avl_compare, // compare_keys - scv_avl_destroy, // destroy_value - scv_avl_copy // copy_value -}; - -void grpc_subchannel_index_init(void) { - g_subchannel_index = grpc_avl_create(&subchannel_avl_vtable); - gpr_mu_init(&g_mu); - gpr_ref_init(&g_refcount, 1); -} - -void grpc_subchannel_index_shutdown(void) { - // TODO(juanlishen): This refcounting mechanism may lead to memory leackage. - // To solve that, we should force polling to flush any pending callbacks, then - // shutdown safely. - grpc_subchannel_index_unref(); -} - -void grpc_subchannel_index_unref(void) { - if (gpr_unref(&g_refcount)) { - gpr_mu_destroy(&g_mu); - grpc_avl_unref(g_subchannel_index, grpc_core::ExecCtx::Get()); - } -} - -void grpc_subchannel_index_ref(void) { gpr_ref_non_zero(&g_refcount); } - -grpc_subchannel* grpc_subchannel_index_find(grpc_subchannel_key* key) { - // Lock, and take a reference to the subchannel index. - // We don't need to do the search under a lock as avl's are immutable. - gpr_mu_lock(&g_mu); - grpc_avl index = grpc_avl_ref(g_subchannel_index, grpc_core::ExecCtx::Get()); - gpr_mu_unlock(&g_mu); - - grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF( - (grpc_subchannel*)grpc_avl_get(index, key, grpc_core::ExecCtx::Get()), - "index_find"); - grpc_avl_unref(index, grpc_core::ExecCtx::Get()); - - return c; -} - -grpc_subchannel* grpc_subchannel_index_register(grpc_subchannel_key* key, - grpc_subchannel* constructed) { - grpc_subchannel* c = nullptr; - bool need_to_unref_constructed = false; - - while (c == nullptr) { - need_to_unref_constructed = false; - - // Compare and swap loop: - // - take a reference to the current index - gpr_mu_lock(&g_mu); - grpc_avl index = - grpc_avl_ref(g_subchannel_index, grpc_core::ExecCtx::Get()); - gpr_mu_unlock(&g_mu); - - // - Check to see if a subchannel already exists - c = static_cast( - grpc_avl_get(index, key, grpc_core::ExecCtx::Get())); - if (c != nullptr) { - c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "index_register"); - } - if (c != nullptr) { - // yes -> we're done - need_to_unref_constructed = true; - } else { - // no -> update the avl and compare/swap - grpc_avl updated = - grpc_avl_add(grpc_avl_ref(index, grpc_core::ExecCtx::Get()), - subchannel_key_copy(key), - GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"), - grpc_core::ExecCtx::Get()); - - // it may happen (but it's expected to be unlikely) - // that some other thread has changed the index: - // compare/swap here to check that, and retry as necessary - gpr_mu_lock(&g_mu); - if (index.root == g_subchannel_index.root) { - GPR_SWAP(grpc_avl, updated, g_subchannel_index); - c = constructed; - } - gpr_mu_unlock(&g_mu); - - grpc_avl_unref(updated, grpc_core::ExecCtx::Get()); - } - grpc_avl_unref(index, grpc_core::ExecCtx::Get()); - } - - if (need_to_unref_constructed) { - GRPC_SUBCHANNEL_UNREF(constructed, "index_register"); - } - - return c; -} - -void grpc_subchannel_index_unregister(grpc_subchannel_key* key, - grpc_subchannel* constructed) { - bool done = false; - while (!done) { - // Compare and swap loop: - // - take a reference to the current index - gpr_mu_lock(&g_mu); - grpc_avl index = - grpc_avl_ref(g_subchannel_index, grpc_core::ExecCtx::Get()); - gpr_mu_unlock(&g_mu); - - // Check to see if this key still refers to the previously - // registered subchannel - grpc_subchannel* c = static_cast( - grpc_avl_get(index, key, grpc_core::ExecCtx::Get())); - if (c != constructed) { - grpc_avl_unref(index, grpc_core::ExecCtx::Get()); - break; - } - - // compare and swap the update (some other thread may have - // mutated the index behind us) - grpc_avl updated = - grpc_avl_remove(grpc_avl_ref(index, grpc_core::ExecCtx::Get()), key, - grpc_core::ExecCtx::Get()); - - gpr_mu_lock(&g_mu); - if (index.root == g_subchannel_index.root) { - GPR_SWAP(grpc_avl, updated, g_subchannel_index); - done = true; - } - gpr_mu_unlock(&g_mu); - - grpc_avl_unref(updated, grpc_core::ExecCtx::Get()); - grpc_avl_unref(index, grpc_core::ExecCtx::Get()); - } -} - -void grpc_subchannel_index_test_only_set_force_creation(bool force_creation) { - g_force_creation = force_creation; -} diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_index.h b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_index.h deleted file mode 100644 index a7dae9d47..000000000 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_index.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H - -#include - -#include "src/core/ext/filters/client_channel/subchannel.h" - -/** \file Provides an index of active subchannels so that they can be - shared amongst channels */ - -/** Create a key that can be used to uniquely identify a subchannel */ -grpc_subchannel_key* grpc_subchannel_key_create( - const grpc_subchannel_args* args); - -/** Destroy a subchannel key */ -void grpc_subchannel_key_destroy(grpc_subchannel_key* key); - -/** Given a subchannel key, find the subchannel registered for it. - Returns NULL if no such channel exists. - Thread-safe. */ -grpc_subchannel* grpc_subchannel_index_find(grpc_subchannel_key* key); - -/** Register a subchannel against a key. - Takes ownership of \a constructed. - Returns the registered subchannel. This may be different from - \a constructed in the case of a registration race. */ -grpc_subchannel* grpc_subchannel_index_register(grpc_subchannel_key* key, - grpc_subchannel* constructed); - -/** Remove \a constructed as the registered subchannel for \a key. */ -void grpc_subchannel_index_unregister(grpc_subchannel_key* key, - grpc_subchannel* constructed); - -int grpc_subchannel_key_compare(const grpc_subchannel_key* a, - const grpc_subchannel_key* b); - -/** Initialize the subchannel index (global) */ -void grpc_subchannel_index_init(void); -/** Shutdown the subchannel index (global) */ -void grpc_subchannel_index_shutdown(void); - -/** Increment the refcount (non-zero) of subchannel index (global). */ -void grpc_subchannel_index_ref(void); - -/** Decrement the refcount of subchannel index (global). If the refcount drops - to zero, unref the subchannel index and destroy its mutex. */ -void grpc_subchannel_index_unref(void); - -/** \em TEST ONLY. - * If \a force_creation is true, all key comparisons will be false, resulting in - * new subchannels always being created. Otherwise, the keys will be compared as - * usual. - * - * This function is *not* threadsafe on purpose: it should *only* be used in - * test code. - * - * Tests using this function \em MUST run tests with and without \a - * force_creation set. */ -void grpc_subchannel_index_test_only_set_force_creation(bool force_creation); - -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_pool_interface.cc b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_pool_interface.cc new file mode 100644 index 000000000..bb35f228b --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_pool_interface.cc @@ -0,0 +1,97 @@ +// +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include + +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" + +#include "src/core/lib/gpr/useful.h" + +// The subchannel pool to reuse subchannels. +#define GRPC_ARG_SUBCHANNEL_POOL "grpc.subchannel_pool" +// The subchannel key ID that is only used in test to make each key unique. +#define GRPC_ARG_SUBCHANNEL_KEY_TEST_ONLY_ID "grpc.subchannel_key_test_only_id" + +namespace grpc_core { + +TraceFlag grpc_subchannel_pool_trace(false, "subchannel_pool"); + +SubchannelKey::SubchannelKey(const grpc_channel_args* args) { + Init(args, grpc_channel_args_normalize); +} + +SubchannelKey::~SubchannelKey() { + grpc_channel_args_destroy(const_cast(args_)); +} + +SubchannelKey::SubchannelKey(const SubchannelKey& other) { + Init(other.args_, grpc_channel_args_copy); +} + +SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) { + grpc_channel_args_destroy(const_cast(args_)); + Init(other.args_, grpc_channel_args_copy); + return *this; +} + +int SubchannelKey::Cmp(const SubchannelKey& other) const { + return grpc_channel_args_compare(args_, other.args_); +} + +void SubchannelKey::Init( + const grpc_channel_args* args, + grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) { + args_ = copy_channel_args(args); +} + +namespace { + +void* arg_copy(void* p) { + auto* subchannel_pool = static_cast(p); + subchannel_pool->Ref().release(); + return p; +} + +void arg_destroy(void* p) { + auto* subchannel_pool = static_cast(p); + subchannel_pool->Unref(); +} + +int arg_cmp(void* a, void* b) { return GPR_ICMP(a, b); } + +const grpc_arg_pointer_vtable subchannel_pool_arg_vtable = { + arg_copy, arg_destroy, arg_cmp}; + +} // namespace + +grpc_arg SubchannelPoolInterface::CreateChannelArg( + SubchannelPoolInterface* subchannel_pool) { + return grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_SUBCHANNEL_POOL), subchannel_pool, + &subchannel_pool_arg_vtable); +} + +SubchannelPoolInterface* +SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs( + const grpc_channel_args* args) { + const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_POOL); + if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr; + return static_cast(arg->value.pointer.p); +} + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_pool_interface.h b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_pool_interface.h new file mode 100644 index 000000000..eeb56faf0 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/filters/client_channel/subchannel_pool_interface.h @@ -0,0 +1,94 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H + +#include + +#include "src/core/lib/avl/avl.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/abstract.h" +#include "src/core/lib/gprpp/ref_counted.h" + +namespace grpc_core { + +class Subchannel; + +extern TraceFlag grpc_subchannel_pool_trace; + +// A key that can uniquely identify a subchannel. +class SubchannelKey { + public: + explicit SubchannelKey(const grpc_channel_args* args); + ~SubchannelKey(); + + // Copyable. + SubchannelKey(const SubchannelKey& other); + SubchannelKey& operator=(const SubchannelKey& other); + // Not movable. + SubchannelKey(SubchannelKey&&) = delete; + SubchannelKey& operator=(SubchannelKey&&) = delete; + + int Cmp(const SubchannelKey& other) const; + + private: + // Initializes the subchannel key with the given \a args and the function to + // copy channel args. + void Init( + const grpc_channel_args* args, + grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)); + + const grpc_channel_args* args_; +}; + +// Interface for subchannel pool. +// TODO(juanlishen): This refcounting mechanism may lead to memory leak. +// To solve that, we should force polling to flush any pending callbacks, then +// shut down safely. See https://github.com/grpc/grpc/issues/12560. +class SubchannelPoolInterface : public RefCounted { + public: + SubchannelPoolInterface() : RefCounted(&grpc_subchannel_pool_trace) {} + virtual ~SubchannelPoolInterface() {} + + // Registers a subchannel against a key. Returns the subchannel registered + // with \a key, which may be different from \a constructed because we reuse + // (instead of update) any existing subchannel already registered with \a key. + virtual Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) GRPC_ABSTRACT; + + // Removes the registered subchannel found by \a key. + virtual void UnregisterSubchannel(SubchannelKey* key) GRPC_ABSTRACT; + + // Finds the subchannel registered for the given subchannel key. Returns NULL + // if no such channel exists. Thread-safe. + virtual Subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; + + // Creates a channel arg from \a subchannel pool. + static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool); + + // Gets the subchannel pool from the channel args. + static SubchannelPoolInterface* GetSubchannelPoolFromChannelArgs( + const grpc_channel_args* args); + + GRPC_ABSTRACT_BASE_CLASS +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.cc b/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.cc index 27d3eac8d..b4cb07f0f 100644 --- a/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.cc @@ -27,6 +27,7 @@ #include #include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel_init.h" @@ -128,27 +129,35 @@ static void cancel_timer_if_needed(grpc_deadline_state* deadline_state) { } } -// Callback run when the call is complete. -static void on_complete(void* arg, grpc_error* error) { +// Callback run when we receive trailing metadata. +static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { grpc_deadline_state* deadline_state = static_cast(arg); cancel_timer_if_needed(deadline_state); - // Invoke the next callback. - GRPC_CLOSURE_RUN(deadline_state->next_on_complete, GRPC_ERROR_REF(error)); + // Invoke the original callback. + GRPC_CLOSURE_RUN(deadline_state->original_recv_trailing_metadata_ready, + GRPC_ERROR_REF(error)); } -// Inject our own on_complete callback into op. -static void inject_on_complete_cb(grpc_deadline_state* deadline_state, - grpc_transport_stream_op_batch* op) { - deadline_state->next_on_complete = op->on_complete; - GRPC_CLOSURE_INIT(&deadline_state->on_complete, on_complete, deadline_state, +// Inject our own recv_trailing_metadata_ready callback into op. +static void inject_recv_trailing_metadata_ready( + grpc_deadline_state* deadline_state, grpc_transport_stream_op_batch* op) { + deadline_state->original_recv_trailing_metadata_ready = + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + GRPC_CLOSURE_INIT(&deadline_state->recv_trailing_metadata_ready, + recv_trailing_metadata_ready, deadline_state, grpc_schedule_on_exec_ctx); - op->on_complete = &deadline_state->on_complete; + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &deadline_state->recv_trailing_metadata_ready; } // Callback and associated state for starting the timer after call stack // initialization has been completed. struct start_timer_after_init_state { - bool in_call_combiner; + start_timer_after_init_state(grpc_call_element* elem, grpc_millis deadline) + : elem(elem), deadline(deadline) {} + ~start_timer_after_init_state() { start_timer_if_needed(elem, deadline); } + + bool in_call_combiner = false; grpc_call_element* elem; grpc_millis deadline; grpc_closure closure; @@ -167,20 +176,16 @@ static void start_timer_after_init(void* arg, grpc_error* error) { "scheduling deadline timer"); return; } - start_timer_if_needed(state->elem, state->deadline); - gpr_free(state); + grpc_core::Delete(state); GRPC_CALL_COMBINER_STOP(deadline_state->call_combiner, "done scheduling deadline timer"); } -void grpc_deadline_state_init(grpc_call_element* elem, - grpc_call_stack* call_stack, - grpc_call_combiner* call_combiner, - grpc_millis deadline) { - grpc_deadline_state* deadline_state = - static_cast(elem->call_data); - deadline_state->call_stack = call_stack; - deadline_state->call_combiner = call_combiner; +grpc_deadline_state::grpc_deadline_state(grpc_call_element* elem, + grpc_call_stack* call_stack, + grpc_call_combiner* call_combiner, + grpc_millis deadline) + : call_stack(call_stack), call_combiner(call_combiner) { // Deadline will always be infinite on servers, so the timer will only be // set on clients with a finite deadline. if (deadline != GRPC_MILLIS_INF_FUTURE) { @@ -192,21 +197,14 @@ void grpc_deadline_state_init(grpc_call_element* elem, // create a closure to start the timer, and we schedule that closure // to be run after call stack initialization is done. struct start_timer_after_init_state* state = - static_cast( - gpr_zalloc(sizeof(*state))); - state->elem = elem; - state->deadline = deadline; + grpc_core::New(elem, deadline); GRPC_CLOSURE_INIT(&state->closure, start_timer_after_init, state, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_SCHED(&state->closure, GRPC_ERROR_NONE); } } -void grpc_deadline_state_destroy(grpc_call_element* elem) { - grpc_deadline_state* deadline_state = - static_cast(elem->call_data); - cancel_timer_if_needed(deadline_state); -} +grpc_deadline_state::~grpc_deadline_state() { cancel_timer_if_needed(this); } void grpc_deadline_state_reset(grpc_call_element* elem, grpc_millis new_deadline) { @@ -226,7 +224,7 @@ void grpc_deadline_state_client_start_transport_stream_op_batch( // Make sure we know when the call is complete, so that we can cancel // the timer. if (op->recv_trailing_metadata) { - inject_on_complete_cb(deadline_state, op); + inject_recv_trailing_metadata_ready(deadline_state, op); } } } @@ -265,8 +263,8 @@ typedef struct server_call_data { // Constructor for call_data. Used for both client and server filters. static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - grpc_deadline_state_init(elem, args->call_stack, args->call_combiner, - args->deadline); + new (elem->call_data) grpc_deadline_state( + elem, args->call_stack, args->call_combiner, args->deadline); return GRPC_ERROR_NONE; } @@ -274,7 +272,9 @@ static grpc_error* init_call_elem(grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { - grpc_deadline_state_destroy(elem); + grpc_deadline_state* deadline_state = + static_cast(elem->call_data); + deadline_state->~grpc_deadline_state(); } // Method for starting a call op for client filter. @@ -289,11 +289,10 @@ static void client_start_transport_stream_op_batch( static void recv_initial_metadata_ready(void* arg, grpc_error* error) { grpc_call_element* elem = static_cast(arg); server_call_data* calld = static_cast(elem->call_data); - // Get deadline from metadata and start the timer if needed. start_timer_if_needed(elem, calld->recv_initial_metadata->deadline); // Invoke the next callback. - calld->next_recv_initial_metadata_ready->cb( - calld->next_recv_initial_metadata_ready->cb_arg, error); + GRPC_CLOSURE_RUN(calld->next_recv_initial_metadata_ready, + GRPC_ERROR_REF(error)); } // Method for starting a call op for server filter. @@ -323,7 +322,7 @@ static void server_start_transport_stream_op_batch( // the client never sends trailing metadata, because this is the // hook that tells us when the call is complete on the server side. if (op->recv_trailing_metadata) { - inject_on_complete_cb(&calld->base.deadline_state, op); + inject_recv_trailing_metadata_ready(&calld->base.deadline_state, op); } } // Chain to next filter. diff --git a/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.h b/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.h index 13207cbd6..e37032999 100644 --- a/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.h +++ b/Sources/CgRPC/src/core/ext/filters/deadline/deadline_filter.h @@ -22,42 +22,38 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/timer.h" -typedef enum grpc_deadline_timer_state { +enum grpc_deadline_timer_state { GRPC_DEADLINE_STATE_INITIAL, GRPC_DEADLINE_STATE_PENDING, GRPC_DEADLINE_STATE_FINISHED -} grpc_deadline_timer_state; +}; // State used for filters that enforce call deadlines. // Must be the first field in the filter's call_data. -typedef struct grpc_deadline_state { +struct grpc_deadline_state { + grpc_deadline_state(grpc_call_element* elem, grpc_call_stack* call_stack, + grpc_call_combiner* call_combiner, grpc_millis deadline); + ~grpc_deadline_state(); + // We take a reference to the call stack for the timer callback. grpc_call_stack* call_stack; grpc_call_combiner* call_combiner; - grpc_deadline_timer_state timer_state; + grpc_deadline_timer_state timer_state = GRPC_DEADLINE_STATE_INITIAL; grpc_timer timer; grpc_closure timer_callback; - // Closure to invoke when the call is complete. + // Closure to invoke when we receive trailing metadata. // We use this to cancel the timer. - grpc_closure on_complete; - // The original on_complete closure, which we chain to after our own - // closure is invoked. - grpc_closure* next_on_complete; -} grpc_deadline_state; + grpc_closure recv_trailing_metadata_ready; + // The original recv_trailing_metadata_ready closure, which we chain to + // after our own closure is invoked. + grpc_closure* original_recv_trailing_metadata_ready; +}; // // NOTE: All of these functions require that the first field in // elem->call_data is a grpc_deadline_state. // -// assumes elem->call_data is zero'd -void grpc_deadline_state_init(grpc_call_element* elem, - grpc_call_stack* call_stack, - grpc_call_combiner* call_combiner, - grpc_millis deadline); - -void grpc_deadline_state_destroy(grpc_call_element* elem); - // Cancels the existing timer and starts a new one with new_deadline. // // Note: It is generally safe to call this with an earlier deadline diff --git a/Sources/CgRPC/src/core/ext/filters/http/client/http_client_filter.cc b/Sources/CgRPC/src/core/ext/filters/http/client/http_client_filter.cc index ae94ce47b..bf9a01f65 100644 --- a/Sources/CgRPC/src/core/ext/filters/http/client/http_client_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/http/client/http_client_filter.cc @@ -37,10 +37,31 @@ #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 /* default maximum size of payload eligable for GET request */ -static const size_t kMaxPayloadSizeForGet = 2048; +static constexpr size_t kMaxPayloadSizeForGet = 2048; + +static void recv_initial_metadata_ready(void* user_data, grpc_error* error); +static void recv_trailing_metadata_ready(void* user_data, grpc_error* error); +static void on_send_message_next_done(void* arg, grpc_error* error); +static void send_message_on_complete(void* arg, grpc_error* error); namespace { struct call_data { + call_data(grpc_call_element* elem, const grpc_call_element_args& args) + : call_combiner(args.call_combiner) { + GRPC_CLOSURE_INIT(&recv_initial_metadata_ready, + ::recv_initial_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready, + ::recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_send_message_next_done, ::on_send_message_next_done, + elem, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&send_message_on_complete, ::send_message_on_complete, + elem, grpc_schedule_on_exec_ctx); + } + + ~call_data() { GRPC_ERROR_UNREF(recv_initial_metadata_error); } + grpc_call_combiner* call_combiner; // State for handling send_initial_metadata ops. grpc_linked_mdelem method; @@ -51,15 +72,18 @@ struct call_data { grpc_linked_mdelem user_agent; // State for handling recv_initial_metadata ops. grpc_metadata_batch* recv_initial_metadata; - grpc_closure* original_recv_initial_metadata_ready; + grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; + grpc_closure* original_recv_initial_metadata_ready = nullptr; grpc_closure recv_initial_metadata_ready; // State for handling recv_trailing_metadata ops. grpc_metadata_batch* recv_trailing_metadata; - grpc_closure* original_recv_trailing_metadata_on_complete; - grpc_closure recv_trailing_metadata_on_complete; + grpc_closure* original_recv_trailing_metadata_ready; + grpc_closure recv_trailing_metadata_ready; + grpc_error* recv_trailing_metadata_error = GRPC_ERROR_NONE; + bool seen_recv_trailing_metadata_ready = false; // State for handling send_message ops. grpc_transport_stream_op_batch* send_message_batch; - size_t send_message_bytes_read; + size_t send_message_bytes_read = 0; grpc_core::ManualConstructor send_message_cache; grpc_core::ManualConstructor send_message_caching_stream; @@ -78,7 +102,12 @@ struct channel_data { static grpc_error* client_filter_incoming_metadata(grpc_call_element* elem, grpc_metadata_batch* b) { if (b->idx.named.status != nullptr) { - if (grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) { + /* If both gRPC status and HTTP status are provided in the response, we + * should prefer the gRPC status code, as mentioned in + * https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. + */ + if (b->idx.named.grpc_status != nullptr || + grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) { grpc_metadata_batch_remove(b, b->idx.named.status); } else { char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md), @@ -147,23 +176,40 @@ static void recv_initial_metadata_ready(void* user_data, grpc_error* error) { call_data* calld = static_cast(elem->call_data); if (error == GRPC_ERROR_NONE) { error = client_filter_incoming_metadata(elem, calld->recv_initial_metadata); + calld->recv_initial_metadata_error = GRPC_ERROR_REF(error); } else { GRPC_ERROR_REF(error); } - GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, error); + grpc_closure* closure = calld->original_recv_initial_metadata_ready; + calld->original_recv_initial_metadata_ready = nullptr; + if (calld->seen_recv_trailing_metadata_ready) { + GRPC_CALL_COMBINER_START( + calld->call_combiner, &calld->recv_trailing_metadata_ready, + calld->recv_trailing_metadata_error, "continue recv_trailing_metadata"); + } + GRPC_CLOSURE_RUN(closure, error); } -static void recv_trailing_metadata_on_complete(void* user_data, - grpc_error* error) { +static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); + if (calld->original_recv_initial_metadata_ready != nullptr) { + calld->recv_trailing_metadata_error = GRPC_ERROR_REF(error); + calld->seen_recv_trailing_metadata_ready = true; + GRPC_CALL_COMBINER_STOP(calld->call_combiner, + "deferring recv_trailing_metadata_ready until " + "after recv_initial_metadata_ready"); + return; + } if (error == GRPC_ERROR_NONE) { error = client_filter_incoming_metadata(elem, calld->recv_trailing_metadata); } else { GRPC_ERROR_REF(error); } - GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_on_complete, error); + error = grpc_error_add_child( + error, GRPC_ERROR_REF(calld->recv_initial_metadata_error)); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error); } static void send_message_on_complete(void* arg, grpc_error* error) { @@ -312,8 +358,10 @@ static void hc_start_transport_stream_op_batch( /* substitute our callback for the higher callback */ calld->recv_trailing_metadata = batch->payload->recv_trailing_metadata.recv_trailing_metadata; - calld->original_recv_trailing_metadata_on_complete = batch->on_complete; - batch->on_complete = &calld->recv_trailing_metadata_on_complete; + calld->original_recv_trailing_metadata_ready = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; } grpc_error* error = GRPC_ERROR_NONE; @@ -415,25 +463,17 @@ static void hc_start_transport_stream_op_batch( /* Constructor for call_data */ static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); - calld->call_combiner = args->call_combiner; - GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready, - recv_initial_metadata_ready, elem, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_on_complete, - recv_trailing_metadata_on_complete, elem, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete, - elem, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->on_send_message_next_done, - on_send_message_next_done, elem, grpc_schedule_on_exec_ctx); + new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, - grpc_closure* ignored) {} + grpc_closure* ignored) { + call_data* calld = static_cast(elem->call_data); + calld->~call_data(); +} static grpc_mdelem scheme_from_args(const grpc_channel_args* args) { unsigned i; diff --git a/Sources/CgRPC/src/core/ext/filters/http/client_authority_filter.cc b/Sources/CgRPC/src/core/ext/filters/http/client_authority_filter.cc index 1f57ab5ce..125059c93 100644 --- a/Sources/CgRPC/src/core/ext/filters/http/client_authority_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/http/client_authority_filter.cc @@ -45,6 +45,7 @@ struct call_data { struct channel_data { grpc_slice default_authority; + grpc_mdelem default_authority_mdelem; }; void authority_start_transport_stream_op_batch( @@ -59,8 +60,7 @@ void authority_start_transport_stream_op_batch( initial_metadata->idx.named.authority == nullptr) { grpc_error* error = grpc_metadata_batch_add_head( initial_metadata, &calld->authority_storage, - grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY, - grpc_slice_ref(chand->default_authority))); + GRPC_MDELEM_REF(chand->default_authority_mdelem)); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(batch, error, calld->call_combiner); @@ -93,7 +93,7 @@ grpc_error* init_channel_elem(grpc_channel_element* elem, if (default_authority_arg == nullptr) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "GRPC_ARG_DEFAULT_AUTHORITY channel arg. not found. Note that direct " - "channels must explicity specify a value for this argument."); + "channels must explicitly specify a value for this argument."); } const char* default_authority_str = grpc_channel_arg_get_string(default_authority_arg); @@ -102,7 +102,9 @@ grpc_error* init_channel_elem(grpc_channel_element* elem, "GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string"); } chand->default_authority = - grpc_slice_from_copied_string(default_authority_str); + grpc_slice_intern(grpc_slice_from_static_string(default_authority_str)); + chand->default_authority_mdelem = grpc_mdelem_create( + GRPC_MDSTR_AUTHORITY, chand->default_authority, nullptr); GPR_ASSERT(!args->is_last); return GRPC_ERROR_NONE; } @@ -110,7 +112,8 @@ grpc_error* init_channel_elem(grpc_channel_element* elem, /* Destructor for channel data */ void destroy_channel_elem(grpc_channel_element* elem) { channel_data* chand = static_cast(elem->channel_data); - grpc_slice_unref(chand->default_authority); + grpc_slice_unref_internal(chand->default_authority); + GRPC_MDELEM_UNREF(chand->default_authority_mdelem); } } // namespace diff --git a/Sources/CgRPC/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/Sources/CgRPC/src/core/ext/filters/http/message_compress/message_compress_filter.cc index f8f478b6c..9c8c8d9e1 100644 --- a/Sources/CgRPC/src/core/ext/filters/http/message_compress/message_compress_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/http/message_compress/message_compress_filter.cc @@ -39,6 +39,10 @@ #include "src/core/lib/surface/call.h" #include "src/core/lib/transport/static_metadata.h" +static void start_send_message_batch(void* arg, grpc_error* unused); +static void send_message_on_complete(void* arg, grpc_error* error); +static void on_send_message_next_done(void* arg, grpc_error* error); + namespace { enum initial_metadata_state { // Initial metadata not yet seen. @@ -50,6 +54,23 @@ enum initial_metadata_state { }; struct call_data { + call_data(grpc_call_element* elem, const grpc_call_element_args& args) + : call_combiner(args.call_combiner) { + GRPC_CLOSURE_INIT(&start_send_message_batch_in_call_combiner, + start_send_message_batch, elem, + grpc_schedule_on_exec_ctx); + grpc_slice_buffer_init(&slices); + GRPC_CLOSURE_INIT(&send_message_on_complete, ::send_message_on_complete, + elem, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_send_message_next_done, ::on_send_message_next_done, + elem, grpc_schedule_on_exec_ctx); + } + + ~call_data() { + grpc_slice_buffer_destroy_internal(&slices); + GRPC_ERROR_UNREF(cancel_error); + } + grpc_call_combiner* call_combiner; grpc_linked_mdelem compression_algorithm_storage; grpc_linked_mdelem stream_compression_algorithm_storage; @@ -57,11 +78,12 @@ struct call_data { grpc_linked_mdelem accept_stream_encoding_storage; /** Compression algorithm we'll try to use. It may be given by incoming * metadata, or by the channel's default compression settings. */ - grpc_message_compression_algorithm message_compression_algorithm; - initial_metadata_state send_initial_metadata_state; - grpc_error* cancel_error; + grpc_message_compression_algorithm message_compression_algorithm = + GRPC_MESSAGE_COMPRESS_NONE; + initial_metadata_state send_initial_metadata_state = INITIAL_METADATA_UNSEEN; + grpc_error* cancel_error = GRPC_ERROR_NONE; grpc_closure start_send_message_batch_in_call_combiner; - grpc_transport_stream_op_batch* send_message_batch; + grpc_transport_stream_op_batch* send_message_batch = nullptr; grpc_slice_buffer slices; /**< Buffers up input slices to be compressed */ grpc_core::ManualConstructor replacement_stream; @@ -116,8 +138,8 @@ static grpc_error* process_send_initial_metadata( if (initial_metadata->idx.named.grpc_internal_encoding_request != nullptr) { grpc_mdelem md = initial_metadata->idx.named.grpc_internal_encoding_request->md; - if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md), - &compression_algorithm)) { + if (GPR_UNLIKELY(!grpc_compression_algorithm_parse( + GRPC_MDVALUE(md), &compression_algorithm))) { char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (unknown). Ignoring.", val); @@ -125,8 +147,8 @@ static grpc_error* process_send_initial_metadata( calld->message_compression_algorithm = GRPC_MESSAGE_COMPRESS_NONE; stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE; } - if (!GPR_BITGET(channeld->enabled_algorithms_bitset, - compression_algorithm)) { + if (GPR_UNLIKELY(!GPR_BITGET(channeld->enabled_algorithms_bitset, + compression_algorithm))) { char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (previously disabled). " @@ -424,16 +446,7 @@ static void compress_start_transport_stream_op_batch( /* Constructor for call_data */ static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); - calld->call_combiner = args->call_combiner; - calld->cancel_error = GRPC_ERROR_NONE; - grpc_slice_buffer_init(&calld->slices); - GRPC_CLOSURE_INIT(&calld->start_send_message_batch_in_call_combiner, - start_send_message_batch, elem, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->on_send_message_next_done, - on_send_message_next_done, elem, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete, - elem, grpc_schedule_on_exec_ctx); + new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } @@ -442,8 +455,7 @@ static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { call_data* calld = static_cast(elem->call_data); - grpc_slice_buffer_destroy_internal(&calld->slices); - GRPC_ERROR_UNREF(calld->cancel_error); + calld->~call_data(); } /* Constructor for channel_data */ diff --git a/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.cc b/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.cc index c20201587..ce1be8370 100644 --- a/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.cc @@ -23,6 +23,7 @@ #include #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/b64.h" @@ -34,44 +35,72 @@ #define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 +static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err); +static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err); +static void hs_recv_message_ready(void* user_data, grpc_error* err); + namespace { + struct call_data { + call_data(grpc_call_element* elem, const grpc_call_element_args& args) + : call_combiner(args.call_combiner) { + GRPC_CLOSURE_INIT(&recv_initial_metadata_ready, + hs_recv_initial_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&recv_message_ready, hs_recv_message_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready, + hs_recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + } + + ~call_data() { + GRPC_ERROR_UNREF(recv_initial_metadata_ready_error); + if (have_read_stream) { + read_stream->Orphan(); + } + } + grpc_call_combiner* call_combiner; + // Outgoing headers to add to send_initial_metadata. grpc_linked_mdelem status; grpc_linked_mdelem content_type; - /* did this request come with path query containing request payload */ - bool seen_path_with_query; - /* flag to ensure payload_bin is delivered only once */ - bool payload_bin_delivered; - - grpc_metadata_batch* recv_initial_metadata; - uint32_t* recv_initial_metadata_flags; - /** Closure to call when finished with the hs_on_recv hook */ - grpc_closure* on_done_recv; - /** Closure to call when we retrieve read message from the path URI - */ - grpc_closure* recv_message_ready; - grpc_closure* on_complete; - grpc_core::OrphanablePtr* pp_recv_message; + // If we see the recv_message contents in the GET query string, we + // store it here. grpc_core::ManualConstructor read_stream; + bool have_read_stream = false; - /** Receive closures are chained: we inject this closure as the on_done_recv - up-call on transport_op, and remember to call our on_done_recv member - after handling it. */ - grpc_closure hs_on_recv; - grpc_closure hs_on_complete; - grpc_closure hs_recv_message_ready; + // State for intercepting recv_initial_metadata. + grpc_closure recv_initial_metadata_ready; + grpc_error* recv_initial_metadata_ready_error = GRPC_ERROR_NONE; + grpc_closure* original_recv_initial_metadata_ready; + grpc_metadata_batch* recv_initial_metadata = nullptr; + uint32_t* recv_initial_metadata_flags; + bool seen_recv_initial_metadata_ready = false; + + // State for intercepting recv_message. + grpc_closure* original_recv_message_ready; + grpc_closure recv_message_ready; + grpc_core::OrphanablePtr* recv_message; + bool seen_recv_message_ready = false; + + // State for intercepting recv_trailing_metadata + grpc_closure recv_trailing_metadata_ready; + grpc_closure* original_recv_trailing_metadata_ready; + grpc_error* recv_trailing_metadata_ready_error; + bool seen_recv_trailing_metadata_ready = false; }; struct channel_data { - uint8_t unused; + bool surface_user_agent; }; + } // namespace -static grpc_error* server_filter_outgoing_metadata(grpc_call_element* elem, - grpc_metadata_batch* b) { +static grpc_error* hs_filter_outgoing_metadata(grpc_call_element* elem, + grpc_metadata_batch* b) { if (b->idx.named.grpc_message != nullptr) { grpc_slice pct_encoded_msg = grpc_percent_encode_slice( GRPC_MDVALUE(b->idx.named.grpc_message->md), @@ -86,8 +115,8 @@ static grpc_error* server_filter_outgoing_metadata(grpc_call_element* elem, return GRPC_ERROR_NONE; } -static void add_error(const char* error_name, grpc_error** cumulative, - grpc_error* new_err) { +static void hs_add_error(const char* error_name, grpc_error** cumulative, + grpc_error* new_err) { if (new_err == GRPC_ERROR_NONE) return; if (*cumulative == GRPC_ERROR_NONE) { *cumulative = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_name); @@ -95,8 +124,8 @@ static void add_error(const char* error_name, grpc_error** cumulative, *cumulative = grpc_error_add_child(*cumulative, new_err); } -static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem, - grpc_metadata_batch* b) { +static grpc_error* hs_filter_incoming_metadata(grpc_call_element* elem, + grpc_metadata_batch* b) { call_data* calld = static_cast(elem->call_data); grpc_error* error = GRPC_ERROR_NONE; static const char* error_name = "Failed processing incoming headers"; @@ -119,14 +148,14 @@ static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem, *calld->recv_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; } else { - add_error(error_name, &error, - grpc_attach_md_to_error( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->idx.named.method->md)); + hs_add_error(error_name, &error, + grpc_attach_md_to_error( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), + b->idx.named.method->md)); } grpc_metadata_batch_remove(b, b->idx.named.method); } else { - add_error( + hs_add_error( error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), @@ -135,31 +164,31 @@ static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem, if (b->idx.named.te != nullptr) { if (!grpc_mdelem_eq(b->idx.named.te->md, GRPC_MDELEM_TE_TRAILERS)) { - add_error(error_name, &error, - grpc_attach_md_to_error( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->idx.named.te->md)); + hs_add_error(error_name, &error, + grpc_attach_md_to_error( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), + b->idx.named.te->md)); } grpc_metadata_batch_remove(b, b->idx.named.te); } else { - add_error(error_name, &error, - grpc_error_set_str( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), - GRPC_ERROR_STR_KEY, grpc_slice_from_static_string("te"))); + hs_add_error(error_name, &error, + grpc_error_set_str( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), + GRPC_ERROR_STR_KEY, grpc_slice_from_static_string("te"))); } if (b->idx.named.scheme != nullptr) { if (!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) && !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) && !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_GRPC)) { - add_error(error_name, &error, - grpc_attach_md_to_error( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->idx.named.scheme->md)); + hs_add_error(error_name, &error, + grpc_attach_md_to_error( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), + b->idx.named.scheme->md)); } grpc_metadata_batch_remove(b, b->idx.named.scheme); } else { - add_error( + hs_add_error( error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), @@ -196,10 +225,11 @@ static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem, } if (b->idx.named.path == nullptr) { - add_error(error_name, &error, - grpc_error_set_str( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), - GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":path"))); + hs_add_error( + error_name, &error, + grpc_error_set_str( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), + GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":path"))); } else if (*calld->recv_initial_metadata_flags & GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { /* We have a cacheable request made with GET verb. The path contains the @@ -235,7 +265,7 @@ static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem, GRPC_SLICE_LENGTH(query_slice), k_url_safe)); calld->read_stream.Init(&read_slice_buffer, 0); grpc_slice_buffer_destroy_internal(&read_slice_buffer); - calld->seen_path_with_query = true; + calld->have_read_stream = true; grpc_slice_unref_internal(query_slice); } else { gpr_log(GPR_ERROR, "GET request without QUERY"); @@ -246,70 +276,106 @@ static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem, grpc_linked_mdelem* el = b->idx.named.host; grpc_mdelem md = GRPC_MDELEM_REF(el->md); grpc_metadata_batch_remove(b, el); - add_error(error_name, &error, - grpc_metadata_batch_add_head( - b, el, - grpc_mdelem_from_slices( - GRPC_MDSTR_AUTHORITY, - grpc_slice_ref_internal(GRPC_MDVALUE(md))))); + hs_add_error(error_name, &error, + grpc_metadata_batch_add_head( + b, el, + grpc_mdelem_from_slices( + GRPC_MDSTR_AUTHORITY, + grpc_slice_ref_internal(GRPC_MDVALUE(md))))); GRPC_MDELEM_UNREF(md); } if (b->idx.named.authority == nullptr) { - add_error( + hs_add_error( error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority"))); } + channel_data* chand = static_cast(elem->channel_data); + if (!chand->surface_user_agent && b->idx.named.user_agent != nullptr) { + grpc_metadata_batch_remove(b, b->idx.named.user_agent); + } + return error; } -static void hs_on_recv(void* user_data, grpc_error* err) { +static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); + calld->seen_recv_initial_metadata_ready = true; if (err == GRPC_ERROR_NONE) { - err = server_filter_incoming_metadata(elem, calld->recv_initial_metadata); + err = hs_filter_incoming_metadata(elem, calld->recv_initial_metadata); + calld->recv_initial_metadata_ready_error = GRPC_ERROR_REF(err); + if (calld->seen_recv_message_ready) { + // We've already seen the recv_message callback, but we previously + // deferred it, so we need to return it here. + // Replace the recv_message byte stream if needed. + if (calld->have_read_stream) { + calld->recv_message->reset(calld->read_stream.get()); + calld->have_read_stream = false; + } + // Re-enter call combiner for original_recv_message_ready, since the + // surface code will release the call combiner for each callback it + // receives. + GRPC_CALL_COMBINER_START( + calld->call_combiner, calld->original_recv_message_ready, + GRPC_ERROR_REF(err), + "resuming recv_message_ready from recv_initial_metadata_ready"); + } } else { GRPC_ERROR_REF(err); } - GRPC_CLOSURE_RUN(calld->on_done_recv, err); + if (calld->seen_recv_trailing_metadata_ready) { + GRPC_CALL_COMBINER_START(calld->call_combiner, + &calld->recv_trailing_metadata_ready, + calld->recv_trailing_metadata_ready_error, + "resuming hs_recv_trailing_metadata_ready from " + "hs_recv_initial_metadata_ready"); + } + GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, err); } -static void hs_on_complete(void* user_data, grpc_error* err) { +static void hs_recv_message_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - /* Call recv_message_ready if we got the payload via the path field */ - if (calld->seen_path_with_query && calld->recv_message_ready != nullptr) { - calld->pp_recv_message->reset( - calld->payload_bin_delivered ? nullptr - : reinterpret_cast( - calld->read_stream.get())); - // Re-enter call combiner for recv_message_ready, since the surface - // code will release the call combiner for each callback it receives. - GRPC_CALL_COMBINER_START(calld->call_combiner, calld->recv_message_ready, - GRPC_ERROR_REF(err), - "resuming recv_message_ready from on_complete"); - calld->recv_message_ready = nullptr; - calld->payload_bin_delivered = true; + calld->seen_recv_message_ready = true; + if (calld->seen_recv_initial_metadata_ready) { + // We've already seen the recv_initial_metadata callback, so + // replace the recv_message byte stream if needed and invoke the + // original recv_message callback immediately. + if (calld->have_read_stream) { + calld->recv_message->reset(calld->read_stream.get()); + calld->have_read_stream = false; + } + GRPC_CLOSURE_RUN(calld->original_recv_message_ready, GRPC_ERROR_REF(err)); + } else { + // We have not yet seen the recv_initial_metadata callback, so we + // need to wait to see if this is a GET request. + // Note that we release the call combiner here, so that other + // callbacks can run. + GRPC_CALL_COMBINER_STOP( + calld->call_combiner, + "pausing recv_message_ready until recv_initial_metadata_ready"); } - GRPC_CLOSURE_RUN(calld->on_complete, GRPC_ERROR_REF(err)); } -static void hs_recv_message_ready(void* user_data, grpc_error* err) { +static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - if (calld->seen_path_with_query) { - // Do nothing. This is probably a GET request, and payload will be - // returned in hs_on_complete callback. - // Note that we release the call combiner here, so that other - // callbacks can run. + if (!calld->seen_recv_initial_metadata_ready) { + calld->recv_trailing_metadata_ready_error = GRPC_ERROR_REF(err); + calld->seen_recv_trailing_metadata_ready = true; GRPC_CALL_COMBINER_STOP(calld->call_combiner, - "pausing recv_message_ready until on_complete"); - } else { - GRPC_CLOSURE_RUN(calld->recv_message_ready, GRPC_ERROR_REF(err)); + "deferring hs_recv_trailing_metadata_ready until " + "ater hs_recv_initial_metadata_ready"); + return; } + err = grpc_error_add_child( + GRPC_ERROR_REF(err), + GRPC_ERROR_REF(calld->recv_initial_metadata_ready_error)); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); } static grpc_error* hs_mutate_op(grpc_call_element* elem, @@ -320,18 +386,18 @@ static grpc_error* hs_mutate_op(grpc_call_element* elem, if (op->send_initial_metadata) { grpc_error* error = GRPC_ERROR_NONE; static const char* error_name = "Failed sending initial metadata"; - add_error(error_name, &error, - grpc_metadata_batch_add_head( - op->payload->send_initial_metadata.send_initial_metadata, - &calld->status, GRPC_MDELEM_STATUS_200)); - add_error(error_name, &error, - grpc_metadata_batch_add_tail( - op->payload->send_initial_metadata.send_initial_metadata, - &calld->content_type, - GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)); - add_error( + hs_add_error(error_name, &error, + grpc_metadata_batch_add_head( + op->payload->send_initial_metadata.send_initial_metadata, + &calld->status, GRPC_MDELEM_STATUS_200)); + hs_add_error(error_name, &error, + grpc_metadata_batch_add_tail( + op->payload->send_initial_metadata.send_initial_metadata, + &calld->content_type, + GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)); + hs_add_error( error_name, &error, - server_filter_outgoing_metadata( + hs_filter_outgoing_metadata( elem, op->payload->send_initial_metadata.send_initial_metadata)); if (error != GRPC_ERROR_NONE) return error; } @@ -343,27 +409,28 @@ static grpc_error* hs_mutate_op(grpc_call_element* elem, op->payload->recv_initial_metadata.recv_initial_metadata; calld->recv_initial_metadata_flags = op->payload->recv_initial_metadata.recv_flags; - calld->on_done_recv = + calld->original_recv_initial_metadata_ready = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = - &calld->hs_on_recv; + &calld->recv_initial_metadata_ready; } if (op->recv_message) { - calld->recv_message_ready = op->payload->recv_message.recv_message_ready; - calld->pp_recv_message = op->payload->recv_message.recv_message; - if (op->payload->recv_message.recv_message_ready) { - op->payload->recv_message.recv_message_ready = - &calld->hs_recv_message_ready; - } - if (op->on_complete) { - calld->on_complete = op->on_complete; - op->on_complete = &calld->hs_on_complete; - } + calld->recv_message = op->payload->recv_message.recv_message; + calld->original_recv_message_ready = + op->payload->recv_message.recv_message_ready; + op->payload->recv_message.recv_message_ready = &calld->recv_message_ready; + } + + if (op->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; } if (op->send_trailing_metadata) { - grpc_error* error = server_filter_outgoing_metadata( + grpc_error* error = hs_filter_outgoing_metadata( elem, op->payload->send_trailing_metadata.send_trailing_metadata); if (error != GRPC_ERROR_NONE) return error; } @@ -385,50 +452,44 @@ static void hs_start_transport_stream_op_batch( } /* Constructor for call_data */ -static grpc_error* init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { - /* grab pointers to our data from the call element */ - call_data* calld = static_cast(elem->call_data); - /* initialize members */ - calld->call_combiner = args->call_combiner; - GRPC_CLOSURE_INIT(&calld->hs_on_recv, hs_on_recv, elem, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->hs_on_complete, hs_on_complete, elem, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->hs_recv_message_ready, hs_recv_message_ready, elem, - grpc_schedule_on_exec_ctx); +static grpc_error* hs_init_call_elem(grpc_call_element* elem, + const grpc_call_element_args* args) { + new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } /* Destructor for call_data */ -static void destroy_call_elem(grpc_call_element* elem, - const grpc_call_final_info* final_info, - grpc_closure* ignored) { +static void hs_destroy_call_elem(grpc_call_element* elem, + const grpc_call_final_info* final_info, + grpc_closure* ignored) { call_data* calld = static_cast(elem->call_data); - if (calld->seen_path_with_query && !calld->payload_bin_delivered) { - calld->read_stream->Orphan(); - } + calld->~call_data(); } /* Constructor for channel_data */ -static grpc_error* init_channel_elem(grpc_channel_element* elem, - grpc_channel_element_args* args) { +static grpc_error* hs_init_channel_elem(grpc_channel_element* elem, + grpc_channel_element_args* args) { + channel_data* chand = static_cast(elem->channel_data); GPR_ASSERT(!args->is_last); + chand->surface_user_agent = grpc_channel_arg_get_bool( + grpc_channel_args_find(args->channel_args, + const_cast(GRPC_ARG_SURFACE_USER_AGENT)), + true); return GRPC_ERROR_NONE; } /* Destructor for channel data */ -static void destroy_channel_elem(grpc_channel_element* elem) {} +static void hs_destroy_channel_elem(grpc_channel_element* elem) {} const grpc_channel_filter grpc_http_server_filter = { hs_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), - init_call_elem, + hs_init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, - destroy_call_elem, + hs_destroy_call_elem, sizeof(channel_data), - init_channel_elem, - destroy_channel_elem, + hs_init_channel_elem, + hs_destroy_channel_elem, grpc_channel_next_get_info, "http-server"}; diff --git a/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.h b/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.h index 4eb130b1f..e4e0546f6 100644 --- a/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.h +++ b/Sources/CgRPC/src/core/ext/filters/http/server/http_server_filter.h @@ -23,7 +23,7 @@ #include "src/core/lib/channel/channel_stack.h" -/* Processes metadata on the client side for HTTP2 transports */ +/* Processes metadata on the server side for HTTP2 transports */ extern const grpc_channel_filter grpc_http_server_filter; #endif /* GRPC_CORE_EXT_FILTERS_HTTP_SERVER_HTTP_SERVER_FILTER_H */ diff --git a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc b/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc deleted file mode 100644 index 0d349e2a8..000000000 --- a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc +++ /dev/null @@ -1,222 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -#include -#include -#include -#include -#include - -#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h" -#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/transport/static_metadata.h" - -namespace { -struct call_data { - intptr_t id; /**< an id unique to the call */ - bool have_trailing_md_string; - grpc_slice trailing_md_string; - bool have_initial_md_string; - grpc_slice initial_md_string; - bool have_service_method; - grpc_slice service_method; - - /* stores the recv_initial_metadata op's ready closure, which we wrap with our - * own (on_initial_md_ready) in order to capture the incoming initial metadata - * */ - grpc_closure* ops_recv_initial_metadata_ready; - - /* to get notified of the availability of the incoming initial metadata. */ - grpc_closure on_initial_md_ready; - grpc_metadata_batch* recv_initial_metadata; -}; - -struct channel_data { - intptr_t id; /**< an id unique to the channel */ -}; -} // namespace - -static void on_initial_md_ready(void* user_data, grpc_error* err) { - grpc_call_element* elem = static_cast(user_data); - call_data* calld = static_cast(elem->call_data); - - if (err == GRPC_ERROR_NONE) { - if (calld->recv_initial_metadata->idx.named.path != nullptr) { - calld->service_method = grpc_slice_ref_internal( - GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md)); - calld->have_service_method = true; - } else { - err = grpc_error_add_child( - err, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing :path header")); - } - if (calld->recv_initial_metadata->idx.named.lb_token != nullptr) { - calld->initial_md_string = grpc_slice_ref_internal( - GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md)); - calld->have_initial_md_string = true; - grpc_metadata_batch_remove( - calld->recv_initial_metadata, - calld->recv_initial_metadata->idx.named.lb_token); - } - } else { - GRPC_ERROR_REF(err); - } - calld->ops_recv_initial_metadata_ready->cb( - calld->ops_recv_initial_metadata_ready->cb_arg, err); - GRPC_ERROR_UNREF(err); -} - -/* Constructor for call_data */ -static grpc_error* init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); - calld->id = (intptr_t)args->call_stack; - GRPC_CLOSURE_INIT(&calld->on_initial_md_ready, on_initial_md_ready, elem, - grpc_schedule_on_exec_ctx); - - /* TODO(dgq): do something with the data - channel_data *chand = elem->channel_data; - grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_CREATION, - (intptr_t)chand->id, - (intptr_t)calld->id, - NULL, - NULL, - NULL, - NULL}; - */ - - return GRPC_ERROR_NONE; -} - -/* Destructor for call_data */ -static void destroy_call_elem(grpc_call_element* elem, - const grpc_call_final_info* final_info, - grpc_closure* ignored) { - call_data* calld = static_cast(elem->call_data); - - /* TODO(dgq): do something with the data - channel_data *chand = elem->channel_data; - grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION, - (intptr_t)chand->id, - (intptr_t)calld->id, - final_info, - calld->initial_md_string, - calld->trailing_md_string, - calld->service_method}; - */ - - if (calld->have_initial_md_string) { - grpc_slice_unref_internal(calld->initial_md_string); - } - if (calld->have_trailing_md_string) { - grpc_slice_unref_internal(calld->trailing_md_string); - } - if (calld->have_service_method) { - grpc_slice_unref_internal(calld->service_method); - } -} - -/* Constructor for channel_data */ -static grpc_error* init_channel_elem(grpc_channel_element* elem, - grpc_channel_element_args* args) { - GPR_ASSERT(!args->is_last); - - channel_data* chand = static_cast(elem->channel_data); - chand->id = (intptr_t)args->channel_stack; - - /* TODO(dgq): do something with the data - grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CHANNEL_CREATION, - (intptr_t)chand, - 0, - NULL, - NULL, - NULL, - NULL}; - */ - - return GRPC_ERROR_NONE; -} - -/* Destructor for channel data */ -static void destroy_channel_elem(grpc_channel_element* elem) { - /* TODO(dgq): do something with the data - channel_data *chand = elem->channel_data; - grpc_load_reporting_call_data lr_call_data = { - GRPC_LR_POINT_CHANNEL_DESTRUCTION, - (intptr_t)chand->id, - 0, - NULL, - NULL, - NULL, - NULL}; - */ -} - -static grpc_filtered_mdelem lr_trailing_md_filter(void* user_data, - grpc_mdelem md) { - grpc_call_element* elem = static_cast(user_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_LB_COST_BIN)) { - calld->trailing_md_string = GRPC_MDVALUE(md); - return GRPC_FILTERED_REMOVE(); - } - return GRPC_FILTERED_MDELEM(md); -} - -static void lr_start_transport_stream_op_batch( - grpc_call_element* elem, grpc_transport_stream_op_batch* op) { - GPR_TIMER_SCOPE("lr_start_transport_stream_op_batch", 0); - call_data* calld = static_cast(elem->call_data); - - if (op->recv_initial_metadata) { - /* substitute our callback for the higher callback */ - calld->recv_initial_metadata = - op->payload->recv_initial_metadata.recv_initial_metadata; - calld->ops_recv_initial_metadata_ready = - op->payload->recv_initial_metadata.recv_initial_metadata_ready; - op->payload->recv_initial_metadata.recv_initial_metadata_ready = - &calld->on_initial_md_ready; - } else if (op->send_trailing_metadata) { - GRPC_LOG_IF_ERROR( - "grpc_metadata_batch_filter", - grpc_metadata_batch_filter( - op->payload->send_trailing_metadata.send_trailing_metadata, - lr_trailing_md_filter, elem, - "LR trailing metadata filtering error")); - } - grpc_call_next_op(elem, op); -} - -const grpc_channel_filter grpc_server_load_reporting_filter = { - lr_start_transport_stream_op_batch, - grpc_channel_next_op, - sizeof(call_data), - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - destroy_call_elem, - sizeof(channel_data), - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "load_reporting"}; diff --git a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc b/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc deleted file mode 100644 index 667c0c56e..000000000 --- a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include -#include -#include - -#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h" -#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/surface/channel_init.h" - -static bool is_load_reporting_enabled(const grpc_channel_args* a) { - return grpc_channel_arg_get_bool( - grpc_channel_args_find(a, GRPC_ARG_ENABLE_LOAD_REPORTING), false); -} - -static bool maybe_add_server_load_reporting_filter( - grpc_channel_stack_builder* builder, void* arg) { - const grpc_channel_args* args = - grpc_channel_stack_builder_get_channel_arguments(builder); - const grpc_channel_filter* filter = - static_cast(arg); - grpc_channel_stack_builder_iterator* it = - grpc_channel_stack_builder_iterator_find(builder, filter->name); - const bool already_has_load_reporting_filter = - !grpc_channel_stack_builder_iterator_is_end(it); - grpc_channel_stack_builder_iterator_destroy(it); - if (is_load_reporting_enabled(args) && !already_has_load_reporting_filter) { - return grpc_channel_stack_builder_prepend_filter(builder, filter, nullptr, - nullptr); - } - return true; -} - -grpc_arg grpc_load_reporting_enable_arg() { - return grpc_channel_arg_integer_create((char*)GRPC_ARG_ENABLE_LOAD_REPORTING, - 1); -} - -/* Plugin registration */ - -void grpc_server_load_reporting_plugin_init(void) { - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, - maybe_add_server_load_reporting_filter, - (void*)&grpc_server_load_reporting_filter); -} - -void grpc_server_load_reporting_plugin_shutdown() {} diff --git a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_plugin.h b/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_plugin.h deleted file mode 100644 index c20aaa744..000000000 --- a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_plugin.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_PLUGIN_H -#define GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_PLUGIN_H - -#include - -#include - -#include "src/core/lib/channel/channel_stack.h" - -/** Identifiers for the invocation point of the users LR callback */ -typedef enum grpc_load_reporting_source { - GRPC_LR_POINT_UNKNOWN = 0, - GRPC_LR_POINT_CHANNEL_CREATION, - GRPC_LR_POINT_CHANNEL_DESTRUCTION, - GRPC_LR_POINT_CALL_CREATION, - GRPC_LR_POINT_CALL_DESTRUCTION -} grpc_load_reporting_source; - -/** Call information to be passed to the provided LR callback. */ -typedef struct grpc_load_reporting_call_data { - const grpc_load_reporting_source source; /**< point of last data update. */ - - /** Unique identifier for the channel associated with the data */ - intptr_t channel_id; - - /** Unique identifier for the call associated with the data. If the call - * hasn't been created yet, it'll have a value of zero. */ - intptr_t call_id; - - /** Only valid when \a source is \a GRPC_LR_POINT_CALL_DESTRUCTION, that is, - * once the call has completed */ - const grpc_call_final_info* final_info; - - const char* initial_md_string; /**< value string for LR's initial md key */ - const char* trailing_md_string; /**< value string for LR's trailing md key */ - const char* method_name; /**< Corresponds to :path header */ -} grpc_load_reporting_call_data; - -/** Return a \a grpc_arg enabling load reporting */ -grpc_arg grpc_load_reporting_enable_arg(); - -#endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_PLUGIN_H \ - */ diff --git a/Sources/CgRPC/src/core/ext/filters/max_age/max_age_filter.cc b/Sources/CgRPC/src/core/ext/filters/max_age/max_age_filter.cc index 1fe8288bd..ec7f4e254 100644 --- a/Sources/CgRPC/src/core/ext/filters/max_age/max_age_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/max_age/max_age_filter.cc @@ -106,7 +106,7 @@ struct channel_data { +--------------------------------+----------------+---------+ MAX_IDLE_STATE_INIT: The initial and final state of 'idle_state'. The - channel has 1 or 1+ active calls, and the the timer is not set. Note that + channel has 1 or 1+ active calls, and the timer is not set. Note that we may put a virtual call to hold this state at channel initialization or shutdown, so that the channel won't enter other states. @@ -429,8 +429,7 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, ? GRPC_MILLIS_INF_FUTURE : DEFAULT_MAX_CONNECTION_IDLE_MS; chand->idle_state = MAX_IDLE_STATE_INIT; - gpr_atm_no_barrier_store(&chand->last_enter_idle_time_millis, - GRPC_MILLIS_INF_PAST); + gpr_atm_no_barrier_store(&chand->last_enter_idle_time_millis, GPR_ATM_MIN); for (size_t i = 0; i < args->channel_args->num_args; ++i) { if (0 == strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_CONNECTION_AGE_MS)) { diff --git a/Sources/CgRPC/src/core/ext/filters/message_size/message_size_filter.cc b/Sources/CgRPC/src/core/ext/filters/message_size/message_size_filter.cc index c7fc3f2e6..94d6942aa 100644 --- a/Sources/CgRPC/src/core/ext/filters/message_size/message_size_filter.cc +++ b/Sources/CgRPC/src/core/ext/filters/message_size/message_size_filter.cc @@ -90,27 +90,70 @@ RefCountedPtr MessageSizeLimits::CreateFromJson( } // namespace } // namespace grpc_core +static void recv_message_ready(void* user_data, grpc_error* error); +static void recv_trailing_metadata_ready(void* user_data, grpc_error* error); + namespace { +struct channel_data { + message_size_limits limits; + // Maps path names to refcounted_message_size_limits structs. + grpc_core::RefCountedPtr>> + method_limit_table; +}; + struct call_data { + call_data(grpc_call_element* elem, const channel_data& chand, + const grpc_call_element_args& args) + : call_combiner(args.call_combiner), limits(chand.limits) { + GRPC_CLOSURE_INIT(&recv_message_ready, ::recv_message_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready, + ::recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + // Get max sizes from channel data, then merge in per-method config values. + // Note: Per-method config is only available on the client, so we + // apply the max request size to the send limit and the max response + // size to the receive limit. + if (chand.method_limit_table != nullptr) { + grpc_core::RefCountedPtr limits = + grpc_core::ServiceConfig::MethodConfigTableLookup( + *chand.method_limit_table, args.path); + if (limits != nullptr) { + if (limits->limits().max_send_size >= 0 && + (limits->limits().max_send_size < this->limits.max_send_size || + this->limits.max_send_size < 0)) { + this->limits.max_send_size = limits->limits().max_send_size; + } + if (limits->limits().max_recv_size >= 0 && + (limits->limits().max_recv_size < this->limits.max_recv_size || + this->limits.max_recv_size < 0)) { + this->limits.max_recv_size = limits->limits().max_recv_size; + } + } + } + } + + ~call_data() { GRPC_ERROR_UNREF(error); } + grpc_call_combiner* call_combiner; message_size_limits limits; // Receive closures are chained: we inject this closure as the // recv_message_ready up-call on transport_stream_op, and remember to // call our next_recv_message_ready member after handling it. grpc_closure recv_message_ready; + grpc_closure recv_trailing_metadata_ready; + // The error caused by a message that is too large, or GRPC_ERROR_NONE + grpc_error* error = GRPC_ERROR_NONE; // Used by recv_message_ready. - grpc_core::OrphanablePtr* recv_message; + grpc_core::OrphanablePtr* recv_message = nullptr; // Original recv_message_ready callback, invoked after our own. - grpc_closure* next_recv_message_ready; -}; - -struct channel_data { - message_size_limits limits; - // Maps path names to refcounted_message_size_limits structs. - grpc_core::RefCountedPtr>> - method_limit_table; + grpc_closure* next_recv_message_ready = nullptr; + // Original recv_trailing_metadata callback, invoked after our own. + grpc_closure* original_recv_trailing_metadata_ready; + bool seen_recv_trailing_metadata = false; + grpc_error* recv_trailing_metadata_error; }; } // namespace @@ -130,18 +173,52 @@ static void recv_message_ready(void* user_data, grpc_error* error) { grpc_error* new_error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED); + GRPC_ERROR_UNREF(calld->error); if (error == GRPC_ERROR_NONE) { error = new_error; } else { error = grpc_error_add_child(error, new_error); - GRPC_ERROR_UNREF(new_error); } + calld->error = GRPC_ERROR_REF(error); gpr_free(message_string); } else { GRPC_ERROR_REF(error); } // Invoke the next callback. - GRPC_CLOSURE_RUN(calld->next_recv_message_ready, error); + grpc_closure* closure = calld->next_recv_message_ready; + calld->next_recv_message_ready = nullptr; + if (calld->seen_recv_trailing_metadata) { + /* We might potentially see another RECV_MESSAGE op. In that case, we do not + * want to run the recv_trailing_metadata_ready closure again. The newer + * RECV_MESSAGE op cannot cause any errors since the transport has already + * invoked the recv_trailing_metadata_ready closure and all further + * RECV_MESSAGE ops will get null payloads. */ + calld->seen_recv_trailing_metadata = false; + GRPC_CALL_COMBINER_START(calld->call_combiner, + &calld->recv_trailing_metadata_ready, + calld->recv_trailing_metadata_error, + "continue recv_trailing_metadata_ready"); + } + GRPC_CLOSURE_RUN(closure, error); +} + +// Callback invoked on completion of recv_trailing_metadata +// Notifies the recv_trailing_metadata batch of any message size failures +static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + if (calld->next_recv_message_ready != nullptr) { + calld->seen_recv_trailing_metadata = true; + calld->recv_trailing_metadata_error = GRPC_ERROR_REF(error); + GRPC_CALL_COMBINER_STOP(calld->call_combiner, + "deferring recv_trailing_metadata_ready until " + "after recv_message_ready"); + return; + } + error = + grpc_error_add_child(GRPC_ERROR_REF(error), GRPC_ERROR_REF(calld->error)); + // Invoke the next callback. + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error); } // Start transport stream op. @@ -172,6 +249,13 @@ static void start_transport_stream_op_batch( calld->recv_message = op->payload->recv_message.recv_message; op->payload->recv_message.recv_message_ready = &calld->recv_message_ready; } + // Inject callback for receiving trailing metadata. + if (op->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; + } // Chain to the next filter. grpc_call_next_op(elem, op); } @@ -180,40 +264,17 @@ static void start_transport_stream_op_batch( static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - calld->call_combiner = args->call_combiner; - calld->next_recv_message_ready = nullptr; - GRPC_CLOSURE_INIT(&calld->recv_message_ready, recv_message_ready, elem, - grpc_schedule_on_exec_ctx); - // Get max sizes from channel data, then merge in per-method config values. - // Note: Per-method config is only available on the client, so we - // apply the max request size to the send limit and the max response - // size to the receive limit. - calld->limits = chand->limits; - if (chand->method_limit_table != nullptr) { - grpc_core::RefCountedPtr limits = - grpc_core::ServiceConfig::MethodConfigTableLookup( - *chand->method_limit_table, args->path); - if (limits != nullptr) { - if (limits->limits().max_send_size >= 0 && - (limits->limits().max_send_size < calld->limits.max_send_size || - calld->limits.max_send_size < 0)) { - calld->limits.max_send_size = limits->limits().max_send_size; - } - if (limits->limits().max_recv_size >= 0 && - (limits->limits().max_recv_size < calld->limits.max_recv_size || - calld->limits.max_recv_size < 0)) { - calld->limits.max_recv_size = limits->limits().max_recv_size; - } - } - } + new (elem->call_data) call_data(elem, *chand, *args); return GRPC_ERROR_NONE; } // Destructor for call_data. static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, - grpc_closure* ignored) {} + grpc_closure* ignored) { + call_data* calld = (call_data*)elem->call_data; + calld->~call_data(); +} static int default_size(const grpc_channel_args* args, int without_minimal_stack) { diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/client/chttp2_connector.cc index e7522ffba..c324c2c92 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -55,7 +55,7 @@ typedef struct { grpc_closure connected; - grpc_handshake_manager* handshake_mgr; + grpc_core::RefCountedPtr handshake_mgr; } chttp2_connector; static void chttp2_connector_ref(grpc_connector* con) { @@ -79,7 +79,7 @@ static void chttp2_connector_shutdown(grpc_connector* con, grpc_error* why) { gpr_mu_lock(&c->mu); c->shutdown = true; if (c->handshake_mgr != nullptr) { - grpc_handshake_manager_shutdown(c->handshake_mgr, GRPC_ERROR_REF(why)); + c->handshake_mgr->Shutdown(GRPC_ERROR_REF(why)); } // If handshaking is not yet in progress, shutdown the endpoint. // Otherwise, the handshaker will do this for us. @@ -91,7 +91,7 @@ static void chttp2_connector_shutdown(grpc_connector* con, grpc_error* why) { } static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + auto* args = static_cast(arg); chttp2_connector* c = static_cast(args->user_data); gpr_mu_lock(&c->mu); if (error != GRPC_ERROR_NONE || c->shutdown) { @@ -117,6 +117,9 @@ static void on_handshake_done(void* arg, grpc_error* error) { c->args.interested_parties); c->result->transport = grpc_create_chttp2_transport(args->args, args->endpoint, true); + grpc_core::RefCountedPtr socket_node = + grpc_chttp2_transport_get_socket_node(c->result->transport); + c->result->socket_uuid = socket_node == nullptr ? 0 : socket_node->uuid(); GPR_ASSERT(c->result->transport); // TODO(roth): We ideally want to wait until we receive HTTP/2 // settings from the server before we consider the connection @@ -149,21 +152,20 @@ static void on_handshake_done(void* arg, grpc_error* error) { grpc_closure* notify = c->notify; c->notify = nullptr; GRPC_CLOSURE_SCHED(notify, error); - grpc_handshake_manager_destroy(c->handshake_mgr); - c->handshake_mgr = nullptr; + c->handshake_mgr.reset(); gpr_mu_unlock(&c->mu); chttp2_connector_unref(reinterpret_cast(c)); } static void start_handshake_locked(chttp2_connector* c) { - c->handshake_mgr = grpc_handshake_manager_create(); - grpc_handshakers_add(HANDSHAKER_CLIENT, c->args.channel_args, - c->handshake_mgr); + c->handshake_mgr = grpc_core::MakeRefCounted(); + grpc_core::HandshakerRegistry::AddHandshakers( + grpc_core::HANDSHAKER_CLIENT, c->args.channel_args, + c->args.interested_parties, c->handshake_mgr.get()); grpc_endpoint_add_to_pollset_set(c->endpoint, c->args.interested_parties); - grpc_handshake_manager_do_handshake( - c->handshake_mgr, c->args.interested_parties, c->endpoint, - c->args.channel_args, c->args.deadline, nullptr /* acceptor */, - on_handshake_done, c); + c->handshake_mgr->DoHandshake(c->endpoint, c->args.channel_args, + c->args.deadline, nullptr /* acceptor */, + on_handshake_done, c); c->endpoint = nullptr; // Endpoint handed off to handshake manager. } @@ -200,7 +202,8 @@ static void chttp2_connector_connect(grpc_connector* con, grpc_closure* notify) { chttp2_connector* c = reinterpret_cast(con); grpc_resolved_address addr; - grpc_get_subchannel_address_arg(args->channel_args, &addr); + grpc_core::Subchannel::GetAddressFromSubchannelAddressArg(args->channel_args, + &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == nullptr); c->notify = notify; @@ -211,9 +214,17 @@ static void chttp2_connector_connect(grpc_connector* con, GRPC_CLOSURE_INIT(&c->connected, connected, c, grpc_schedule_on_exec_ctx); GPR_ASSERT(!c->connecting); c->connecting = true; - grpc_tcp_client_connect(&c->connected, &c->endpoint, args->interested_parties, - args->channel_args, &addr, args->deadline); + grpc_closure* closure = &c->connected; + grpc_endpoint** ep = &c->endpoint; gpr_mu_unlock(&c->mu); + // In some implementations, the closure can be flushed before + // grpc_tcp_client_connect and since the closure requires access to c->mu, + // this can result in a deadlock. Refer + // https://github.com/grpc/grpc/issues/16427 + // grpc_tcp_client_connect would fill c->endpoint with proper contents and we + // make sure that we would still exist at that point by taking a ref. + grpc_tcp_client_connect(closure, ep, args->interested_parties, + args->channel_args, &addr, args->deadline); } static const grpc_connector_vtable chttp2_connector_vtable = { diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create.cc index e6c8c3826..8aabcfa20 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -39,15 +39,13 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} -static grpc_subchannel* client_channel_factory_create_subchannel( - grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) { - grpc_subchannel_args final_sc_args; - memcpy(&final_sc_args, args, sizeof(*args)); - final_sc_args.args = grpc_default_authority_add_if_not_present(args->args); +static grpc_core::Subchannel* client_channel_factory_create_subchannel( + grpc_client_channel_factory* cc_factory, const grpc_channel_args* args) { + grpc_channel_args* new_args = grpc_default_authority_add_if_not_present(args); grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_subchannel* s = grpc_subchannel_create(connector, &final_sc_args); + grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); grpc_connector_unref(connector); - grpc_channel_args_destroy(const_cast(final_sc_args.args)); + grpc_channel_args_destroy(new_args); return s; } diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc index b95c9dae5..5bdcb387c 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc @@ -50,7 +50,7 @@ grpc_channel* grpc_insecure_channel_create_from_fd( GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); grpc_endpoint* client = grpc_tcp_client_create_from_fd( - grpc_fd_create(fd, "client"), args, "fd-client"); + grpc_fd_create(fd, "client", true), args, "fd-client"); grpc_transport* transport = grpc_create_chttp2_transport(final_args, client, true); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc index 5ce73a95d..eb2fee2af 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc @@ -27,7 +27,6 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/memory.h" @@ -39,6 +38,7 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" +#include "src/core/lib/uri/uri_parser.h" static void client_channel_factory_ref( grpc_client_channel_factory* cc_factory) {} @@ -46,10 +46,10 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} -static grpc_subchannel_args* get_secure_naming_subchannel_args( - const grpc_subchannel_args* args) { +static grpc_channel_args* get_secure_naming_channel_args( + const grpc_channel_args* args) { grpc_channel_credentials* channel_credentials = - grpc_channel_credentials_find_in_args(args->args); + grpc_channel_credentials_find_in_args(args); if (channel_credentials == nullptr) { gpr_log(GPR_ERROR, "Can't create subchannel: channel credentials missing for secure " @@ -57,7 +57,7 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( return nullptr; } // Make sure security connector does not already exist in args. - if (grpc_security_connector_find_in_args(args->args) != nullptr) { + if (grpc_security_connector_find_in_args(args) != nullptr) { gpr_log(GPR_ERROR, "Can't create subchannel: security connector already present in " "channel args."); @@ -65,19 +65,19 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( } // To which address are we connecting? By default, use the server URI. const grpc_arg* server_uri_arg = - grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI); + grpc_channel_args_find(args, GRPC_ARG_SERVER_URI); const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg); GPR_ASSERT(server_uri_str != nullptr); grpc_uri* server_uri = grpc_uri_parse(server_uri_str, true /* supress errors */); GPR_ASSERT(server_uri != nullptr); const grpc_core::TargetAuthorityTable* target_authority_table = - grpc_core::FindTargetAuthorityTableInArgs(args->args); + grpc_core::FindTargetAuthorityTableInArgs(args); grpc_core::UniquePtr authority; if (target_authority_table != nullptr) { // Find the authority for the target. const char* target_uri_str = - grpc_get_subchannel_address_uri_arg(args->args); + grpc_core::Subchannel::GetUriFromSubchannelAddressArg(args); grpc_uri* target_uri = grpc_uri_parse(target_uri_str, false /* suppress errors */); GPR_ASSERT(target_uri != nullptr); @@ -100,24 +100,23 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( } grpc_arg args_to_add[2]; size_t num_args_to_add = 0; - if (grpc_channel_args_find(args->args, GRPC_ARG_DEFAULT_AUTHORITY) == - nullptr) { + if (grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) == nullptr) { // If the channel args don't already contain GRPC_ARG_DEFAULT_AUTHORITY, add // the arg, setting it to the value just obtained. args_to_add[num_args_to_add++] = grpc_channel_arg_string_create( const_cast(GRPC_ARG_DEFAULT_AUTHORITY), authority.get()); } grpc_channel_args* args_with_authority = - grpc_channel_args_copy_and_add(args->args, args_to_add, num_args_to_add); + grpc_channel_args_copy_and_add(args, args_to_add, num_args_to_add); grpc_uri_destroy(server_uri); - grpc_channel_security_connector* subchannel_security_connector = nullptr; // Create the security connector using the credentials and target name. grpc_channel_args* new_args_from_connector = nullptr; - const grpc_security_status security_status = - grpc_channel_credentials_create_security_connector( - channel_credentials, authority.get(), args_with_authority, - &subchannel_security_connector, &new_args_from_connector); - if (security_status != GRPC_SECURITY_OK) { + grpc_core::RefCountedPtr + subchannel_security_connector = + channel_credentials->create_security_connector( + /*call_creds=*/nullptr, authority.get(), args_with_authority, + &new_args_from_connector); + if (subchannel_security_connector == nullptr) { gpr_log(GPR_ERROR, "Failed to create secure subchannel for secure name '%s'", authority.get()); @@ -125,42 +124,33 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( return nullptr; } grpc_arg new_security_connector_arg = - grpc_security_connector_to_arg(&subchannel_security_connector->base); + grpc_security_connector_to_arg(subchannel_security_connector.get()); grpc_channel_args* new_args = grpc_channel_args_copy_and_add( new_args_from_connector != nullptr ? new_args_from_connector : args_with_authority, &new_security_connector_arg, 1); - GRPC_SECURITY_CONNECTOR_UNREF(&subchannel_security_connector->base, - "lb_channel_create"); + subchannel_security_connector.reset(DEBUG_LOCATION, "lb_channel_create"); if (new_args_from_connector != nullptr) { grpc_channel_args_destroy(new_args_from_connector); } grpc_channel_args_destroy(args_with_authority); - grpc_subchannel_args* final_sc_args = - static_cast(gpr_malloc(sizeof(*final_sc_args))); - memcpy(final_sc_args, args, sizeof(*args)); - final_sc_args->args = new_args; - return final_sc_args; + return new_args; } -static grpc_subchannel* client_channel_factory_create_subchannel( - grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) { - grpc_subchannel_args* subchannel_args = - get_secure_naming_subchannel_args(args); - if (subchannel_args == nullptr) { - gpr_log( - GPR_ERROR, - "Failed to create subchannel arguments during subchannel creation."); +static grpc_core::Subchannel* client_channel_factory_create_subchannel( + grpc_client_channel_factory* cc_factory, const grpc_channel_args* args) { + grpc_channel_args* new_args = get_secure_naming_channel_args(args); + if (new_args == nullptr) { + gpr_log(GPR_ERROR, + "Failed to create channel args during subchannel creation."); return nullptr; } grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_subchannel* s = grpc_subchannel_create(connector, subchannel_args); + grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); grpc_connector_unref(connector); - grpc_channel_args_destroy( - const_cast(subchannel_args->args)); - gpr_free(subchannel_args); + grpc_channel_args_destroy(new_args); return s; } @@ -216,6 +206,7 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds, grpc_channel_credentials_to_arg(creds)}; grpc_channel_args* new_args = grpc_channel_args_copy_and_add( args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); + new_args = creds->update_arguments(new_args); // Create channel. channel = client_channel_factory_create_channel( &client_channel_factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/server/chttp2_server.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/server/chttp2_server.cc index 687cc483f..040ea2044 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/server/chttp2_server.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/server/chttp2_server.cc @@ -37,8 +37,10 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/gpr/host_port.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" @@ -52,7 +54,9 @@ typedef struct { bool shutdown; grpc_closure tcp_server_shutdown_complete; grpc_closure* server_destroy_listener_done; - grpc_handshake_manager* pending_handshake_mgrs; + grpc_core::HandshakeManager* pending_handshake_mgrs; + grpc_core::RefCountedPtr + channelz_listen_socket; } server_state; typedef struct { @@ -60,13 +64,14 @@ typedef struct { server_state* svr_state; grpc_pollset* accepting_pollset; grpc_tcp_server_acceptor* acceptor; - grpc_handshake_manager* handshake_mgr; + grpc_core::RefCountedPtr handshake_mgr; // State for enforcing handshake timeout on receiving HTTP/2 settings. grpc_chttp2_transport* transport; grpc_millis deadline; grpc_timer timer; grpc_closure on_timeout; grpc_closure on_receive_settings; + grpc_pollset_set* interested_parties; } server_connection_state; static void server_connection_state_unref( @@ -76,6 +81,9 @@ static void server_connection_state_unref( GRPC_CHTTP2_UNREF_TRANSPORT(connection_state->transport, "receive settings timeout"); } + grpc_pollset_set_del_pollset(connection_state->interested_parties, + connection_state->accepting_pollset); + grpc_pollset_set_destroy(connection_state->interested_parties); gpr_free(connection_state); } } @@ -104,13 +112,20 @@ static void on_receive_settings(void* arg, grpc_error* error) { } static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + auto* args = static_cast(arg); server_connection_state* connection_state = static_cast(args->user_data); gpr_mu_lock(&connection_state->svr_state->mu); + grpc_resource_user* resource_user = grpc_server_get_default_resource_user( + connection_state->svr_state->server); if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) { const char* error_str = grpc_error_string(error); gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str); + grpc_resource_user* resource_user = grpc_server_get_default_resource_user( + connection_state->svr_state->server); + if (resource_user != nullptr) { + grpc_resource_user_free(resource_user, GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); + } if (error == GRPC_ERROR_NONE && args->endpoint != nullptr) { // We were shut down after handshaking completed successfully, so // destroy the endpoint here. @@ -129,11 +144,12 @@ static void on_handshake_done(void* arg, grpc_error* error) { // handshaker may have handed off the connection to some external // code, so we can just clean up here without creating a transport. if (args->endpoint != nullptr) { - grpc_transport* transport = - grpc_create_chttp2_transport(args->args, args->endpoint, false); + grpc_transport* transport = grpc_create_chttp2_transport( + args->args, args->endpoint, false, resource_user); grpc_server_setup_transport( connection_state->svr_state->server, transport, - connection_state->accepting_pollset, args->args); + connection_state->accepting_pollset, args->args, + grpc_chttp2_transport_get_socket_node(transport), resource_user); // Use notify_on_receive_settings callback to enforce the // handshake deadline. connection_state->transport = @@ -152,13 +168,17 @@ static void on_handshake_done(void* arg, grpc_error* error) { connection_state, grpc_schedule_on_exec_ctx); grpc_timer_init(&connection_state->timer, connection_state->deadline, &connection_state->on_timeout); + } else { + if (resource_user != nullptr) { + grpc_resource_user_free(resource_user, + GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); + } } } - grpc_handshake_manager_pending_list_remove( - &connection_state->svr_state->pending_handshake_mgrs, - connection_state->handshake_mgr); + connection_state->handshake_mgr->RemoveFromPendingMgrList( + &connection_state->svr_state->pending_handshake_mgrs); gpr_mu_unlock(&connection_state->svr_state->mu); - grpc_handshake_manager_destroy(connection_state->handshake_mgr); + connection_state->handshake_mgr.reset(); gpr_free(connection_state->acceptor); grpc_tcp_server_unref(connection_state->svr_state->tcp_server); server_connection_state_unref(connection_state); @@ -176,11 +196,24 @@ static void on_accept(void* arg, grpc_endpoint* tcp, gpr_free(acceptor); return; } - grpc_handshake_manager* handshake_mgr = grpc_handshake_manager_create(); - grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs, - handshake_mgr); - gpr_mu_unlock(&state->mu); + grpc_resource_user* resource_user = + grpc_server_get_default_resource_user(state->server); + if (resource_user != nullptr && + !grpc_resource_user_safe_alloc(resource_user, + GRPC_RESOURCE_QUOTA_CHANNEL_SIZE)) { + gpr_log( + GPR_ERROR, + "Memory quota exhausted, rejecting the connection, no handshaking."); + gpr_mu_unlock(&state->mu); + grpc_endpoint_shutdown(tcp, GRPC_ERROR_NONE); + grpc_endpoint_destroy(tcp); + gpr_free(acceptor); + return; + } + auto handshake_mgr = grpc_core::MakeRefCounted(); + handshake_mgr->AddToPendingMgrList(&state->pending_handshake_mgrs); grpc_tcp_server_ref(state->tcp_server); + gpr_mu_unlock(&state->mu); server_connection_state* connection_state = static_cast( gpr_zalloc(sizeof(*connection_state))); @@ -189,17 +222,21 @@ static void on_accept(void* arg, grpc_endpoint* tcp, connection_state->accepting_pollset = accepting_pollset; connection_state->acceptor = acceptor; connection_state->handshake_mgr = handshake_mgr; - grpc_handshakers_add(HANDSHAKER_SERVER, state->args, - connection_state->handshake_mgr); + connection_state->interested_parties = grpc_pollset_set_create(); + grpc_pollset_set_add_pollset(connection_state->interested_parties, + connection_state->accepting_pollset); + grpc_core::HandshakerRegistry::AddHandshakers( + grpc_core::HANDSHAKER_SERVER, state->args, + connection_state->interested_parties, + connection_state->handshake_mgr.get()); const grpc_arg* timeout_arg = grpc_channel_args_find(state->args, GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS); connection_state->deadline = grpc_core::ExecCtx::Get()->Now() + grpc_channel_arg_get_integer(timeout_arg, {120 * GPR_MS_PER_SEC, 1, INT_MAX}); - grpc_handshake_manager_do_handshake( - connection_state->handshake_mgr, nullptr /* interested_parties */, tcp, - state->args, connection_state->deadline, acceptor, on_handshake_done, + connection_state->handshake_mgr->DoHandshake( + tcp, state->args, connection_state->deadline, acceptor, on_handshake_done, connection_state); } @@ -221,8 +258,10 @@ static void tcp_server_shutdown_complete(void* arg, grpc_error* error) { gpr_mu_lock(&state->mu); grpc_closure* destroy_done = state->server_destroy_listener_done; GPR_ASSERT(state->shutdown); - grpc_handshake_manager_pending_list_shutdown_all( - state->pending_handshake_mgrs, GRPC_ERROR_REF(error)); + if (state->pending_handshake_mgrs != nullptr) { + state->pending_handshake_mgrs->ShutdownAllPending(GRPC_ERROR_REF(error)); + } + state->channelz_listen_socket.reset(); gpr_mu_unlock(&state->mu); // Flush queued work before destroying handshaker factory, since that // may do a synchronous unref. @@ -262,6 +301,8 @@ grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr, server_state* state = nullptr; grpc_error** errors = nullptr; size_t naddrs = 0; + const grpc_arg* arg = nullptr; + intptr_t socket_uuid = 0; *port_num = -1; @@ -323,9 +364,17 @@ grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr, } grpc_resolved_addresses_destroy(resolved); + arg = grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ); + if (grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT)) { + state->channelz_listen_socket = + grpc_core::MakeRefCounted( + grpc_core::UniquePtr(gpr_strdup(addr))); + socket_uuid = state->channelz_listen_socket->uuid(); + } + /* Register with the server only upon success */ grpc_server_add_listener(server, state, server_start_listener, - server_destroy_listener); + server_destroy_listener, socket_uuid); goto done; /* Error path: cleanup and return */ diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc index 371e46381..c29c1e58c 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc @@ -43,8 +43,9 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server* server, char* name; gpr_asprintf(&name, "fd:%d", fd); - grpc_endpoint* server_endpoint = grpc_tcp_create( - grpc_fd_create(fd, name), grpc_server_get_channel_args(server), name); + grpc_endpoint* server_endpoint = + grpc_tcp_create(grpc_fd_create(fd, name, true), + grpc_server_get_channel_args(server), name); gpr_free(name); @@ -60,7 +61,7 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server* server, grpc_endpoint_add_to_pollset(server_endpoint, pollsets[i]); } - grpc_server_setup_transport(server, transport, nullptr, server_args); + grpc_server_setup_transport(server, transport, nullptr, server_args, nullptr); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); } diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc index 6689a17da..98fdb6207 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc @@ -31,6 +31,7 @@ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/surface/api_trace.h" @@ -40,9 +41,8 @@ int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr, grpc_server_credentials* creds) { grpc_core::ExecCtx exec_ctx; grpc_error* err = GRPC_ERROR_NONE; - grpc_server_security_connector* sc = nullptr; + grpc_core::RefCountedPtr sc; int port_num = 0; - grpc_security_status status; grpc_channel_args* args = nullptr; GRPC_API_TRACE( "grpc_server_add_secure_http2_port(" @@ -54,30 +54,27 @@ int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr, "No credentials specified for secure server port (creds==NULL)"); goto done; } - status = grpc_server_credentials_create_security_connector(creds, &sc); - if (status != GRPC_SECURITY_OK) { + sc = creds->create_security_connector(); + if (sc == nullptr) { char* msg; gpr_asprintf(&msg, "Unable to create secure server with credentials of type %s.", - creds->type); - err = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg), - GRPC_ERROR_INT_SECURITY_STATUS, status); + creds->type()); + err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); goto done; } // Create channel args. grpc_arg args_to_add[2]; args_to_add[0] = grpc_server_credentials_to_arg(creds); - args_to_add[1] = grpc_security_connector_to_arg(&sc->base); + args_to_add[1] = grpc_security_connector_to_arg(sc.get()); args = grpc_channel_args_copy_and_add(grpc_server_get_channel_args(server), args_to_add, GPR_ARRAY_SIZE(args_to_add)); // Add server port. err = grpc_chttp2_server_add_port(server, addr, args, &port_num); done: - if (sc != nullptr) { - GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); - } + sc.reset(DEBUG_LOCATION, "server"); if (err != GRPC_ERROR_NONE) { const char* msg = grpc_error_string(err); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/bin_decoder.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/bin_decoder.cc index f0f32da02..b660a4565 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/bin_decoder.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/bin_decoder.cc @@ -55,7 +55,7 @@ static bool input_is_valid(uint8_t* input_ptr, size_t length) { size_t i; for (i = 0; i < length; ++i) { - if ((decode_table[input_ptr[i]] & 0xC0) != 0) { + if (GPR_UNLIKELY((decode_table[input_ptr[i]] & 0xC0) != 0)) { gpr_log(GPR_ERROR, "Base64 decoding failed, invalid character '%c' in base64 " "input.\n", @@ -86,14 +86,14 @@ size_t grpc_chttp2_base64_infer_length_after_decode(const grpc_slice& slice) { while (len > 0 && bytes[len - 1] == '=') { len--; } - if (GRPC_SLICE_LENGTH(slice) - len > 2) { + if (GPR_UNLIKELY(GRPC_SLICE_LENGTH(slice) - len > 2)) { gpr_log(GPR_ERROR, "Base64 decoding failed. Input has more than 2 paddings."); return 0; } size_t tuples = len / 4; size_t tail_case = len % 4; - if (tail_case == 1) { + if (GPR_UNLIKELY(tail_case == 1)) { gpr_log(GPR_ERROR, "Base64 decoding failed. Input has a length of %zu (without" " padding), which is invalid.\n", @@ -164,7 +164,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_slice input) { struct grpc_base64_decode_context ctx; grpc_slice output; - if (input_length % 4 != 0) { + if (GPR_UNLIKELY(input_length % 4 != 0)) { gpr_log(GPR_ERROR, "Base64 decoding failed, input of " "grpc_chttp2_base64_decode has a length of %d, which is not a " @@ -190,7 +190,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_slice input) { ctx.output_end = GRPC_SLICE_END_PTR(output); ctx.contains_tail = false; - if (!grpc_base64_decode_partial(&ctx)) { + if (GPR_UNLIKELY(!grpc_base64_decode_partial(&ctx))) { char* s = grpc_slice_to_c_string(input); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_free(s); @@ -209,7 +209,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input, struct grpc_base64_decode_context ctx; // The length of a base64 string cannot be 4 * n + 1 - if (input_length % 4 == 1) { + if (GPR_UNLIKELY(input_length % 4 == 1)) { gpr_log(GPR_ERROR, "Base64 decoding failed, input of " "grpc_chttp2_base64_decode_with_length has a length of %d, which " @@ -219,7 +219,8 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input, return grpc_empty_slice(); } - if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) { + if (GPR_UNLIKELY(output_length > + input_length / 4 * 3 + tail_xtra[input_length % 4])) { gpr_log( GPR_ERROR, "Base64 decoding failed, output_length %d is longer " @@ -236,7 +237,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input, ctx.output_end = GRPC_SLICE_END_PTR(output); ctx.contains_tail = true; - if (!grpc_base64_decode_partial(&ctx)) { + if (GPR_UNLIKELY(!grpc_base64_decode_partial(&ctx))) { char* s = grpc_slice_to_c_string(input); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_free(s); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 0ef73961a..1c9b37dad 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ #include #include +#include "src/core/ext/transport/chttp2/transport/context_list.h" #include "src/core/ext/transport/chttp2/transport/frame_data.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/varint.h" @@ -42,6 +43,7 @@ #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -53,6 +55,7 @@ #include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport_impl.h" +#include "src/core/lib/uri/uri_parser.h" #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) #define MAX_WINDOW 0x7fffffffu @@ -154,111 +157,236 @@ bool g_flow_control_enabled = true; * CONSTRUCTION/DESTRUCTION/REFCOUNTING */ -static void destruct_transport(grpc_chttp2_transport* t) { +grpc_chttp2_transport::~grpc_chttp2_transport() { size_t i; - grpc_endpoint_destroy(t->ep); + if (channelz_socket != nullptr) { + channelz_socket.reset(); + } + + grpc_endpoint_destroy(ep); - grpc_slice_buffer_destroy_internal(&t->qbuf); + grpc_slice_buffer_destroy_internal(&qbuf); - grpc_slice_buffer_destroy_internal(&t->outbuf); - grpc_chttp2_hpack_compressor_destroy(&t->hpack_compressor); + grpc_slice_buffer_destroy_internal(&outbuf); + grpc_chttp2_hpack_compressor_destroy(&hpack_compressor); + + grpc_error* error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"); + // ContextList::Execute follows semantics of a callback function and does not + // take a ref on error + grpc_core::ContextList::Execute(cl, nullptr, error); + GRPC_ERROR_UNREF(error); + cl = nullptr; - grpc_slice_buffer_destroy_internal(&t->read_buffer); - grpc_chttp2_hpack_parser_destroy(&t->hpack_parser); - grpc_chttp2_goaway_parser_destroy(&t->goaway_parser); + grpc_slice_buffer_destroy_internal(&read_buffer); + grpc_chttp2_hpack_parser_destroy(&hpack_parser); + grpc_chttp2_goaway_parser_destroy(&goaway_parser); for (i = 0; i < STREAM_LIST_COUNT; i++) { - GPR_ASSERT(t->lists[i].head == nullptr); - GPR_ASSERT(t->lists[i].tail == nullptr); + GPR_ASSERT(lists[i].head == nullptr); + GPR_ASSERT(lists[i].tail == nullptr); } - GRPC_ERROR_UNREF(t->goaway_error); + GRPC_ERROR_UNREF(goaway_error); - GPR_ASSERT(grpc_chttp2_stream_map_size(&t->stream_map) == 0); + GPR_ASSERT(grpc_chttp2_stream_map_size(&stream_map) == 0); - grpc_chttp2_stream_map_destroy(&t->stream_map); - grpc_connectivity_state_destroy(&t->channel_callback.state_tracker); + grpc_chttp2_stream_map_destroy(&stream_map); + grpc_connectivity_state_destroy(&channel_callback.state_tracker); - GRPC_COMBINER_UNREF(t->combiner, "chttp2_transport"); + GRPC_COMBINER_UNREF(combiner, "chttp2_transport"); - cancel_pings(t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed")); + cancel_pings(this, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed")); - while (t->write_cb_pool) { - grpc_chttp2_write_cb* next = t->write_cb_pool->next; - gpr_free(t->write_cb_pool); - t->write_cb_pool = next; + while (write_cb_pool) { + grpc_chttp2_write_cb* next = write_cb_pool->next; + gpr_free(write_cb_pool); + write_cb_pool = next; } - t->flow_control.Destroy(); + flow_control.Destroy(); - GRPC_ERROR_UNREF(t->closed_with_error); - gpr_free(t->ping_acks); - gpr_free(t->peer_string); - gpr_free(t); -} - -#ifndef NDEBUG -void grpc_chttp2_unref_transport(grpc_chttp2_transport* t, const char* reason, - const char* file, int line) { - if (grpc_trace_chttp2_refcount.enabled()) { - gpr_atm val = gpr_atm_no_barrier_load(&t->refs.count); - gpr_log(GPR_DEBUG, "chttp2:unref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", - t, val, val - 1, reason, file, line); - } - if (!gpr_unref(&t->refs)) return; - destruct_transport(t); + GRPC_ERROR_UNREF(closed_with_error); + gpr_free(ping_acks); + gpr_free(peer_string); } -void grpc_chttp2_ref_transport(grpc_chttp2_transport* t, const char* reason, - const char* file, int line) { - if (grpc_trace_chttp2_refcount.enabled()) { - gpr_atm val = gpr_atm_no_barrier_load(&t->refs.count); - gpr_log(GPR_DEBUG, "chttp2: ref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", - t, val, val + 1, reason, file, line); - } - gpr_ref(&t->refs); -} -#else -void grpc_chttp2_unref_transport(grpc_chttp2_transport* t) { - if (!gpr_unref(&t->refs)) return; - destruct_transport(t); -} - -void grpc_chttp2_ref_transport(grpc_chttp2_transport* t) { gpr_ref(&t->refs); } -#endif - static const grpc_transport_vtable* get_vtable(void); -static void init_transport(grpc_chttp2_transport* t, - const grpc_channel_args* channel_args, - grpc_endpoint* ep, bool is_client) { +/* Returns whether bdp is enabled */ +static bool read_channel_args(grpc_chttp2_transport* t, + const grpc_channel_args* channel_args, + bool is_client) { + bool enable_bdp = true; + bool channelz_enabled = GRPC_ENABLE_CHANNELZ_DEFAULT; size_t i; int j; - GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == - GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); - - t->base.vtable = get_vtable(); - t->ep = ep; - /* one ref is for destroy */ - gpr_ref_init(&t->refs, 1); - t->combiner = grpc_combiner_create(); - t->peer_string = grpc_endpoint_get_peer(ep); - t->endpoint_reading = 1; - t->next_stream_id = is_client ? 1 : 2; - t->is_client = is_client; - t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; - t->is_first_frame = true; - grpc_connectivity_state_init( - &t->channel_callback.state_tracker, GRPC_CHANNEL_READY, - is_client ? "client_transport" : "server_transport"); - - grpc_slice_buffer_init(&t->qbuf); - - grpc_slice_buffer_init(&t->outbuf); - grpc_chttp2_hpack_compressor_init(&t->hpack_compressor); + for (i = 0; i < channel_args->num_args; i++) { + if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = + grpc_channel_arg_get_integer(&channel_args->args[i], options); + if (value >= 0) { + if ((t->next_stream_id & 1) != (value & 1)) { + gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", + GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, t->next_stream_id & 1, + is_client ? "client" : "server"); + } else { + t->next_stream_id = static_cast(value); + } + } + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) { + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = + grpc_channel_arg_get_integer(&channel_args->args[i], options); + if (value >= 0) { + grpc_chttp2_hpack_compressor_set_max_usable_size( + &t->hpack_compressor, static_cast(value)); + } + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) { + t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer( + &channel_args->args[i], + {g_default_max_pings_without_data, 0, INT_MAX}); + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_MAX_PING_STRIKES)) { + t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer( + &channel_args->args[i], {g_default_max_ping_strikes, 0, INT_MAX}); + } else if (0 == + strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) { + t->ping_policy.min_sent_ping_interval_without_data = + grpc_channel_arg_get_integer( + &channel_args->args[i], + grpc_integer_options{ + g_default_min_sent_ping_interval_without_data_ms, 0, + INT_MAX}); + } else if (0 == + strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) { + t->ping_policy.min_recv_ping_interval_without_data = + grpc_channel_arg_get_integer( + &channel_args->args[i], + grpc_integer_options{ + g_default_min_recv_ping_interval_without_data_ms, 0, + INT_MAX}); + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { + t->write_buffer_size = static_cast(grpc_channel_arg_get_integer( + &channel_args->args[i], {0, 0, MAX_WRITE_BUFFER_SIZE})); + } else if (0 == + strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) { + enable_bdp = grpc_channel_arg_get_bool(&channel_args->args[i], true); + } else if (0 == + strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], + grpc_integer_options{t->is_client + ? g_default_client_keepalive_time_ms + : g_default_server_keepalive_time_ms, + 1, INT_MAX}); + t->keepalive_time = value == INT_MAX ? GRPC_MILLIS_INF_FUTURE : value; + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], + grpc_integer_options{t->is_client + ? g_default_client_keepalive_timeout_ms + : g_default_server_keepalive_timeout_ms, + 0, INT_MAX}); + t->keepalive_timeout = value == INT_MAX ? GRPC_MILLIS_INF_FUTURE : value; + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { + t->keepalive_permit_without_calls = static_cast( + grpc_channel_arg_get_integer(&channel_args->args[i], {0, 0, 1})); + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_OPTIMIZATION_TARGET)) { + if (channel_args->args[i].type != GRPC_ARG_STRING) { + gpr_log(GPR_ERROR, "%s should be a string", + GRPC_ARG_OPTIMIZATION_TARGET); + } else if (0 == strcmp(channel_args->args[i].value.string, "blend")) { + t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY; + } else if (0 == strcmp(channel_args->args[i].value.string, "latency")) { + t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY; + } else if (0 == + strcmp(channel_args->args[i].value.string, "throughput")) { + t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT; + } else { + gpr_log(GPR_ERROR, "%s value '%s' unknown, assuming 'blend'", + GRPC_ARG_OPTIMIZATION_TARGET, + channel_args->args[i].value.string); + } + } else if (0 == + strcmp(channel_args->args[i].key, GRPC_ARG_ENABLE_CHANNELZ)) { + channelz_enabled = grpc_channel_arg_get_bool( + &channel_args->args[i], GRPC_ENABLE_CHANNELZ_DEFAULT); + } else { + static const struct { + const char* channel_arg_name; + grpc_chttp2_setting_id setting_id; + grpc_integer_options integer_options; + bool availability[2] /* server, client */; + } settings_map[] = {{GRPC_ARG_MAX_CONCURRENT_STREAMS, + GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, + {-1, 0, INT32_MAX}, + {true, false}}, + {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER, + GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, + {-1, 0, INT32_MAX}, + {true, true}}, + {GRPC_ARG_MAX_METADATA_SIZE, + GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, + {-1, 0, INT32_MAX}, + {true, true}}, + {GRPC_ARG_HTTP2_MAX_FRAME_SIZE, + GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, + {-1, 16384, 16777215}, + {true, true}}, + {GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, + GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, + {1, 0, 1}, + {true, true}}, + {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES, + GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, + {-1, 5, INT32_MAX}, + {true, true}}}; + for (j = 0; j < static_cast GPR_ARRAY_SIZE(settings_map); j++) { + if (0 == strcmp(channel_args->args[i].key, + settings_map[j].channel_arg_name)) { + if (!settings_map[j].availability[is_client]) { + gpr_log(GPR_DEBUG, "%s is not available on %s", + settings_map[j].channel_arg_name, + is_client ? "clients" : "servers"); + } else { + int value = grpc_channel_arg_get_integer( + &channel_args->args[i], settings_map[j].integer_options); + if (value >= 0) { + queue_setting_update(t, settings_map[j].setting_id, + static_cast(value)); + } + } + break; + } + } + } + } + if (channelz_enabled) { + // TODO(ncteisen): add an API to endpoint to query for local addr, and pass + // it in here, so SocketNode knows its own address. + t->channelz_socket = + grpc_core::MakeRefCounted( + grpc_core::UniquePtr(), + grpc_core::UniquePtr(gpr_strdup(t->peer_string))); + } + return enable_bdp; +} +static void init_transport_closures(grpc_chttp2_transport* t) { GRPC_CLOSURE_INIT(&t->read_action_locked, read_action_locked, t, grpc_combiner_scheduler(t->combiner)); GRPC_CLOSURE_INIT(&t->benign_reclaimer_locked, benign_reclaimer_locked, t, @@ -286,56 +414,9 @@ static void init_transport(grpc_chttp2_transport* t, GRPC_CLOSURE_INIT(&t->keepalive_watchdog_fired_locked, keepalive_watchdog_fired_locked, t, grpc_combiner_scheduler(t->combiner)); +} - t->goaway_error = GRPC_ERROR_NONE; - grpc_chttp2_goaway_parser_init(&t->goaway_parser); - grpc_chttp2_hpack_parser_init(&t->hpack_parser); - - grpc_slice_buffer_init(&t->read_buffer); - - /* 8 is a random stab in the dark as to a good initial size: it's small enough - that it shouldn't waste memory for infrequently used connections, yet - large enough that the exponential growth should happen nicely when it's - needed. - TODO(ctiller): tune this */ - grpc_chttp2_stream_map_init(&t->stream_map, 8); - - /* copy in initial settings to all setting sets */ - for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { - for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { - t->settings[j][i] = grpc_chttp2_settings_parameters[i].default_value; - } - } - t->dirtied_local_settings = 1; - /* Hack: it's common for implementations to assume 65536 bytes initial send - window -- this should by rights be 0 */ - t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - t->sent_local_settings = 0; - t->write_buffer_size = grpc_core::chttp2::kDefaultWindow; - - if (is_client) { - grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string( - GRPC_CHTTP2_CLIENT_CONNECT_STRING)); - } - - /* configure http2 the way we like it */ - if (is_client) { - queue_setting_update(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); - queue_setting_update(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); - } - queue_setting_update(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, - DEFAULT_MAX_HEADER_LIST_SIZE); - queue_setting_update(t, GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, - 1); - - t->ping_policy.max_pings_without_data = g_default_max_pings_without_data; - t->ping_policy.min_sent_ping_interval_without_data = - g_default_min_sent_ping_interval_without_data_ms; - t->ping_policy.max_ping_strikes = g_default_max_ping_strikes; - t->ping_policy.min_recv_ping_interval_without_data = - g_default_min_recv_ping_interval_without_data_ms; - - /* Keepalive setting */ +static void init_transport_keepalive_settings(grpc_chttp2_transport* t) { if (t->is_client) { t->keepalive_time = g_default_client_keepalive_time_ms == INT_MAX ? GRPC_MILLIS_INF_FUTURE @@ -355,205 +436,121 @@ static void init_transport(grpc_chttp2_transport* t, t->keepalive_permit_without_calls = g_default_server_keepalive_permit_without_calls; } +} - t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY; +static void configure_transport_ping_policy(grpc_chttp2_transport* t) { + t->ping_policy.max_pings_without_data = g_default_max_pings_without_data; + t->ping_policy.min_sent_ping_interval_without_data = + g_default_min_sent_ping_interval_without_data_ms; + t->ping_policy.max_ping_strikes = g_default_max_ping_strikes; + t->ping_policy.min_recv_ping_interval_without_data = + g_default_min_recv_ping_interval_without_data_ms; +} - bool enable_bdp = true; +static void init_keepalive_pings_if_enabled(grpc_chttp2_transport* t) { + if (t->keepalive_time != GRPC_MILLIS_INF_FUTURE) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; + GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); + grpc_timer_init(&t->keepalive_ping_timer, + grpc_core::ExecCtx::Get()->Now() + t->keepalive_time, + &t->init_keepalive_ping_locked); + } else { + /* Use GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED to indicate there are no + inflight keeaplive timers */ + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED; + } +} - if (channel_args) { - for (i = 0; i < channel_args->num_args; i++) { - if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { - const grpc_integer_options options = {-1, 0, INT_MAX}; - const int value = - grpc_channel_arg_get_integer(&channel_args->args[i], options); - if (value >= 0) { - if ((t->next_stream_id & 1) != (value & 1)) { - gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, - t->next_stream_id & 1, is_client ? "client" : "server"); - } else { - t->next_stream_id = static_cast(value); - } - } - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) { - const grpc_integer_options options = {-1, 0, INT_MAX}; - const int value = - grpc_channel_arg_get_integer(&channel_args->args[i], options); - if (value >= 0) { - grpc_chttp2_hpack_compressor_set_max_usable_size( - &t->hpack_compressor, static_cast(value)); - } - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) { - t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer( - &channel_args->args[i], - {g_default_max_pings_without_data, 0, INT_MAX}); - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_MAX_PING_STRIKES)) { - t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer( - &channel_args->args[i], {g_default_max_ping_strikes, 0, INT_MAX}); - } else if (0 == - strcmp( - channel_args->args[i].key, - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) { - t->ping_policy.min_sent_ping_interval_without_data = - grpc_channel_arg_get_integer( - &channel_args->args[i], - grpc_integer_options{ - g_default_min_sent_ping_interval_without_data_ms, 0, - INT_MAX}); - } else if (0 == - strcmp( - channel_args->args[i].key, - GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) { - t->ping_policy.min_recv_ping_interval_without_data = - grpc_channel_arg_get_integer( - &channel_args->args[i], - grpc_integer_options{ - g_default_min_recv_ping_interval_without_data_ms, 0, - INT_MAX}); - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { - t->write_buffer_size = - static_cast(grpc_channel_arg_get_integer( - &channel_args->args[i], {0, 0, MAX_WRITE_BUFFER_SIZE})); - } else if (0 == - strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) { - enable_bdp = grpc_channel_arg_get_bool(&channel_args->args[i], true); - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_KEEPALIVE_TIME_MS)) { - const int value = grpc_channel_arg_get_integer( - &channel_args->args[i], - grpc_integer_options{t->is_client - ? g_default_client_keepalive_time_ms - : g_default_server_keepalive_time_ms, - 1, INT_MAX}); - t->keepalive_time = value == INT_MAX ? GRPC_MILLIS_INF_FUTURE : value; - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { - const int value = grpc_channel_arg_get_integer( - &channel_args->args[i], - grpc_integer_options{t->is_client - ? g_default_client_keepalive_timeout_ms - : g_default_server_keepalive_timeout_ms, - 0, INT_MAX}); - t->keepalive_timeout = - value == INT_MAX ? GRPC_MILLIS_INF_FUTURE : value; - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { - t->keepalive_permit_without_calls = static_cast( - grpc_channel_arg_get_integer(&channel_args->args[i], {0, 0, 1})); - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_OPTIMIZATION_TARGET)) { - if (channel_args->args[i].type != GRPC_ARG_STRING) { - gpr_log(GPR_ERROR, "%s should be a string", - GRPC_ARG_OPTIMIZATION_TARGET); - } else if (0 == strcmp(channel_args->args[i].value.string, "blend")) { - t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY; - } else if (0 == strcmp(channel_args->args[i].value.string, "latency")) { - t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY; - } else if (0 == - strcmp(channel_args->args[i].value.string, "throughput")) { - t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT; - } else { - gpr_log(GPR_ERROR, "%s value '%s' unknown, assuming 'blend'", - GRPC_ARG_OPTIMIZATION_TARGET, - channel_args->args[i].value.string); - } - } else { - static const struct { - const char* channel_arg_name; - grpc_chttp2_setting_id setting_id; - grpc_integer_options integer_options; - bool availability[2] /* server, client */; - } settings_map[] = { - {GRPC_ARG_MAX_CONCURRENT_STREAMS, - GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, - {-1, 0, INT32_MAX}, - {true, false}}, - {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER, - GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, - {-1, 0, INT32_MAX}, - {true, true}}, - {GRPC_ARG_MAX_METADATA_SIZE, - GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, - {-1, 0, INT32_MAX}, - {true, true}}, - {GRPC_ARG_HTTP2_MAX_FRAME_SIZE, - GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, - {-1, 16384, 16777215}, - {true, true}}, - {GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, - GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, - {1, 0, 1}, - {true, true}}, - {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES, - GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, - {-1, 5, INT32_MAX}, - {true, true}}}; - for (j = 0; j < static_cast GPR_ARRAY_SIZE(settings_map); j++) { - if (0 == strcmp(channel_args->args[i].key, - settings_map[j].channel_arg_name)) { - if (!settings_map[j].availability[is_client]) { - gpr_log(GPR_DEBUG, "%s is not available on %s", - settings_map[j].channel_arg_name, - is_client ? "clients" : "servers"); - } else { - int value = grpc_channel_arg_get_integer( - &channel_args->args[i], settings_map[j].integer_options); - if (value >= 0) { - queue_setting_update(t, settings_map[j].setting_id, - static_cast(value)); - } - } - break; - } - } - } +grpc_chttp2_transport::grpc_chttp2_transport( + const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client, + grpc_resource_user* resource_user) + : refs(1, &grpc_trace_chttp2_refcount), + ep(ep), + peer_string(grpc_endpoint_get_peer(ep)), + resource_user(resource_user), + combiner(grpc_combiner_create()), + is_client(is_client), + next_stream_id(is_client ? 1 : 2), + deframe_state(is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0) { + GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == + GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); + base.vtable = get_vtable(); + /* 8 is a random stab in the dark as to a good initial size: it's small enough + that it shouldn't waste memory for infrequently used connections, yet + large enough that the exponential growth should happen nicely when it's + needed. + TODO(ctiller): tune this */ + grpc_chttp2_stream_map_init(&stream_map, 8); + + grpc_slice_buffer_init(&read_buffer); + grpc_connectivity_state_init( + &channel_callback.state_tracker, GRPC_CHANNEL_READY, + is_client ? "client_transport" : "server_transport"); + grpc_slice_buffer_init(&outbuf); + if (is_client) { + grpc_slice_buffer_add(&outbuf, grpc_slice_from_copied_string( + GRPC_CHTTP2_CLIENT_CONNECT_STRING)); + } + grpc_chttp2_hpack_compressor_init(&hpack_compressor); + grpc_slice_buffer_init(&qbuf); + /* copy in initial settings to all setting sets */ + size_t i; + int j; + for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { + for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { + settings[j][i] = grpc_chttp2_settings_parameters[i].default_value; } } + grpc_chttp2_hpack_parser_init(&hpack_parser); + grpc_chttp2_goaway_parser_init(&goaway_parser); + + init_transport_closures(this); + + /* configure http2 the way we like it */ + if (is_client) { + queue_setting_update(this, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); + queue_setting_update(this, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); + } + queue_setting_update(this, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, + DEFAULT_MAX_HEADER_LIST_SIZE); + queue_setting_update(this, + GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1); + + configure_transport_ping_policy(this); + init_transport_keepalive_settings(this); + + bool enable_bdp = true; + if (channel_args) { + enable_bdp = read_channel_args(this, channel_args, is_client); + } if (g_flow_control_enabled) { - t->flow_control.Init(t, - enable_bdp); + flow_control.Init(this, + enable_bdp); } else { - t->flow_control.Init(t); + flow_control.Init(this); enable_bdp = false; } /* No pings allowed before receiving a header or data frame. */ - t->ping_state.pings_before_data_required = 0; - t->ping_state.is_delayed_ping_timer_set = false; - t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST; + ping_state.pings_before_data_required = 0; + ping_state.is_delayed_ping_timer_set = false; + ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST; - t->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST; - t->ping_recv_state.ping_strikes = 0; + ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST; + ping_recv_state.ping_strikes = 0; - /* Start keepalive pings */ - if (t->keepalive_time != GRPC_MILLIS_INF_FUTURE) { - t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; - GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); - grpc_timer_init(&t->keepalive_ping_timer, - grpc_core::ExecCtx::Get()->Now() + t->keepalive_time, - &t->init_keepalive_ping_locked); - } else { - /* Use GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED to indicate there are no - inflight keeaplive timers */ - t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED; - } + init_keepalive_pings_if_enabled(this); if (enable_bdp) { - GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping"); - schedule_bdp_ping_locked(t); - - grpc_chttp2_act_on_flowctl_action(t->flow_control->PeriodicUpdate(), t, + GRPC_CHTTP2_REF_TRANSPORT(this, "bdp_ping"); + schedule_bdp_ping_locked(this); + grpc_chttp2_act_on_flowctl_action(flow_control->PeriodicUpdate(), this, nullptr); } - grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE); - post_benign_reclaimer(t); + grpc_chttp2_initiate_write(this, GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE); + post_benign_reclaimer(this); } static void destroy_transport_locked(void* tp, grpc_error* error) { @@ -563,6 +560,7 @@ static void destroy_transport_locked(void* tp, grpc_error* error) { t, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"), GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state)); + // Must be the last line. GRPC_CHTTP2_UNREF_TRANSPORT(t, "destroy"); } @@ -647,103 +645,108 @@ void grpc_chttp2_stream_unref(grpc_chttp2_stream* s) { } #endif -static int init_stream(grpc_transport* gt, grpc_stream* gs, - grpc_stream_refcount* refcount, const void* server_data, - gpr_arena* arena) { - GPR_TIMER_SCOPE("init_stream", 0); - grpc_chttp2_transport* t = reinterpret_cast(gt); - grpc_chttp2_stream* s = reinterpret_cast(gs); - - s->t = t; - s->refcount = refcount; +grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t, + grpc_stream_refcount* refcount, + const void* server_data, + gpr_arena* arena) + : t(t), refcount(refcount), metadata_buffer{{arena}, {arena}} { /* We reserve one 'active stream' that's dropped when the stream is read-closed. The others are for Chttp2IncomingByteStreams that are actively reading */ - GRPC_CHTTP2_STREAM_REF(s, "chttp2"); - - grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0], arena); - grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1], arena); - grpc_chttp2_data_parser_init(&s->data_parser); - grpc_slice_buffer_init(&s->flow_controlled_buffer); - s->deadline = GRPC_MILLIS_INF_FUTURE; - GRPC_CLOSURE_INIT(&s->complete_fetch_locked, complete_fetch_locked, s, - grpc_schedule_on_exec_ctx); - grpc_slice_buffer_init(&s->unprocessed_incoming_frames_buffer); - s->unprocessed_incoming_frames_buffer_cached_length = 0; - grpc_slice_buffer_init(&s->frame_storage); - grpc_slice_buffer_init(&s->compressed_data_buffer); - grpc_slice_buffer_init(&s->decompressed_data_buffer); - s->pending_byte_stream = false; - s->decompressed_header_bytes = 0; - GRPC_CLOSURE_INIT(&s->reset_byte_stream, reset_byte_stream, s, - grpc_combiner_scheduler(t->combiner)); - + GRPC_CHTTP2_STREAM_REF(this, "chttp2"); GRPC_CHTTP2_REF_TRANSPORT(t, "stream"); if (server_data) { - s->id = static_cast((uintptr_t)server_data); - *t->accepting_stream = s; - grpc_chttp2_stream_map_add(&t->stream_map, s->id, s); + id = static_cast((uintptr_t)server_data); + *t->accepting_stream = this; + grpc_chttp2_stream_map_add(&t->stream_map, id, this); post_destructive_reclaimer(t); } - if (t->flow_control->flow_control_enabled()) { - s->flow_control.Init( + flow_control.Init( static_cast( t->flow_control.get()), - s); + this); } else { - s->flow_control.Init(); + flow_control.Init(); } - return 0; + grpc_slice_buffer_init(&frame_storage); + grpc_slice_buffer_init(&unprocessed_incoming_frames_buffer); + grpc_slice_buffer_init(&flow_controlled_buffer); + grpc_slice_buffer_init(&compressed_data_buffer); + grpc_slice_buffer_init(&decompressed_data_buffer); + + GRPC_CLOSURE_INIT(&complete_fetch_locked, ::complete_fetch_locked, this, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&reset_byte_stream, ::reset_byte_stream, this, + grpc_combiner_scheduler(t->combiner)); } -static void destroy_stream_locked(void* sp, grpc_error* error) { - GPR_TIMER_SCOPE("destroy_stream", 0); - grpc_chttp2_stream* s = static_cast(sp); - grpc_chttp2_transport* t = s->t; +grpc_chttp2_stream::~grpc_chttp2_stream() { + if (t->channelz_socket != nullptr) { + if ((t->is_client && eos_received) || (!t->is_client && eos_sent)) { + t->channelz_socket->RecordStreamSucceeded(); + } else { + t->channelz_socket->RecordStreamFailed(); + } + } - GPR_ASSERT((s->write_closed && s->read_closed) || s->id == 0); - if (s->id != 0) { - GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, s->id) == nullptr); + GPR_ASSERT((write_closed && read_closed) || id == 0); + if (id != 0) { + GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, id) == nullptr); } - grpc_slice_buffer_destroy_internal(&s->unprocessed_incoming_frames_buffer); - grpc_slice_buffer_destroy_internal(&s->frame_storage); - grpc_slice_buffer_destroy_internal(&s->compressed_data_buffer); - grpc_slice_buffer_destroy_internal(&s->decompressed_data_buffer); + grpc_slice_buffer_destroy_internal(&unprocessed_incoming_frames_buffer); + grpc_slice_buffer_destroy_internal(&frame_storage); + grpc_slice_buffer_destroy_internal(&compressed_data_buffer); + grpc_slice_buffer_destroy_internal(&decompressed_data_buffer); - grpc_chttp2_list_remove_stalled_by_transport(t, s); - grpc_chttp2_list_remove_stalled_by_stream(t, s); + grpc_chttp2_list_remove_stalled_by_transport(t, this); + grpc_chttp2_list_remove_stalled_by_stream(t, this); for (int i = 0; i < STREAM_LIST_COUNT; i++) { - if (s->included[i]) { + if (GPR_UNLIKELY(included[i])) { gpr_log(GPR_ERROR, "%s stream %d still included in list %d", - t->is_client ? "client" : "server", s->id, i); + t->is_client ? "client" : "server", id, i); abort(); } } - GPR_ASSERT(s->send_initial_metadata_finished == nullptr); - GPR_ASSERT(s->fetching_send_message == nullptr); - GPR_ASSERT(s->send_trailing_metadata_finished == nullptr); - GPR_ASSERT(s->recv_initial_metadata_ready == nullptr); - GPR_ASSERT(s->recv_message_ready == nullptr); - GPR_ASSERT(s->recv_trailing_metadata_finished == nullptr); - grpc_chttp2_data_parser_destroy(&s->data_parser); - grpc_chttp2_incoming_metadata_buffer_destroy(&s->metadata_buffer[0]); - grpc_chttp2_incoming_metadata_buffer_destroy(&s->metadata_buffer[1]); - grpc_slice_buffer_destroy_internal(&s->flow_controlled_buffer); - GRPC_ERROR_UNREF(s->read_closed_error); - GRPC_ERROR_UNREF(s->write_closed_error); - GRPC_ERROR_UNREF(s->byte_stream_error); + GPR_ASSERT(send_initial_metadata_finished == nullptr); + GPR_ASSERT(fetching_send_message == nullptr); + GPR_ASSERT(send_trailing_metadata_finished == nullptr); + GPR_ASSERT(recv_initial_metadata_ready == nullptr); + GPR_ASSERT(recv_message_ready == nullptr); + GPR_ASSERT(recv_trailing_metadata_finished == nullptr); + grpc_slice_buffer_destroy_internal(&flow_controlled_buffer); + GRPC_ERROR_UNREF(read_closed_error); + GRPC_ERROR_UNREF(write_closed_error); + GRPC_ERROR_UNREF(byte_stream_error); + + flow_control.Destroy(); - s->flow_control.Destroy(); + if (t->resource_user != nullptr) { + grpc_resource_user_free(t->resource_user, GRPC_RESOURCE_QUOTA_CALL_SIZE); + } GRPC_CHTTP2_UNREF_TRANSPORT(t, "stream"); + GRPC_CLOSURE_SCHED(destroy_stream_arg, GRPC_ERROR_NONE); +} - GRPC_CLOSURE_SCHED(s->destroy_stream_arg, GRPC_ERROR_NONE); +static int init_stream(grpc_transport* gt, grpc_stream* gs, + grpc_stream_refcount* refcount, const void* server_data, + gpr_arena* arena) { + GPR_TIMER_SCOPE("init_stream", 0); + grpc_chttp2_transport* t = reinterpret_cast(gt); + new (gs) grpc_chttp2_stream(t, refcount, server_data, arena); + return 0; +} + +static void destroy_stream_locked(void* sp, grpc_error* error) { + GPR_TIMER_SCOPE("destroy_stream", 0); + grpc_chttp2_stream* s = static_cast(sp); + s->~grpc_chttp2_stream(); } static void destroy_stream(grpc_transport* gt, grpc_stream* gs, @@ -779,7 +782,21 @@ grpc_chttp2_stream* grpc_chttp2_parsing_accept_stream(grpc_chttp2_transport* t, if (t->channel_callback.accept_stream == nullptr) { return nullptr; } - grpc_chttp2_stream* accepting; + // Don't accept the stream if memory quota doesn't allow. Note that we should + // simply refuse the stream here instead of canceling the stream after it's + // accepted since the latter will create the call which costs much memory. + if (t->resource_user != nullptr && + !grpc_resource_user_safe_alloc(t->resource_user, + GRPC_RESOURCE_QUOTA_CALL_SIZE)) { + gpr_log(GPR_ERROR, "Memory exhausted, rejecting the stream."); + grpc_slice_buffer_add( + &t->qbuf, + grpc_chttp2_rst_stream_create( + id, static_cast(GRPC_HTTP2_REFUSED_STREAM), nullptr)); + grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM); + return nullptr; + } + grpc_chttp2_stream* accepting = nullptr; GPR_ASSERT(t->accepting_stream == nullptr); t->accepting_stream = &accepting; t->channel_callback.accept_stream(t->channel_callback.accept_stream_user_data, @@ -812,6 +829,12 @@ static void set_write_state(grpc_chttp2_transport* t, write_state_name(t->write_state), write_state_name(st), reason)); t->write_state = st; + /* If the state is being reset back to idle, it means a write was just + * finished. Make sure all the run_after_write closures are scheduled. + * + * This is also our chance to close the transport if the transport was marked + * to be closed after all writes finish (for example, if we received a go-away + * from peer while we had some pending writes) */ if (st == GRPC_CHTTP2_WRITE_STATE_IDLE) { GRPC_CLOSURE_LIST_SCHED(&t->run_after_write); if (t->close_transport_on_writes_finished != nullptr) { @@ -899,6 +922,22 @@ void grpc_chttp2_initiate_write(grpc_chttp2_transport* t, grpc_chttp2_initiate_write_reason_string(reason)); t->is_first_write_in_batch = true; GRPC_CHTTP2_REF_TRANSPORT(t, "writing"); + /* Note that the 'write_action_begin_locked' closure is being scheduled + * on the 'finally_scheduler' of t->combiner. This means that + * 'write_action_begin_locked' is called only *after* all the other + * closures (some of which are potentially initiating more writes on the + * transport) are executed on the t->combiner. + * + * The reason for scheduling on finally_scheduler is to make sure we batch + * as many writes as possible. 'write_action_begin_locked' is the function + * that gathers all the relevant bytes (which are at various places in the + * grpc_chttp2_transport structure) and append them to 'outbuf' field in + * grpc_chttp2_transport thereby batching what would have been potentially + * multiple write operations. + * + * Also, 'write_action_begin_locked' only gathers the bytes into outbuf. + * It does not call the endpoint to write the bytes. That is done by the + * 'write_action' (which is scheduled by 'write_action_begin_locked') */ GRPC_CLOSURE_SCHED( GRPC_CLOSURE_INIT(&t->write_action_begin_locked, write_action_begin_locked, t, @@ -925,24 +964,28 @@ void grpc_chttp2_mark_stream_writable(grpc_chttp2_transport* t, static grpc_closure_scheduler* write_scheduler(grpc_chttp2_transport* t, bool early_results_scheduled, bool partial_write) { + // If we're already in a background poller, don't offload this to an executor + if (grpc_iomgr_is_any_background_poller_thread()) { + return grpc_schedule_on_exec_ctx; + } /* if it's not the first write in a batch, always offload to the executor: we'll probably end up queuing against the kernel anyway, so we'll likely get better latency overall if we switch writing work elsewhere and continue with application work above */ if (!t->is_first_write_in_batch) { - return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT); + return grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT); } /* equivalently, if it's a partial write, we *know* we're going to be taking a thread jump to write it because of the above, may as well do so immediately */ if (partial_write) { - return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT); + return grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT); } switch (t->opt_target) { case GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT: /* executor gives us the largest probability of being able to batch a * write with others on this transport */ - return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT); + return grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT); case GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY: return grpc_schedule_on_exec_ctx; } @@ -1004,12 +1047,17 @@ static void write_action_begin_locked(void* gt, grpc_error* error_ignored) { static void write_action(void* gt, grpc_error* error) { GPR_TIMER_SCOPE("write_action", 0); grpc_chttp2_transport* t = static_cast(gt); + void* cl = t->cl; + t->cl = nullptr; grpc_endpoint_write( t->ep, &t->outbuf, GRPC_CLOSURE_INIT(&t->write_action_end_locked, write_action_end_locked, t, - grpc_combiner_scheduler(t->combiner))); + grpc_combiner_scheduler(t->combiner)), + cl); } +/* Callback from the grpc_endpoint after bytes have been written by calling + * sendmsg */ static void write_action_end_locked(void* tp, grpc_error* error) { GPR_TIMER_SCOPE("terminate_writing_with_lock", 0); grpc_chttp2_transport* t = static_cast(tp); @@ -1071,9 +1119,6 @@ static void queue_setting_update(grpc_chttp2_transport* t, void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t, uint32_t goaway_error, grpc_slice goaway_text) { - // GRPC_CHTTP2_IF_TRACING( - // gpr_log(GPR_INFO, "got goaway [%d]: %s", goaway_error, msg)); - // Discard the error from a previous goaway frame (if any) if (t->goaway_error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(t->goaway_error); @@ -1084,12 +1129,17 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t, GRPC_ERROR_INT_HTTP2_ERROR, static_cast(goaway_error)), GRPC_ERROR_STR_RAW_BYTES, goaway_text); + /* We want to log this irrespective of whether http tracing is enabled */ + gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string, goaway_error, + grpc_error_string(t->goaway_error)); + /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug * data equal to "too_many_pings", it should log the occurrence at a log level * that is enabled by default and double the configured KEEPALIVE_TIME used * for new connections on that channel. */ - if (t->is_client && goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM && - grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0) { + if (GPR_UNLIKELY(t->is_client && + goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM && + grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0)) { gpr_log(GPR_ERROR, "Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug " "data equal to \"too_many_pings\""); @@ -1148,12 +1198,10 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) { } } -/* Flag that this closure barrier wants stats to be updated before finishing */ -#define CLOSURE_BARRIER_STATS_BIT (1 << 0) /* Flag that this closure barrier may be covering a write in a pollset, and so we should not complete this closure until we can prove that the write got scheduled */ -#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1) +#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 0) /* First bit of the reference count, stored in the high order bits (with the low bits being used for flags defined above) */ #define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16) @@ -1205,10 +1253,6 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, grpc_error_add_child(closure->error_data.error, error); } if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) { - if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) { - grpc_transport_move_stats(&s->stats, s->collecting_stats); - s->collecting_stats = nullptr; - } if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) || !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) { GRPC_CLOSURE_RUN(closure, closure->error_data.error); @@ -1334,6 +1378,8 @@ static void perform_stream_op_locked(void* stream_op, GRPC_STATS_INC_HTTP2_OP_BATCHES(); + s->context = op->payload->context; + s->traced = op->is_traced; if (grpc_http_trace.enabled()) { char* str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str, @@ -1350,9 +1396,14 @@ static void perform_stream_op_locked(void* stream_op, } grpc_closure* on_complete = op->on_complete; + // TODO(roth): This is a hack needed because we use data inside of the + // closure itself to do the barrier calculation (i.e., to ensure that + // we don't schedule the closure until all ops in the batch have been + // completed). This can go away once we move to a new C++ closure API + // that provides the ability to create a barrier closure. if (on_complete == nullptr) { - on_complete = - GRPC_CLOSURE_CREATE(do_nothing, nullptr, grpc_schedule_on_exec_ctx); + on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing, + nullptr, grpc_schedule_on_exec_ctx); } /* use final_data as a barrier until enqueue time; the inital counter is @@ -1360,18 +1411,15 @@ static void perform_stream_op_locked(void* stream_op, on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT; on_complete->error_data.error = GRPC_ERROR_NONE; - if (op->collect_stats) { - GPR_ASSERT(s->collecting_stats == nullptr); - s->collecting_stats = op_payload->collect_stats.collect_stats; - on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT; - } - if (op->cancel_stream) { GRPC_STATS_INC_HTTP2_OP_CANCEL(); grpc_chttp2_cancel_stream(t, s, op_payload->cancel_stream.cancel_error); } if (op->send_initial_metadata) { + if (t->is_client && t->channelz_socket != nullptr) { + t->channelz_socket->RecordStreamStartedFromLocal(); + } GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA(); GPR_ASSERT(s->send_initial_metadata_finished == nullptr); on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; @@ -1450,15 +1498,14 @@ static void perform_stream_op_locked(void* stream_op, } } if (op_payload->send_initial_metadata.peer_string != nullptr) { - char* old_peer_string = (char*)gpr_atm_full_xchg( - op_payload->send_initial_metadata.peer_string, - (gpr_atm)gpr_strdup(t->peer_string)); - gpr_free(old_peer_string); + gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string, + (gpr_atm)t->peer_string); } } if (op->send_message) { GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE(); + t->num_messages_in_next_write++; GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE( op->payload->send_message.send_message->length()); on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; @@ -1568,10 +1615,8 @@ static void perform_stream_op_locked(void* stream_op, s->trailing_metadata_available = op_payload->recv_initial_metadata.trailing_metadata_available; if (op_payload->recv_initial_metadata.peer_string != nullptr) { - char* old_peer_string = (char*)gpr_atm_full_xchg( - op_payload->recv_initial_metadata.peer_string, - (gpr_atm)gpr_strdup(t->peer_string)); - gpr_free(old_peer_string); + gpr_atm_rel_store(op_payload->recv_initial_metadata.peer_string, + (gpr_atm)t->peer_string); } grpc_chttp2_maybe_complete_recv_initial_metadata(t, s); } @@ -1603,8 +1648,11 @@ static void perform_stream_op_locked(void* stream_op, if (op->recv_trailing_metadata) { GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA(); + GPR_ASSERT(s->collecting_stats == nullptr); + s->collecting_stats = op_payload->recv_trailing_metadata.collect_stats; GPR_ASSERT(s->recv_trailing_metadata_finished == nullptr); - s->recv_trailing_metadata_finished = add_closure_barrier(on_complete); + s->recv_trailing_metadata_finished = + op_payload->recv_trailing_metadata.recv_trailing_metadata_ready; s->recv_trailing_metadata = op_payload->recv_trailing_metadata.recv_trailing_metadata; s->final_metadata_requested = true; @@ -1642,8 +1690,8 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, gpr_free(str); } - op->handler_private.extra_arg = gs; GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op"); + op->handler_private.extra_arg = gs; GRPC_CLOSURE_SCHED( GRPC_CLOSURE_INIT(&op->handler_private.closure, perform_stream_op_locked, op, grpc_combiner_scheduler(t->combiner)), @@ -1683,16 +1731,16 @@ static void send_ping_locked(grpc_chttp2_transport* t, */ static void send_keepalive_ping_locked(grpc_chttp2_transport* t) { if (t->closed_with_error != GRPC_ERROR_NONE) { - GRPC_CLOSURE_SCHED(&t->start_keepalive_ping_locked, - GRPC_ERROR_REF(t->closed_with_error)); - GRPC_CLOSURE_SCHED(&t->finish_keepalive_ping_locked, - GRPC_ERROR_REF(t->closed_with_error)); + GRPC_CLOSURE_RUN(&t->start_keepalive_ping_locked, + GRPC_ERROR_REF(t->closed_with_error)); + GRPC_CLOSURE_RUN(&t->finish_keepalive_ping_locked, + GRPC_ERROR_REF(t->closed_with_error)); return; } grpc_chttp2_ping_queue* pq = &t->ping_queue; if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) { /* There is a ping in flight. Add yourself to the inflight closure list. */ - GRPC_CLOSURE_SCHED(&t->start_keepalive_ping_locked, GRPC_ERROR_NONE); + GRPC_CLOSURE_RUN(&t->start_keepalive_ping_locked, GRPC_ERROR_NONE); grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INFLIGHT], &t->finish_keepalive_ping_locked, GRPC_ERROR_NONE); return; @@ -1727,6 +1775,9 @@ void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id) { } static void send_goaway(grpc_chttp2_transport* t, grpc_error* error) { + /* We want to log this irrespective of whether http tracing is enabled */ + gpr_log(GPR_INFO, "%s: Sending goaway err=%s", t->peer_string, + grpc_error_string(error)); t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; grpc_http2_error_code http_error; grpc_slice slice; @@ -1800,8 +1851,11 @@ static void perform_transport_op_locked(void* stream_op, static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) { grpc_chttp2_transport* t = reinterpret_cast(gt); - char* msg = grpc_transport_op_string(op); - gpr_free(msg); + if (grpc_http_trace.enabled()) { + char* msg = grpc_transport_op_string(op); + gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t, msg); + gpr_free(msg); + } op->handler_private.extra_arg = gt; GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op"); GRPC_CLOSURE_SCHED(GRPC_CLOSURE_INIT(&op->handler_private.closure, @@ -1960,11 +2014,12 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t, } if (s->read_closed && s->frame_storage.length == 0 && !pending_data && s->recv_trailing_metadata_finished != nullptr) { + grpc_transport_move_stats(&s->stats, s->collecting_stats); + s->collecting_stats = nullptr; grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1], s->recv_trailing_metadata); - grpc_chttp2_complete_closure_step( - t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE, - "recv_trailing_metadata_finished"); + null_then_run_closure(&s->recv_trailing_metadata_finished, + GRPC_ERROR_NONE); } } } @@ -2065,8 +2120,7 @@ void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s, "add_status_message", grpc_chttp2_incoming_metadata_buffer_replace_or_add( &s->metadata_buffer[1], - grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_MESSAGE, - grpc_slice_ref_internal(slice)))); + grpc_mdelem_create(GRPC_MDSTR_GRPC_MESSAGE, slice, nullptr))); } s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; grpc_chttp2_maybe_complete_recv_trailing_metadata(t, s); @@ -2504,6 +2558,10 @@ static void read_action_locked(void* tp, grpc_error* error) { } else if (t->closed_with_error == GRPC_ERROR_NONE) { keep_reading = true; GRPC_CHTTP2_REF_TRANSPORT(t, "keep_reading"); + /* Since we have read a byte, reset the keepalive timer */ + if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) { + grpc_timer_cancel(&t->keepalive_ping_timer); + } } grpc_slice_buffer_reset_and_unref_internal(&t->read_buffer); @@ -2646,6 +2704,7 @@ static void init_keepalive_ping_locked(void* arg, grpc_error* error) { grpc_chttp2_stream_map_size(&t->stream_map) > 0) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING; GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); + grpc_timer_init_unset(&t->keepalive_watchdog_timer); send_keepalive_ping_locked(t); grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING); } else { @@ -2666,6 +2725,15 @@ static void init_keepalive_ping_locked(void* arg, grpc_error* error) { static void start_keepalive_ping_locked(void* arg, grpc_error* error) { grpc_chttp2_transport* t = static_cast(arg); + if (error != GRPC_ERROR_NONE) { + return; + } + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordKeepaliveSent(); + } + if (grpc_http_trace.enabled()) { + gpr_log(GPR_INFO, "%s: Start keepalive ping", t->peer_string); + } GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog"); grpc_timer_init(&t->keepalive_watchdog_timer, grpc_core::ExecCtx::Get()->Now() + t->keepalive_timeout, @@ -2676,6 +2744,9 @@ static void finish_keepalive_ping_locked(void* arg, grpc_error* error) { grpc_chttp2_transport* t = static_cast(arg); if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { + if (grpc_http_trace.enabled()) { + gpr_log(GPR_INFO, "%s: Finish keepalive ping", t->peer_string); + } t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; grpc_timer_cancel(&t->keepalive_watchdog_timer); GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); @@ -2691,17 +2762,19 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) { grpc_chttp2_transport* t = static_cast(arg); if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "%s: Keepalive watchdog fired. Closing transport.", + t->peer_string); t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; close_transport_locked( - t, - grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "keepalive watchdog timeout"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL)); + t, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "keepalive watchdog timeout"), + GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE)); } } else { /* The watchdog timer should have been cancelled by * finish_keepalive_ping_locked. */ - if (error != GRPC_ERROR_CANCELLED) { + if (GPR_UNLIKELY(error != GRPC_ERROR_CANCELLED)) { gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); } @@ -2766,8 +2839,8 @@ Chttp2IncomingByteStream::Chttp2IncomingByteStream( : ByteStream(frame_size, flags), transport_(transport), stream_(stream), + refs_(2), remaining_bytes_(frame_size) { - gpr_ref_init(&refs_, 2); GRPC_ERROR_UNREF(stream->byte_stream_error); stream->byte_stream_error = GRPC_ERROR_NONE; } @@ -2792,14 +2865,6 @@ void Chttp2IncomingByteStream::Orphan() { GRPC_ERROR_NONE); } -void Chttp2IncomingByteStream::Unref() { - if (gpr_unref(&refs_)) { - Delete(this); - } -} - -void Chttp2IncomingByteStream::Ref() { gpr_ref(&refs_); } - void Chttp2IncomingByteStream::NextLocked(void* arg, grpc_error* error_ignored) { Chttp2IncomingByteStream* bs = static_cast(arg); @@ -2862,17 +2927,20 @@ bool Chttp2IncomingByteStream::Next(size_t max_size_hint, } } +void Chttp2IncomingByteStream::MaybeCreateStreamDecompressionCtx() { + if (!stream_->stream_decompression_ctx) { + stream_->stream_decompression_ctx = grpc_stream_compression_context_create( + stream_->stream_decompression_method); + } +} + grpc_error* Chttp2IncomingByteStream::Pull(grpc_slice* slice) { GPR_TIMER_SCOPE("incoming_byte_stream_pull", 0); grpc_error* error; if (stream_->unprocessed_incoming_frames_buffer.length > 0) { if (!stream_->unprocessed_incoming_frames_decompressed) { bool end_of_context; - if (!stream_->stream_decompression_ctx) { - stream_->stream_decompression_ctx = - grpc_stream_compression_context_create( - stream_->stream_decompression_method); - } + MaybeCreateStreamDecompressionCtx(); if (!grpc_stream_decompress(stream_->stream_decompression_ctx, &stream_->unprocessed_incoming_frames_buffer, &stream_->decompressed_data_buffer, nullptr, @@ -3103,11 +3171,18 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), static const grpc_transport_vtable* get_vtable(void) { return &vtable; } +grpc_core::RefCountedPtr +grpc_chttp2_transport_get_socket_node(grpc_transport* transport) { + grpc_chttp2_transport* t = + reinterpret_cast(transport); + return t->channelz_socket; +} + grpc_transport* grpc_create_chttp2_transport( - const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client) { - grpc_chttp2_transport* t = static_cast( - gpr_zalloc(sizeof(grpc_chttp2_transport))); - init_transport(t, channel_args, ep, is_client); + const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client, + grpc_resource_user* resource_user) { + auto t = grpc_core::New(channel_args, ep, is_client, + resource_user); return &t->base; } diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.h index 9d55b3f4b..c22cfb0ad 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.h +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/chttp2_transport.h @@ -21,6 +21,7 @@ #include +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/transport.h" @@ -32,7 +33,11 @@ extern grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount; extern bool g_flow_control_enabled; grpc_transport* grpc_create_chttp2_transport( - const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client); + const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client, + grpc_resource_user* resource_user = nullptr); + +grpc_core::RefCountedPtr +grpc_chttp2_transport_get_socket_node(grpc_transport* transport); /// Takes ownership of \a read_buffer, which (if non-NULL) contains /// leftover bytes previously read from the endpoint (e.g., by handshakers). diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/context_list.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/context_list.cc new file mode 100644 index 000000000..df0980906 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/context_list.cc @@ -0,0 +1,67 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/transport/chttp2/transport/context_list.h" + +namespace { +void (*write_timestamps_callback_g)(void*, grpc_core::Timestamps*, + grpc_error* error) = nullptr; +void* (*get_copied_context_fn_g)(void*) = nullptr; +} // namespace + +namespace grpc_core { +void ContextList::Append(ContextList** head, grpc_chttp2_stream* s) { + if (get_copied_context_fn_g == nullptr || + write_timestamps_callback_g == nullptr) { + return; + } + /* Create a new element in the list and add it at the front */ + ContextList* elem = grpc_core::New(); + elem->trace_context_ = get_copied_context_fn_g(s->context); + elem->byte_offset_ = s->byte_counter; + elem->next_ = *head; + *head = elem; +} + +void ContextList::Execute(void* arg, grpc_core::Timestamps* ts, + grpc_error* error) { + ContextList* head = static_cast(arg); + ContextList* to_be_freed; + while (head != nullptr) { + if (write_timestamps_callback_g) { + ts->byte_offset = static_cast(head->byte_offset_); + write_timestamps_callback_g(head->trace_context_, ts, error); + } + to_be_freed = head; + head = head->next_; + grpc_core::Delete(to_be_freed); + } +} + +void grpc_http2_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)) { + write_timestamps_callback_g = fn; +} + +void grpc_http2_set_fn_get_copied_context(void* (*fn)(void*)) { + get_copied_context_fn_g = fn; +} +} /* namespace grpc_core */ diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/context_list.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/context_list.h new file mode 100644 index 000000000..5b9d2ab37 --- /dev/null +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/context_list.h @@ -0,0 +1,53 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H +#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H + +#include + +#include "src/core/lib/iomgr/buffer_list.h" + +#include "src/core/ext/transport/chttp2/transport/internal.h" + +namespace grpc_core { +/** A list of RPC Contexts */ +class ContextList { + public: + /* Creates a new element with \a context as the value and appends it to the + * list. */ + static void Append(ContextList** head, grpc_chttp2_stream* s); + + /* Executes a function \a fn with each context in the list and \a ts. It also + * frees up the entire list after this operation. It is intended as a callback + * and hence does not take a ref on \a error */ + static void Execute(void* arg, grpc_core::Timestamps* ts, grpc_error* error); + + private: + void* trace_context_ = nullptr; + ContextList* next_ = nullptr; + size_t byte_offset_ = 0; +}; + +void grpc_http2_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)); +void grpc_http2_set_fn_get_copied_context(void* (*fn)(void*)); +} /* namespace grpc_core */ + +#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H */ diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/flow_control.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/flow_control.cc index e89c36320..ee2bb9308 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/flow_control.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/flow_control.cc @@ -40,6 +40,7 @@ namespace chttp2 { namespace { static constexpr const int kTracePadding = 30; +static constexpr const uint32_t kMaxWindowUpdateSize = (1u << 31) - 1; static char* fmt_int64_diff_str(int64_t old_val, int64_t new_val) { char* str; @@ -55,7 +56,7 @@ static char* fmt_int64_diff_str(int64_t old_val, int64_t new_val) { static char* fmt_uint32_diff_str(uint32_t old_val, uint32_t new_val) { char* str; - if (new_val > 0 && old_val != new_val) { + if (old_val != new_val) { gpr_asprintf(&str, "%" PRIu32 " -> %" PRIu32 "", old_val, new_val); } else { gpr_asprintf(&str, "%" PRIu32 "", old_val); @@ -98,17 +99,19 @@ void FlowControlTrace::Finish() { if (sfc_ != nullptr) { srw_str = fmt_int64_diff_str(remote_window_delta_ + remote_window, sfc_->remote_window_delta() + remote_window); - slw_str = fmt_int64_diff_str(local_window_delta_ + acked_local_window, - local_window_delta_ + acked_local_window); - saw_str = fmt_int64_diff_str(announced_window_delta_ + acked_local_window, - announced_window_delta_ + acked_local_window); + slw_str = + fmt_int64_diff_str(local_window_delta_ + acked_local_window, + sfc_->local_window_delta() + acked_local_window); + saw_str = + fmt_int64_diff_str(announced_window_delta_ + acked_local_window, + sfc_->announced_window_delta() + acked_local_window); } else { srw_str = gpr_leftpad("", ' ', kTracePadding); slw_str = gpr_leftpad("", ' ', kTracePadding); saw_str = gpr_leftpad("", ' ', kTracePadding); } gpr_log(GPR_DEBUG, - "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s", + "%p[%u][%s] | %s | trw:%s, tlw:%s, taw:%s, srw:%s, slw:%s, saw:%s", tfc_, sfc_ != nullptr ? sfc_->stream()->id : 0, tfc_->transport()->is_client ? "cli" : "svr", reason_, trw_str, tlw_str, taw_str, srw_str, slw_str, saw_str); @@ -191,7 +194,7 @@ uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) { if ((writing_anyway || announced_window_ <= target_announced_window / 2) && announced_window_ != target_announced_window) { const uint32_t announce = static_cast GPR_CLAMP( - target_announced_window - announced_window_, 0, UINT32_MAX); + target_announced_window - announced_window_, 0, kMaxWindowUpdateSize); announced_window_ += announce; return announce; } @@ -265,7 +268,7 @@ uint32_t StreamFlowControl::MaybeSendUpdate() { FlowControlTrace trace("s updt sent", tfc_, this); if (local_window_delta_ > announced_window_delta_) { uint32_t announce = static_cast GPR_CLAMP( - local_window_delta_ - announced_window_delta_, 0, UINT32_MAX); + local_window_delta_ - announced_window_delta_, 0, kMaxWindowUpdateSize); UpdateAnnouncedWindowDelta(tfc_, announce); return announce; } diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.cc index f8f06f678..1de00735c 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.cc @@ -32,18 +32,12 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/transport.h" -grpc_error* grpc_chttp2_data_parser_init(grpc_chttp2_data_parser* parser) { - parser->state = GRPC_CHTTP2_DATA_FH_0; - parser->parsing_frame = nullptr; - return GRPC_ERROR_NONE; -} - -void grpc_chttp2_data_parser_destroy(grpc_chttp2_data_parser* parser) { - if (parser->parsing_frame != nullptr) { - GRPC_ERROR_UNREF(parser->parsing_frame->Finished( +grpc_chttp2_data_parser::~grpc_chttp2_data_parser() { + if (parsing_frame != nullptr) { + GRPC_ERROR_UNREF(parsing_frame->Finished( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Parser destroyed"), false)); } - GRPC_ERROR_UNREF(parser->error); + GRPC_ERROR_UNREF(error); } grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser, @@ -62,6 +56,7 @@ grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser, if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) { s->received_last_frame = true; + s->eos_received = true; } else { s->received_last_frame = false; } @@ -191,6 +186,9 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames( GPR_ASSERT(stream_out != nullptr); GPR_ASSERT(p->parsing_frame == nullptr); p->frame_size |= (static_cast(*cur)); + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordMessageReceived(); + } p->state = GRPC_CHTTP2_DATA_FRAME; ++cur; message_flags = 0; diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.h index e5d01f764..2c5da99fa 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.h +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_data.h @@ -43,20 +43,18 @@ namespace grpc_core { class Chttp2IncomingByteStream; } // namespace grpc_core -typedef struct { - grpc_chttp2_stream_state state; - uint8_t frame_type; - uint32_t frame_size; - grpc_error* error; +struct grpc_chttp2_data_parser { + grpc_chttp2_data_parser() = default; + ~grpc_chttp2_data_parser(); - bool is_frame_compressed; - grpc_core::Chttp2IncomingByteStream* parsing_frame; -} grpc_chttp2_data_parser; + grpc_chttp2_stream_state state = GRPC_CHTTP2_DATA_FH_0; + uint8_t frame_type = 0; + uint32_t frame_size = 0; + grpc_error* error = GRPC_ERROR_NONE; -/* initialize per-stream state for data frame parsing */ -grpc_error* grpc_chttp2_data_parser_init(grpc_chttp2_data_parser* parser); - -void grpc_chttp2_data_parser_destroy(grpc_chttp2_data_parser* parser); + bool is_frame_compressed = false; + grpc_core::Chttp2IncomingByteStream* parsing_frame = nullptr; +}; /* start processing a new data frame */ grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser, diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc index 4bdd4309a..a0a753459 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc @@ -32,7 +32,7 @@ grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code, grpc_transport_one_way_stats* stats) { static const size_t frame_size = 13; grpc_slice slice = GRPC_SLICE_MALLOC(frame_size); - stats->framing_bytes += frame_size; + if (stats != nullptr) stats->framing_bytes += frame_size; uint8_t* p = GRPC_SLICE_START_PTR(slice); // Frame size. diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_window_update.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_window_update.cc index 4b586dc3e..b8738ea7e 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_window_update.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/frame_window_update.cc @@ -88,8 +88,9 @@ grpc_error* grpc_chttp2_window_update_parser_parse(void* parser, } if (p->byte == 4) { - uint32_t received_update = p->amount; - if (received_update == 0 || (received_update & 0x80000000u)) { + // top bit is reserved and must be ignored. + uint32_t received_update = p->amount & 0x7fffffffu; + if (received_update == 0) { char* msg; gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount); grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.cc index d5ef06388..9b4c3ce7e 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.cc @@ -41,21 +41,25 @@ #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/timeout_encoding.h" -#define HASH_FRAGMENT_1(x) ((x)&255) -#define HASH_FRAGMENT_2(x) ((x >> 8) & 255) -#define HASH_FRAGMENT_3(x) ((x >> 16) & 255) -#define HASH_FRAGMENT_4(x) ((x >> 24) & 255) +#define HASH_FRAGMENT_MASK (GRPC_CHTTP2_HPACKC_NUM_VALUES - 1) +#define HASH_FRAGMENT_1(x) ((x)&HASH_FRAGMENT_MASK) +#define HASH_FRAGMENT_2(x) \ + (((x) >> GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS) & HASH_FRAGMENT_MASK) +#define HASH_FRAGMENT_3(x) \ + (((x) >> (GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS * 2)) & HASH_FRAGMENT_MASK) +#define HASH_FRAGMENT_4(x) \ + (((x) >> (GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS * 3)) & HASH_FRAGMENT_MASK) /* if the probability of this item being seen again is < 1/x then don't add it to the table */ -#define ONE_ON_ADD_PROBABILITY 128 +#define ONE_ON_ADD_PROBABILITY (GRPC_CHTTP2_HPACKC_NUM_VALUES >> 1) /* don't consider adding anything bigger than this to the hpack table */ #define MAX_DECODER_SPACE_USAGE 512 static grpc_slice_refcount terminal_slice_refcount = {nullptr, nullptr}; static const grpc_slice terminal_slice = { &terminal_slice_refcount, /* refcount */ - {{nullptr, 0}} /* data.refcounted */ + {{0, nullptr}} /* data.refcounted */ }; typedef struct { @@ -135,7 +139,7 @@ static void inc_filter(uint8_t idx, uint32_t* sum, uint8_t* elems) { } else { int i; *sum = 0; - for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) { + for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { elems[i] /= 2; (*sum) += elems[i]; } @@ -208,10 +212,6 @@ static uint32_t prepare_space_for_new_elem(grpc_chttp2_hpack_compressor* c, return new_index; } -/* dummy function */ -static void add_nothing(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem, - size_t elem_size) {} - // Add a key to the dynamic table. Both key and value will be added to table at // the decoder. static void add_key_with_index(grpc_chttp2_hpack_compressor* c, @@ -520,17 +520,22 @@ static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem, uint32_t indices_key; /* should this elem be in the table? */ - size_t decoder_space_usage = - grpc_mdelem_get_size_in_hpack_table(elem, st->use_true_binary_metadata); - bool should_add_elem = elem_interned && - decoder_space_usage < MAX_DECODER_SPACE_USAGE && - c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >= - c->filter_elems_sum / ONE_ON_ADD_PROBABILITY; - void (*maybe_add)(grpc_chttp2_hpack_compressor*, grpc_mdelem, size_t) = - should_add_elem ? add_elem : add_nothing; - void (*emit)(grpc_chttp2_hpack_compressor*, uint32_t, grpc_mdelem, - framer_state*) = - should_add_elem ? emit_lithdr_incidx : emit_lithdr_noidx; + const size_t decoder_space_usage = + grpc_chttp2_get_size_in_hpack_table(elem, st->use_true_binary_metadata); + const bool should_add_elem = elem_interned && + decoder_space_usage < MAX_DECODER_SPACE_USAGE && + c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >= + c->filter_elems_sum / ONE_ON_ADD_PROBABILITY; + + auto emit_maybe_add = [&should_add_elem, &elem, &st, &c, &indices_key, + &decoder_space_usage] { + if (should_add_elem) { + emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); + add_elem(c, elem, decoder_space_usage); + } else { + emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); + } + }; /* no hits for the elem... maybe there's a key? */ indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)]; @@ -538,8 +543,7 @@ static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem, GRPC_MDKEY(elem)) && indices_key > c->tail_remote_index) { /* HIT: key (first cuckoo hash) */ - emit(c, dynidx(c, indices_key), elem, st); - maybe_add(c, elem, decoder_space_usage); + emit_maybe_add(); return; } @@ -548,20 +552,23 @@ static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem, GRPC_MDKEY(elem)) && indices_key > c->tail_remote_index) { /* HIT: key (first cuckoo hash) */ - emit(c, dynidx(c, indices_key), elem, st); - maybe_add(c, elem, decoder_space_usage); + emit_maybe_add(); return; } /* no elem, key in the table... fall back to literal emission */ - bool should_add_key = + const bool should_add_key = !elem_interned && decoder_space_usage < MAX_DECODER_SPACE_USAGE; - emit = (should_add_elem || should_add_key) ? emit_lithdr_incidx_v - : emit_lithdr_noidx_v; - maybe_add = - should_add_elem ? add_elem : (should_add_key ? add_key : add_nothing); - emit(c, 0, elem, st); - maybe_add(c, elem, decoder_space_usage); + if (should_add_elem || should_add_key) { + emit_lithdr_incidx_v(c, 0, elem, st); + } else { + emit_lithdr_noidx_v(c, 0, elem, st); + } + if (should_add_elem) { + add_elem(c, elem, decoder_space_usage); + } else if (should_add_key) { + add_key(c, elem, decoder_space_usage); + } } #define STRLEN_LIT(x) (sizeof(x) - 1) @@ -684,11 +691,22 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c, emit_advertise_table_size_change(c, &st); } for (size_t i = 0; i < extra_headers_size; ++i) { - hpack_enc(c, *extra_headers[i], &st); + grpc_mdelem md = *extra_headers[i]; + uint8_t static_index = grpc_chttp2_get_static_hpack_table_index(md); + if (static_index) { + emit_indexed(c, static_index, &st); + } else { + hpack_enc(c, md, &st); + } } grpc_metadata_batch_assert_ok(metadata); for (grpc_linked_mdelem* l = metadata->list.head; l; l = l->next) { - hpack_enc(c, l->md, &st); + uint8_t static_index = grpc_chttp2_get_static_hpack_table_index(l->md); + if (static_index) { + emit_indexed(c, static_index, &st); + } else { + hpack_enc(c, l->md, &st); + } } grpc_millis deadline = metadata->deadline; if (deadline != GRPC_MILLIS_INF_FUTURE) { diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.h index b37093213..e31a7399d 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.h +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_encoder.h @@ -28,8 +28,9 @@ #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" -#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256 -#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256 +// This should be <= 8. We use 6 to save space. +#define GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS 6 +#define GRPC_CHTTP2_HPACKC_NUM_VALUES (1 << GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS) /* initial table size, per spec */ #define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096 /* maximum table size we'll actually use */ @@ -58,7 +59,7 @@ typedef struct { a new literal should be added to the compression table or not. They track a single integer that counts how often a particular value has been seen. When that count reaches max (255), all values are halved. */ - uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS]; + uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; /* entry tables for keys & elems: these tables track values that have been seen and *may* be in the decompressor table */ diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_parser.cc index 907ba7117..ccf225697 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_parser.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_parser.cc @@ -1622,7 +1622,7 @@ grpc_error* grpc_chttp2_header_parser_parse(void* hpack_parser, grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_slice slice, int is_last) { - GPR_TIMER_SCOPE("grpc_chttp2_hpack_parser_parse", 0); + GPR_TIMER_SCOPE("grpc_chttp2_header_parser_parse", 0); grpc_chttp2_hpack_parser* parser = static_cast(hpack_parser); if (s != nullptr) { diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.cc index 792925835..fcfb01872 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.cc @@ -29,6 +29,7 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/murmur_hash.h" +#include "src/core/lib/transport/static_metadata.h" extern grpc_core::TraceFlag grpc_http_trace; @@ -366,3 +367,31 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( return r; } + +static size_t get_base64_encoded_size(size_t raw_length) { + static const uint8_t tail_xtra[3] = {0, 2, 3}; + return raw_length / 3 * 4 + tail_xtra[raw_length % 3]; +} + +size_t grpc_chttp2_get_size_in_hpack_table(grpc_mdelem elem, + bool use_true_binary_metadata) { + size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); + size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem)); + if (grpc_is_binary_header(GRPC_MDKEY(elem))) { + return overhead_and_key + (use_true_binary_metadata + ? value_len + 1 + : get_base64_encoded_size(value_len)); + } else { + return overhead_and_key + value_len; + } +} + +uint8_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md) { + if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) { + uint8_t index = GRPC_MDELEM_DATA(md) - grpc_static_mdelem_table; + if (index < GRPC_CHTTP2_LAST_STATIC_ENTRY) { + return index + 1; // Hpack static metadata element indices start at 1 + } + } + return 0; +} diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.h index 98026a4ba..a0ffc6fab 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.h +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/hpack_table.h @@ -83,6 +83,15 @@ grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl* tbl, /* add a table entry to the index */ grpc_error* grpc_chttp2_hptbl_add(grpc_chttp2_hptbl* tbl, grpc_mdelem md) GRPC_MUST_USE_RESULT; + +size_t grpc_chttp2_get_size_in_hpack_table(grpc_mdelem elem, + bool use_true_binary_metadata); + +/* Returns the static hpack table index that corresponds to /a elem. Returns 0 + if /a elem is not statically stored or if it is not in the static hpack + table */ +uint8_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md); + /* Find a key/value pair in the table... returns the index in the table of the most similar entry, or 0 if the value was not found */ typedef struct { diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.cc index 4d7dfd900..dca15e768 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.cc @@ -27,18 +27,6 @@ #include #include -void grpc_chttp2_incoming_metadata_buffer_init( - grpc_chttp2_incoming_metadata_buffer* buffer, gpr_arena* arena) { - buffer->arena = arena; - grpc_metadata_batch_init(&buffer->batch); - buffer->batch.deadline = GRPC_MILLIS_INF_FUTURE; -} - -void grpc_chttp2_incoming_metadata_buffer_destroy( - grpc_chttp2_incoming_metadata_buffer* buffer) { - grpc_metadata_batch_destroy(&buffer->batch); -} - grpc_error* grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) { buffer->size += GRPC_MDELEM_LENGTH(elem); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.h index d029cf00d..c551b3cc8 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.h +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/incoming_metadata.h @@ -23,17 +23,20 @@ #include "src/core/lib/transport/transport.h" -typedef struct { +struct grpc_chttp2_incoming_metadata_buffer { + grpc_chttp2_incoming_metadata_buffer(gpr_arena* arena) : arena(arena) { + grpc_metadata_batch_init(&batch); + batch.deadline = GRPC_MILLIS_INF_FUTURE; + } + ~grpc_chttp2_incoming_metadata_buffer() { + grpc_metadata_batch_destroy(&batch); + } + gpr_arena* arena; grpc_metadata_batch batch; - size_t size; // total size of metadata -} grpc_chttp2_incoming_metadata_buffer; - -/** assumes everything initially zeroed */ -void grpc_chttp2_incoming_metadata_buffer_init( - grpc_chttp2_incoming_metadata_buffer* buffer, gpr_arena* arena); -void grpc_chttp2_incoming_metadata_buffer_destroy( - grpc_chttp2_incoming_metadata_buffer* buffer); + size_t size = 0; // total size of metadata +}; + void grpc_chttp2_incoming_metadata_buffer_publish( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_metadata_batch* batch); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/internal.h b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/internal.h index ca6e71597..341f5b397 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/internal.h +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/internal.h @@ -36,6 +36,7 @@ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" @@ -44,6 +45,10 @@ #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/transport_impl.h" +namespace grpc_core { +class ContextList; +} + /* streams are kept in various linked lists depending on what things need to happen to them... this enum labels each list */ typedef enum { @@ -102,8 +107,8 @@ const char* grpc_chttp2_initiate_write_reason_string( grpc_chttp2_initiate_write_reason reason); typedef struct { - grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT]; - uint64_t inflight_id; + grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT] = {}; + uint64_t inflight_id = 0; } grpc_chttp2_ping_queue; typedef struct { @@ -231,8 +236,12 @@ class Chttp2IncomingByteStream : public ByteStream { // alone for now. We can revisit this once we're able to link against // libc++, at which point we can eliminate New<> and Delete<> and // switch to std::shared_ptr<>. - void Ref(); - void Unref(); + void Ref() { refs_.Ref(); } + void Unref() { + if (refs_.Unref()) { + grpc_core::Delete(this); + } + } void PublishError(grpc_error* error); @@ -246,10 +255,12 @@ class Chttp2IncomingByteStream : public ByteStream { static void NextLocked(void* arg, grpc_error* error_ignored); static void OrphanLocked(void* arg, grpc_error* error_ignored); + void MaybeCreateStreamDecompressionCtx(); + grpc_chttp2_transport* transport_; // Immutable. grpc_chttp2_stream* stream_; // Immutable. - gpr_refcount refs_; + grpc_core::RefCount refs_; /* Accessed only by transport thread when stream->pending_byte_stream == false * Accessed only by application thread when stream->pending_byte_stream == @@ -277,34 +288,41 @@ typedef enum { } grpc_chttp2_keepalive_state; struct grpc_chttp2_transport { + grpc_chttp2_transport(const grpc_channel_args* channel_args, + grpc_endpoint* ep, bool is_client, + grpc_resource_user* resource_user); + ~grpc_chttp2_transport(); + grpc_transport base; /* must be first */ - gpr_refcount refs; + grpc_core::RefCount refs; grpc_endpoint* ep; char* peer_string; + grpc_resource_user* resource_user; + grpc_combiner* combiner; - grpc_closure* notify_on_receive_settings; + grpc_closure* notify_on_receive_settings = nullptr; /** write execution state of the transport */ - grpc_chttp2_write_state write_state; + grpc_chttp2_write_state write_state = GRPC_CHTTP2_WRITE_STATE_IDLE; /** is this the first write in a series of writes? set when we initiate writing from idle, cleared when we initiate writing from writing+more */ - bool is_first_write_in_batch; + bool is_first_write_in_batch = false; /** is the transport destroying itself? */ - uint8_t destroying; + uint8_t destroying = false; /** has the upper layer closed the transport? */ - grpc_error* closed_with_error; + grpc_error* closed_with_error = GRPC_ERROR_NONE; /** is there a read request to the endpoint outstanding? */ - uint8_t endpoint_reading; + uint8_t endpoint_reading = 1; - grpc_chttp2_optimization_target opt_target; + grpc_chttp2_optimization_target opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY; /** various lists of streams */ - grpc_chttp2_stream_list lists[STREAM_LIST_COUNT]; + grpc_chttp2_stream_list lists[STREAM_LIST_COUNT] = {}; /** maps stream id to grpc_chttp2_stream objects */ grpc_chttp2_stream_map stream_map; @@ -321,7 +339,7 @@ struct grpc_chttp2_transport { /** address to place a newly accepted stream - set and unset by grpc_chttp2_parsing_accept_stream; used by init_stream to publish the accepted server stream */ - grpc_chttp2_stream** accepting_stream; + grpc_chttp2_stream** accepting_stream = nullptr; struct { /* accept stream callback */ @@ -345,41 +363,43 @@ struct grpc_chttp2_transport { /** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set? */ - uint32_t write_buffer_size; + uint32_t write_buffer_size = grpc_core::chttp2::kDefaultWindow; /** Set to a grpc_error object if a goaway frame is received. By default, set * to GRPC_ERROR_NONE */ - grpc_error* goaway_error; + grpc_error* goaway_error = GRPC_ERROR_NONE; - grpc_chttp2_sent_goaway_state sent_goaway_state; + grpc_chttp2_sent_goaway_state sent_goaway_state = GRPC_CHTTP2_NO_GOAWAY_SEND; /** are the local settings dirty and need to be sent? */ - bool dirtied_local_settings; + bool dirtied_local_settings = true; /** have local settings been sent? */ - bool sent_local_settings; - /** bitmask of setting indexes to send out */ - uint32_t force_send_settings; + bool sent_local_settings = false; + /** bitmask of setting indexes to send out + Hack: it's common for implementations to assume 65536 bytes initial send + window -- this should by rights be 0 */ + uint32_t force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; /** settings values */ uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS]; /** what is the next stream id to be allocated by this peer? copied to next_stream_id in parsing when parsing commences */ - uint32_t next_stream_id; + uint32_t next_stream_id = 0; /** last new stream id */ - uint32_t last_new_stream_id; + uint32_t last_new_stream_id = 0; /** ping queues for various ping insertion points */ - grpc_chttp2_ping_queue ping_queue; + grpc_chttp2_ping_queue ping_queue = grpc_chttp2_ping_queue(); grpc_chttp2_repeated_ping_policy ping_policy; grpc_chttp2_repeated_ping_state ping_state; - uint64_t ping_ctr; /* unique id for pings */ + uint64_t ping_ctr = 0; /* unique id for pings */ grpc_closure retry_initiate_ping_locked; /** ping acks */ - size_t ping_ack_count; - size_t ping_ack_capacity; - uint64_t* ping_acks; + size_t ping_ack_count = 0; + size_t ping_ack_capacity = 0; + uint64_t* ping_acks = nullptr; grpc_chttp2_server_ping_recv_state ping_recv_state; /** parser for headers */ @@ -405,22 +425,22 @@ struct grpc_chttp2_transport { int64_t initial_window_update = 0; /* deframing */ - grpc_chttp2_deframe_transport_state deframe_state; - uint8_t incoming_frame_type; - uint8_t incoming_frame_flags; - uint8_t header_eof; - bool is_first_frame; - uint32_t expect_continuation_stream_id; - uint32_t incoming_frame_size; - uint32_t incoming_stream_id; + grpc_chttp2_deframe_transport_state deframe_state = GRPC_DTS_CLIENT_PREFIX_0; + uint8_t incoming_frame_type = 0; + uint8_t incoming_frame_flags = 0; + uint8_t header_eof = 0; + bool is_first_frame = true; + uint32_t expect_continuation_stream_id = 0; + uint32_t incoming_frame_size = 0; + uint32_t incoming_stream_id = 0; /* active parser */ - void* parser_data; - grpc_chttp2_stream* incoming_stream; + void* parser_data = nullptr; + grpc_chttp2_stream* incoming_stream = nullptr; grpc_error* (*parser)(void* parser_user_data, grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_slice slice, int is_last); - grpc_chttp2_write_cb* write_cb_pool; + grpc_chttp2_write_cb* write_cb_pool = nullptr; /* bdp estimator */ grpc_closure next_bdp_ping_timer_expired_locked; @@ -429,23 +449,23 @@ struct grpc_chttp2_transport { /* if non-NULL, close the transport with this error when writes are finished */ - grpc_error* close_transport_on_writes_finished; + grpc_error* close_transport_on_writes_finished = GRPC_ERROR_NONE; /* a list of closures to run after writes are finished */ - grpc_closure_list run_after_write; + grpc_closure_list run_after_write = GRPC_CLOSURE_LIST_INIT; /* buffer pool state */ /** have we scheduled a benign cleanup? */ - bool benign_reclaimer_registered; + bool benign_reclaimer_registered = false; /** have we scheduled a destructive cleanup? */ - bool destructive_reclaimer_registered; + bool destructive_reclaimer_registered = false; /** benign cleanup closure */ grpc_closure benign_reclaimer_locked; /** destructive cleanup closure */ grpc_closure destructive_reclaimer_locked; /* next bdp ping timer */ - bool have_next_bdp_ping_timer; + bool have_next_bdp_ping_timer = false; grpc_timer next_bdp_ping_timer; /* keep-alive ping support */ @@ -466,9 +486,12 @@ struct grpc_chttp2_transport { /** grace period for a ping to complete before watchdog kicks in */ grpc_millis keepalive_timeout; /** if keepalive pings are allowed when there's no outstanding streams */ - bool keepalive_permit_without_calls; + bool keepalive_permit_without_calls = false; /** keep-alive state machine state */ grpc_chttp2_keepalive_state keepalive_state; + grpc_core::ContextList* cl = nullptr; + grpc_core::RefCountedPtr channelz_socket; + uint32_t num_messages_in_next_write = 0; }; typedef enum { @@ -479,6 +502,11 @@ typedef enum { } grpc_published_metadata_method; struct grpc_chttp2_stream { + grpc_chttp2_stream(grpc_chttp2_transport* t, grpc_stream_refcount* refcount, + const void* server_data, gpr_arena* arena); + ~grpc_chttp2_stream(); + + void* context; grpc_chttp2_transport* t; grpc_stream_refcount* refcount; @@ -486,59 +514,63 @@ struct grpc_chttp2_stream { grpc_closure* destroy_stream_arg; grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; - uint8_t included[STREAM_LIST_COUNT]; + uint8_t included[STREAM_LIST_COUNT] = {}; /** HTTP2 stream id for this stream, or zero if one has not been assigned */ - uint32_t id; + uint32_t id = 0; /** things the upper layers would like to send */ - grpc_metadata_batch* send_initial_metadata; - grpc_closure* send_initial_metadata_finished; - grpc_metadata_batch* send_trailing_metadata; - grpc_closure* send_trailing_metadata_finished; + grpc_metadata_batch* send_initial_metadata = nullptr; + grpc_closure* send_initial_metadata_finished = nullptr; + grpc_metadata_batch* send_trailing_metadata = nullptr; + grpc_closure* send_trailing_metadata_finished = nullptr; grpc_core::OrphanablePtr fetching_send_message; - uint32_t fetched_send_message_length; - grpc_slice fetching_slice; + uint32_t fetched_send_message_length = 0; + grpc_slice fetching_slice = grpc_empty_slice(); int64_t next_message_end_offset; - int64_t flow_controlled_bytes_written; - int64_t flow_controlled_bytes_flowed; + int64_t flow_controlled_bytes_written = 0; + int64_t flow_controlled_bytes_flowed = 0; grpc_closure complete_fetch_locked; - grpc_closure* fetching_send_message_finished; + grpc_closure* fetching_send_message_finished = nullptr; grpc_metadata_batch* recv_initial_metadata; - grpc_closure* recv_initial_metadata_ready; - bool* trailing_metadata_available; + grpc_closure* recv_initial_metadata_ready = nullptr; + bool* trailing_metadata_available = nullptr; grpc_core::OrphanablePtr* recv_message; - grpc_closure* recv_message_ready; + grpc_closure* recv_message_ready = nullptr; grpc_metadata_batch* recv_trailing_metadata; - grpc_closure* recv_trailing_metadata_finished; + grpc_closure* recv_trailing_metadata_finished = nullptr; - grpc_transport_stream_stats* collecting_stats; - grpc_transport_stream_stats stats; + grpc_transport_stream_stats* collecting_stats = nullptr; + grpc_transport_stream_stats stats = grpc_transport_stream_stats(); /** Is this stream closed for writing. */ - bool write_closed; + bool write_closed = false; /** Is this stream reading half-closed. */ - bool read_closed; + bool read_closed = false; /** Are all published incoming byte streams closed. */ - bool all_incoming_byte_streams_finished; + bool all_incoming_byte_streams_finished = false; /** Has this stream seen an error. If true, then pending incoming frames can be thrown away. */ - bool seen_error; + bool seen_error = false; /** Are we buffering writes on this stream? If yes, we won't become writable until there's enough queued up in the flow_controlled_buffer */ - bool write_buffering; + bool write_buffering = false; /** Has trailing metadata been received. */ - bool received_trailing_metadata; + bool received_trailing_metadata = false; + + /* have we sent or received the EOS bit? */ + bool eos_received = false; + bool eos_sent = false; /** the error that resulted in this stream being read-closed */ - grpc_error* read_closed_error; + grpc_error* read_closed_error = GRPC_ERROR_NONE; /** the error that resulted in this stream being write-closed */ - grpc_error* write_closed_error; + grpc_error* write_closed_error = GRPC_ERROR_NONE; - grpc_published_metadata_method published_metadata[2]; - bool final_metadata_requested; + grpc_published_metadata_method published_metadata[2] = {}; + bool final_metadata_requested = false; grpc_chttp2_incoming_metadata_buffer metadata_buffer[2]; @@ -548,33 +580,33 @@ struct grpc_chttp2_stream { * Accessed only by application thread when stream->pending_byte_stream == * true */ grpc_slice_buffer unprocessed_incoming_frames_buffer; - grpc_closure* on_next; /* protected by t combiner */ - bool pending_byte_stream; /* protected by t combiner */ + grpc_closure* on_next = nullptr; /* protected by t combiner */ + bool pending_byte_stream = false; /* protected by t combiner */ // cached length of buffer to be used by the transport thread in cases where // stream->pending_byte_stream == true. The value is saved before // application threads are allowed to modify // unprocessed_incoming_frames_buffer - size_t unprocessed_incoming_frames_buffer_cached_length; + size_t unprocessed_incoming_frames_buffer_cached_length = 0; grpc_closure reset_byte_stream; - grpc_error* byte_stream_error; /* protected by t combiner */ - bool received_last_frame; /* protected by t combiner */ + grpc_error* byte_stream_error = GRPC_ERROR_NONE; /* protected by t combiner */ + bool received_last_frame = false; /* protected by t combiner */ - grpc_millis deadline; + grpc_millis deadline = GRPC_MILLIS_INF_FUTURE; /** saw some stream level error */ - grpc_error* forced_close_error; + grpc_error* forced_close_error = GRPC_ERROR_NONE; /** how many header frames have we received? */ - uint8_t header_frames_received; + uint8_t header_frames_received = 0; /** parsing state for data frames */ /* Accessed only by transport thread when stream->pending_byte_stream == false * Accessed only by application thread when stream->pending_byte_stream == * true */ grpc_chttp2_data_parser data_parser; /** number of bytes received - reset at end of parse thread execution */ - int64_t received_bytes; + int64_t received_bytes = 0; - bool sent_initial_metadata; - bool sent_trailing_metadata; + bool sent_initial_metadata = false; + bool sent_trailing_metadata = false; grpc_core::PolymorphicManualConstructor< grpc_core::chttp2::StreamFlowControlBase, @@ -584,32 +616,38 @@ struct grpc_chttp2_stream { grpc_slice_buffer flow_controlled_buffer; - grpc_chttp2_write_cb* on_flow_controlled_cbs; - grpc_chttp2_write_cb* on_write_finished_cbs; - grpc_chttp2_write_cb* finish_after_write; - size_t sending_bytes; + grpc_chttp2_write_cb* on_flow_controlled_cbs = nullptr; + grpc_chttp2_write_cb* on_write_finished_cbs = nullptr; + grpc_chttp2_write_cb* finish_after_write = nullptr; + size_t sending_bytes = 0; /* Stream compression method to be used. */ - grpc_stream_compression_method stream_compression_method; + grpc_stream_compression_method stream_compression_method = + GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS; /* Stream decompression method to be used. */ - grpc_stream_compression_method stream_decompression_method; + grpc_stream_compression_method stream_decompression_method = + GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS; /** Stream compression decompress context */ - grpc_stream_compression_context* stream_decompression_ctx; + grpc_stream_compression_context* stream_decompression_ctx = nullptr; /** Stream compression compress context */ - grpc_stream_compression_context* stream_compression_ctx; + grpc_stream_compression_context* stream_compression_ctx = nullptr; /** Buffer storing data that is compressed but not sent */ grpc_slice_buffer compressed_data_buffer; /** Amount of uncompressed bytes sent out when compressed_data_buffer is * emptied */ - size_t uncompressed_data_size; + size_t uncompressed_data_size = 0; /** Temporary buffer storing decompressed data */ grpc_slice_buffer decompressed_data_buffer; /** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed */ - bool unprocessed_incoming_frames_decompressed; + bool unprocessed_incoming_frames_decompressed = false; + /** Whether the bytes needs to be traced using Fathom */ + bool traced = false; /** gRPC header bytes that are already decompressed */ - size_t decompressed_header_bytes; + size_t decompressed_header_bytes = 0; + /** Byte counter for number of bytes written */ + size_t byte_counter = 0; }; /** Transport writing call flow: @@ -754,15 +792,29 @@ void grpc_chttp2_stream_unref(grpc_chttp2_stream* s); grpc_chttp2_ref_transport(t, r, __FILE__, __LINE__) #define GRPC_CHTTP2_UNREF_TRANSPORT(t, r) \ grpc_chttp2_unref_transport(t, r, __FILE__, __LINE__) -void grpc_chttp2_unref_transport(grpc_chttp2_transport* t, const char* reason, - const char* file, int line); -void grpc_chttp2_ref_transport(grpc_chttp2_transport* t, const char* reason, - const char* file, int line); +inline void grpc_chttp2_unref_transport(grpc_chttp2_transport* t, + const char* reason, const char* file, + int line) { + if (t->refs.Unref(grpc_core::DebugLocation(file, line), reason)) { + grpc_core::Delete(t); + } +} +inline void grpc_chttp2_ref_transport(grpc_chttp2_transport* t, + const char* reason, const char* file, + int line) { + t->refs.Ref(grpc_core::DebugLocation(file, line), reason); +} #else #define GRPC_CHTTP2_REF_TRANSPORT(t, r) grpc_chttp2_ref_transport(t) #define GRPC_CHTTP2_UNREF_TRANSPORT(t, r) grpc_chttp2_unref_transport(t) -void grpc_chttp2_unref_transport(grpc_chttp2_transport* t); -void grpc_chttp2_ref_transport(grpc_chttp2_transport* t); +inline void grpc_chttp2_unref_transport(grpc_chttp2_transport* t) { + if (t->refs.Unref()) { + grpc_core::Delete(t); + } +} +inline void grpc_chttp2_ref_transport(grpc_chttp2_transport* t) { + t->refs.Ref(); +} #endif void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/parsing.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/parsing.cc index a10c9ada4..1ff96d3cd 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/parsing.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/parsing.cc @@ -368,6 +368,7 @@ static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t) { &s->data_parser, t->incoming_frame_flags, s->id, s); } error_handler: + intptr_t unused; if (err == GRPC_ERROR_NONE) { t->incoming_stream = s; /* t->parser = grpc_chttp2_data_parser_parse;*/ @@ -375,7 +376,7 @@ static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t) { t->parser_data = &s->data_parser; t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST; return GRPC_ERROR_NONE; - } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, nullptr)) { + } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, &unused)) { /* handle stream errors by closing the stream */ if (s != nullptr) { grpc_chttp2_mark_stream_closed(t, s, true, false, err); @@ -409,66 +410,81 @@ static void on_initial_header(void* tp, grpc_mdelem md) { gpr_free(value); } - if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && - !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { - /* TODO(ctiller): check for a status like " 0" */ - s->seen_error = true; - } + if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) { + // We don't use grpc_mdelem_eq here to avoid executing additional + // instructions. The reasoning is if the payload is not equal, we already + // know that the metadata elements are not equal because the md is + // confirmed to be static. If we had used grpc_mdelem_eq here, then if the + // payloads are not equal, grpc_mdelem_eq executes more instructions to + // determine if they're equal or not. + if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload || + md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) { + s->seen_error = true; + } + } else { + if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && + !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { + /* TODO(ctiller): check for a status like " 0" */ + s->seen_error = true; + } - if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) { - grpc_millis* cached_timeout = - static_cast(grpc_mdelem_get_user_data(md, free_timeout)); - grpc_millis timeout; - if (cached_timeout != nullptr) { - timeout = *cached_timeout; - } else { - if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout)) { - char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val); - gpr_free(val); - timeout = GRPC_MILLIS_INF_FUTURE; + if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) { + grpc_millis* cached_timeout = static_cast( + grpc_mdelem_get_user_data(md, free_timeout)); + grpc_millis timeout; + if (cached_timeout != nullptr) { + timeout = *cached_timeout; + } else { + if (GPR_UNLIKELY( + !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) { + char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); + gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val); + gpr_free(val); + timeout = GRPC_MILLIS_INF_FUTURE; + } + if (GRPC_MDELEM_IS_INTERNED(md)) { + /* store the result */ + cached_timeout = + static_cast(gpr_malloc(sizeof(grpc_millis))); + *cached_timeout = timeout; + grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); + } } - if (GRPC_MDELEM_IS_INTERNED(md)) { - /* store the result */ - cached_timeout = - static_cast(gpr_malloc(sizeof(grpc_millis))); - *cached_timeout = timeout; - grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); + if (timeout != GRPC_MILLIS_INF_FUTURE) { + grpc_chttp2_incoming_metadata_buffer_set_deadline( + &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout); } + GRPC_MDELEM_UNREF(md); + return; } - if (timeout != GRPC_MILLIS_INF_FUTURE) { - grpc_chttp2_incoming_metadata_buffer_set_deadline( - &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout); - } + } + + const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md); + const size_t metadata_size_limit = + t->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; + if (new_size > metadata_size_limit) { + gpr_log(GPR_DEBUG, + "received initial metadata size exceeds limit (%" PRIuPTR + " vs. %" PRIuPTR ")", + new_size, metadata_size_limit); + grpc_chttp2_cancel_stream( + t, s, + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "received initial metadata size exceeds limit"), + GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_RESOURCE_EXHAUSTED)); + grpc_chttp2_parsing_become_skip_parser(t); + s->seen_error = true; GRPC_MDELEM_UNREF(md); } else { - const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md); - const size_t metadata_size_limit = - t->settings[GRPC_ACKED_SETTINGS] - [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; - if (new_size > metadata_size_limit) { - gpr_log(GPR_DEBUG, - "received initial metadata size exceeds limit (%" PRIuPTR - " vs. %" PRIuPTR ")", - new_size, metadata_size_limit); - grpc_chttp2_cancel_stream( - t, s, - grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "received initial metadata size exceeds limit"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); + grpc_error* error = + grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md); + if (error != GRPC_ERROR_NONE) { + grpc_chttp2_cancel_stream(t, s, error); grpc_chttp2_parsing_become_skip_parser(t); s->seen_error = true; GRPC_MDELEM_UNREF(md); - } else { - grpc_error* error = - grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md); - if (error != GRPC_ERROR_NONE) { - grpc_chttp2_cancel_stream(t, s, error); - grpc_chttp2_parsing_become_skip_parser(t); - s->seen_error = true; - GRPC_MDELEM_UNREF(md); - } } } } @@ -490,8 +506,19 @@ static void on_trailing_header(void* tp, grpc_mdelem md) { gpr_free(value); } - if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && - !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { + if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) { + // We don't use grpc_mdelem_eq here to avoid executing additional + // instructions. The reasoning is if the payload is not equal, we already + // know that the metadata elements are not equal because the md is + // confirmed to be static. If we had used grpc_mdelem_eq here, then if the + // payloads are not equal, grpc_mdelem_eq executes more instructions to + // determine if they're equal or not. + if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload || + md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) { + s->seen_error = true; + } + } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && + !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { /* TODO(ctiller): check for a status like " 0" */ s->seen_error = true; } @@ -550,15 +577,15 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */ s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); if (s == nullptr) { - if (is_continuation) { + if (GPR_UNLIKELY(is_continuation)) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_ERROR, "grpc_chttp2_stream disbanded before CONTINUATION received")); return init_skip_frame_parser(t, 1); } if (t->is_client) { - if ((t->incoming_stream_id & 1) && - t->incoming_stream_id < t->next_stream_id) { + if (GPR_LIKELY((t->incoming_stream_id & 1) && + t->incoming_stream_id < t->next_stream_id)) { /* this is an old (probably cancelled) grpc_chttp2_stream */ } else { GRPC_CHTTP2_IF_TRACING(gpr_log( @@ -569,7 +596,7 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser); } return err; - } else if (t->last_new_stream_id >= t->incoming_stream_id) { + } else if (GPR_UNLIKELY(t->last_new_stream_id >= t->incoming_stream_id)) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring out of order new grpc_chttp2_stream request on server; " @@ -577,31 +604,35 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, "id=%d, new grpc_chttp2_stream id=%d", t->last_new_stream_id, t->incoming_stream_id)); return init_skip_frame_parser(t, 1); - } else if ((t->incoming_stream_id & 1) == 0) { + } else if (GPR_UNLIKELY((t->incoming_stream_id & 1) == 0)) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring grpc_chttp2_stream with non-client generated index %d", t->incoming_stream_id)); return init_skip_frame_parser(t, 1); - } else if (grpc_chttp2_stream_map_size(&t->stream_map) >= - t->settings[GRPC_ACKED_SETTINGS] - [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]) { + } else if (GPR_UNLIKELY( + grpc_chttp2_stream_map_size(&t->stream_map) >= + t->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS])) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Max stream count exceeded"); } t->last_new_stream_id = t->incoming_stream_id; s = t->incoming_stream = grpc_chttp2_parsing_accept_stream(t, t->incoming_stream_id); - if (s == nullptr) { + if (GPR_UNLIKELY(s == nullptr)) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted")); return init_skip_frame_parser(t, 1); } + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordStreamStartedFromRemote(); + } } else { t->incoming_stream = s; } GPR_ASSERT(s != nullptr); s->stats.incoming.framing_bytes += 9; - if (s->read_closed) { + if (GPR_UNLIKELY(s->read_closed)) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "skipping already closed grpc_chttp2_stream header")); t->incoming_stream = nullptr; @@ -609,6 +640,9 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, } t->parser = grpc_chttp2_header_parser_parse; t->parser_data = &t->hpack_parser; + if (t->header_eof) { + s->eos_received = true; + } switch (s->header_frames_received) { case 0: if (t->is_client && t->header_eof) { @@ -723,9 +757,10 @@ static grpc_error* parse_frame_slice(grpc_chttp2_transport* t, grpc_slice slice, int is_last) { grpc_chttp2_stream* s = t->incoming_stream; grpc_error* err = t->parser(t->parser_data, t, s, slice, is_last); - if (err == GRPC_ERROR_NONE) { + intptr_t unused; + if (GPR_LIKELY(err == GRPC_ERROR_NONE)) { return err; - } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, nullptr)) { + } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, &unused)) { if (grpc_http_trace.enabled()) { const char* msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); diff --git a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/writing.cc b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/writing.cc index 85efe2708..cf77ddc82 100644 --- a/Sources/CgRPC/src/core/ext/transport/chttp2/transport/writing.cc +++ b/Sources/CgRPC/src/core/ext/transport/chttp2/transport/writing.cc @@ -18,6 +18,7 @@ #include +#include "src/core/ext/transport/chttp2/transport/context_list.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include @@ -139,22 +140,27 @@ static bool update_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s, static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s, const char* staller) { - gpr_log( - GPR_DEBUG, - "%s:%p stream %d stalled by %s [fc:pending=%" PRIdPTR - ":pending-compressed=%" PRIdPTR ":flowed=%" PRId64 - ":peer_initwin=%d:t_win=%" PRId64 ":s_win=%d:s_delta=%" PRId64 "]", - t->peer_string, t, s->id, staller, s->flow_controlled_buffer.length, - s->compressed_data_buffer.length, s->flow_controlled_bytes_flowed, - t->settings[GRPC_ACKED_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], - t->flow_control->remote_window(), - static_cast GPR_MAX( - 0, - s->flow_control->remote_window_delta() + - (int64_t)t->settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]), - s->flow_control->remote_window_delta()); + if (grpc_flowctl_trace.enabled()) { + gpr_log( + GPR_DEBUG, + "%s:%p stream %d moved to stalled list by %s. This is FULLY expected " + "to happen in a healthy program that is not seeing flow control stalls." + " However, if you know that there are unwanted stalls, here is some " + "helpful data: [fc:pending=%" PRIdPTR ":pending-compressed=%" PRIdPTR + ":flowed=%" PRId64 ":peer_initwin=%d:t_win=%" PRId64 + ":s_win=%d:s_delta=%" PRId64 "]", + t->peer_string, t, s->id, staller, s->flow_controlled_buffer.length, + s->compressed_data_buffer.length, s->flow_controlled_bytes_flowed, + t->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + t->flow_control->remote_window(), + static_cast GPR_MAX( + 0, + s->flow_control->remote_window_delta() + + (int64_t)t->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]), + s->flow_control->remote_window_delta()); + } } static bool stream_ref_if_not_destroyed(gpr_refcount* r) { @@ -337,10 +343,10 @@ class DataSendContext { s_->fetching_send_message == nullptr); if (is_last_data_frame && s_->send_trailing_metadata != nullptr && s_->stream_compression_ctx != nullptr) { - if (!grpc_stream_compress( + if (GPR_UNLIKELY(!grpc_stream_compress( s_->stream_compression_ctx, &s_->flow_controlled_buffer, &s_->compressed_data_buffer, nullptr, MAX_SIZE_T, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)) { + GRPC_STREAM_COMPRESSION_FLUSH_FINISH))) { gpr_log(GPR_ERROR, "Stream compression failed."); } grpc_stream_compression_context_destroy(s_->stream_compression_ctx); @@ -368,10 +374,10 @@ class DataSendContext { grpc_stream_compression_context_create(s_->stream_compression_method); } s_->uncompressed_data_size = s_->flow_controlled_buffer.length; - if (!grpc_stream_compress(s_->stream_compression_ctx, - &s_->flow_controlled_buffer, - &s_->compressed_data_buffer, nullptr, MAX_SIZE_T, - GRPC_STREAM_COMPRESSION_FLUSH_SYNC)) { + if (GPR_UNLIKELY(!grpc_stream_compress( + s_->stream_compression_ctx, &s_->flow_controlled_buffer, + &s_->compressed_data_buffer, nullptr, MAX_SIZE_T, + GRPC_STREAM_COMPRESSION_FLUSH_SYNC))) { gpr_log(GPR_ERROR, "Stream compression failed."); } } @@ -564,6 +570,7 @@ class StreamWriteContext { void SentLastFrame() { s_->send_trailing_metadata = nullptr; s_->sent_trailing_metadata = true; + s_->eos_sent = true; if (!t_->is_client && !s_->read_closed) { grpc_slice_buffer_add( @@ -599,11 +606,18 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write( (according to available window sizes) and add to the output buffer */ while (grpc_chttp2_stream* s = ctx.NextStream()) { StreamWriteContext stream_ctx(&ctx, s); + size_t orig_len = t->outbuf.length; stream_ctx.FlushInitialMetadata(); stream_ctx.FlushWindowUpdates(); stream_ctx.FlushData(); stream_ctx.FlushTrailingMetadata(); - + if (t->outbuf.length > orig_len) { + /* Add this stream to the list of the contexts to be traced at TCP */ + s->byte_counter += t->outbuf.length - orig_len; + if (s->traced && grpc_endpoint_can_track_err(t->ep)) { + grpc_core::ContextList::Append(&t->cl, s); + } + } if (stream_ctx.stream_became_writable()) { if (!grpc_chttp2_list_add_writing_stream(t, s)) { /* already in writing list: drop ref */ @@ -627,6 +641,11 @@ void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error* error) { GPR_TIMER_SCOPE("grpc_chttp2_end_write", 0); grpc_chttp2_stream* s; + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordMessagesSent(t->num_messages_in_next_write); + } + t->num_messages_in_next_write = 0; + while (grpc_chttp2_list_pop_writing_stream(t, &s)) { if (s->sending_bytes != 0) { update_list(t, s, static_cast(s->sending_bytes), diff --git a/Sources/CgRPC/src/core/ext/transport/inproc/inproc_transport.cc b/Sources/CgRPC/src/core/ext/transport/inproc/inproc_transport.cc index 2c3bff5c1..0b9bf5dd1 100644 --- a/Sources/CgRPC/src/core/ext/transport/inproc/inproc_transport.cc +++ b/Sources/CgRPC/src/core/ext/transport/inproc/inproc_transport.cc @@ -40,18 +40,68 @@ if (grpc_inproc_trace.enabled()) gpr_log(__VA_ARGS__); \ } while (0) -static grpc_slice g_empty_slice; -static grpc_slice g_fake_path_key; -static grpc_slice g_fake_path_value; -static grpc_slice g_fake_auth_key; -static grpc_slice g_fake_auth_value; +namespace { +grpc_slice g_empty_slice; +grpc_slice g_fake_path_key; +grpc_slice g_fake_path_value; +grpc_slice g_fake_auth_key; +grpc_slice g_fake_auth_value; + +struct inproc_stream; +bool cancel_stream_locked(inproc_stream* s, grpc_error* error); +void op_state_machine(void* arg, grpc_error* error); +void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, + bool is_initial); +grpc_error* fill_in_metadata(inproc_stream* s, + const grpc_metadata_batch* metadata, + uint32_t flags, grpc_metadata_batch* out_md, + uint32_t* outflags, bool* markfilled); + +struct shared_mu { + shared_mu() { + // Share one lock between both sides since both sides get affected + gpr_mu_init(&mu); + gpr_ref_init(&refs, 2); + } -typedef struct { gpr_mu mu; gpr_refcount refs; -} shared_mu; +}; + +struct inproc_transport { + inproc_transport(const grpc_transport_vtable* vtable, shared_mu* mu, + bool is_client) + : mu(mu), is_client(is_client) { + base.vtable = vtable; + // Start each side of transport with 2 refs since they each have a ref + // to the other + gpr_ref_init(&refs, 2); + grpc_connectivity_state_init(&connectivity, GRPC_CHANNEL_READY, + is_client ? "inproc_client" : "inproc_server"); + } + + ~inproc_transport() { + grpc_connectivity_state_destroy(&connectivity); + if (gpr_unref(&mu->refs)) { + gpr_free(mu); + } + } + + void ref() { + INPROC_LOG(GPR_INFO, "ref_transport %p", this); + gpr_ref(&refs); + } + + void unref() { + INPROC_LOG(GPR_INFO, "unref_transport %p", this); + if (!gpr_unref(&refs)) { + return; + } + INPROC_LOG(GPR_INFO, "really_destroy_transport %p", this); + this->~inproc_transport(); + gpr_free(this); + } -typedef struct inproc_transport { grpc_transport base; shared_mu* mu; gpr_refcount refs; @@ -60,129 +110,174 @@ typedef struct inproc_transport { void (*accept_stream_cb)(void* user_data, grpc_transport* transport, const void* server_data); void* accept_stream_data; - bool is_closed; + bool is_closed = false; struct inproc_transport* other_side; - struct inproc_stream* stream_list; -} inproc_transport; + struct inproc_stream* stream_list = nullptr; +}; + +struct inproc_stream { + inproc_stream(inproc_transport* t, grpc_stream_refcount* refcount, + const void* server_data, gpr_arena* arena) + : t(t), refs(refcount), arena(arena) { + // Ref this stream right now for ctor and list. + ref("inproc_init_stream:init"); + ref("inproc_init_stream:list"); + + grpc_metadata_batch_init(&to_read_initial_md); + grpc_metadata_batch_init(&to_read_trailing_md); + GRPC_CLOSURE_INIT(&op_closure, op_state_machine, this, + grpc_schedule_on_exec_ctx); + grpc_metadata_batch_init(&write_buffer_initial_md); + grpc_metadata_batch_init(&write_buffer_trailing_md); + + stream_list_prev = nullptr; + gpr_mu_lock(&t->mu->mu); + stream_list_next = t->stream_list; + if (t->stream_list) { + t->stream_list->stream_list_prev = this; + } + t->stream_list = this; + gpr_mu_unlock(&t->mu->mu); + + if (!server_data) { + t->ref(); + inproc_transport* st = t->other_side; + st->ref(); + other_side = nullptr; // will get filled in soon + // Pass the client-side stream address to the server-side for a ref + ref("inproc_init_stream:clt"); // ref it now on behalf of server + // side to avoid destruction + INPROC_LOG(GPR_INFO, "calling accept stream cb %p %p", + st->accept_stream_cb, st->accept_stream_data); + (*st->accept_stream_cb)(st->accept_stream_data, &st->base, (void*)this); + } else { + // This is the server-side and is being called through accept_stream_cb + inproc_stream* cs = (inproc_stream*)server_data; + other_side = cs; + // Ref the server-side stream on behalf of the client now + ref("inproc_init_stream:srv"); + + // Now we are about to affect the other side, so lock the transport + // to make sure that it doesn't get destroyed + gpr_mu_lock(&t->mu->mu); + cs->other_side = this; + // Now transfer from the other side's write_buffer if any to the to_read + // buffer + if (cs->write_buffer_initial_md_filled) { + fill_in_metadata(this, &cs->write_buffer_initial_md, + cs->write_buffer_initial_md_flags, &to_read_initial_md, + &to_read_initial_md_flags, &to_read_initial_md_filled); + deadline = GPR_MIN(deadline, cs->write_buffer_deadline); + grpc_metadata_batch_clear(&cs->write_buffer_initial_md); + cs->write_buffer_initial_md_filled = false; + } + if (cs->write_buffer_trailing_md_filled) { + fill_in_metadata(this, &cs->write_buffer_trailing_md, 0, + &to_read_trailing_md, nullptr, + &to_read_trailing_md_filled); + grpc_metadata_batch_clear(&cs->write_buffer_trailing_md); + cs->write_buffer_trailing_md_filled = false; + } + if (cs->write_buffer_cancel_error != GRPC_ERROR_NONE) { + cancel_other_error = cs->write_buffer_cancel_error; + cs->write_buffer_cancel_error = GRPC_ERROR_NONE; + } + + gpr_mu_unlock(&t->mu->mu); + } + } + + ~inproc_stream() { + GRPC_ERROR_UNREF(write_buffer_cancel_error); + GRPC_ERROR_UNREF(cancel_self_error); + GRPC_ERROR_UNREF(cancel_other_error); + + if (recv_inited) { + grpc_slice_buffer_destroy_internal(&recv_message); + } + + t->unref(); + + if (closure_at_destroy) { + GRPC_CLOSURE_SCHED(closure_at_destroy, GRPC_ERROR_NONE); + } + } + +#ifndef NDEBUG +#define STREAM_REF(refs, reason) grpc_stream_ref(refs, reason) +#define STREAM_UNREF(refs, reason) grpc_stream_unref(refs, reason) +#else +#define STREAM_REF(refs, reason) grpc_stream_ref(refs) +#define STREAM_UNREF(refs, reason) grpc_stream_unref(refs) +#endif + void ref(const char* reason) { + INPROC_LOG(GPR_INFO, "ref_stream %p %s", this, reason); + STREAM_REF(refs, reason); + } + + void unref(const char* reason) { + INPROC_LOG(GPR_INFO, "unref_stream %p %s", this, reason); + STREAM_UNREF(refs, reason); + } +#undef STREAM_REF +#undef STREAM_UNREF -typedef struct inproc_stream { inproc_transport* t; grpc_metadata_batch to_read_initial_md; - uint32_t to_read_initial_md_flags; - bool to_read_initial_md_filled; + uint32_t to_read_initial_md_flags = 0; + bool to_read_initial_md_filled = false; grpc_metadata_batch to_read_trailing_md; - bool to_read_trailing_md_filled; - bool ops_needed; - bool op_closure_scheduled; + bool to_read_trailing_md_filled = false; + bool ops_needed = false; + bool op_closure_scheduled = false; grpc_closure op_closure; // Write buffer used only during gap at init time when client-side // stream is set up but server side stream is not yet set up grpc_metadata_batch write_buffer_initial_md; - bool write_buffer_initial_md_filled; - uint32_t write_buffer_initial_md_flags; - grpc_millis write_buffer_deadline; + bool write_buffer_initial_md_filled = false; + uint32_t write_buffer_initial_md_flags = 0; + grpc_millis write_buffer_deadline = GRPC_MILLIS_INF_FUTURE; grpc_metadata_batch write_buffer_trailing_md; - bool write_buffer_trailing_md_filled; - grpc_error* write_buffer_cancel_error; + bool write_buffer_trailing_md_filled = false; + grpc_error* write_buffer_cancel_error = GRPC_ERROR_NONE; struct inproc_stream* other_side; - bool other_side_closed; // won't talk anymore - bool write_buffer_other_side_closed; // on hold + bool other_side_closed = false; // won't talk anymore + bool write_buffer_other_side_closed = false; // on hold grpc_stream_refcount* refs; - grpc_closure* closure_at_destroy; + grpc_closure* closure_at_destroy = nullptr; gpr_arena* arena; - grpc_transport_stream_op_batch* send_message_op; - grpc_transport_stream_op_batch* send_trailing_md_op; - grpc_transport_stream_op_batch* recv_initial_md_op; - grpc_transport_stream_op_batch* recv_message_op; - grpc_transport_stream_op_batch* recv_trailing_md_op; + grpc_transport_stream_op_batch* send_message_op = nullptr; + grpc_transport_stream_op_batch* send_trailing_md_op = nullptr; + grpc_transport_stream_op_batch* recv_initial_md_op = nullptr; + grpc_transport_stream_op_batch* recv_message_op = nullptr; + grpc_transport_stream_op_batch* recv_trailing_md_op = nullptr; grpc_slice_buffer recv_message; grpc_core::ManualConstructor recv_stream; - bool recv_inited; + bool recv_inited = false; - bool initial_md_sent; - bool trailing_md_sent; - bool initial_md_recvd; - bool trailing_md_recvd; + bool initial_md_sent = false; + bool trailing_md_sent = false; + bool initial_md_recvd = false; + bool trailing_md_recvd = false; - bool closed; + bool closed = false; - grpc_error* cancel_self_error; - grpc_error* cancel_other_error; + grpc_error* cancel_self_error = GRPC_ERROR_NONE; + grpc_error* cancel_other_error = GRPC_ERROR_NONE; - grpc_millis deadline; + grpc_millis deadline = GRPC_MILLIS_INF_FUTURE; - bool listed; + bool listed = true; struct inproc_stream* stream_list_prev; struct inproc_stream* stream_list_next; -} inproc_stream; - -static grpc_closure do_nothing_closure; -static bool cancel_stream_locked(inproc_stream* s, grpc_error* error); -static void op_state_machine(void* arg, grpc_error* error); - -static void ref_transport(inproc_transport* t) { - INPROC_LOG(GPR_INFO, "ref_transport %p", t); - gpr_ref(&t->refs); -} - -static void really_destroy_transport(inproc_transport* t) { - INPROC_LOG(GPR_INFO, "really_destroy_transport %p", t); - grpc_connectivity_state_destroy(&t->connectivity); - if (gpr_unref(&t->mu->refs)) { - gpr_free(t->mu); - } - gpr_free(t); -} - -static void unref_transport(inproc_transport* t) { - INPROC_LOG(GPR_INFO, "unref_transport %p", t); - if (gpr_unref(&t->refs)) { - really_destroy_transport(t); - } -} +}; -#ifndef NDEBUG -#define STREAM_REF(refs, reason) grpc_stream_ref(refs, reason) -#define STREAM_UNREF(refs, reason) grpc_stream_unref(refs, reason) -#else -#define STREAM_REF(refs, reason) grpc_stream_ref(refs) -#define STREAM_UNREF(refs, reason) grpc_stream_unref(refs) -#endif - -static void ref_stream(inproc_stream* s, const char* reason) { - INPROC_LOG(GPR_INFO, "ref_stream %p %s", s, reason); - STREAM_REF(s->refs, reason); -} - -static void unref_stream(inproc_stream* s, const char* reason) { - INPROC_LOG(GPR_INFO, "unref_stream %p %s", s, reason); - STREAM_UNREF(s->refs, reason); -} - -static void really_destroy_stream(inproc_stream* s) { - INPROC_LOG(GPR_INFO, "really_destroy_stream %p", s); - - GRPC_ERROR_UNREF(s->write_buffer_cancel_error); - GRPC_ERROR_UNREF(s->cancel_self_error); - GRPC_ERROR_UNREF(s->cancel_other_error); - - if (s->recv_inited) { - grpc_slice_buffer_destroy_internal(&s->recv_message); - } - - unref_transport(s->t); - - if (s->closure_at_destroy) { - GRPC_CLOSURE_SCHED(s->closure_at_destroy, GRPC_ERROR_NONE); - } -} - -static void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, - bool is_initial) { +void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, + bool is_initial) { for (grpc_linked_mdelem* md = md_batch->list.head; md != nullptr; md = md->next) { char* key = grpc_slice_to_c_string(GRPC_MDKEY(md->md)); @@ -194,10 +289,10 @@ static void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, } } -static grpc_error* fill_in_metadata(inproc_stream* s, - const grpc_metadata_batch* metadata, - uint32_t flags, grpc_metadata_batch* out_md, - uint32_t* outflags, bool* markfilled) { +grpc_error* fill_in_metadata(inproc_stream* s, + const grpc_metadata_batch* metadata, + uint32_t flags, grpc_metadata_batch* out_md, + uint32_t* outflags, bool* markfilled) { if (grpc_inproc_trace.enabled()) { log_metadata(metadata, s->t->is_client, outflags != nullptr); } @@ -222,109 +317,16 @@ static grpc_error* fill_in_metadata(inproc_stream* s, return error; } -static int init_stream(grpc_transport* gt, grpc_stream* gs, - grpc_stream_refcount* refcount, const void* server_data, - gpr_arena* arena) { +int init_stream(grpc_transport* gt, grpc_stream* gs, + grpc_stream_refcount* refcount, const void* server_data, + gpr_arena* arena) { INPROC_LOG(GPR_INFO, "init_stream %p %p %p", gt, gs, server_data); inproc_transport* t = reinterpret_cast(gt); - inproc_stream* s = reinterpret_cast(gs); - s->arena = arena; - - s->refs = refcount; - // Ref this stream right now - ref_stream(s, "inproc_init_stream:init"); - - grpc_metadata_batch_init(&s->to_read_initial_md); - s->to_read_initial_md_flags = 0; - s->to_read_initial_md_filled = false; - grpc_metadata_batch_init(&s->to_read_trailing_md); - s->to_read_trailing_md_filled = false; - grpc_metadata_batch_init(&s->write_buffer_initial_md); - s->write_buffer_initial_md_flags = 0; - s->write_buffer_initial_md_filled = false; - grpc_metadata_batch_init(&s->write_buffer_trailing_md); - s->write_buffer_trailing_md_filled = false; - s->ops_needed = false; - s->op_closure_scheduled = false; - GRPC_CLOSURE_INIT(&s->op_closure, op_state_machine, s, - grpc_schedule_on_exec_ctx); - s->t = t; - s->closure_at_destroy = nullptr; - s->other_side_closed = false; - - s->initial_md_sent = s->trailing_md_sent = s->initial_md_recvd = - s->trailing_md_recvd = false; - - s->closed = false; - - s->cancel_self_error = GRPC_ERROR_NONE; - s->cancel_other_error = GRPC_ERROR_NONE; - s->write_buffer_cancel_error = GRPC_ERROR_NONE; - s->deadline = GRPC_MILLIS_INF_FUTURE; - s->write_buffer_deadline = GRPC_MILLIS_INF_FUTURE; - - s->stream_list_prev = nullptr; - gpr_mu_lock(&t->mu->mu); - s->listed = true; - ref_stream(s, "inproc_init_stream:list"); - s->stream_list_next = t->stream_list; - if (t->stream_list) { - t->stream_list->stream_list_prev = s; - } - t->stream_list = s; - gpr_mu_unlock(&t->mu->mu); - - if (!server_data) { - ref_transport(t); - inproc_transport* st = t->other_side; - ref_transport(st); - s->other_side = nullptr; // will get filled in soon - // Pass the client-side stream address to the server-side for a ref - ref_stream(s, "inproc_init_stream:clt"); // ref it now on behalf of server - // side to avoid destruction - INPROC_LOG(GPR_INFO, "calling accept stream cb %p %p", st->accept_stream_cb, - st->accept_stream_data); - (*st->accept_stream_cb)(st->accept_stream_data, &st->base, (void*)s); - } else { - // This is the server-side and is being called through accept_stream_cb - inproc_stream* cs = (inproc_stream*)server_data; - s->other_side = cs; - // Ref the server-side stream on behalf of the client now - ref_stream(s, "inproc_init_stream:srv"); - - // Now we are about to affect the other side, so lock the transport - // to make sure that it doesn't get destroyed - gpr_mu_lock(&s->t->mu->mu); - cs->other_side = s; - // Now transfer from the other side's write_buffer if any to the to_read - // buffer - if (cs->write_buffer_initial_md_filled) { - fill_in_metadata(s, &cs->write_buffer_initial_md, - cs->write_buffer_initial_md_flags, - &s->to_read_initial_md, &s->to_read_initial_md_flags, - &s->to_read_initial_md_filled); - s->deadline = GPR_MIN(s->deadline, cs->write_buffer_deadline); - grpc_metadata_batch_clear(&cs->write_buffer_initial_md); - cs->write_buffer_initial_md_filled = false; - } - if (cs->write_buffer_trailing_md_filled) { - fill_in_metadata(s, &cs->write_buffer_trailing_md, 0, - &s->to_read_trailing_md, nullptr, - &s->to_read_trailing_md_filled); - grpc_metadata_batch_clear(&cs->write_buffer_trailing_md); - cs->write_buffer_trailing_md_filled = false; - } - if (cs->write_buffer_cancel_error != GRPC_ERROR_NONE) { - s->cancel_other_error = cs->write_buffer_cancel_error; - cs->write_buffer_cancel_error = GRPC_ERROR_NONE; - } - - gpr_mu_unlock(&s->t->mu->mu); - } + new (gs) inproc_stream(t, refcount, server_data, arena); return 0; // return value is not important } -static void close_stream_locked(inproc_stream* s) { +void close_stream_locked(inproc_stream* s) { if (!s->closed) { // Release the metadata that we would have written out grpc_metadata_batch_destroy(&s->write_buffer_initial_md); @@ -342,21 +344,21 @@ static void close_stream_locked(inproc_stream* s) { n->stream_list_prev = p; } s->listed = false; - unref_stream(s, "close_stream:list"); + s->unref("close_stream:list"); } s->closed = true; - unref_stream(s, "close_stream:closing"); + s->unref("close_stream:closing"); } } // This function means that we are done talking/listening to the other side -static void close_other_side_locked(inproc_stream* s, const char* reason) { +void close_other_side_locked(inproc_stream* s, const char* reason) { if (s->other_side != nullptr) { // First release the metadata that came from the other side's arena grpc_metadata_batch_destroy(&s->to_read_initial_md); grpc_metadata_batch_destroy(&s->to_read_trailing_md); - unref_stream(s->other_side, reason); + s->other_side->unref(reason); s->other_side_closed = true; s->other_side = nullptr; } else if (!s->other_side_closed) { @@ -368,11 +370,15 @@ static void close_other_side_locked(inproc_stream* s, const char* reason) { // this stream_op_batch is only one of the pending operations for this // stream. This is called when one of the pending operations for the stream // is done and about to be NULLed out -static void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error, - grpc_transport_stream_op_batch* op, - const char* msg) { +void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error, + grpc_transport_stream_op_batch* op, + const char* msg) { int is_sm = static_cast(op == s->send_message_op); int is_stm = static_cast(op == s->send_trailing_md_op); + // TODO(vjpai): We should not consider the recv ops here, since they + // have their own callbacks. We should invoke a batch's on_complete + // as soon as all of the batch's send ops are complete, even if there + // are still recv ops pending. int is_rim = static_cast(op == s->recv_initial_md_op); int is_rm = static_cast(op == s->recv_message_op); int is_rtm = static_cast(op == s->recv_trailing_md_op); @@ -383,8 +389,7 @@ static void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error, } } -static void maybe_schedule_op_closure_locked(inproc_stream* s, - grpc_error* error) { +void maybe_schedule_op_closure_locked(inproc_stream* s, grpc_error* error) { if (s && s->ops_needed && !s->op_closure_scheduled) { GRPC_CLOSURE_SCHED(&s->op_closure, GRPC_ERROR_REF(error)); s->op_closure_scheduled = true; @@ -392,7 +397,7 @@ static void maybe_schedule_op_closure_locked(inproc_stream* s, } } -static void fail_helper_locked(inproc_stream* s, grpc_error* error) { +void fail_helper_locked(inproc_stream* s, grpc_error* error) { INPROC_LOG(GPR_INFO, "op_state_machine %p fail_helper", s); // If we're failing this side, we need to make sure that // we also send or have already sent trailing metadata @@ -496,6 +501,11 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) { s->send_trailing_md_op = nullptr; } if (s->recv_trailing_md_op) { + INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-metadata-ready %p", + s, error); + GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata + .recv_trailing_metadata_ready, + GRPC_ERROR_REF(error)); INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-md-on-complete %p", s, error); complete_if_batch_end_locked( @@ -517,8 +527,7 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) { // that the incoming byte stream's next() call will always return // synchronously. That assumption is true today but may not always be // true in the future. -static void message_transfer_locked(inproc_stream* sender, - inproc_stream* receiver) { +void message_transfer_locked(inproc_stream* sender, inproc_stream* receiver) { size_t remaining = sender->send_message_op->payload->send_message.send_message->length(); if (receiver->recv_inited) { @@ -564,7 +573,7 @@ static void message_transfer_locked(inproc_stream* sender, sender->send_message_op = nullptr; } -static void op_state_machine(void* arg, grpc_error* error) { +void op_state_machine(void* arg, grpc_error* error) { // This function gets called when we have contents in the unprocessed reads // Get what we want based on our ops wanted // Schedule our appropriate closures @@ -599,10 +608,8 @@ static void op_state_machine(void* arg, grpc_error* error) { if (other->recv_message_op) { message_transfer_locked(s, other); maybe_schedule_op_closure_locked(other, GRPC_ERROR_NONE); - } else if (!s->t->is_client && - (s->trailing_md_sent || other->recv_trailing_md_op)) { - // A server send will never be matched if the client is waiting - // for trailing metadata already + } else if (!s->t->is_client && s->trailing_md_sent) { + // A server send will never be matched if the server already sent status s->send_message_op->payload->send_message.send_message.reset(); complete_if_batch_end_locked( s, GRPC_ERROR_NONE, s->send_message_op, @@ -613,11 +620,15 @@ static void op_state_machine(void* arg, grpc_error* error) { // Pause a send trailing metadata if there is still an outstanding // send message unless we know that the send message will never get // matched to a receive. This happens on the client if the server has - // already sent status. + // already sent status or on the server if the client has requested + // status if (s->send_trailing_md_op && (!s->send_message_op || (s->t->is_client && - (s->trailing_md_recvd || s->to_read_trailing_md_filled)))) { + (s->trailing_md_recvd || s->to_read_trailing_md_filled)) || + (!s->t->is_client && other && + (other->trailing_md_recvd || other->to_read_trailing_md_filled || + other->recv_trailing_md_op)))) { grpc_metadata_batch* dest = (other == nullptr) ? &s->write_buffer_trailing_md : &other->to_read_trailing_md; @@ -638,6 +649,12 @@ static void op_state_machine(void* arg, grpc_error* error) { } s->trailing_md_sent = true; if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) { + INPROC_LOG(GPR_INFO, + "op_state_machine %p scheduling trailing-metadata-ready", s); + GRPC_CLOSURE_SCHED( + s->recv_trailing_md_op->payload->recv_trailing_metadata + .recv_trailing_metadata_ready, + GRPC_ERROR_NONE); INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling trailing-md-on-complete", s); GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete, @@ -709,10 +726,6 @@ static void op_state_machine(void* arg, grpc_error* error) { maybe_schedule_op_closure_locked(other, GRPC_ERROR_NONE); } } - if (s->recv_trailing_md_op && s->t->is_client && other && - other->send_message_op) { - maybe_schedule_op_closure_locked(other, GRPC_ERROR_NONE); - } if (s->to_read_trailing_md_filled) { if (s->trailing_md_recvd) { new_err = @@ -728,6 +741,7 @@ static void op_state_machine(void* arg, grpc_error* error) { if (s->recv_message_op != nullptr) { // This message needs to be wrapped up because it will never be // satisfied + *s->recv_message_op->payload->recv_message.recv_message = nullptr; INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling message-ready", s); GRPC_CLOSURE_SCHED( s->recv_message_op->payload->recv_message.recv_message_ready, @@ -766,6 +780,10 @@ static void op_state_machine(void* arg, grpc_error* error) { INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling trailing-md-on-complete %p", s, new_err); + GRPC_CLOSURE_SCHED( + s->recv_trailing_md_op->payload->recv_trailing_metadata + .recv_trailing_metadata_ready, + GRPC_ERROR_REF(new_err)); GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete, GRPC_ERROR_REF(new_err)); s->recv_trailing_md_op = nullptr; @@ -786,6 +804,7 @@ static void op_state_machine(void* arg, grpc_error* error) { // No further message will come on this stream, so finish off the // recv_message_op INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling message-ready", s); + *s->recv_message_op->payload->recv_message.recv_message = nullptr; GRPC_CLOSURE_SCHED( s->recv_message_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); @@ -823,7 +842,7 @@ static void op_state_machine(void* arg, grpc_error* error) { GRPC_ERROR_UNREF(new_err); } -static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) { +bool cancel_stream_locked(inproc_stream* s, grpc_error* error) { bool ret = false; // was the cancel accepted INPROC_LOG(GPR_INFO, "cancel_stream %p with %s", s, grpc_error_string(error)); if (s->cancel_self_error == GRPC_ERROR_NONE) { @@ -859,6 +878,9 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) { // couldn't complete that because we hadn't yet sent out trailing // md, now's the chance if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) { + GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata + .recv_trailing_metadata_ready, + GRPC_ERROR_REF(s->cancel_self_error)); complete_if_batch_end_locked( s, s->cancel_self_error, s->recv_trailing_md_op, "cancel_stream scheduling trailing-md-on-complete"); @@ -873,8 +895,10 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) { return ret; } -static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, - grpc_transport_stream_op_batch* op) { +void do_nothing(void* arg, grpc_error* error) {} + +void perform_stream_op(grpc_transport* gt, grpc_stream* gs, + grpc_transport_stream_op_batch* op) { INPROC_LOG(GPR_INFO, "perform_stream_op %p %p %p", gt, gs, op); inproc_stream* s = reinterpret_cast(gs); gpr_mu* mu = &s->t->mu->mu; // save aside in case s gets closed @@ -892,8 +916,14 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, } grpc_error* error = GRPC_ERROR_NONE; grpc_closure* on_complete = op->on_complete; + // TODO(roth): This is a hack needed because we use data inside of the + // closure itself to do the barrier calculation (i.e., to ensure that + // we don't schedule the closure until all ops in the batch have been + // completed). This can go away once we move to a new C++ closure API + // that provides the ability to create a barrier closure. if (on_complete == nullptr) { - on_complete = &do_nothing_closure; + on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing, + nullptr, grpc_schedule_on_exec_ctx); } if (op->cancel_stream) { @@ -977,18 +1007,18 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, } // We want to initiate the closure if: - // 1. We want to send a message and the other side wants to receive or end + // 1. We want to send a message and the other side wants to receive // 2. We want to send trailing metadata and there isn't an unmatched send + // or the other side wants trailing metadata // 3. We want initial metadata and the other side has sent it // 4. We want to receive a message and there is a message ready // 5. There is trailing metadata, even if nothing specifically wants // that because that can shut down the receive message as well - if ((op->send_message && other && - ((other->recv_message_op != nullptr) || - (other->recv_trailing_md_op != nullptr))) || - (op->send_trailing_metadata && !op->send_message) || + if ((op->send_message && other && other->recv_message_op != nullptr) || + (op->send_trailing_metadata && + (!s->send_message_op || (other && other->recv_trailing_md_op))) || (op->recv_initial_metadata && s->to_read_initial_md_filled) || - (op->recv_message && other && (other->send_message_op != nullptr)) || + (op->recv_message && other && other->send_message_op != nullptr) || (s->to_read_trailing_md_filled || s->trailing_md_recvd)) { if (!s->op_closure_scheduled) { GRPC_CLOSURE_SCHED(&s->op_closure, GRPC_ERROR_NONE); @@ -1026,6 +1056,15 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready, GRPC_ERROR_REF(error)); } + if (op->recv_trailing_metadata) { + INPROC_LOG( + GPR_INFO, + "perform_stream_op error %p scheduling trailing-metadata-ready %p", + s, error); + GRPC_CLOSURE_SCHED( + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready, + GRPC_ERROR_REF(error)); + } } INPROC_LOG(GPR_INFO, "perform_stream_op %p scheduling on_complete %p", s, error); @@ -1039,7 +1078,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, GRPC_ERROR_UNREF(error); } -static void close_transport_locked(inproc_transport* t) { +void close_transport_locked(inproc_transport* t) { INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed); grpc_connectivity_state_set( &t->connectivity, GRPC_CHANNEL_SHUTDOWN, @@ -1059,7 +1098,7 @@ static void close_transport_locked(inproc_transport* t) { } } -static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) { +void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) { inproc_transport* t = reinterpret_cast(gt); INPROC_LOG(GPR_INFO, "perform_transport_op %p %p", t, op); gpr_mu_lock(&t->mu->mu); @@ -1092,49 +1131,70 @@ static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) { gpr_mu_unlock(&t->mu->mu); } -static void destroy_stream(grpc_transport* gt, grpc_stream* gs, - grpc_closure* then_schedule_closure) { +void destroy_stream(grpc_transport* gt, grpc_stream* gs, + grpc_closure* then_schedule_closure) { INPROC_LOG(GPR_INFO, "destroy_stream %p %p", gs, then_schedule_closure); inproc_stream* s = reinterpret_cast(gs); s->closure_at_destroy = then_schedule_closure; - really_destroy_stream(s); + s->~inproc_stream(); } -static void destroy_transport(grpc_transport* gt) { +void destroy_transport(grpc_transport* gt) { inproc_transport* t = reinterpret_cast(gt); INPROC_LOG(GPR_INFO, "destroy_transport %p", t); gpr_mu_lock(&t->mu->mu); close_transport_locked(t); gpr_mu_unlock(&t->mu->mu); - unref_transport(t->other_side); - unref_transport(t); + t->other_side->unref(); + t->unref(); } /******************************************************************************* * INTEGRATION GLUE */ -static void set_pollset(grpc_transport* gt, grpc_stream* gs, - grpc_pollset* pollset) { +void set_pollset(grpc_transport* gt, grpc_stream* gs, grpc_pollset* pollset) { // Nothing to do here } -static void set_pollset_set(grpc_transport* gt, grpc_stream* gs, - grpc_pollset_set* pollset_set) { +void set_pollset_set(grpc_transport* gt, grpc_stream* gs, + grpc_pollset_set* pollset_set) { // Nothing to do here } -static grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; } +grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; } + +const grpc_transport_vtable inproc_vtable = { + sizeof(inproc_stream), "inproc", init_stream, + set_pollset, set_pollset_set, perform_stream_op, + perform_transport_op, destroy_stream, destroy_transport, + get_endpoint}; /******************************************************************************* - * GLOBAL INIT AND DESTROY + * Main inproc transport functions */ -static void do_nothing(void* arg, grpc_error* error) {} +void inproc_transports_create(grpc_transport** server_transport, + const grpc_channel_args* server_args, + grpc_transport** client_transport, + const grpc_channel_args* client_args) { + INPROC_LOG(GPR_INFO, "inproc_transports_create"); + shared_mu* mu = new (gpr_malloc(sizeof(*mu))) shared_mu(); + inproc_transport* st = new (gpr_malloc(sizeof(*st))) + inproc_transport(&inproc_vtable, mu, /*is_client=*/false); + inproc_transport* ct = new (gpr_malloc(sizeof(*ct))) + inproc_transport(&inproc_vtable, mu, /*is_client=*/true); + st->other_side = ct; + ct->other_side = st; + *server_transport = reinterpret_cast(st); + *client_transport = reinterpret_cast(ct); +} +} // namespace +/******************************************************************************* + * GLOBAL INIT AND DESTROY + */ void grpc_inproc_transport_init(void) { grpc_core::ExecCtx exec_ctx; - GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, nullptr, - grpc_schedule_on_exec_ctx); g_empty_slice = grpc_slice_from_static_buffer(nullptr, 0); grpc_slice key_tmp = grpc_slice_from_static_string(":path"); @@ -1150,48 +1210,6 @@ void grpc_inproc_transport_init(void) { g_fake_auth_value = grpc_slice_from_static_string("inproc-fail"); } -static const grpc_transport_vtable inproc_vtable = { - sizeof(inproc_stream), "inproc", init_stream, - set_pollset, set_pollset_set, perform_stream_op, - perform_transport_op, destroy_stream, destroy_transport, - get_endpoint}; - -/******************************************************************************* - * Main inproc transport functions - */ -static void inproc_transports_create(grpc_transport** server_transport, - const grpc_channel_args* server_args, - grpc_transport** client_transport, - const grpc_channel_args* client_args) { - INPROC_LOG(GPR_INFO, "inproc_transports_create"); - inproc_transport* st = - static_cast(gpr_zalloc(sizeof(*st))); - inproc_transport* ct = - static_cast(gpr_zalloc(sizeof(*ct))); - // Share one lock between both sides since both sides get affected - st->mu = ct->mu = static_cast(gpr_malloc(sizeof(*st->mu))); - gpr_mu_init(&st->mu->mu); - gpr_ref_init(&st->mu->refs, 2); - st->base.vtable = &inproc_vtable; - ct->base.vtable = &inproc_vtable; - // Start each side of transport with 2 refs since they each have a ref - // to the other - gpr_ref_init(&st->refs, 2); - gpr_ref_init(&ct->refs, 2); - st->is_client = false; - ct->is_client = true; - grpc_connectivity_state_init(&st->connectivity, GRPC_CHANNEL_READY, - "inproc_server"); - grpc_connectivity_state_init(&ct->connectivity, GRPC_CHANNEL_READY, - "inproc_client"); - st->other_side = ct; - ct->other_side = st; - st->stream_list = nullptr; - ct->stream_list = nullptr; - *server_transport = reinterpret_cast(st); - *client_transport = reinterpret_cast(ct); -} - grpc_channel* grpc_inproc_channel_create(grpc_server* server, grpc_channel_args* args, void* reserved) { @@ -1216,7 +1234,9 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server, inproc_transports_create(&server_transport, server_args, &client_transport, client_args); - grpc_server_setup_transport(server, server_transport, nullptr, server_args); + // TODO(ncteisen): design and support channelz GetSocket for inproc. + grpc_server_setup_transport(server, server_transport, nullptr, server_args, + nullptr); grpc_channel* channel = grpc_channel_create( "inproc", client_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport); diff --git a/Sources/CgRPC/src/core/lib/channel/channel_stack.cc b/Sources/CgRPC/src/core/lib/channel/channel_stack.cc index a9459b150..df956c717 100644 --- a/Sources/CgRPC/src/core/lib/channel/channel_stack.cc +++ b/Sources/CgRPC/src/core/lib/channel/channel_stack.cc @@ -21,6 +21,7 @@ #include #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/gpr/alloc.h" #include #include @@ -43,16 +44,12 @@ grpc_core::TraceFlag grpc_trace_channel(false, "channel"); per-filter memory, aligned to GPR_MAX_ALIGNMENT } */ -/* Given a size, round up to the next multiple of sizeof(void*) */ -#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ - (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u)) - size_t grpc_channel_stack_size(const grpc_channel_filter** filters, size_t filter_count) { /* always need the header, and size for the channel elements */ - size_t size = - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) + - ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element)); + size_t size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * + sizeof(grpc_channel_element)); size_t i; GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 && @@ -60,19 +57,19 @@ size_t grpc_channel_stack_size(const grpc_channel_filter** filters, /* add the size for each filter */ for (i = 0; i < filter_count; i++) { - size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data); + size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data); } return size; } -#define CHANNEL_ELEMS_FROM_STACK(stk) \ - ((grpc_channel_element*)((char*)(stk) + ROUND_UP_TO_ALIGNMENT_SIZE( \ +#define CHANNEL_ELEMS_FROM_STACK(stk) \ + ((grpc_channel_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ sizeof(grpc_channel_stack)))) -#define CALL_ELEMS_FROM_STACK(stk) \ - ((grpc_call_element*)((char*)(stk) + \ - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)))) +#define CALL_ELEMS_FROM_STACK(stk) \ + ((grpc_call_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ + sizeof(grpc_call_stack)))) grpc_channel_element* grpc_channel_stack_element( grpc_channel_stack* channel_stack, size_t index) { @@ -95,8 +92,8 @@ grpc_error* grpc_channel_stack_init( const grpc_channel_args* channel_args, grpc_transport* optional_transport, const char* name, grpc_channel_stack* stack) { size_t call_size = - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) + - ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element)); + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element)); grpc_channel_element* elems; grpc_channel_element_args args; char* user_data; @@ -106,9 +103,9 @@ grpc_error* grpc_channel_stack_init( GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg, name); elems = CHANNEL_ELEMS_FROM_STACK(stack); - user_data = - (reinterpret_cast(elems)) + - ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element)); + user_data = (reinterpret_cast(elems)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * + sizeof(grpc_channel_element)); /* init per-filter data */ grpc_error* first_error = GRPC_ERROR_NONE; @@ -128,8 +125,9 @@ grpc_error* grpc_channel_stack_init( GRPC_ERROR_UNREF(error); } } - user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data); - call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data); + user_data += + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data); + call_size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data); } GPR_ASSERT(user_data > (char*)stack); @@ -159,21 +157,24 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack, size_t count = channel_stack->count; grpc_call_element* call_elems; char* user_data; - size_t i; elem_args->call_stack->count = count; GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy, destroy_arg, "CALL_STACK"); call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack); user_data = (reinterpret_cast(call_elems)) + - ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ grpc_error* first_error = GRPC_ERROR_NONE; - for (i = 0; i < count; i++) { + for (size_t i = 0; i < count; i++) { call_elems[i].filter = channel_elems[i].filter; call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].call_data = user_data; + user_data += + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); + } + for (size_t i = 0; i < count; i++) { grpc_error* error = call_elems[i].filter->init_call_elem(&call_elems[i], elem_args); if (error != GRPC_ERROR_NONE) { @@ -183,8 +184,6 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack, GRPC_ERROR_UNREF(error); } } - user_data += - ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); } return first_error; } @@ -193,18 +192,13 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack, grpc_polling_entity* pollent) { size_t count = call_stack->count; grpc_call_element* call_elems; - char* user_data; size_t i; call_elems = CALL_ELEMS_FROM_STACK(call_stack); - user_data = (reinterpret_cast(call_elems)) + - ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ for (i = 0; i < count; i++) { call_elems[i].filter->set_pollset_or_pollset_set(&call_elems[i], pollent); - user_data += - ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); } } @@ -248,11 +242,11 @@ grpc_channel_stack* grpc_channel_stack_from_top_element( grpc_channel_element* elem) { return reinterpret_cast( reinterpret_cast(elem) - - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack))); + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack))); } grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) { return reinterpret_cast( reinterpret_cast(elem) - - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack))); + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack))); } diff --git a/Sources/CgRPC/src/core/lib/channel/channel_stack.h b/Sources/CgRPC/src/core/lib/channel/channel_stack.h index 4bf821866..0de8c6707 100644 --- a/Sources/CgRPC/src/core/lib/channel/channel_stack.h +++ b/Sources/CgRPC/src/core/lib/channel/channel_stack.h @@ -79,11 +79,11 @@ typedef struct { } grpc_call_stats; /** Information about the call upon completion. */ -typedef struct { +struct grpc_call_final_info { grpc_call_stats stats; - grpc_status_code final_status; - const char** error_string; -} grpc_call_final_info; + grpc_status_code final_status = GRPC_STATUS_OK; + const char* error_string = nullptr; +}; /* Channel filters specify: 1. the amount of memory needed in the channel & call (via the sizeof_XXX @@ -138,7 +138,7 @@ typedef struct { is_first, is_last designate this elements position in the stack, and are useful for asserting correct configuration by upper layer code. The filter does not need to do any chaining. - Implementations may assume that elem->call_data is all zeros. */ + Implementations may assume that elem->channel_data is all zeros. */ grpc_error* (*init_channel_elem)(grpc_channel_element* elem, grpc_channel_element_args* args); /* Destroy per channel data. diff --git a/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.cc b/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.cc index 8a7244903..8b3008f22 100644 --- a/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.cc +++ b/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.cc @@ -25,9 +25,6 @@ #include #include -grpc_core::TraceFlag grpc_trace_channel_stack_builder(false, - "channel_stack_builder"); - typedef struct filter_node { struct filter_node* next; struct filter_node* prev; @@ -43,6 +40,7 @@ struct grpc_channel_stack_builder { // various set/get-able parameters grpc_channel_args* args; grpc_transport* transport; + grpc_resource_user* resource_user; char* target; const char* name; }; @@ -160,6 +158,11 @@ void grpc_channel_stack_builder_set_channel_arguments( builder->args = grpc_channel_args_copy(args); } +const grpc_channel_args* grpc_channel_stack_builder_get_channel_arguments( + grpc_channel_stack_builder* builder) { + return builder->args; +} + void grpc_channel_stack_builder_set_transport( grpc_channel_stack_builder* builder, grpc_transport* transport) { GPR_ASSERT(builder->transport == nullptr); @@ -171,9 +174,15 @@ grpc_transport* grpc_channel_stack_builder_get_transport( return builder->transport; } -const grpc_channel_args* grpc_channel_stack_builder_get_channel_arguments( +void grpc_channel_stack_builder_set_resource_user( + grpc_channel_stack_builder* builder, grpc_resource_user* resource_user) { + GPR_ASSERT(builder->resource_user == nullptr); + builder->resource_user = resource_user; +} + +grpc_resource_user* grpc_channel_stack_builder_get_resource_user( grpc_channel_stack_builder* builder) { - return builder->args; + return builder->resource_user; } bool grpc_channel_stack_builder_append_filter( diff --git a/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.h b/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.h index c9a170bc8..89c30e0c5 100644 --- a/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.h +++ b/Sources/CgRPC/src/core/lib/channel/channel_stack_builder.h @@ -54,6 +54,14 @@ void grpc_channel_stack_builder_set_transport( grpc_transport* grpc_channel_stack_builder_get_transport( grpc_channel_stack_builder* builder); +/// Attach \a resource_user to the builder (does not take ownership) +void grpc_channel_stack_builder_set_resource_user( + grpc_channel_stack_builder* builder, grpc_resource_user* resource_user); + +/// Fetch attached resource user +grpc_resource_user* grpc_channel_stack_builder_get_resource_user( + grpc_channel_stack_builder* builder); + /// Set channel arguments: copies args void grpc_channel_stack_builder_set_channel_arguments( grpc_channel_stack_builder* builder, const grpc_channel_args* args); @@ -155,6 +163,4 @@ grpc_error* grpc_channel_stack_builder_finish( /// Destroy the builder without creating a channel stack void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder* builder); -extern grpc_core::TraceFlag grpc_trace_channel_stack_builder; - #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/channel_trace.cc b/Sources/CgRPC/src/core/lib/channel/channel_trace.cc index 654300cd3..f0d21db32 100644 --- a/Sources/CgRPC/src/core/lib/channel/channel_trace.cc +++ b/Sources/CgRPC/src/core/lib/channel/channel_trace.cc @@ -28,7 +28,6 @@ #include #include -#include "src/core/lib/channel/channel_trace_registry.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" @@ -40,55 +39,53 @@ #include "src/core/lib/transport/error_utils.h" namespace grpc_core { +namespace channelz { -ChannelTrace::TraceEvent::TraceEvent( - Severity severity, grpc_slice data, - RefCountedPtr referenced_tracer, ReferencedType type) +ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_entity) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_tracer_(std::move(referenced_tracer)), - referenced_type_(type) {} + referenced_entity_(std::move(referenced_entity)), + memory_usage_(sizeof(TraceEvent) + grpc_slice_memory_usage(data)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), - next_(nullptr) {} + next_(nullptr), + memory_usage_(sizeof(TraceEvent) + grpc_slice_memory_usage(data)) {} ChannelTrace::TraceEvent::~TraceEvent() { grpc_slice_unref_internal(data_); } -ChannelTrace::ChannelTrace(size_t max_events) - : channel_uuid_(-1), - num_events_logged_(0), - list_size_(0), - max_list_size_(max_events), +ChannelTrace::ChannelTrace(size_t max_event_memory) + : num_events_logged_(0), + event_list_memory_usage_(0), + max_event_memory_(max_event_memory), head_trace_(nullptr), tail_trace_(nullptr) { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 + if (max_event_memory_ == 0) + return; // tracing is disabled if max_event_memory_ == 0 gpr_mu_init(&tracer_mu_); - channel_uuid_ = grpc_channel_trace_registry_register_channel_trace(this); time_created_ = grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME); } ChannelTrace::~ChannelTrace() { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 + if (max_event_memory_ == 0) + return; // tracing is disabled if max_event_memory_ == 0 TraceEvent* it = head_trace_; while (it != nullptr) { TraceEvent* to_free = it; it = it->next(); Delete(to_free); } - grpc_channel_trace_registry_unregister_channel_trace(channel_uuid_); gpr_mu_destroy(&tracer_mu_); } -intptr_t ChannelTrace::GetUuid() const { return channel_uuid_; } - void ChannelTrace::AddTraceEventHelper(TraceEvent* new_trace_event) { ++num_events_logged_; // first event case @@ -100,73 +97,38 @@ void ChannelTrace::AddTraceEventHelper(TraceEvent* new_trace_event) { tail_trace_->set_next(new_trace_event); tail_trace_ = tail_trace_->next(); } - ++list_size_; - // maybe garbage collect the end - if (list_size_ > max_list_size_) { + event_list_memory_usage_ += new_trace_event->memory_usage(); + // maybe garbage collect the tail until we are under the memory limit. + while (event_list_memory_usage_ > max_event_memory_) { TraceEvent* to_free = head_trace_; + event_list_memory_usage_ -= to_free->memory_usage(); head_trace_ = head_trace_->next(); Delete(to_free); - --list_size_; } } void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 + if (max_event_memory_ == 0) { + grpc_slice_unref_internal(data); + return; // tracing is disabled if max_event_memory_ == 0 + } AddTraceEventHelper(New(severity, data)); } -void ChannelTrace::AddTraceEventReferencingChannel( +void ChannelTrace::AddTraceEventWithReference( Severity severity, grpc_slice data, - RefCountedPtr referenced_tracer) { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 + RefCountedPtr referenced_entity) { + if (max_event_memory_ == 0) { + grpc_slice_unref_internal(data); + return; // tracing is disabled if max_event_memory_ == 0 + } // create and fill up the new event AddTraceEventHelper( - New(severity, data, std::move(referenced_tracer), Channel)); -} - -void ChannelTrace::AddTraceEventReferencingSubchannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_tracer) { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 - // create and fill up the new event - AddTraceEventHelper(New( - severity, data, std::move(referenced_tracer), Subchannel)); + New(severity, data, std::move(referenced_entity))); } namespace { -// returns an allocated string that represents tm according to RFC-3339, and, -// more specifically, follows: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// "Uses RFC 3339, where generated output will always be Z-normalized and uses -// 0, 3, 6 or 9 fractional digits." -char* fmt_time(gpr_timespec tm) { - char time_buffer[35]; - char ns_buffer[11]; // '.' + 9 digits of precision - struct tm* tm_info = localtime((const time_t*)&tm.tv_sec); - strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); - snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); - // This loop trims off trailing zeros by inserting a null character that the - // right point. We iterate in chunks of three because we want 0, 3, 6, or 9 - // fractional digits. - for (int i = 7; i >= 1; i -= 3) { - if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && - ns_buffer[i + 2] == '0') { - ns_buffer[i] = '\0'; - // Edge case in which all fractional digits were 0. - if (i == 1) { - ns_buffer[0] = '\0'; - } - } else { - break; - } - } - char* full_time_str; - gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer); - return full_time_str; -} - const char* severity_string(ChannelTrace::Severity severity) { switch (severity) { case ChannelTrace::Severity::Info: @@ -190,50 +152,52 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "severity", severity_string(severity_), GRPC_JSON_STRING, false); - json_iterator = - grpc_json_create_child(json_iterator, json, "timestamp", - fmt_time(timestamp_), GRPC_JSON_STRING, true); - if (referenced_tracer_ != nullptr) { + json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", + gpr_format_timespec(timestamp_), + GRPC_JSON_STRING, true); + if (referenced_entity_ != nullptr) { + const bool is_channel = + (referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || + referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_tracer_->channel_uuid_); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); grpc_json* child_ref = grpc_json_create_child( - json_iterator, json, - (referenced_type_ == Channel) ? "channelRef" : "subchannelRef", nullptr, - GRPC_JSON_OBJECT, false); + json_iterator, json, is_channel ? "channelRef" : "subchannelRef", + nullptr, GRPC_JSON_OBJECT, false); json_iterator = grpc_json_create_child( - nullptr, child_ref, - (referenced_type_ == Channel) ? "channelId" : "subchannelId", uuid_str, + nullptr, child_ref, is_channel ? "channelId" : "subchannelId", uuid_str, GRPC_JSON_STRING, true); json_iterator = child_ref; } } -char* ChannelTrace::RenderTrace() const { - if (!max_list_size_) - return nullptr; // tracing is disabled if max_events == 0 +grpc_json* ChannelTrace::RenderJson() const { + if (max_event_memory_ == 0) + return nullptr; // tracing is disabled if max_event_memory_ == 0 grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT); - char* num_events_logged_str; - gpr_asprintf(&num_events_logged_str, "%" PRId64, num_events_logged_); grpc_json* json_iterator = nullptr; - json_iterator = - grpc_json_create_child(json_iterator, json, "numEventsLogged", - num_events_logged_str, GRPC_JSON_STRING, true); - json_iterator = - grpc_json_create_child(json_iterator, json, "creationTime", - fmt_time(time_created_), GRPC_JSON_STRING, true); - grpc_json* events = grpc_json_create_child(json_iterator, json, "events", - nullptr, GRPC_JSON_ARRAY, false); - json_iterator = nullptr; - TraceEvent* it = head_trace_; - while (it != nullptr) { - json_iterator = grpc_json_create_child(json_iterator, events, nullptr, - nullptr, GRPC_JSON_OBJECT, false); - it->RenderTraceEvent(json_iterator); - it = it->next(); + if (num_events_logged_ > 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "numEventsLogged", num_events_logged_); + } + json_iterator = grpc_json_create_child( + json_iterator, json, "creationTimestamp", + gpr_format_timespec(time_created_), GRPC_JSON_STRING, true); + // only add in the event list if it is non-empty. + if (head_trace_ != nullptr) { + grpc_json* events = grpc_json_create_child(json_iterator, json, "events", + nullptr, GRPC_JSON_ARRAY, false); + json_iterator = nullptr; + TraceEvent* it = head_trace_; + while (it != nullptr) { + json_iterator = grpc_json_create_child(json_iterator, events, nullptr, + nullptr, GRPC_JSON_OBJECT, false); + it->RenderTraceEvent(json_iterator); + it = it->next(); + } } - char* json_str = grpc_json_dump_to_string(json, 0); - grpc_json_destroy(json); - return json_str; + return json; } +} // namespace channelz } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/channel/channel_trace.h b/Sources/CgRPC/src/core/lib/channel/channel_trace.h index 1df1e585f..8ff91ee8c 100644 --- a/Sources/CgRPC/src/core/lib/channel/channel_trace.h +++ b/Sources/CgRPC/src/core/lib/channel/channel_trace.h @@ -28,18 +28,22 @@ #include "src/core/lib/json/json.h" namespace grpc_core { +namespace channelz { + +namespace testing { +size_t GetSizeofTraceEvent(void); +} + +class BaseNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: // https://github.com/grpc/proposal/blob/master/A14-channelz.md -class ChannelTrace : public RefCounted { +class ChannelTrace { public: - ChannelTrace(size_t max_events); + ChannelTrace(size_t max_event_memory); ~ChannelTrace(); - // returns the tracer's uuid - intptr_t GetUuid() const; - enum Severity { Unset = 0, // never to be used Info, // we start at 1 to avoid using proto default values @@ -49,45 +53,42 @@ class ChannelTrace : public RefCounted { // Adds a new trace event to the tracing object // + // NOTE: each ChannelTrace tracks the memory used by its list of trace + // events, so adding an event with a large amount of data could cause other + // trace event to be evicted. If a single trace is larger than the limit, it + // will cause all events to be evicted. The limit is set with the arg: + // GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE. + // // TODO(ncteisen): as this call is used more and more throughout the gRPC // stack, determine if it makes more sense to accept a char* instead of a // slice. void AddTraceEvent(Severity severity, grpc_slice data); // Adds a new trace event to the tracing object. This trace event refers to a - // an event on a child of the channel. For example, if this channel has - // created a new subchannel, then it would record that with a TraceEvent - // referencing the new subchannel. + // an event that concerns a different channelz entity. For example, if this + // channel has created a new subchannel, then it would record that with + // a TraceEvent referencing the new subchannel. // - // TODO(ncteisen): Once channelz is implemented, the events should reference - // the overall channelz object, not just the ChannelTrace object. - // TODO(ncteisen): as this call is used more and more throughout the gRPC - // stack, determine if it makes more sense to accept a char* instead of a - // slice. - void AddTraceEventReferencingChannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_tracer); - void AddTraceEventReferencingSubchannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_tracer); + // NOTE: see the note in the method above. + // + // TODO(ncteisen): see the todo in the method above. + void AddTraceEventWithReference(Severity severity, grpc_slice data, + RefCountedPtr referenced_entity); - // Returns the tracing data rendered as a grpc json string. - // The string is owned by the caller and must be freed. - char* RenderTrace() const; + // Creates and returns the raw grpc_json object, so a parent channelz + // object may incorporate the json before rendering. + grpc_json* RenderJson() const; private: - // Types of objects that can be references by trace events. - enum ReferencedType { Channel, Subchannel }; + friend size_t testing::GetSizeofTraceEvent(void); + // Private class to encapsulate all the data and bookkeeping needed for a // a trace event. class TraceEvent { public: - // Constructor for a TraceEvent that references a different channel. - // TODO(ncteisen): once channelz is implemented, this should reference the - // overall channelz object, not just the ChannelTrace object + // Constructor for a TraceEvent that references a channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_tracer, - ReferencedType type); + RefCountedPtr referenced_entity_); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -103,31 +104,31 @@ class ChannelTrace : public RefCounted { TraceEvent* next() const { return next_; } void set_next(TraceEvent* next) { next_ = next; } + size_t memory_usage() const { return memory_usage_; } + private: Severity severity_; grpc_slice data_; gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_tracer_; - // the type that the referenced tracer points to. Unused if this trace - // does not point to any channel or subchannel - ReferencedType referenced_type_; + RefCountedPtr referenced_entity_; + size_t memory_usage_; }; // TraceEvent // Internal helper to add and link in a trace event void AddTraceEventHelper(TraceEvent* new_trace_event); gpr_mu tracer_mu_; - intptr_t channel_uuid_; uint64_t num_events_logged_; - size_t list_size_; - size_t max_list_size_; + size_t event_list_memory_usage_; + size_t max_event_memory_; TraceEvent* head_trace_; TraceEvent* tail_trace_; gpr_timespec time_created_; }; +} // namespace channelz } // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/channel_trace_registry.cc b/Sources/CgRPC/src/core/lib/channel/channel_trace_registry.cc deleted file mode 100644 index 6c8243146..000000000 --- a/Sources/CgRPC/src/core/lib/channel/channel_trace_registry.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/avl/avl.h" -#include "src/core/lib/channel/channel_trace.h" -#include "src/core/lib/channel/channel_trace_registry.h" -#include "src/core/lib/gpr/useful.h" - -#include -#include - -// file global lock and avl. -static gpr_mu g_mu; -static grpc_avl g_avl; -static gpr_atm g_uuid = 0; - -// avl vtable for uuid (intptr_t) -> ChannelTrace -// this table is only looking, it does not own anything. -static void destroy_intptr(void* not_used, void* user_data) {} -static void* copy_intptr(void* key, void* user_data) { return key; } -static long compare_intptr(void* key1, void* key2, void* user_data) { - return GPR_ICMP(key1, key2); -} - -static void destroy_channel_trace(void* trace, void* user_data) {} -static void* copy_channel_trace(void* trace, void* user_data) { return trace; } -static const grpc_avl_vtable avl_vtable = { - destroy_intptr, copy_intptr, compare_intptr, destroy_channel_trace, - copy_channel_trace}; - -void grpc_channel_trace_registry_init() { - gpr_mu_init(&g_mu); - g_avl = grpc_avl_create(&avl_vtable); -} - -void grpc_channel_trace_registry_shutdown() { - grpc_avl_unref(g_avl, nullptr); - gpr_mu_destroy(&g_mu); -} - -intptr_t grpc_channel_trace_registry_register_channel_trace( - grpc_core::ChannelTrace* channel_trace) { - intptr_t prior = gpr_atm_no_barrier_fetch_add(&g_uuid, 1); - gpr_mu_lock(&g_mu); - g_avl = grpc_avl_add(g_avl, (void*)prior, channel_trace, nullptr); - gpr_mu_unlock(&g_mu); - return prior; -} - -void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid) { - gpr_mu_lock(&g_mu); - g_avl = grpc_avl_remove(g_avl, (void*)uuid, nullptr); - gpr_mu_unlock(&g_mu); -} - -grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace( - intptr_t uuid) { - gpr_mu_lock(&g_mu); - grpc_core::ChannelTrace* ret = static_cast( - grpc_avl_get(g_avl, (void*)uuid, nullptr)); - gpr_mu_unlock(&g_mu); - return ret; -} diff --git a/Sources/CgRPC/src/core/lib/channel/channel_trace_registry.h b/Sources/CgRPC/src/core/lib/channel/channel_trace_registry.h deleted file mode 100644 index 391ecba7d..000000000 --- a/Sources/CgRPC/src/core/lib/channel/channel_trace_registry.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H -#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H - -#include - -#include "src/core/lib/channel/channel_trace.h" - -#include - -// TODO(ncteisen): convert this file to C++ - -void grpc_channel_trace_registry_init(); -void grpc_channel_trace_registry_shutdown(); - -// globally registers a ChannelTrace. Returns its unique uuid -intptr_t grpc_channel_trace_registry_register_channel_trace( - grpc_core::ChannelTrace* channel_trace); -// globally unregisters the ChannelTrace that is associated to uuid. -void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid); -// if object with uuid has previously been registered, returns the ChannelTrace -// associated with that uuid. Else returns nullptr. -grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace( - intptr_t uuid); - -#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/channelz.cc b/Sources/CgRPC/src/core/lib/channel/channelz.cc new file mode 100644 index 000000000..8a596ad46 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/channel/channelz.cc @@ -0,0 +1,460 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/channel/channelz.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channelz_registry.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/slice/b64.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/uri/uri_parser.h" + +namespace grpc_core { +namespace channelz { + +BaseNode::BaseNode(EntityType type) : type_(type), uuid_(-1) { + // The registry will set uuid_ under its lock. + ChannelzRegistry::Register(this); +} + +BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } + +char* BaseNode::RenderJsonString() { + grpc_json* json = RenderJson(); + GPR_ASSERT(json != nullptr); + char* json_str = grpc_json_dump_to_string(json, 0); + grpc_json_destroy(json); + return json_str; +} + +CallCountingHelper::CallCountingHelper() { + num_cores_ = GPR_MAX(1, gpr_cpu_num_cores()); + per_cpu_counter_data_storage_ = static_cast( + gpr_zalloc(sizeof(AtomicCounterData) * num_cores_)); +} + +CallCountingHelper::~CallCountingHelper() { + gpr_free(per_cpu_counter_data_storage_); +} + +void CallCountingHelper::RecordCallStarted() { + gpr_atm_no_barrier_fetch_add( + &per_cpu_counter_data_storage_[grpc_core::ExecCtx::Get()->starting_cpu()] + .calls_started, + static_cast(1)); + gpr_atm_no_barrier_store( + &per_cpu_counter_data_storage_[grpc_core::ExecCtx::Get()->starting_cpu()] + .last_call_started_millis, + (gpr_atm)ExecCtx::Get()->Now()); +} + +void CallCountingHelper::RecordCallFailed() { + gpr_atm_no_barrier_fetch_add( + &per_cpu_counter_data_storage_[grpc_core::ExecCtx::Get()->starting_cpu()] + .calls_failed, + static_cast(1)); +} + +void CallCountingHelper::RecordCallSucceeded() { + gpr_atm_no_barrier_fetch_add( + &per_cpu_counter_data_storage_[grpc_core::ExecCtx::Get()->starting_cpu()] + .calls_succeeded, + static_cast(1)); +} + +void CallCountingHelper::CollectData(CounterData* out) { + for (size_t core = 0; core < num_cores_; ++core) { + out->calls_started += gpr_atm_no_barrier_load( + &per_cpu_counter_data_storage_[core].calls_started); + out->calls_succeeded += gpr_atm_no_barrier_load( + &per_cpu_counter_data_storage_[core].calls_succeeded); + out->calls_failed += gpr_atm_no_barrier_load( + &per_cpu_counter_data_storage_[core].calls_failed); + gpr_atm last_call = gpr_atm_no_barrier_load( + &per_cpu_counter_data_storage_[core].last_call_started_millis); + if (last_call > out->last_call_started_millis) { + out->last_call_started_millis = last_call; + } + } +} + +void CallCountingHelper::PopulateCallCounts(grpc_json* json) { + grpc_json* json_iterator = nullptr; + CounterData data; + CollectData(&data); + if (data.calls_started != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "callsStarted", data.calls_started); + } + if (data.calls_succeeded != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "callsSucceeded", data.calls_succeeded); + } + if (data.calls_failed) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "callsFailed", data.calls_failed); + } + if (data.calls_started != 0) { + gpr_timespec ts = grpc_millis_to_timespec(data.last_call_started_millis, + GPR_CLOCK_REALTIME); + json_iterator = + grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + } +} + +ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) + : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel + : EntityType::kInternalChannel), + channel_(channel), + target_(UniquePtr(grpc_channel_get_target(channel_))), + trace_(channel_tracer_max_nodes) {} + +ChannelNode::~ChannelNode() {} + +grpc_json* ChannelNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "channelId", uuid()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + // template method. Child classes may override this to add their specific + // functionality. + PopulateConnectivityState(json); + // populate the target. + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); + // fill in the channel trace if applicable + grpc_json* trace_json = trace_.RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallCounts(json); + json = top_level_json; + // template method. Child classes may override this to add their specific + // functionality. + PopulateChildRefs(json); + return top_level_json; +} + +RefCountedPtr ChannelNode::MakeChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) { + return MakeRefCounted( + channel, channel_tracer_max_nodes, is_top_level_channel); +} + +ServerNode::ServerNode(grpc_server* server, size_t channel_tracer_max_nodes) + : BaseNode(EntityType::kServer), + server_(server), + trace_(channel_tracer_max_nodes) {} + +ServerNode::~ServerNode() {} + +char* ServerNode::RenderServerSockets(intptr_t start_socket_id, + intptr_t max_results) { + // if user does not set max_results, we choose 500. + size_t pagination_limit = max_results == 0 ? 500 : max_results; + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + ChildSocketsList socket_refs; + grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); + // declared early so it can be used outside of the loop. + size_t i = 0; + if (!socket_refs.empty()) { + // create list of socket refs + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); + for (i = 0; i < GPR_MIN(socket_refs.size(), pagination_limit); ++i) { + grpc_json* socket_ref_json = grpc_json_create_child( + nullptr, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); + json_iterator = grpc_json_add_number_string_child( + socket_ref_json, nullptr, "socketId", socket_refs[i]->uuid()); + grpc_json_create_child(json_iterator, socket_ref_json, "name", + socket_refs[i]->remote(), GRPC_JSON_STRING, false); + } + } + if (i == socket_refs.size()) { + json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, + GRPC_JSON_TRUE, false); + } + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + +grpc_json* ServerNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "serverId", uuid()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + // fill in the channel trace if applicable + grpc_json* trace_json = trace_.RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallCounts(json); + json = top_level_json; + ChildRefsList listen_sockets; + grpc_server_populate_listen_sockets(server_, &listen_sockets); + if (!listen_sockets.empty()) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "listenSocket", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < listen_sockets.size(); ++i) { + json_iterator = + grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_add_number_string_child(json_iterator, nullptr, "socketId", + listen_sockets[i]); + } + } + return top_level_json; +} + +static void PopulateSocketAddressJson(grpc_json* json, const char* name, + const char* addr_str) { + if (addr_str == nullptr) return; + grpc_json* json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, name, nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + grpc_uri* uri = grpc_uri_parse(addr_str, true); + if ((uri != nullptr) && ((strcmp(uri->scheme, "ipv4") == 0) || + (strcmp(uri->scheme, "ipv6") == 0))) { + const char* host_port = uri->path; + if (*host_port == '/') ++host_port; + char* host = nullptr; + char* port = nullptr; + GPR_ASSERT(gpr_split_host_port(host_port, &host, &port)); + int port_num = -1; + if (port != nullptr) { + port_num = atoi(port); + } + char* b64_host = grpc_base64_encode(host, strlen(host), false, false); + json_iterator = grpc_json_create_child(json_iterator, json, "tcpip_address", + nullptr, GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "port", port_num); + json_iterator = grpc_json_create_child(json_iterator, json, "ip_address", + b64_host, GRPC_JSON_STRING, true); + gpr_free(host); + gpr_free(port); + + } else if (uri != nullptr && strcmp(uri->scheme, "unix") == 0) { + json_iterator = grpc_json_create_child(json_iterator, json, "uds_address", + nullptr, GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = + grpc_json_create_child(json_iterator, json, "filename", + gpr_strdup(uri->path), GRPC_JSON_STRING, true); + } else { + json_iterator = grpc_json_create_child(json_iterator, json, "other_address", + nullptr, GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, "name", + addr_str, GRPC_JSON_STRING, false); + } + grpc_uri_destroy(uri); +} + +SocketNode::SocketNode(UniquePtr local, UniquePtr remote) + : BaseNode(EntityType::kSocket), + local_(std::move(local)), + remote_(std::move(remote)) {} + +void SocketNode::RecordStreamStartedFromLocal() { + gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast(1)); + gpr_atm_no_barrier_store(&last_local_stream_created_millis_, + (gpr_atm)ExecCtx::Get()->Now()); +} + +void SocketNode::RecordStreamStartedFromRemote() { + gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast(1)); + gpr_atm_no_barrier_store(&last_remote_stream_created_millis_, + (gpr_atm)ExecCtx::Get()->Now()); +} + +void SocketNode::RecordMessagesSent(uint32_t num_sent) { + gpr_atm_no_barrier_fetch_add(&messages_sent_, static_cast(num_sent)); + gpr_atm_no_barrier_store(&last_message_sent_millis_, + (gpr_atm)ExecCtx::Get()->Now()); +} + +void SocketNode::RecordMessageReceived() { + gpr_atm_no_barrier_fetch_add(&messages_received_, static_cast(1)); + gpr_atm_no_barrier_store(&last_message_received_millis_, + (gpr_atm)ExecCtx::Get()->Now()); +} + +grpc_json* SocketNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "socketId", uuid()); + json = top_level_json; + PopulateSocketAddressJson(json, "remote", remote_.get()); + PopulateSocketAddressJson(json, "local", local_.get()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + gpr_timespec ts; + if (streams_started_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "streamsStarted", streams_started_); + if (last_local_stream_created_millis_ != 0) { + ts = grpc_millis_to_timespec(last_local_stream_created_millis_, + GPR_CLOCK_REALTIME); + json_iterator = grpc_json_create_child( + json_iterator, json, "lastLocalStreamCreatedTimestamp", + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + } + if (last_remote_stream_created_millis_ != 0) { + ts = grpc_millis_to_timespec(last_remote_stream_created_millis_, + GPR_CLOCK_REALTIME); + json_iterator = grpc_json_create_child( + json_iterator, json, "lastRemoteStreamCreatedTimestamp", + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + } + } + if (streams_succeeded_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "streamsSucceeded", streams_succeeded_); + } + if (streams_failed_) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "streamsFailed", streams_failed_); + } + if (messages_sent_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "messagesSent", messages_sent_); + ts = grpc_millis_to_timespec(last_message_sent_millis_, GPR_CLOCK_REALTIME); + json_iterator = + grpc_json_create_child(json_iterator, json, "lastMessageSentTimestamp", + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + } + if (messages_received_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "messagesReceived", messages_received_); + ts = grpc_millis_to_timespec(last_message_received_millis_, + GPR_CLOCK_REALTIME); + json_iterator = grpc_json_create_child( + json_iterator, json, "lastMessageReceivedTimestamp", + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + } + if (keepalives_sent_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "keepAlivesSent", keepalives_sent_); + } + return top_level_json; +} + +ListenSocketNode::ListenSocketNode(UniquePtr local_addr) + : BaseNode(EntityType::kSocket), local_addr_(std::move(local_addr)) {} + +grpc_json* ListenSocketNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "socketId", uuid()); + json = top_level_json; + PopulateSocketAddressJson(json, "local", local_addr_.get()); + + return top_level_json; +} + +} // namespace channelz +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/channel/channelz.h b/Sources/CgRPC/src/core/lib/channel/channelz.h new file mode 100644 index 000000000..e43792126 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/channel/channelz.h @@ -0,0 +1,296 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_H +#define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H + +#include + +#include + +#include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/json/json.h" + +// Channel arg key for client channel factory. +#define GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC \ + "grpc.channelz_channel_node_creation_func" + +// Channel arg key to signal that the channel is an internal channel. +#define GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL \ + "grpc.channelz_channel_is_internal_channel" + +/** This is the default value for whether or not to enable channelz. If + * GRPC_ARG_ENABLE_CHANNELZ is set, it will override this default value. */ +#define GRPC_ENABLE_CHANNELZ_DEFAULT true + +/** This is the default value for the maximum amount of memory used by trace + * events per channel trace node. If + * GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE is set, it will override + * this default value. */ +#define GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT 1024 * 4 + +namespace grpc_core { + +namespace channelz { + +// TODO(ncteisen), this only contains the uuids of the children for now, +// since that is all that is strictly needed. In a future enhancement we will +// add human readable names as in the channelz.proto +typedef InlinedVector ChildRefsList; + +class SocketNode; +typedef InlinedVector ChildSocketsList; + +namespace testing { +class CallCountingHelperPeer; +class ChannelNodePeer; +} // namespace testing + +// base class for all channelz entities +class BaseNode : public RefCounted { + public: + // There are only four high level channelz entities. However, to support + // GetTopChannelsRequest, we split the Channel entity into two different + // types. All children of BaseNode must be one of these types. + enum class EntityType { + kTopLevelChannel, + kInternalChannel, + kSubchannel, + kServer, + kSocket, + }; + + explicit BaseNode(EntityType type); + virtual ~BaseNode(); + + // All children must implement this function. + virtual grpc_json* RenderJson() GRPC_ABSTRACT; + + // Renders the json and returns allocated string that must be freed by the + // caller. + char* RenderJsonString(); + + EntityType type() const { return type_; } + intptr_t uuid() const { return uuid_; } + + private: + // to allow the ChannelzRegistry to set uuid_ under its lock. + friend class ChannelzRegistry; + const EntityType type_; + intptr_t uuid_; +}; + +// This class is a helper class for channelz entities that deal with Channels, +// Subchannels, and Servers, since those have similar proto definitions. +// This class has the ability to: +// - track calls_{started,succeeded,failed} +// - track last_call_started_timestamp +// - perform rendering of the above items +class CallCountingHelper { + public: + CallCountingHelper(); + ~CallCountingHelper(); + + void RecordCallStarted(); + void RecordCallFailed(); + void RecordCallSucceeded(); + + // Common rendering of the call count data and last_call_started_timestamp. + void PopulateCallCounts(grpc_json* json); + + private: + // testing peer friend. + friend class testing::CallCountingHelperPeer; + + struct AtomicCounterData { + gpr_atm calls_started = 0; + gpr_atm calls_succeeded = 0; + gpr_atm calls_failed = 0; + gpr_atm last_call_started_millis = 0; + }; + + struct CounterData { + intptr_t calls_started = 0; + intptr_t calls_succeeded = 0; + intptr_t calls_failed = 0; + intptr_t last_call_started_millis = 0; + }; + + // collects the sharded data into one CounterData struct. + void CollectData(CounterData* out); + + AtomicCounterData* per_cpu_counter_data_storage_ = nullptr; + size_t num_cores_ = 0; +}; + +// Handles channelz bookkeeping for channels +class ChannelNode : public BaseNode { + public: + static RefCountedPtr MakeChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + + ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + ~ChannelNode() override; + + grpc_json* RenderJson() override; + + // template methods. RenderJSON uses these methods to render its JSON + // representation. These are virtual so that children classes may provide + // their specific mechanism for populating these parts of the channelz + // object. + // + // ChannelNode does not have a notion of connectivity state or child refs, + // so it leaves these implementations blank. + // + // This is utilizing the template method design pattern. + // + // TODO(ncteisen): remove these template methods in favor of manual traversal + // and mutation of the grpc_json object. + virtual void PopulateConnectivityState(grpc_json* json) {} + virtual void PopulateChildRefs(grpc_json* json) {} + + void MarkChannelDestroyed() { + GPR_ASSERT(channel_ != nullptr); + channel_ = nullptr; + } + + bool ChannelIsDestroyed() { return channel_ == nullptr; } + + // proxy methods to composed classes. + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_.AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); + } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } + + private: + // to allow the channel trace test to access trace_. + friend class testing::ChannelNodePeer; + grpc_channel* channel_ = nullptr; + UniquePtr target_; + CallCountingHelper call_counter_; + ChannelTrace trace_; +}; + +// Handles channelz bookkeeping for servers +class ServerNode : public BaseNode { + public: + ServerNode(grpc_server* server, size_t channel_tracer_max_nodes); + ~ServerNode() override; + + grpc_json* RenderJson() override; + + char* RenderServerSockets(intptr_t start_socket_id, + intptr_t pagination_limit); + + // proxy methods to composed classes. + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_.AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); + } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } + + private: + grpc_server* server_; + CallCountingHelper call_counter_; + ChannelTrace trace_; +}; + +// Handles channelz bookkeeping for sockets +class SocketNode : public BaseNode { + public: + SocketNode(UniquePtr local, UniquePtr remote); + ~SocketNode() override {} + + grpc_json* RenderJson() override; + + void RecordStreamStartedFromLocal(); + void RecordStreamStartedFromRemote(); + void RecordStreamSucceeded() { + gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast(1)); + } + void RecordStreamFailed() { + gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast(1)); + } + void RecordMessagesSent(uint32_t num_sent); + void RecordMessageReceived(); + void RecordKeepaliveSent() { + gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast(1)); + } + + const char* remote() { return remote_.get(); } + + private: + gpr_atm streams_started_ = 0; + gpr_atm streams_succeeded_ = 0; + gpr_atm streams_failed_ = 0; + gpr_atm messages_sent_ = 0; + gpr_atm messages_received_ = 0; + gpr_atm keepalives_sent_ = 0; + gpr_atm last_local_stream_created_millis_ = 0; + gpr_atm last_remote_stream_created_millis_ = 0; + gpr_atm last_message_sent_millis_ = 0; + gpr_atm last_message_received_millis_ = 0; + UniquePtr local_; + UniquePtr remote_; +}; + +// Handles channelz bookkeeping for listen sockets +class ListenSocketNode : public BaseNode { + public: + // ListenSocketNode takes ownership of host. + explicit ListenSocketNode(UniquePtr local_addr); + ~ListenSocketNode() override {} + + grpc_json* RenderJson() override; + + private: + UniquePtr local_addr_; +}; + +// Creation functions + +typedef RefCountedPtr (*ChannelNodeCreationFunc)(grpc_channel*, + size_t, bool); + +} // namespace channelz +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/channelz_registry.cc b/Sources/CgRPC/src/core/lib/channel/channelz_registry.cc new file mode 100644 index 000000000..7cca247d6 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/channel/channelz_registry.cc @@ -0,0 +1,324 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" +#include "src/core/lib/channel/channelz_registry.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/mutex_lock.h" + +#include +#include +#include + +#include + +namespace grpc_core { +namespace channelz { +namespace { + +// singleton instance of the registry. +ChannelzRegistry* g_channelz_registry = nullptr; + +const int kPaginationLimit = 100; + +} // anonymous namespace + +void ChannelzRegistry::Init() { g_channelz_registry = New(); } + +void ChannelzRegistry::Shutdown() { Delete(g_channelz_registry); } + +ChannelzRegistry* ChannelzRegistry::Default() { + GPR_DEBUG_ASSERT(g_channelz_registry != nullptr); + return g_channelz_registry; +} + +ChannelzRegistry::ChannelzRegistry() { gpr_mu_init(&mu_); } + +ChannelzRegistry::~ChannelzRegistry() { gpr_mu_destroy(&mu_); } + +void ChannelzRegistry::InternalRegister(BaseNode* node) { + MutexLock lock(&mu_); + entities_.push_back(node); + node->uuid_ = ++uuid_generator_; +} + +void ChannelzRegistry::MaybePerformCompactionLocked() { + constexpr double kEmptinessTheshold = 1 / 3; + double emptiness_ratio = + double(num_empty_slots_) / double(entities_.capacity()); + if (emptiness_ratio > kEmptinessTheshold) { + int front = 0; + for (size_t i = 0; i < entities_.size(); ++i) { + if (entities_[i] != nullptr) { + entities_[front++] = entities_[i]; + } + } + for (int i = 0; i < num_empty_slots_; ++i) { + entities_.pop_back(); + } + num_empty_slots_ = 0; + } +} + +int ChannelzRegistry::FindByUuidLocked(intptr_t target_uuid, + bool direct_hit_needed) { + int left = 0; + int right = int(entities_.size() - 1); + while (left <= right) { + int true_middle = left + (right - left) / 2; + int first_non_null = true_middle; + while (first_non_null < right && entities_[first_non_null] == nullptr) { + first_non_null++; + } + if (entities_[first_non_null] == nullptr) { + right = true_middle - 1; + continue; + } + intptr_t uuid = entities_[first_non_null]->uuid(); + if (uuid == target_uuid) { + return int(first_non_null); + } + if (uuid < target_uuid) { + left = first_non_null + 1; + } else { + right = true_middle - 1; + } + } + return direct_hit_needed ? -1 : left; +} + +void ChannelzRegistry::InternalUnregister(intptr_t uuid) { + GPR_ASSERT(uuid >= 1); + MutexLock lock(&mu_); + GPR_ASSERT(uuid <= uuid_generator_); + int idx = FindByUuidLocked(uuid, true); + GPR_ASSERT(idx >= 0); + entities_[idx] = nullptr; + num_empty_slots_++; + MaybePerformCompactionLocked(); +} + +BaseNode* ChannelzRegistry::InternalGet(intptr_t uuid) { + MutexLock lock(&mu_); + if (uuid < 1 || uuid > uuid_generator_) { + return nullptr; + } + int idx = FindByUuidLocked(uuid, true); + return idx < 0 ? nullptr : entities_[idx]; +} + +char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { + MutexLock lock(&mu_); + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + InlinedVector top_level_channels; + bool reached_pagination_limit = false; + int start_idx = GPR_MAX(FindByUuidLocked(start_channel_id, false), 0); + for (size_t i = start_idx; i < entities_.size(); ++i) { + if (entities_[i] != nullptr && + entities_[i]->type() == + grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel && + entities_[i]->uuid() >= start_channel_id) { + // check if we are over pagination limit to determine if we need to set + // the "end" element. If we don't go through this block, we know that + // when the loop terminates, we have <= to kPaginationLimit. + if (top_level_channels.size() == kPaginationLimit) { + reached_pagination_limit = true; + break; + } + top_level_channels.push_back(entities_[i]); + } + } + if (!top_level_channels.empty()) { + // create list of channels + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < top_level_channels.size(); ++i) { + grpc_json* channel_json = top_level_channels[i]->RenderJson(); + json_iterator = + grpc_json_link_child(array_parent, channel_json, json_iterator); + } + } + if (!reached_pagination_limit) { + grpc_json_create_child(nullptr, json, "end", nullptr, GRPC_JSON_TRUE, + false); + } + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + +char* ChannelzRegistry::InternalGetServers(intptr_t start_server_id) { + MutexLock lock(&mu_); + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + InlinedVector servers; + bool reached_pagination_limit = false; + int start_idx = GPR_MAX(FindByUuidLocked(start_server_id, false), 0); + for (size_t i = start_idx; i < entities_.size(); ++i) { + if (entities_[i] != nullptr && + entities_[i]->type() == + grpc_core::channelz::BaseNode::EntityType::kServer && + entities_[i]->uuid() >= start_server_id) { + // check if we are over pagination limit to determine if we need to set + // the "end" element. If we don't go through this block, we know that + // when the loop terminates, we have <= to kPaginationLimit. + if (servers.size() == kPaginationLimit) { + reached_pagination_limit = true; + break; + } + servers.push_back(entities_[i]); + } + } + if (!servers.empty()) { + // create list of servers + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "server", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < servers.size(); ++i) { + grpc_json* server_json = servers[i]->RenderJson(); + json_iterator = + grpc_json_link_child(array_parent, server_json, json_iterator); + } + } + if (!reached_pagination_limit) { + grpc_json_create_child(nullptr, json, "end", nullptr, GRPC_JSON_TRUE, + false); + } + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + +void ChannelzRegistry::InternalLogAllEntities() { + MutexLock lock(&mu_); + for (size_t i = 0; i < entities_.size(); ++i) { + if (entities_[i] != nullptr) { + char* json = entities_[i]->RenderJsonString(); + gpr_log(GPR_INFO, "%s", json); + gpr_free(json); + } + } +} + +} // namespace channelz +} // namespace grpc_core + +char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { + return grpc_core::channelz::ChannelzRegistry::GetTopChannels( + start_channel_id); +} + +char* grpc_channelz_get_servers(intptr_t start_server_id) { + return grpc_core::channelz::ChannelzRegistry::GetServers(start_server_id); +} + +char* grpc_channelz_get_server(intptr_t server_id) { + grpc_core::channelz::BaseNode* server_node = + grpc_core::channelz::ChannelzRegistry::Get(server_id); + if (server_node == nullptr || + server_node->type() != + grpc_core::channelz::BaseNode::EntityType::kServer) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* channel_json = server_node->RenderJson(); + channel_json->key = "server"; + grpc_json_link_child(json, channel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + +char* grpc_channelz_get_server_sockets(intptr_t server_id, + intptr_t start_socket_id, + intptr_t max_results) { + grpc_core::channelz::BaseNode* base_node = + grpc_core::channelz::ChannelzRegistry::Get(server_id); + if (base_node == nullptr || + base_node->type() != grpc_core::channelz::BaseNode::EntityType::kServer) { + return nullptr; + } + // This cast is ok since we have just checked to make sure base_node is + // actually a server node + grpc_core::channelz::ServerNode* server_node = + static_cast(base_node); + return server_node->RenderServerSockets(start_socket_id, max_results); +} + +char* grpc_channelz_get_channel(intptr_t channel_id) { + grpc_core::channelz::BaseNode* channel_node = + grpc_core::channelz::ChannelzRegistry::Get(channel_id); + if (channel_node == nullptr || + (channel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel && + channel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kInternalChannel)) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* channel_json = channel_node->RenderJson(); + channel_json->key = "channel"; + grpc_json_link_child(json, channel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + +char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { + grpc_core::channelz::BaseNode* subchannel_node = + grpc_core::channelz::ChannelzRegistry::Get(subchannel_id); + if (subchannel_node == nullptr || + subchannel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kSubchannel) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* subchannel_json = subchannel_node->RenderJson(); + subchannel_json->key = "subchannel"; + grpc_json_link_child(json, subchannel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + +char* grpc_channelz_get_socket(intptr_t socket_id) { + grpc_core::channelz::BaseNode* socket_node = + grpc_core::channelz::ChannelzRegistry::Get(socket_id); + if (socket_node == nullptr || + socket_node->type() != + grpc_core::channelz::BaseNode::EntityType::kSocket) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* socket_json = socket_node->RenderJson(); + socket_json->key = "socket"; + grpc_json_link_child(json, socket_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} diff --git a/Sources/CgRPC/src/core/lib/channel/channelz_registry.h b/Sources/CgRPC/src/core/lib/channel/channelz_registry.h new file mode 100644 index 000000000..73b330785 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/channel/channelz_registry.h @@ -0,0 +1,115 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H +#define GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H + +#include + +#include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" +#include "src/core/lib/gprpp/inlined_vector.h" + +#include + +namespace grpc_core { +namespace channelz { + +namespace testing { +class ChannelzRegistryPeer; +} + +// singleton registry object to track all objects that are needed to support +// channelz bookkeeping. All objects share globally distributed uuids. +class ChannelzRegistry { + public: + // To be called in grpc_init() + static void Init(); + + // To be called in grpc_shutdown(); + static void Shutdown(); + + static void Register(BaseNode* node) { + return Default()->InternalRegister(node); + } + static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); } + static BaseNode* Get(intptr_t uuid) { return Default()->InternalGet(uuid); } + + // Returns the allocated JSON string that represents the proto + // GetTopChannelsResponse as per channelz.proto. + static char* GetTopChannels(intptr_t start_channel_id) { + return Default()->InternalGetTopChannels(start_channel_id); + } + + // Returns the allocated JSON string that represents the proto + // GetServersResponse as per channelz.proto. + static char* GetServers(intptr_t start_server_id) { + return Default()->InternalGetServers(start_server_id); + } + + // Test only helper function to dump the JSON representation to std out. + // This can aid in debugging channelz code. + static void LogAllEntities() { Default()->InternalLogAllEntities(); } + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + friend class testing::ChannelzRegistryPeer; + + ChannelzRegistry(); + ~ChannelzRegistry(); + + // Returned the singleton instance of ChannelzRegistry; + static ChannelzRegistry* Default(); + + // globally registers an Entry. Returns its unique uuid + void InternalRegister(BaseNode* node); + + // globally unregisters the object that is associated to uuid. Also does + // sanity check that an object doesn't try to unregister the wrong type. + void InternalUnregister(intptr_t uuid); + + // if object with uuid has previously been registered as the correct type, + // returns the void* associated with that uuid. Else returns nullptr. + BaseNode* InternalGet(intptr_t uuid); + + char* InternalGetTopChannels(intptr_t start_channel_id); + char* InternalGetServers(intptr_t start_server_id); + + // If entities_ has over a certain threshold of empty slots, it will + // compact the vector and move all used slots to the front. + void MaybePerformCompactionLocked(); + + // Performs binary search on entities_ to find the index with that uuid. + // If direct_hit_needed, then will return -1 in case of absence. + // Else, will return idx of the first uuid higher than the target. + int FindByUuidLocked(intptr_t uuid, bool direct_hit_needed); + + void InternalLogAllEntities(); + + // protects members + gpr_mu mu_; + InlinedVector entities_; + intptr_t uuid_generator_ = 0; + int num_empty_slots_ = 0; +}; + +} // namespace channelz +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/connected_channel.cc b/Sources/CgRPC/src/core/lib/channel/connected_channel.cc index ddd302940..e2ea334de 100644 --- a/Sources/CgRPC/src/core/lib/channel/connected_channel.cc +++ b/Sources/CgRPC/src/core/lib/channel/connected_channel.cc @@ -51,6 +51,7 @@ typedef struct connected_channel_call_data { callback_state on_complete[6]; // Max number of pending batches. callback_state recv_initial_metadata_ready; callback_state recv_message_ready; + callback_state recv_trailing_metadata_ready; } call_data; static void run_in_call_combiner(void* arg, grpc_error* error) { @@ -111,6 +112,12 @@ static void con_start_transport_stream_op_batch( intercept_callback(calld, state, false, "recv_message_ready", &batch->payload->recv_message.recv_message_ready); } + if (batch->recv_trailing_metadata) { + callback_state* state = &calld->recv_trailing_metadata_ready; + intercept_callback( + calld, state, false, "recv_trailing_metadata_ready", + &batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready); + } if (batch->cancel_stream) { // There can be more than one cancellation batch in flight at any // given time, so we can't just pick out a fixed index into @@ -121,7 +128,7 @@ static void con_start_transport_stream_op_batch( static_cast(gpr_malloc(sizeof(*state))); intercept_callback(calld, state, true, "on_complete (cancel_stream)", &batch->on_complete); - } else { + } else if (batch->on_complete != nullptr) { callback_state* state = get_state_for_batch(calld, batch); intercept_callback(calld, state, false, "on_complete", &batch->on_complete); } diff --git a/Sources/CgRPC/src/core/lib/channel/context.h b/Sources/CgRPC/src/core/lib/channel/context.h index 5daf48a9a..763e4ffc9 100644 --- a/Sources/CgRPC/src/core/lib/channel/context.h +++ b/Sources/CgRPC/src/core/lib/channel/context.h @@ -41,9 +41,9 @@ typedef enum { GRPC_CONTEXT_COUNT } grpc_context_index; -typedef struct { - void* value; - void (*destroy)(void*); -} grpc_call_context_element; +struct grpc_call_context_element { + void* value = nullptr; + void (*destroy)(void*) = nullptr; +}; #endif /* GRPC_CORE_LIB_CHANNEL_CONTEXT_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/handshaker.cc b/Sources/CgRPC/src/core/lib/channel/handshaker.cc index 2faeb64cb..6bb05cee2 100644 --- a/Sources/CgRPC/src/core/lib/channel/handshaker.cc +++ b/Sources/CgRPC/src/core/lib/channel/handshaker.cc @@ -28,279 +28,231 @@ #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/slice/slice_internal.h" -grpc_core::TraceFlag grpc_handshaker_trace(false, "handshaker"); +namespace grpc_core { -// -// grpc_handshaker -// +TraceFlag grpc_handshaker_trace(false, "handshaker"); -void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, - grpc_handshaker* handshaker) { - handshaker->vtable = vtable; -} - -void grpc_handshaker_destroy(grpc_handshaker* handshaker) { - handshaker->vtable->destroy(handshaker); -} - -void grpc_handshaker_shutdown(grpc_handshaker* handshaker, grpc_error* why) { - handshaker->vtable->shutdown(handshaker, why); -} - -void grpc_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args) { - handshaker->vtable->do_handshake(handshaker, acceptor, on_handshake_done, - args); -} +namespace { -const char* grpc_handshaker_name(grpc_handshaker* handshaker) { - return handshaker->vtable->name; +char* HandshakerArgsString(HandshakerArgs* args) { + char* args_str = grpc_channel_args_string(args->args); + size_t num_args = args->args != nullptr ? args->args->num_args : 0; + size_t read_buffer_length = + args->read_buffer != nullptr ? args->read_buffer->length : 0; + char* str; + gpr_asprintf(&str, + "{endpoint=%p, args=%p {size=%" PRIuPTR + ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}", + args->endpoint, args->args, num_args, args_str, + args->read_buffer, read_buffer_length, args->exit_early); + gpr_free(args_str); + return str; } -// -// grpc_handshake_manager -// - -struct grpc_handshake_manager { - gpr_mu mu; - gpr_refcount refs; - bool shutdown; - // An array of handshakers added via grpc_handshake_manager_add(). - size_t count; - grpc_handshaker** handshakers; - // The index of the handshaker to invoke next and closure to invoke it. - size_t index; - grpc_closure call_next_handshaker; - // The acceptor to call the handshakers with. - grpc_tcp_server_acceptor* acceptor; - // Deadline timer across all handshakers. - grpc_timer deadline_timer; - grpc_closure on_timeout; - // The final callback and user_data to invoke after the last handshaker. - grpc_closure on_handshake_done; - void* user_data; - // Handshaker args. - grpc_handshaker_args args; - // Links to the previous and next managers in a list of all pending handshakes - // Used at server side only. - grpc_handshake_manager* prev; - grpc_handshake_manager* next; -}; +} // namespace -grpc_handshake_manager* grpc_handshake_manager_create() { - grpc_handshake_manager* mgr = static_cast( - gpr_zalloc(sizeof(grpc_handshake_manager))); - gpr_mu_init(&mgr->mu); - gpr_ref_init(&mgr->refs, 1); - return mgr; -} +HandshakeManager::HandshakeManager() { gpr_mu_init(&mu_); } -void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head, - grpc_handshake_manager* mgr) { - GPR_ASSERT(mgr->prev == nullptr); - GPR_ASSERT(mgr->next == nullptr); - mgr->next = *head; +/// Add \a mgr to the server side list of all pending handshake managers, the +/// list starts with \a *head. +// Not thread-safe. Caller needs to synchronize. +void HandshakeManager::AddToPendingMgrList(HandshakeManager** head) { + GPR_ASSERT(prev_ == nullptr); + GPR_ASSERT(next_ == nullptr); + next_ = *head; if (*head) { - (*head)->prev = mgr; + (*head)->prev_ = this; } - *head = mgr; + *head = this; } -void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head, - grpc_handshake_manager* mgr) { - if (mgr->next != nullptr) { - mgr->next->prev = mgr->prev; +/// Remove \a mgr from the server side list of all pending handshake managers. +// Not thread-safe. Caller needs to synchronize. +void HandshakeManager::RemoveFromPendingMgrList(HandshakeManager** head) { + if (next_ != nullptr) { + next_->prev_ = prev_; } - if (mgr->prev != nullptr) { - mgr->prev->next = mgr->next; + if (prev_ != nullptr) { + prev_->next_ = next_; } else { - GPR_ASSERT(*head == mgr); - *head = mgr->next; + GPR_ASSERT(*head == this); + *head = next_; } } -void grpc_handshake_manager_pending_list_shutdown_all( - grpc_handshake_manager* head, grpc_error* why) { +/// Shutdown all pending handshake managers starting at head on the server +/// side. Not thread-safe. Caller needs to synchronize. +void HandshakeManager::ShutdownAllPending(grpc_error* why) { + auto* head = this; while (head != nullptr) { - grpc_handshake_manager_shutdown(head, GRPC_ERROR_REF(why)); - head = head->next; + head->Shutdown(GRPC_ERROR_REF(why)); + head = head->next_; } GRPC_ERROR_UNREF(why); } -static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; } - -void grpc_handshake_manager_add(grpc_handshake_manager* mgr, - grpc_handshaker* handshaker) { +void HandshakeManager::Add(RefCountedPtr handshaker) { if (grpc_handshaker_trace.enabled()) { gpr_log( GPR_INFO, "handshake_manager %p: adding handshaker %s [%p] at index %" PRIuPTR, - mgr, grpc_handshaker_name(handshaker), handshaker, mgr->count); + this, handshaker->name(), handshaker.get(), handshakers_.size()); } - gpr_mu_lock(&mgr->mu); - // To avoid allocating memory for each handshaker we add, we double - // the number of elements every time we need more. - size_t realloc_count = 0; - if (mgr->count == 0) { - realloc_count = 2; - } else if (mgr->count >= 2 && is_power_of_2(mgr->count)) { - realloc_count = mgr->count * 2; - } - if (realloc_count > 0) { - mgr->handshakers = static_cast(gpr_realloc( - mgr->handshakers, realloc_count * sizeof(grpc_handshaker*))); - } - mgr->handshakers[mgr->count++] = handshaker; - gpr_mu_unlock(&mgr->mu); + MutexLock lock(&mu_); + handshakers_.push_back(std::move(handshaker)); } -static void grpc_handshake_manager_unref(grpc_handshake_manager* mgr) { - if (gpr_unref(&mgr->refs)) { - for (size_t i = 0; i < mgr->count; ++i) { - grpc_handshaker_destroy(mgr->handshakers[i]); - } - gpr_free(mgr->handshakers); - gpr_mu_destroy(&mgr->mu); - gpr_free(mgr); - } -} - -void grpc_handshake_manager_destroy(grpc_handshake_manager* mgr) { - grpc_handshake_manager_unref(mgr); +HandshakeManager::~HandshakeManager() { + handshakers_.clear(); + gpr_mu_destroy(&mu_); } -void grpc_handshake_manager_shutdown(grpc_handshake_manager* mgr, - grpc_error* why) { - gpr_mu_lock(&mgr->mu); - // Shutdown the handshaker that's currently in progress, if any. - if (!mgr->shutdown && mgr->index > 0) { - mgr->shutdown = true; - grpc_handshaker_shutdown(mgr->handshakers[mgr->index - 1], - GRPC_ERROR_REF(why)); +void HandshakeManager::Shutdown(grpc_error* why) { + { + MutexLock lock(&mu_); + // Shutdown the handshaker that's currently in progress, if any. + if (!is_shutdown_ && index_ > 0) { + is_shutdown_ = true; + handshakers_[index_ - 1]->Shutdown(GRPC_ERROR_REF(why)); + } } - gpr_mu_unlock(&mgr->mu); GRPC_ERROR_UNREF(why); } -static char* handshaker_args_string(grpc_handshaker_args* args) { - char* args_str = grpc_channel_args_string(args->args); - size_t num_args = args->args != nullptr ? args->args->num_args : 0; - size_t read_buffer_length = - args->read_buffer != nullptr ? args->read_buffer->length : 0; - char* str; - gpr_asprintf(&str, - "{endpoint=%p, args=%p {size=%" PRIuPTR - ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}", - args->endpoint, args->args, num_args, args_str, - args->read_buffer, read_buffer_length, args->exit_early); - gpr_free(args_str); - return str; -} - // Helper function to call either the next handshaker or the // on_handshake_done callback. // Returns true if we've scheduled the on_handshake_done callback. -static bool call_next_handshaker_locked(grpc_handshake_manager* mgr, - grpc_error* error) { +bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) { if (grpc_handshaker_trace.enabled()) { - char* args_str = handshaker_args_string(&mgr->args); + char* args_str = HandshakerArgsString(&args_); gpr_log(GPR_INFO, "handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR ", args=%s", - mgr, grpc_error_string(error), mgr->shutdown, mgr->index, args_str); + this, grpc_error_string(error), is_shutdown_, index_, args_str); gpr_free(args_str); } - GPR_ASSERT(mgr->index <= mgr->count); + GPR_ASSERT(index_ <= handshakers_.size()); // If we got an error or we've been shut down or we're exiting early or // we've finished the last handshaker, invoke the on_handshake_done // callback. Otherwise, call the next handshaker. - if (error != GRPC_ERROR_NONE || mgr->shutdown || mgr->args.exit_early || - mgr->index == mgr->count) { + if (error != GRPC_ERROR_NONE || is_shutdown_ || args_.exit_early || + index_ == handshakers_.size()) { + if (error == GRPC_ERROR_NONE && is_shutdown_) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("handshaker shutdown"); + // It is possible that the endpoint has already been destroyed by + // a shutdown call while this callback was sitting on the ExecCtx + // with no error. + if (args_.endpoint != nullptr) { + // TODO(roth): It is currently necessary to shutdown endpoints + // before destroying then, even when we know that there are no + // pending read/write callbacks. This should be fixed, at which + // point this can be removed. + grpc_endpoint_shutdown(args_.endpoint, GRPC_ERROR_REF(error)); + grpc_endpoint_destroy(args_.endpoint); + args_.endpoint = nullptr; + grpc_channel_args_destroy(args_.args); + args_.args = nullptr; + grpc_slice_buffer_destroy_internal(args_.read_buffer); + gpr_free(args_.read_buffer); + args_.read_buffer = nullptr; + } + } if (grpc_handshaker_trace.enabled()) { - gpr_log(GPR_INFO, "handshake_manager %p: handshaking complete", mgr); + gpr_log(GPR_INFO, + "handshake_manager %p: handshaking complete -- scheduling " + "on_handshake_done with error=%s", + this, grpc_error_string(error)); } // Cancel deadline timer, since we're invoking the on_handshake_done // callback now. - grpc_timer_cancel(&mgr->deadline_timer); - GRPC_CLOSURE_SCHED(&mgr->on_handshake_done, error); - mgr->shutdown = true; + grpc_timer_cancel(&deadline_timer_); + GRPC_CLOSURE_SCHED(&on_handshake_done_, error); + is_shutdown_ = true; } else { + auto handshaker = handshakers_[index_]; if (grpc_handshaker_trace.enabled()) { gpr_log( GPR_INFO, "handshake_manager %p: calling handshaker %s [%p] at index %" PRIuPTR, - mgr, grpc_handshaker_name(mgr->handshakers[mgr->index]), - mgr->handshakers[mgr->index], mgr->index); + this, handshaker->name(), handshaker.get(), index_); } - grpc_handshaker_do_handshake(mgr->handshakers[mgr->index], mgr->acceptor, - &mgr->call_next_handshaker, &mgr->args); + handshaker->DoHandshake(acceptor_, &call_next_handshaker_, &args_); } - ++mgr->index; - return mgr->shutdown; + ++index_; + return is_shutdown_; } -// A function used as the handshaker-done callback when chaining -// handshakers together. -static void call_next_handshaker(void* arg, grpc_error* error) { - grpc_handshake_manager* mgr = static_cast(arg); - gpr_mu_lock(&mgr->mu); - bool done = call_next_handshaker_locked(mgr, GRPC_ERROR_REF(error)); - gpr_mu_unlock(&mgr->mu); +void HandshakeManager::CallNextHandshakerFn(void* arg, grpc_error* error) { + auto* mgr = static_cast(arg); + bool done; + { + MutexLock lock(&mgr->mu_); + done = mgr->CallNextHandshakerLocked(GRPC_ERROR_REF(error)); + } // If we're invoked the final callback, we won't be coming back // to this function, so we can release our reference to the // handshake manager. if (done) { - grpc_handshake_manager_unref(mgr); + mgr->Unref(); } } -// Callback invoked when deadline is exceeded. -static void on_timeout(void* arg, grpc_error* error) { - grpc_handshake_manager* mgr = static_cast(arg); - if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled. - grpc_handshake_manager_shutdown( - mgr, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake timed out")); +void HandshakeManager::OnTimeoutFn(void* arg, grpc_error* error) { + auto* mgr = static_cast(arg); + if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled + mgr->Shutdown(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake timed out")); } - grpc_handshake_manager_unref(mgr); + mgr->Unref(); } -void grpc_handshake_manager_do_handshake( - grpc_handshake_manager* mgr, grpc_pollset_set* interested_parties, - grpc_endpoint* endpoint, const grpc_channel_args* channel_args, - grpc_millis deadline, grpc_tcp_server_acceptor* acceptor, - grpc_iomgr_cb_func on_handshake_done, void* user_data) { - gpr_mu_lock(&mgr->mu); - GPR_ASSERT(mgr->index == 0); - GPR_ASSERT(!mgr->shutdown); - // Construct handshaker args. These will be passed through all - // handshakers and eventually be freed by the on_handshake_done callback. - mgr->args.interested_parties = interested_parties; - mgr->args.endpoint = endpoint; - mgr->args.args = grpc_channel_args_copy(channel_args); - mgr->args.user_data = user_data; - mgr->args.read_buffer = static_cast( - gpr_malloc(sizeof(*mgr->args.read_buffer))); - grpc_slice_buffer_init(mgr->args.read_buffer); - // Initialize state needed for calling handshakers. - mgr->acceptor = acceptor; - GRPC_CLOSURE_INIT(&mgr->call_next_handshaker, call_next_handshaker, mgr, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&mgr->on_handshake_done, on_handshake_done, &mgr->args, - grpc_schedule_on_exec_ctx); - // Start deadline timer, which owns a ref. - gpr_ref(&mgr->refs); - GRPC_CLOSURE_INIT(&mgr->on_timeout, on_timeout, mgr, - grpc_schedule_on_exec_ctx); - grpc_timer_init(&mgr->deadline_timer, deadline, &mgr->on_timeout); - // Start first handshaker, which also owns a ref. - gpr_ref(&mgr->refs); - bool done = call_next_handshaker_locked(mgr, GRPC_ERROR_NONE); - gpr_mu_unlock(&mgr->mu); +void HandshakeManager::DoHandshake(grpc_endpoint* endpoint, + const grpc_channel_args* channel_args, + grpc_millis deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_iomgr_cb_func on_handshake_done, + void* user_data) { + bool done; + { + MutexLock lock(&mu_); + GPR_ASSERT(index_ == 0); + GPR_ASSERT(!is_shutdown_); + // Construct handshaker args. These will be passed through all + // handshakers and eventually be freed by the on_handshake_done callback. + args_.endpoint = endpoint; + args_.args = grpc_channel_args_copy(channel_args); + args_.user_data = user_data; + args_.read_buffer = + static_cast(gpr_malloc(sizeof(*args_.read_buffer))); + grpc_slice_buffer_init(args_.read_buffer); + // Initialize state needed for calling handshakers. + acceptor_ = acceptor; + GRPC_CLOSURE_INIT(&call_next_handshaker_, + &HandshakeManager::CallNextHandshakerFn, this, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_handshake_done_, on_handshake_done, &args_, + grpc_schedule_on_exec_ctx); + // Start deadline timer, which owns a ref. + Ref().release(); + GRPC_CLOSURE_INIT(&on_timeout_, &HandshakeManager::OnTimeoutFn, this, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&deadline_timer_, deadline, &on_timeout_); + // Start first handshaker, which also owns a ref. + Ref().release(); + done = CallNextHandshakerLocked(GRPC_ERROR_NONE); + } if (done) { - grpc_handshake_manager_unref(mgr); + Unref(); } } + +} // namespace grpc_core + +void grpc_handshake_manager_add(grpc_handshake_manager* mgr, + grpc_handshaker* handshaker) { + // This is a transition method to aid the API change for handshakers. + using namespace grpc_core; + RefCountedPtr refd_hs(static_cast(handshaker)); + mgr->Add(refd_hs); +} diff --git a/Sources/CgRPC/src/core/lib/channel/handshaker.h b/Sources/CgRPC/src/core/lib/channel/handshaker.h index be7fd127e..912d524c8 100644 --- a/Sources/CgRPC/src/core/lib/channel/handshaker.h +++ b/Sources/CgRPC/src/core/lib/channel/handshaker.h @@ -21,12 +21,21 @@ #include +#include + #include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/tcp_server.h" +#include "src/core/lib/iomgr/timer.h" + +namespace grpc_core { /// Handshakers are used to perform initial handshakes on a connection /// before the client sends the initial request. Some examples of what @@ -35,12 +44,6 @@ /// /// In general, handshakers should be used via a handshake manager. -/// -/// grpc_handshaker -/// - -typedef struct grpc_handshaker grpc_handshaker; - /// Arguments passed through handshakers and to the on_handshake_done callback. /// /// For handshakers, all members are input/output parameters; for @@ -55,116 +58,121 @@ typedef struct grpc_handshaker grpc_handshaker; /// /// For the on_handshake_done callback, all members are input arguments, /// which the callback takes ownership of. -typedef struct { - grpc_pollset_set* interested_parties; - grpc_endpoint* endpoint; - grpc_channel_args* args; - grpc_slice_buffer* read_buffer; +struct HandshakerArgs { + grpc_endpoint* endpoint = nullptr; + grpc_channel_args* args = nullptr; + grpc_slice_buffer* read_buffer = nullptr; // A handshaker may set this to true before invoking on_handshake_done // to indicate that subsequent handshakers should be skipped. - bool exit_early; + bool exit_early = false; // User data passed through the handshake manager. Not used by // individual handshakers. - void* user_data; -} grpc_handshaker_args; + void* user_data = nullptr; +}; -typedef struct { - /// Destroys the handshaker. - void (*destroy)(grpc_handshaker* handshaker); +/// +/// Handshaker +/// - /// Shuts down the handshaker (e.g., to clean up when the operation is - /// aborted in the middle). - void (*shutdown)(grpc_handshaker* handshaker, grpc_error* why); - - /// Performs handshaking, modifying \a args as needed (e.g., to - /// replace \a endpoint with a wrapped endpoint). - /// When finished, invokes \a on_handshake_done. - /// \a acceptor will be NULL for client-side handshakers. - void (*do_handshake)(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args); - - /// The name of the handshaker, for debugging purposes. - const char* name; -} grpc_handshaker_vtable; - -/// Base struct. To subclass, make this the first member of the -/// implementation struct. -struct grpc_handshaker { - const grpc_handshaker_vtable* vtable; +class Handshaker : public RefCounted { + public: + virtual ~Handshaker() = default; + virtual void Shutdown(grpc_error* why) GRPC_ABSTRACT; + virtual void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) GRPC_ABSTRACT; + virtual const char* name() const GRPC_ABSTRACT; + GRPC_ABSTRACT_BASE_CLASS }; -/// Called by concrete implementations to initialize the base struct. -void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, - grpc_handshaker* handshaker); +// +// HandshakeManager +// -void grpc_handshaker_destroy(grpc_handshaker* handshaker); -void grpc_handshaker_shutdown(grpc_handshaker* handshaker, grpc_error* why); -void grpc_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args); -const char* grpc_handshaker_name(grpc_handshaker* handshaker); +class HandshakeManager : public RefCounted { + public: + HandshakeManager(); + ~HandshakeManager(); -/// -/// grpc_handshake_manager -/// + /// Add \a mgr to the server side list of all pending handshake managers, the + /// list starts with \a *head. + // Not thread-safe. Caller needs to synchronize. + void AddToPendingMgrList(HandshakeManager** head); + + /// Remove \a mgr from the server side list of all pending handshake managers. + // Not thread-safe. Caller needs to synchronize. + void RemoveFromPendingMgrList(HandshakeManager** head); -typedef struct grpc_handshake_manager grpc_handshake_manager; + /// Shutdown all pending handshake managers starting at head on the server + /// side. Not thread-safe. Caller needs to synchronize. + void ShutdownAllPending(grpc_error* why); -/// Creates a new handshake manager. Caller takes ownership. -grpc_handshake_manager* grpc_handshake_manager_create(); + /// Adds a handshaker to the handshake manager. + /// Takes ownership of \a handshaker. + void Add(RefCountedPtr handshaker); -/// Adds a handshaker to the handshake manager. -/// Takes ownership of \a handshaker. + /// Shuts down the handshake manager (e.g., to clean up when the operation is + /// aborted in the middle). + void Shutdown(grpc_error* why); + + /// Invokes handshakers in the order they were added. + /// Takes ownership of \a endpoint, and then passes that ownership to + /// the \a on_handshake_done callback. + /// Does NOT take ownership of \a channel_args. Instead, makes a copy before + /// invoking the first handshaker. + /// \a acceptor will be nullptr for client-side handshakers. + /// + /// When done, invokes \a on_handshake_done with a HandshakerArgs + /// object as its argument. If the callback is invoked with error != + /// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done + /// the necessary clean-up. Otherwise, the callback takes ownership of + /// the arguments. + void DoHandshake(grpc_endpoint* endpoint, + const grpc_channel_args* channel_args, grpc_millis deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_iomgr_cb_func on_handshake_done, void* user_data); + + private: + bool CallNextHandshakerLocked(grpc_error* error); + + // A function used as the handshaker-done callback when chaining + // handshakers together. + static void CallNextHandshakerFn(void* arg, grpc_error* error); + + // Callback invoked when deadline is exceeded. + static void OnTimeoutFn(void* arg, grpc_error* error); + + static const size_t HANDSHAKERS_INIT_SIZE = 2; + + gpr_mu mu_; + bool is_shutdown_ = false; + // An array of handshakers added via grpc_handshake_manager_add(). + InlinedVector, HANDSHAKERS_INIT_SIZE> handshakers_; + // The index of the handshaker to invoke next and closure to invoke it. + size_t index_ = 0; + grpc_closure call_next_handshaker_; + // The acceptor to call the handshakers with. + grpc_tcp_server_acceptor* acceptor_; + // Deadline timer across all handshakers. + grpc_timer deadline_timer_; + grpc_closure on_timeout_; + // The final callback and user_data to invoke after the last handshaker. + grpc_closure on_handshake_done_; + // Handshaker args. + HandshakerArgs args_; + // Links to the previous and next managers in a list of all pending handshakes + // Used at server side only. + HandshakeManager* prev_ = nullptr; + HandshakeManager* next_ = nullptr; +}; + +} // namespace grpc_core + +// TODO(arjunroy): These are transitional to account for the new handshaker API +// and will eventually be removed entirely. +typedef grpc_core::HandshakeManager grpc_handshake_manager; +typedef grpc_core::Handshaker grpc_handshaker; void grpc_handshake_manager_add(grpc_handshake_manager* mgr, grpc_handshaker* handshaker); -/// Destroys the handshake manager. -void grpc_handshake_manager_destroy(grpc_handshake_manager* mgr); - -/// Shuts down the handshake manager (e.g., to clean up when the operation is -/// aborted in the middle). -/// The caller must still call grpc_handshake_manager_destroy() after -/// calling this function. -void grpc_handshake_manager_shutdown(grpc_handshake_manager* mgr, - grpc_error* why); - -/// Invokes handshakers in the order they were added. -/// \a interested_parties may be non-nullptr to provide a pollset_set that -/// may be used during handshaking. Ownership is not taken. -/// Takes ownership of \a endpoint, and then passes that ownership to -/// the \a on_handshake_done callback. -/// Does NOT take ownership of \a channel_args. Instead, makes a copy before -/// invoking the first handshaker. -/// \a acceptor will be nullptr for client-side handshakers. -/// -/// When done, invokes \a on_handshake_done with a grpc_handshaker_args -/// object as its argument. If the callback is invoked with error != -/// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done -/// the necessary clean-up. Otherwise, the callback takes ownership of -/// the arguments. -void grpc_handshake_manager_do_handshake( - grpc_handshake_manager* mgr, grpc_pollset_set* interested_parties, - grpc_endpoint* endpoint, const grpc_channel_args* channel_args, - grpc_millis deadline, grpc_tcp_server_acceptor* acceptor, - grpc_iomgr_cb_func on_handshake_done, void* user_data); - -/// Add \a mgr to the server side list of all pending handshake managers, the -/// list starts with \a *head. -// Not thread-safe. Caller needs to synchronize. -void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head, - grpc_handshake_manager* mgr); - -/// Remove \a mgr from the server side list of all pending handshake managers. -// Not thread-safe. Caller needs to synchronize. -void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head, - grpc_handshake_manager* mgr); - -/// Shutdown all pending handshake managers on the server side. -// Not thread-safe. Caller needs to synchronize. -void grpc_handshake_manager_pending_list_shutdown_all( - grpc_handshake_manager* head, grpc_error* why); - #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/handshaker_factory.cc b/Sources/CgRPC/src/core/lib/channel/handshaker_factory.cc deleted file mode 100644 index 4fd43635b..000000000 --- a/Sources/CgRPC/src/core/lib/channel/handshaker_factory.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/channel/handshaker_factory.h" - -#include - -void grpc_handshaker_factory_add_handshakers( - grpc_handshaker_factory* handshaker_factory, const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr) { - if (handshaker_factory != nullptr) { - GPR_ASSERT(handshaker_factory->vtable != nullptr); - handshaker_factory->vtable->add_handshakers(handshaker_factory, args, - handshake_mgr); - } -} - -void grpc_handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory) { - if (handshaker_factory != nullptr) { - GPR_ASSERT(handshaker_factory->vtable != nullptr); - handshaker_factory->vtable->destroy(handshaker_factory); - } -} diff --git a/Sources/CgRPC/src/core/lib/channel/handshaker_factory.h b/Sources/CgRPC/src/core/lib/channel/handshaker_factory.h index 3e45fcf20..3972af1f4 100644 --- a/Sources/CgRPC/src/core/lib/channel/handshaker_factory.h +++ b/Sources/CgRPC/src/core/lib/channel/handshaker_factory.h @@ -27,24 +27,18 @@ // A handshaker factory is used to create handshakers. -typedef struct grpc_handshaker_factory grpc_handshaker_factory; +namespace grpc_core { -typedef struct { - void (*add_handshakers)(grpc_handshaker_factory* handshaker_factory, - const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr); - void (*destroy)(grpc_handshaker_factory* handshaker_factory); -} grpc_handshaker_factory_vtable; +class HandshakerFactory { + public: + virtual void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) GRPC_ABSTRACT; + virtual ~HandshakerFactory() = default; -struct grpc_handshaker_factory { - const grpc_handshaker_factory_vtable* vtable; + GRPC_ABSTRACT_BASE_CLASS }; -void grpc_handshaker_factory_add_handshakers( - grpc_handshaker_factory* handshaker_factory, const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr); - -void grpc_handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory); +} // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H */ diff --git a/Sources/CgRPC/src/core/lib/channel/handshaker_registry.cc b/Sources/CgRPC/src/core/lib/channel/handshaker_registry.cc index eec3e1b35..b65129a6e 100644 --- a/Sources/CgRPC/src/core/lib/channel/handshaker_registry.cc +++ b/Sources/CgRPC/src/core/lib/channel/handshaker_registry.cc @@ -19,8 +19,11 @@ #include #include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/memory.h" #include +#include #include @@ -28,70 +31,83 @@ // grpc_handshaker_factory_list // -typedef struct { - grpc_handshaker_factory** list; - size_t num_factories; -} grpc_handshaker_factory_list; - -static void grpc_handshaker_factory_list_register( - grpc_handshaker_factory_list* list, bool at_start, - grpc_handshaker_factory* factory) { - list->list = static_cast(gpr_realloc( - list->list, - (list->num_factories + 1) * sizeof(grpc_handshaker_factory*))); - if (at_start) { - memmove(list->list + 1, list->list, - sizeof(grpc_handshaker_factory*) * list->num_factories); - list->list[0] = factory; - } else { - list->list[list->num_factories] = factory; - } - ++list->num_factories; -} +namespace grpc_core { + +namespace { + +class HandshakerFactoryList { + public: + void Register(bool at_start, UniquePtr factory); + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr); + + private: + InlinedVector, 2> factories_; +}; -static void grpc_handshaker_factory_list_add_handshakers( - grpc_handshaker_factory_list* list, const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr) { - for (size_t i = 0; i < list->num_factories; ++i) { - grpc_handshaker_factory_add_handshakers(list->list[i], args, handshake_mgr); +HandshakerFactoryList* g_handshaker_factory_lists = nullptr; + +} // namespace + +void HandshakerFactoryList::Register(bool at_start, + UniquePtr factory) { + factories_.push_back(std::move(factory)); + if (at_start) { + auto* end = &factories_[factories_.size() - 1]; + std::rotate(&factories_[0], end, end + 1); } } -static void grpc_handshaker_factory_list_destroy( - grpc_handshaker_factory_list* list) { - for (size_t i = 0; i < list->num_factories; ++i) { - grpc_handshaker_factory_destroy(list->list[i]); +void HandshakerFactoryList::AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) { + for (size_t idx = 0; idx < factories_.size(); ++idx) { + auto& handshaker_factory = factories_[idx]; + handshaker_factory->AddHandshakers(args, interested_parties, handshake_mgr); } - gpr_free(list->list); } // // plugin // -static grpc_handshaker_factory_list - g_handshaker_factory_lists[NUM_HANDSHAKER_TYPES]; - -void grpc_handshaker_factory_registry_init() { - memset(g_handshaker_factory_lists, 0, sizeof(g_handshaker_factory_lists)); +void HandshakerRegistry::Init() { + GPR_ASSERT(g_handshaker_factory_lists == nullptr); + g_handshaker_factory_lists = static_cast( + gpr_malloc(sizeof(*g_handshaker_factory_lists) * NUM_HANDSHAKER_TYPES)); + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + for (auto idx = 0; idx < NUM_HANDSHAKER_TYPES; ++idx) { + auto factory_list = g_handshaker_factory_lists + idx; + new (factory_list) HandshakerFactoryList(); + } } -void grpc_handshaker_factory_registry_shutdown() { - for (size_t i = 0; i < NUM_HANDSHAKER_TYPES; ++i) { - grpc_handshaker_factory_list_destroy(&g_handshaker_factory_lists[i]); +void HandshakerRegistry::Shutdown() { + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + for (auto idx = 0; idx < NUM_HANDSHAKER_TYPES; ++idx) { + auto factory_list = g_handshaker_factory_lists + idx; + factory_list->~HandshakerFactoryList(); } + gpr_free(g_handshaker_factory_lists); + g_handshaker_factory_lists = nullptr; } -void grpc_handshaker_factory_register(bool at_start, - grpc_handshaker_type handshaker_type, - grpc_handshaker_factory* factory) { - grpc_handshaker_factory_list_register( - &g_handshaker_factory_lists[handshaker_type], at_start, factory); +void HandshakerRegistry::RegisterHandshakerFactory( + bool at_start, HandshakerType handshaker_type, + UniquePtr factory) { + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + auto& factory_list = g_handshaker_factory_lists[handshaker_type]; + factory_list.Register(at_start, std::move(factory)); } -void grpc_handshakers_add(grpc_handshaker_type handshaker_type, - const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr) { - grpc_handshaker_factory_list_add_handshakers( - &g_handshaker_factory_lists[handshaker_type], args, handshake_mgr); +void HandshakerRegistry::AddHandshakers(HandshakerType handshaker_type, + const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) { + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + auto& factory_list = g_handshaker_factory_lists[handshaker_type]; + factory_list.AddHandshakers(args, interested_parties, handshake_mgr); } + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/channel/handshaker_registry.h b/Sources/CgRPC/src/core/lib/channel/handshaker_registry.h index 82ad9c5b9..1b93a8dd4 100644 --- a/Sources/CgRPC/src/core/lib/channel/handshaker_registry.h +++ b/Sources/CgRPC/src/core/lib/channel/handshaker_registry.h @@ -25,24 +25,30 @@ #include "src/core/lib/channel/handshaker_factory.h" +namespace grpc_core { + typedef enum { HANDSHAKER_CLIENT = 0, HANDSHAKER_SERVER, NUM_HANDSHAKER_TYPES, // Must be last. -} grpc_handshaker_type; - -void grpc_handshaker_factory_registry_init(); -void grpc_handshaker_factory_registry_shutdown(); - -/// Registers a new handshaker factory. Takes ownership. -/// If \a at_start is true, the new handshaker will be at the beginning of -/// the list. Otherwise, it will be added to the end. -void grpc_handshaker_factory_register(bool at_start, - grpc_handshaker_type handshaker_type, - grpc_handshaker_factory* factory); - -void grpc_handshakers_add(grpc_handshaker_type handshaker_type, - const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr); +} HandshakerType; + +class HandshakerRegistry { + public: + /// Registers a new handshaker factory. Takes ownership. + /// If \a at_start is true, the new handshaker will be at the beginning of + /// the list. Otherwise, it will be added to the end. + static void RegisterHandshakerFactory(bool at_start, + HandshakerType handshaker_type, + UniquePtr factory); + static void AddHandshakers(HandshakerType handshaker_type, + const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr); + static void Init(); + static void Shutdown(); +}; + +} // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H */ diff --git a/Sources/CgRPC/src/core/lib/debug/stats.h b/Sources/CgRPC/src/core/lib/debug/stats.h index 749665262..9e88ad700 100644 --- a/Sources/CgRPC/src/core/lib/debug/stats.h +++ b/Sources/CgRPC/src/core/lib/debug/stats.h @@ -35,6 +35,9 @@ extern grpc_stats_data* grpc_stats_per_cpu_storage; #define GRPC_THREAD_STATS_DATA() \ (&grpc_stats_per_cpu_storage[grpc_core::ExecCtx::Get()->starting_cpu()]) +/* Only collect stats if GRPC_COLLECT_STATS is defined or it is a debug build. + */ +#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) #define GRPC_STATS_INC_COUNTER(ctr) \ (gpr_atm_no_barrier_fetch_add(&GRPC_THREAD_STATS_DATA()->counters[(ctr)], 1)) @@ -42,6 +45,10 @@ extern grpc_stats_data* grpc_stats_per_cpu_storage; (gpr_atm_no_barrier_fetch_add( \ &GRPC_THREAD_STATS_DATA()->histograms[histogram##_FIRST_SLOT + (index)], \ 1)) +#else /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */ +#define GRPC_STATS_INC_COUNTER(ctr) +#define GRPC_STATS_INC_HISTOGRAM(histogram, index) +#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */ void grpc_stats_init(void); void grpc_stats_shutdown(void); diff --git a/Sources/CgRPC/src/core/lib/debug/stats_data.cc b/Sources/CgRPC/src/core/lib/debug/stats_data.cc index 309ece94b..f8c27db0a 100644 --- a/Sources/CgRPC/src/core/lib/debug/stats_data.cc +++ b/Sources/CgRPC/src/core/lib/debug/stats_data.cc @@ -40,6 +40,8 @@ const char* grpc_stats_counter_name[GRPC_STATS_COUNTER_COUNT] = { "pollset_kick_wakeup_fd", "pollset_kick_wakeup_cv", "pollset_kick_own_thread", + "syscall_epoll_ctl", + "pollset_fd_cache_hits", "histogram_slow_lookups", "syscall_write", "syscall_read", @@ -144,6 +146,9 @@ const char* grpc_stats_counter_doc[GRPC_STATS_COUNTER_COUNT] = { "polling wakeup (only valid for epoll1 right now)", "How many times could a polling wakeup be satisfied by keeping the waking " "thread awake? (only valid for epoll1 right now)", + "Number of epoll_ctl calls made (only valid for epollex right now)", + "Number of epoll_ctl calls skipped because the fd was cached as already " + "being added. (only valid for epollex right now)", "Number of times histogram increments went through the slow (binary " "search) path", "Number of write syscalls (or equivalent - eg sendmsg) made by this " diff --git a/Sources/CgRPC/src/core/lib/debug/stats_data.h b/Sources/CgRPC/src/core/lib/debug/stats_data.h index da1266ad7..1f3861f49 100644 --- a/Sources/CgRPC/src/core/lib/debug/stats_data.h +++ b/Sources/CgRPC/src/core/lib/debug/stats_data.h @@ -41,6 +41,8 @@ typedef enum { GRPC_STATS_COUNTER_POLLSET_KICK_WAKEUP_FD, GRPC_STATS_COUNTER_POLLSET_KICK_WAKEUP_CV, GRPC_STATS_COUNTER_POLLSET_KICK_OWN_THREAD, + GRPC_STATS_COUNTER_SYSCALL_EPOLL_CTL, + GRPC_STATS_COUNTER_POLLSET_FD_CACHE_HITS, GRPC_STATS_COUNTER_HISTOGRAM_SLOW_LOOKUPS, GRPC_STATS_COUNTER_SYSCALL_WRITE, GRPC_STATS_COUNTER_SYSCALL_READ, @@ -174,6 +176,7 @@ typedef enum { GRPC_STATS_HISTOGRAM_SERVER_CQS_CHECKED_BUCKETS = 8, GRPC_STATS_HISTOGRAM_BUCKETS = 840 } grpc_stats_histogram_constants; +#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) #define GRPC_STATS_INC_CLIENT_CALLS_CREATED() \ GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED) #define GRPC_STATS_INC_SERVER_CALLS_CREATED() \ @@ -202,6 +205,10 @@ typedef enum { GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_POLLSET_KICK_WAKEUP_CV) #define GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD() \ GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_POLLSET_KICK_OWN_THREAD) +#define GRPC_STATS_INC_SYSCALL_EPOLL_CTL() \ + GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_SYSCALL_EPOLL_CTL) +#define GRPC_STATS_INC_POLLSET_FD_CACHE_HITS() \ + GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_POLLSET_FD_CACHE_HITS) #define GRPC_STATS_INC_HISTOGRAM_SLOW_LOOKUPS() \ GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_HISTOGRAM_SLOW_LOOKUPS) #define GRPC_STATS_INC_SYSCALL_WRITE() \ @@ -427,6 +434,119 @@ void grpc_stats_inc_http2_send_flowctl_per_write(int x); #define GRPC_STATS_INC_SERVER_CQS_CHECKED(value) \ grpc_stats_inc_server_cqs_checked((int)(value)) void grpc_stats_inc_server_cqs_checked(int x); +#else +#define GRPC_STATS_INC_CLIENT_CALLS_CREATED() +#define GRPC_STATS_INC_SERVER_CALLS_CREATED() +#define GRPC_STATS_INC_CQS_CREATED() +#define GRPC_STATS_INC_CLIENT_CHANNELS_CREATED() +#define GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED() +#define GRPC_STATS_INC_SERVER_CHANNELS_CREATED() +#define GRPC_STATS_INC_SYSCALL_POLL() +#define GRPC_STATS_INC_SYSCALL_WAIT() +#define GRPC_STATS_INC_POLLSET_KICK() +#define GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER() +#define GRPC_STATS_INC_POLLSET_KICKED_AGAIN() +#define GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD() +#define GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV() +#define GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD() +#define GRPC_STATS_INC_SYSCALL_EPOLL_CTL() +#define GRPC_STATS_INC_POLLSET_FD_CACHE_HITS() +#define GRPC_STATS_INC_HISTOGRAM_SLOW_LOOKUPS() +#define GRPC_STATS_INC_SYSCALL_WRITE() +#define GRPC_STATS_INC_SYSCALL_READ() +#define GRPC_STATS_INC_TCP_BACKUP_POLLERS_CREATED() +#define GRPC_STATS_INC_TCP_BACKUP_POLLER_POLLS() +#define GRPC_STATS_INC_HTTP2_OP_BATCHES() +#define GRPC_STATS_INC_HTTP2_OP_CANCEL() +#define GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA() +#define GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE() +#define GRPC_STATS_INC_HTTP2_OP_SEND_TRAILING_METADATA() +#define GRPC_STATS_INC_HTTP2_OP_RECV_INITIAL_METADATA() +#define GRPC_STATS_INC_HTTP2_OP_RECV_MESSAGE() +#define GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA() +#define GRPC_STATS_INC_HTTP2_SETTINGS_WRITES() +#define GRPC_STATS_INC_HTTP2_PINGS_SENT() +#define GRPC_STATS_INC_HTTP2_WRITES_BEGUN() +#define GRPC_STATS_INC_HTTP2_WRITES_OFFLOADED() +#define GRPC_STATS_INC_HTTP2_WRITES_CONTINUED() +#define GRPC_STATS_INC_HTTP2_PARTIAL_WRITES() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_INITIAL_WRITE() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_START_NEW_STREAM() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_MESSAGE() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_INITIAL_METADATA() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_TRAILING_METADATA() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RETRY_SEND_PING() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CONTINUE_PINGS() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_GOAWAY_SENT() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RST_STREAM() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CLOSE_FROM_API() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_STREAM_FLOW_CONTROL() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_SETTINGS() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_BDP_ESTIMATOR_PING() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_SETTING() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_UPDATE() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_APPLICATION_PING() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_KEEPALIVE_PING() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL_UNSTALLED() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_PING_RESPONSE() +#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FORCE_RST_STREAM() +#define GRPC_STATS_INC_HTTP2_SPURIOUS_WRITES_BEGUN() +#define GRPC_STATS_INC_HPACK_RECV_INDEXED() +#define GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX() +#define GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX_V() +#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX() +#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX_V() +#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX() +#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX_V() +#define GRPC_STATS_INC_HPACK_RECV_UNCOMPRESSED() +#define GRPC_STATS_INC_HPACK_RECV_HUFFMAN() +#define GRPC_STATS_INC_HPACK_RECV_BINARY() +#define GRPC_STATS_INC_HPACK_RECV_BINARY_BASE64() +#define GRPC_STATS_INC_HPACK_SEND_INDEXED() +#define GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX() +#define GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V() +#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX() +#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V() +#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NVRIDX() +#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NVRIDX_V() +#define GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED() +#define GRPC_STATS_INC_HPACK_SEND_HUFFMAN() +#define GRPC_STATS_INC_HPACK_SEND_BINARY() +#define GRPC_STATS_INC_HPACK_SEND_BINARY_BASE64() +#define GRPC_STATS_INC_COMBINER_LOCKS_INITIATED() +#define GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_ITEMS() +#define GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_FINAL_ITEMS() +#define GRPC_STATS_INC_COMBINER_LOCKS_OFFLOADED() +#define GRPC_STATS_INC_CALL_COMBINER_LOCKS_INITIATED() +#define GRPC_STATS_INC_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS() +#define GRPC_STATS_INC_CALL_COMBINER_SET_NOTIFY_ON_CANCEL() +#define GRPC_STATS_INC_CALL_COMBINER_CANCELLED() +#define GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS() +#define GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS() +#define GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF() +#define GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED() +#define GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED() +#define GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES() +#define GRPC_STATS_INC_SERVER_REQUESTED_CALLS() +#define GRPC_STATS_INC_SERVER_SLOWPATH_REQUESTS_QUEUED() +#define GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_FAILURES() +#define GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES() +#define GRPC_STATS_INC_CQ_EV_QUEUE_TRANSIENT_POP_FAILURES() +#define GRPC_STATS_INC_CALL_INITIAL_SIZE(value) +#define GRPC_STATS_INC_POLL_EVENTS_RETURNED(value) +#define GRPC_STATS_INC_TCP_WRITE_SIZE(value) +#define GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(value) +#define GRPC_STATS_INC_TCP_READ_SIZE(value) +#define GRPC_STATS_INC_TCP_READ_OFFER(value) +#define GRPC_STATS_INC_TCP_READ_OFFER_IOV_SIZE(value) +#define GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE(value) +#define GRPC_STATS_INC_HTTP2_SEND_INITIAL_METADATA_PER_WRITE(value) +#define GRPC_STATS_INC_HTTP2_SEND_MESSAGE_PER_WRITE(value) +#define GRPC_STATS_INC_HTTP2_SEND_TRAILING_METADATA_PER_WRITE(value) +#define GRPC_STATS_INC_HTTP2_SEND_FLOWCTL_PER_WRITE(value) +#define GRPC_STATS_INC_SERVER_CQS_CHECKED(value) +#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */ extern const int grpc_stats_histo_buckets[13]; extern const int grpc_stats_histo_start[13]; extern const int* const grpc_stats_histo_bucket_boundaries[13]; diff --git a/Sources/CgRPC/src/core/lib/debug/trace.cc b/Sources/CgRPC/src/core/lib/debug/trace.cc index 01c1e867d..cafdb15c6 100644 --- a/Sources/CgRPC/src/core/lib/debug/trace.cc +++ b/Sources/CgRPC/src/core/lib/debug/trace.cc @@ -21,6 +21,7 @@ #include "src/core/lib/debug/trace.h" #include +#include #include #include @@ -79,6 +80,8 @@ void TraceFlagList::LogAllTracers() { // Flags register themselves on the list during construction TraceFlag::TraceFlag(bool default_enabled, const char* name) : name_(name) { + static_assert(std::is_trivially_destructible::value, + "TraceFlag needs to be trivially destructible."); set_enabled(default_enabled); TraceFlagList::Add(this); } diff --git a/Sources/CgRPC/src/core/lib/debug/trace.h b/Sources/CgRPC/src/core/lib/debug/trace.h index 28157c638..462349452 100644 --- a/Sources/CgRPC/src/core/lib/debug/trace.h +++ b/Sources/CgRPC/src/core/lib/debug/trace.h @@ -53,18 +53,19 @@ void grpc_tracer_enable_flag(grpc_core::TraceFlag* flag); class TraceFlag { public: TraceFlag(bool default_enabled, const char* name); - ~TraceFlag() {} + // This needs to be trivially destructible as it is used as global variable. + ~TraceFlag() = default; const char* name() const { return name_; } -// This following define may be commented out to ensure that the compiler -// deletes any "if (tracer.enabled()) {...}" codeblocks. This is useful to -// test the performance impact tracers have on the system. -// -// #define COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD -#ifdef COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD - bool enabled() { return false; } -#else +// Use the symbol GRPC_USE_TRACERS to determine if tracers will be enabled in +// opt builds (tracers are always on in dbg builds). The default in OSS is for +// tracers to be on since we support binary distributions of gRPC for the +// wrapped language (wr don't want to force recompilation to get tracing). +// Internally, however, for performance reasons, we compile them out by +// default, since internal build systems make recompiling trivial. +#define GRPC_USE_TRACERS // tracers on by default in OSS +#if defined(GRPC_USE_TRACERS) || !defined(NDEBUG) bool enabled() { #ifdef GRPC_THREADSAFE_TRACER return gpr_atm_no_barrier_load(&value_) != 0; @@ -72,7 +73,9 @@ class TraceFlag { return value_; #endif // GRPC_THREADSAFE_TRACER } -#endif // COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD +#else + bool enabled() { return false; } +#endif /* defined(GRPC_USE_TRACERS) || !defined(NDEBUG) */ private: friend void grpc_core::testing::grpc_tracer_enable_flag(TraceFlag* flag); @@ -100,8 +103,9 @@ typedef TraceFlag DebugOnlyTraceFlag; #else class DebugOnlyTraceFlag { public: - DebugOnlyTraceFlag(bool default_enabled, const char* name) {} - bool enabled() { return false; } + constexpr DebugOnlyTraceFlag(bool default_enabled, const char* name) {} + constexpr bool enabled() const { return false; } + constexpr const char* name() const { return "DebugOnlyTraceFlag"; } private: void set_enabled(bool enabled) {} diff --git a/Sources/CgRPC/src/core/lib/gpr/alloc.h b/Sources/CgRPC/src/core/lib/gpr/alloc.h new file mode 100644 index 000000000..762b51bf6 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/gpr/alloc.h @@ -0,0 +1,28 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPR_ALLOC_H +#define GRPC_CORE_LIB_GPR_ALLOC_H + +#include + +/// Given a size, round up to the next multiple of sizeof(void*). +#define GPR_ROUND_UP_TO_ALIGNMENT_SIZE(x) \ + (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u)) + +#endif /* GRPC_CORE_LIB_GPR_ALLOC_H */ diff --git a/Sources/CgRPC/src/core/lib/gpr/arena.cc b/Sources/CgRPC/src/core/lib/gpr/arena.cc index b02c5b9fb..836a7ca79 100644 --- a/Sources/CgRPC/src/core/lib/gpr/arena.cc +++ b/Sources/CgRPC/src/core/lib/gpr/arena.cc @@ -21,40 +21,87 @@ #include "src/core/lib/gpr/arena.h" #include +#include #include #include #include +#include + +#include "src/core/lib/gpr/alloc.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gprpp/memory.h" + +namespace { +enum init_strategy { + NO_INIT, // Do not initialize the arena blocks. + ZERO_INIT, // Initialize arena blocks with 0. + NON_ZERO_INIT, // Initialize arena blocks with a non-zero value. +}; + +gpr_once g_init_strategy_once = GPR_ONCE_INIT; +init_strategy g_init_strategy = NO_INIT; +} // namespace + +static void set_strategy_from_env() { + char* str = gpr_getenv("GRPC_ARENA_INIT_STRATEGY"); + if (str == nullptr) { + g_init_strategy = NO_INIT; + } else if (strcmp(str, "zero_init") == 0) { + g_init_strategy = ZERO_INIT; + } else if (strcmp(str, "non_zero_init") == 0) { + g_init_strategy = NON_ZERO_INIT; + } else { + g_init_strategy = NO_INIT; + } + gpr_free(str); +} + +static void* gpr_arena_alloc_maybe_init(size_t size) { + void* mem = gpr_malloc_aligned(size, GPR_MAX_ALIGNMENT); + gpr_once_init(&g_init_strategy_once, set_strategy_from_env); + if (GPR_UNLIKELY(g_init_strategy != NO_INIT)) { + if (g_init_strategy == ZERO_INIT) { + memset(mem, 0, size); + } else { // NON_ZERO_INIT. + memset(mem, 0xFE, size); + } + } + return mem; +} + +void gpr_arena_init() { + gpr_once_init(&g_init_strategy_once, set_strategy_from_env); +} // Uncomment this to use a simple arena that simply allocates the // requested amount of memory for each call to gpr_arena_alloc(). This // effectively eliminates the efficiency gain of using an arena, but it // may be useful for debugging purposes. //#define SIMPLE_ARENA_FOR_DEBUGGING - #ifdef SIMPLE_ARENA_FOR_DEBUGGING -#include - struct gpr_arena { + gpr_arena() { gpr_mu_init(&mu); } + ~gpr_arena() { + gpr_mu_destroy(&mu); + for (size_t i = 0; i < num_ptrs; ++i) { + gpr_free_aligned(ptrs[i]); + } + gpr_free(ptrs); + } + gpr_mu mu; - void** ptrs; - size_t num_ptrs; + void** ptrs = nullptr; + size_t num_ptrs = 0; }; gpr_arena* gpr_arena_create(size_t ignored_initial_size) { - gpr_arena* arena = (gpr_arena*)gpr_zalloc(sizeof(*arena)); - gpr_mu_init(&arena->mu); - return arena; + return grpc_core::New(); } size_t gpr_arena_destroy(gpr_arena* arena) { - gpr_mu_destroy(&arena->mu); - for (size_t i = 0; i < arena->num_ptrs; ++i) { - gpr_free(arena->ptrs[i]); - } - gpr_free(arena->ptrs); - gpr_free(arena); + grpc_core::Delete(arena); return 1; // Value doesn't matter, since it won't be used. } @@ -62,7 +109,8 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) { gpr_mu_lock(&arena->mu); arena->ptrs = (void**)gpr_realloc(arena->ptrs, sizeof(void*) * (arena->num_ptrs + 1)); - void* retval = arena->ptrs[arena->num_ptrs++] = gpr_zalloc(size); + void* retval = arena->ptrs[arena->num_ptrs++] = + gpr_arena_alloc_maybe_init(size); gpr_mu_unlock(&arena->mu); return retval; } @@ -74,79 +122,71 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) { // arena API to C++, we should consider replacing gpr_arena_alloc() with a // template that takes the type of the value being allocated, which // would allow us to use the alignment actually needed by the caller. -#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ - (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u)) typedef struct zone { - size_t size_begin; - size_t size_end; - gpr_atm next_atm; + zone* next = nullptr; } zone; struct gpr_arena { - gpr_atm size_so_far; + gpr_arena(size_t initial_size) + : initial_zone_size(initial_size), last_zone(&initial_zone) { + gpr_mu_init(&arena_growth_mutex); + } + ~gpr_arena() { + gpr_mu_destroy(&arena_growth_mutex); + zone* z = initial_zone.next; + while (z) { + zone* next_z = z->next; + z->~zone(); + gpr_free_aligned(z); + z = next_z; + } + } + + // Keep track of the total used size. We use this in our call sizing + // historesis. + gpr_atm total_used = 0; + size_t initial_zone_size; zone initial_zone; + zone* last_zone; + gpr_mu arena_growth_mutex; }; -static void* zalloc_aligned(size_t size) { - void* ptr = gpr_malloc_aligned(size, GPR_MAX_ALIGNMENT); - memset(ptr, 0, size); - return ptr; -} - gpr_arena* gpr_arena_create(size_t initial_size) { - initial_size = ROUND_UP_TO_ALIGNMENT_SIZE(initial_size); - gpr_arena* a = static_cast(zalloc_aligned( - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size)); - a->initial_zone.size_end = initial_size; - return a; + initial_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_size); + return new (gpr_arena_alloc_maybe_init( + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size)) + gpr_arena(initial_size); } size_t gpr_arena_destroy(gpr_arena* arena) { - gpr_atm size = gpr_atm_no_barrier_load(&arena->size_so_far); - zone* z = (zone*)gpr_atm_no_barrier_load(&arena->initial_zone.next_atm); + const gpr_atm size = gpr_atm_no_barrier_load(&arena->total_used); + arena->~gpr_arena(); gpr_free_aligned(arena); - while (z) { - zone* next_z = (zone*)gpr_atm_no_barrier_load(&z->next_atm); - gpr_free_aligned(z); - z = next_z; - } return static_cast(size); } void* gpr_arena_alloc(gpr_arena* arena, size_t size) { - size = ROUND_UP_TO_ALIGNMENT_SIZE(size); - size_t start = static_cast( - gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size)); - zone* z = &arena->initial_zone; - while (start > z->size_end) { - zone* next_z = (zone*)gpr_atm_acq_load(&z->next_atm); - if (next_z == nullptr) { - size_t next_z_size = - static_cast(gpr_atm_no_barrier_load(&arena->size_so_far)); - next_z = static_cast(zalloc_aligned( - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + next_z_size)); - next_z->size_begin = z->size_end; - next_z->size_end = z->size_end + next_z_size; - if (!gpr_atm_rel_cas(&z->next_atm, static_cast(NULL), - (gpr_atm)next_z)) { - gpr_free_aligned(next_z); - next_z = (zone*)gpr_atm_acq_load(&z->next_atm); - } - } - z = next_z; - } - if (start + size > z->size_end) { - return gpr_arena_alloc(arena, size); + size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size); + size_t begin = gpr_atm_no_barrier_fetch_add(&arena->total_used, size); + if (begin + size <= arena->initial_zone_size) { + return reinterpret_cast(arena) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + begin; + } else { + // If the allocation isn't able to end in the initial zone, create a new + // zone for this allocation, and any unused space in the initial zone is + // wasted. This overflowing and wasting is uncommon because of our arena + // sizing historesis (that is, most calls should have a large enough initial + // zone and will not need to grow the arena). + gpr_mu_lock(&arena->arena_growth_mutex); + zone* z = new (gpr_arena_alloc_maybe_init( + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + size)) zone(); + arena->last_zone->next = z; + arena->last_zone = z; + gpr_mu_unlock(&arena->arena_growth_mutex); + return reinterpret_cast(z) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)); } - GPR_ASSERT(start >= z->size_begin); - GPR_ASSERT(start + size <= z->size_end); - char* ptr = (z == &arena->initial_zone) - ? reinterpret_cast(arena) + - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) - : reinterpret_cast(z) + - ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)); - return ptr + start - z->size_begin; } #endif // SIMPLE_ARENA_FOR_DEBUGGING diff --git a/Sources/CgRPC/src/core/lib/gpr/arena.h b/Sources/CgRPC/src/core/lib/gpr/arena.h index 6d2a073dd..069892b22 100644 --- a/Sources/CgRPC/src/core/lib/gpr/arena.h +++ b/Sources/CgRPC/src/core/lib/gpr/arena.h @@ -37,5 +37,7 @@ gpr_arena* gpr_arena_create(size_t initial_size); void* gpr_arena_alloc(gpr_arena* arena, size_t size); // Destroy an arena, returning the total number of bytes allocated size_t gpr_arena_destroy(gpr_arena* arena); +// Initializes the Arena component. +void gpr_arena_init(); #endif /* GRPC_CORE_LIB_GPR_ARENA_H */ diff --git a/Sources/CgRPC/src/core/lib/gpr/fork.cc b/Sources/CgRPC/src/core/lib/gpr/fork.cc deleted file mode 100644 index 812522b05..000000000 --- a/Sources/CgRPC/src/core/lib/gpr/fork.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/gpr/fork.h" - -#include - -#include - -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/gpr/useful.h" - -/* - * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK - * AROUND VERY SPECIFIC USE CASES. - */ - -static int override_fork_support_enabled = -1; -static int fork_support_enabled; - -void grpc_fork_support_init() { -#ifdef GRPC_ENABLE_FORK_SUPPORT - fork_support_enabled = 1; -#else - fork_support_enabled = 0; -#endif - bool env_var_set = false; - char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT"); - if (env != nullptr) { - static const char* truthy[] = {"yes", "Yes", "YES", "true", - "True", "TRUE", "1"}; - static const char* falsey[] = {"no", "No", "NO", "false", - "False", "FALSE", "0"}; - for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) { - if (0 == strcmp(env, truthy[i])) { - fork_support_enabled = 1; - env_var_set = true; - break; - } - } - if (!env_var_set) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) { - if (0 == strcmp(env, falsey[i])) { - fork_support_enabled = 0; - env_var_set = true; - break; - } - } - } - gpr_free(env); - } - if (override_fork_support_enabled != -1) { - fork_support_enabled = override_fork_support_enabled; - } -} - -int grpc_fork_support_enabled() { return fork_support_enabled; } - -void grpc_enable_fork_support(int enable) { - override_fork_support_enabled = enable; -} diff --git a/Sources/CgRPC/src/core/lib/gpr/log_posix.cc b/Sources/CgRPC/src/core/lib/gpr/log_posix.cc index 0acb22557..b6edc14ab 100644 --- a/Sources/CgRPC/src/core/lib/gpr/log_posix.cc +++ b/Sources/CgRPC/src/core/lib/gpr/log_posix.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,7 @@ void gpr_default_log(gpr_log_func_args* args) { } char* prefix; - gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]", + gpr_asprintf(&prefix, "%s%s.%09d %7" PRIdPTR " %s:%d]", gpr_log_severity_string(args->severity), time_buffer, (int)(now.tv_nsec), gettid(), display_file, args->line); diff --git a/Sources/CgRPC/src/core/lib/gpr/mpscq.h b/Sources/CgRPC/src/core/lib/gpr/mpscq.h index 6b67880d1..5ded2522b 100644 --- a/Sources/CgRPC/src/core/lib/gpr/mpscq.h +++ b/Sources/CgRPC/src/core/lib/gpr/mpscq.h @@ -38,9 +38,11 @@ typedef struct gpr_mpscq_node { // Actual queue type typedef struct gpr_mpscq { - gpr_atm head; // make sure head & tail don't share a cacheline - char padding[GPR_CACHELINE_SIZE]; + union { + char padding[GPR_CACHELINE_SIZE]; + gpr_atm head; + }; gpr_mpscq_node* tail; gpr_mpscq_node stub; } gpr_mpscq; diff --git a/Sources/CgRPC/src/core/lib/gpr/string.cc b/Sources/CgRPC/src/core/lib/gpr/string.cc index ef2a6900b..0a76fc1f5 100644 --- a/Sources/CgRPC/src/core/lib/gpr/string.cc +++ b/Sources/CgRPC/src/core/lib/gpr/string.cc @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -54,6 +56,32 @@ typedef struct { char* data; } dump_out; +char* gpr_format_timespec(gpr_timespec tm) { + char time_buffer[35]; + char ns_buffer[11]; // '.' + 9 digits of precision + struct tm* tm_info = localtime((const time_t*)&tm.tv_sec); + strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); + snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); + // This loop trims off trailing zeros by inserting a null character that the + // right point. We iterate in chunks of three because we want 0, 3, 6, or 9 + // fractional digits. + for (int i = 7; i >= 1; i -= 3) { + if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && + ns_buffer[i + 2] == '0') { + ns_buffer[i] = '\0'; + // Edge case in which all fractional digits were 0. + if (i == 1) { + ns_buffer[0] = '\0'; + } + } else { + break; + } + } + char* full_time_str; + gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer); + return full_time_str; +} + static dump_out dump_out_create(void) { dump_out r = {0, 0, nullptr}; return r; diff --git a/Sources/CgRPC/src/core/lib/gpr/string.h b/Sources/CgRPC/src/core/lib/gpr/string.h index 2e8a4898d..ce51fe463 100644 --- a/Sources/CgRPC/src/core/lib/gpr/string.h +++ b/Sources/CgRPC/src/core/lib/gpr/string.h @@ -21,6 +21,8 @@ #include +#include + #include #include @@ -81,6 +83,14 @@ char* gpr_strjoin_sep(const char** strs, size_t nstrs, const char* sep, void gpr_string_split(const char* input, const char* sep, char*** strs, size_t* nstrs); +/* Returns an allocated string that represents tm according to RFC-3339, and, + more specifically, follows: + https://developers.google.com/protocol-buffers/docs/proto3#json + + Uses RFC 3339, where generated output will always be Z-normalized and uses + 0, 3, 6 or 9 fractional digits. */ +char* gpr_format_timespec(gpr_timespec); + /* A vector of strings... for building up a final string one piece at a time */ typedef struct { char** strs; diff --git a/Sources/CgRPC/src/core/lib/gpr/sync_posix.cc b/Sources/CgRPC/src/core/lib/gpr/sync_posix.cc index 848d23730..c09a7598a 100644 --- a/Sources/CgRPC/src/core/lib/gpr/sync_posix.cc +++ b/Sources/CgRPC/src/core/lib/gpr/sync_posix.cc @@ -27,6 +27,44 @@ #include #include "src/core/lib/profiling/timers.h" +// For debug of the timer manager crash only. +// TODO (mxyan): remove after bug is fixed. +#ifdef GRPC_DEBUG_TIMER_MANAGER +#include +void (*g_grpc_debug_timer_manager_stats)( + int64_t timer_manager_init_count, int64_t timer_manager_shutdown_count, + int64_t fork_count, int64_t timer_wait_err, int64_t timer_cv_value, + int64_t timer_mu_value, int64_t abstime_sec_value, + int64_t abstime_nsec_value, int64_t abs_deadline_sec_value, + int64_t abs_deadline_nsec_value, int64_t now1_sec_value, + int64_t now1_nsec_value, int64_t now2_sec_value, int64_t now2_nsec_value, + int64_t add_result_sec_value, int64_t add_result_nsec_value, + int64_t sub_result_sec_value, int64_t sub_result_nsec_value, + int64_t next_value, int64_t start_time_sec, + int64_t start_time_nsec) = nullptr; +int64_t g_timer_manager_init_count = 0; +int64_t g_timer_manager_shutdown_count = 0; +int64_t g_fork_count = 0; +int64_t g_timer_wait_err = 0; +int64_t g_timer_cv_value = 0; +int64_t g_timer_mu_value = 0; +int64_t g_abstime_sec_value = -1; +int64_t g_abstime_nsec_value = -1; +int64_t g_abs_deadline_sec_value = -1; +int64_t g_abs_deadline_nsec_value = -1; +int64_t g_now1_sec_value = -1; +int64_t g_now1_nsec_value = -1; +int64_t g_now2_sec_value = -1; +int64_t g_now2_nsec_value = -1; +int64_t g_add_result_sec_value = -1; +int64_t g_add_result_nsec_value = -1; +int64_t g_sub_result_sec_value = -1; +int64_t g_sub_result_nsec_value = -1; +int64_t g_next_value = -1; +int64_t g_start_time_sec = -1; +int64_t g_start_time_nsec = -1; +#endif // GRPC_DEBUG_TIMER_MANAGER + #ifdef GPR_LOW_LEVEL_COUNTERS gpr_atm gpr_mu_locks = 0; gpr_atm gpr_counter_atm_cas = 0; @@ -72,22 +110,118 @@ void gpr_cv_init(gpr_cv* cv) { void gpr_cv_destroy(gpr_cv* cv) { GPR_ASSERT(pthread_cond_destroy(cv) == 0); } +// For debug of the timer manager crash only. +// TODO (mxyan): remove after bug is fixed. +#ifdef GRPC_DEBUG_TIMER_MANAGER +static gpr_timespec gpr_convert_clock_type_debug_timespec( + gpr_timespec t, gpr_clock_type clock_type, gpr_timespec& now1, + gpr_timespec& now2, gpr_timespec& add_result, gpr_timespec& sub_result) { + if (t.clock_type == clock_type) { + return t; + } + + if (t.tv_sec == INT64_MAX || t.tv_sec == INT64_MIN) { + t.clock_type = clock_type; + return t; + } + + if (clock_type == GPR_TIMESPAN) { + return gpr_time_sub(t, gpr_now(t.clock_type)); + } + + if (t.clock_type == GPR_TIMESPAN) { + return gpr_time_add(gpr_now(clock_type), t); + } + + now1 = gpr_now(t.clock_type); + sub_result = gpr_time_sub(t, now1); + now2 = gpr_now(clock_type); + add_result = gpr_time_add(now2, sub_result); + return add_result; +} + +#define gpr_convert_clock_type_debug(t, clock_type, now1, now2, add_result, \ + sub_result) \ + gpr_convert_clock_type_debug_timespec((t), (clock_type), (now1), (now2), \ + (add_result), (sub_result)) +#else +#define gpr_convert_clock_type_debug(t, clock_type, now1, now2, add_result, \ + sub_result) \ + gpr_convert_clock_type((t), (clock_type)) +#endif + int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) { int err = 0; +#ifdef GRPC_DEBUG_TIMER_MANAGER + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. + gpr_timespec abs_deadline_copy; + abs_deadline_copy.tv_sec = abs_deadline.tv_sec; + abs_deadline_copy.tv_nsec = abs_deadline.tv_nsec; + gpr_timespec now1; + gpr_timespec now2; + gpr_timespec add_result; + gpr_timespec sub_result; + memset(&now1, 0, sizeof(now1)); + memset(&now2, 0, sizeof(now2)); + memset(&add_result, 0, sizeof(add_result)); + memset(&sub_result, 0, sizeof(sub_result)); +#endif if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) == 0) { err = pthread_cond_wait(cv, mu); } else { struct timespec abs_deadline_ts; #if GPR_LINUX - abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_MONOTONIC); + abs_deadline = gpr_convert_clock_type_debug( + abs_deadline, GPR_CLOCK_MONOTONIC, now1, now2, add_result, sub_result); #else - abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME); + abs_deadline = gpr_convert_clock_type_debug( + abs_deadline, GPR_CLOCK_REALTIME, now1, now2, add_result, sub_result); #endif // GPR_LINUX abs_deadline_ts.tv_sec = static_cast(abs_deadline.tv_sec); abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec; err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts); +#ifdef GRPC_DEBUG_TIMER_MANAGER + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. + if (GPR_UNLIKELY(!(err == 0 || err == ETIMEDOUT || err == EAGAIN))) { + g_abstime_sec_value = abs_deadline_ts.tv_sec; + g_abstime_nsec_value = abs_deadline_ts.tv_nsec; + } +#endif + } + +#ifdef GRPC_DEBUG_TIMER_MANAGER + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. + if (GPR_UNLIKELY(!(err == 0 || err == ETIMEDOUT || err == EAGAIN))) { + if (g_grpc_debug_timer_manager_stats) { + g_timer_wait_err = err; + g_timer_cv_value = (int64_t)cv; + g_timer_mu_value = (int64_t)mu; + g_abs_deadline_sec_value = abs_deadline_copy.tv_sec; + g_abs_deadline_nsec_value = abs_deadline_copy.tv_nsec; + g_now1_sec_value = now1.tv_sec; + g_now1_nsec_value = now1.tv_nsec; + g_now2_sec_value = now2.tv_sec; + g_now2_nsec_value = now2.tv_nsec; + g_add_result_sec_value = add_result.tv_sec; + g_add_result_nsec_value = add_result.tv_nsec; + g_sub_result_sec_value = sub_result.tv_sec; + g_sub_result_nsec_value = sub_result.tv_nsec; + g_grpc_debug_timer_manager_stats( + g_timer_manager_init_count, g_timer_manager_shutdown_count, + g_fork_count, g_timer_wait_err, g_timer_cv_value, g_timer_mu_value, + g_abstime_sec_value, g_abstime_nsec_value, g_abs_deadline_sec_value, + g_abs_deadline_nsec_value, g_now1_sec_value, g_now1_nsec_value, + g_now2_sec_value, g_now2_nsec_value, g_add_result_sec_value, + g_add_result_nsec_value, g_sub_result_sec_value, + g_sub_result_nsec_value, g_next_value, g_start_time_sec, + g_start_time_nsec); + } } +#endif GPR_ASSERT(err == 0 || err == ETIMEDOUT || err == EAGAIN); return err == ETIMEDOUT; } diff --git a/Sources/CgRPC/src/core/lib/gpr/time.cc b/Sources/CgRPC/src/core/lib/gpr/time.cc index 64c1c98f5..8927dab5a 100644 --- a/Sources/CgRPC/src/core/lib/gpr/time.cc +++ b/Sources/CgRPC/src/core/lib/gpr/time.cc @@ -135,6 +135,10 @@ gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) { gpr_timespec sum; int64_t inc = 0; GPR_ASSERT(b.clock_type == GPR_TIMESPAN); + // tv_nsec in a timespan is always +ve. -ve timespan is represented as (-ve + // tv_sec, +ve tv_nsec). For example, timespan = -2.5 seconds is represented + // as {-3, 5e8, GPR_TIMESPAN} + GPR_ASSERT(b.tv_nsec >= 0); sum.clock_type = a.clock_type; sum.tv_nsec = a.tv_nsec + b.tv_nsec; if (sum.tv_nsec >= GPR_NS_PER_SEC) { @@ -165,6 +169,10 @@ gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) { int64_t dec = 0; if (b.clock_type == GPR_TIMESPAN) { diff.clock_type = a.clock_type; + // tv_nsec in a timespan is always +ve. -ve timespan is represented as (-ve + // tv_sec, +ve tv_nsec). For example, timespan = -2.5 seconds is represented + // as {-3, 5e8, GPR_TIMESPAN} + GPR_ASSERT(b.tv_nsec >= 0); } else { GPR_ASSERT(a.clock_type == b.clock_type); diff.clock_type = GPR_TIMESPAN; diff --git a/Sources/CgRPC/src/core/lib/gpr/time_posix.cc b/Sources/CgRPC/src/core/lib/gpr/time_posix.cc index 28836bfa5..1b3e36486 100644 --- a/Sources/CgRPC/src/core/lib/gpr/time_posix.cc +++ b/Sources/CgRPC/src/core/lib/gpr/time_posix.cc @@ -133,12 +133,18 @@ gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl; #ifdef GPR_LOW_LEVEL_COUNTERS gpr_atm gpr_now_call_count; #endif - gpr_timespec gpr_now(gpr_clock_type clock_type) { #ifdef GPR_LOW_LEVEL_COUNTERS __atomic_fetch_add(&gpr_now_call_count, 1, __ATOMIC_RELAXED); #endif - return gpr_now_impl(clock_type); + // validate clock type + GPR_ASSERT(clock_type == GPR_CLOCK_MONOTONIC || + clock_type == GPR_CLOCK_REALTIME || + clock_type == GPR_CLOCK_PRECISE); + gpr_timespec ts = gpr_now_impl(clock_type); + // tv_nsecs must be in the range [0, 1e9). + GPR_ASSERT(ts.tv_nsec >= 0 && ts.tv_nsec < 1e9); + return ts; } void gpr_sleep_until(gpr_timespec until) { diff --git a/Sources/CgRPC/src/core/lib/gprpp/abstract.h b/Sources/CgRPC/src/core/lib/gprpp/abstract.h index cc96edc49..5b7018e07 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/abstract.h +++ b/Sources/CgRPC/src/core/lib/gprpp/abstract.h @@ -28,7 +28,10 @@ // gRPC currently can't depend on libstdc++, so we can't use "= 0" for // pure virtual methods. Instead, we use this macro. -#define GRPC_ABSTRACT \ - { GPR_ASSERT(false); } +#define GRPC_ABSTRACT \ + { \ + gpr_log(GPR_ERROR, "Function marked GRPC_ABSTRACT was not implemented"); \ + GPR_ASSERT(false); \ + } #endif /* GRPC_CORE_LIB_GPRPP_ABSTRACT_H */ diff --git a/Sources/CgRPC/src/core/lib/gprpp/fork.cc b/Sources/CgRPC/src/core/lib/gprpp/fork.cc new file mode 100644 index 000000000..3b9c16510 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/gprpp/fork.cc @@ -0,0 +1,268 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/gprpp/fork.h" + +#include + +#include +#include +#include + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/memory.h" + +/* + * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK + * AROUND VERY SPECIFIC USE CASES. + */ + +namespace grpc_core { +namespace internal { +// The exec_ctx_count has 2 modes, blocked and unblocked. +// When unblocked, the count is 2-indexed; exec_ctx_count=2 indicates +// 0 active ExecCtxs, exex_ctx_count=3 indicates 1 active ExecCtxs... + +// When blocked, the exec_ctx_count is 0-indexed. Note that ExecCtx +// creation can only be blocked if there is exactly 1 outstanding ExecCtx, +// meaning that BLOCKED and UNBLOCKED counts partition the integers +#define UNBLOCKED(n) (n + 2) +#define BLOCKED(n) (n) + +class ExecCtxState { + public: + ExecCtxState() : fork_complete_(true) { + gpr_mu_init(&mu_); + gpr_cv_init(&cv_); + gpr_atm_no_barrier_store(&count_, UNBLOCKED(0)); + } + + void IncExecCtxCount() { + gpr_atm count = gpr_atm_no_barrier_load(&count_); + while (true) { + if (count <= BLOCKED(1)) { + // This only occurs if we are trying to fork. Wait until the fork() + // operation completes before allowing new ExecCtxs. + gpr_mu_lock(&mu_); + if (gpr_atm_no_barrier_load(&count_) <= BLOCKED(1)) { + while (!fork_complete_) { + gpr_cv_wait(&cv_, &mu_, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + gpr_mu_unlock(&mu_); + } else if (gpr_atm_no_barrier_cas(&count_, count, count + 1)) { + break; + } + count = gpr_atm_no_barrier_load(&count_); + } + } + + void DecExecCtxCount() { gpr_atm_no_barrier_fetch_add(&count_, -1); } + + bool BlockExecCtx() { + // Assumes there is an active ExecCtx when this function is called + if (gpr_atm_no_barrier_cas(&count_, UNBLOCKED(1), BLOCKED(1))) { + gpr_mu_lock(&mu_); + fork_complete_ = false; + gpr_mu_unlock(&mu_); + return true; + } + return false; + } + + void AllowExecCtx() { + gpr_mu_lock(&mu_); + gpr_atm_no_barrier_store(&count_, UNBLOCKED(0)); + fork_complete_ = true; + gpr_cv_broadcast(&cv_); + gpr_mu_unlock(&mu_); + } + + ~ExecCtxState() { + gpr_mu_destroy(&mu_); + gpr_cv_destroy(&cv_); + } + + private: + bool fork_complete_; + gpr_mu mu_; + gpr_cv cv_; + gpr_atm count_; +}; + +class ThreadState { + public: + ThreadState() : awaiting_threads_(false), threads_done_(false), count_(0) { + gpr_mu_init(&mu_); + gpr_cv_init(&cv_); + } + + void IncThreadCount() { + gpr_mu_lock(&mu_); + count_++; + gpr_mu_unlock(&mu_); + } + + void DecThreadCount() { + gpr_mu_lock(&mu_); + count_--; + if (awaiting_threads_ && count_ == 0) { + threads_done_ = true; + gpr_cv_signal(&cv_); + } + gpr_mu_unlock(&mu_); + } + void AwaitThreads() { + gpr_mu_lock(&mu_); + awaiting_threads_ = true; + threads_done_ = (count_ == 0); + while (!threads_done_) { + gpr_cv_wait(&cv_, &mu_, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + awaiting_threads_ = true; + gpr_mu_unlock(&mu_); + } + + ~ThreadState() { + gpr_mu_destroy(&mu_); + gpr_cv_destroy(&cv_); + } + + private: + bool awaiting_threads_; + bool threads_done_; + gpr_mu mu_; + gpr_cv cv_; + int count_; +}; + +} // namespace + +void Fork::GlobalInit() { + if (!override_enabled_) { +#ifdef GRPC_ENABLE_FORK_SUPPORT + support_enabled_ = true; +#else + support_enabled_ = false; +#endif + bool env_var_set = false; + char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT"); + if (env != nullptr) { + static const char* truthy[] = {"yes", "Yes", "YES", "true", + "True", "TRUE", "1"}; + static const char* falsey[] = {"no", "No", "NO", "false", + "False", "FALSE", "0"}; + for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) { + if (0 == strcmp(env, truthy[i])) { + support_enabled_ = true; + env_var_set = true; + break; + } + } + if (!env_var_set) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) { + if (0 == strcmp(env, falsey[i])) { + support_enabled_ = false; + env_var_set = true; + break; + } + } + } + gpr_free(env); + } + } + if (support_enabled_) { + exec_ctx_state_ = grpc_core::New(); + thread_state_ = grpc_core::New(); + } +} + +void Fork::GlobalShutdown() { + if (support_enabled_) { + grpc_core::Delete(exec_ctx_state_); + grpc_core::Delete(thread_state_); + } +} + +bool Fork::Enabled() { return support_enabled_; } + +// Testing Only +void Fork::Enable(bool enable) { + override_enabled_ = true; + support_enabled_ = enable; +} + +void Fork::IncExecCtxCount() { + if (support_enabled_) { + exec_ctx_state_->IncExecCtxCount(); + } +} + +void Fork::DecExecCtxCount() { + if (support_enabled_) { + exec_ctx_state_->DecExecCtxCount(); + } +} + +void Fork::SetResetChildPollingEngineFunc( + Fork::child_postfork_func reset_child_polling_engine) { + reset_child_polling_engine_ = reset_child_polling_engine; +} +Fork::child_postfork_func Fork::GetResetChildPollingEngineFunc() { + return reset_child_polling_engine_; +} + +bool Fork::BlockExecCtx() { + if (support_enabled_) { + return exec_ctx_state_->BlockExecCtx(); + } + return false; +} + +void Fork::AllowExecCtx() { + if (support_enabled_) { + exec_ctx_state_->AllowExecCtx(); + } +} + +void Fork::IncThreadCount() { + if (support_enabled_) { + thread_state_->IncThreadCount(); + } +} + +void Fork::DecThreadCount() { + if (support_enabled_) { + thread_state_->DecThreadCount(); + } +} +void Fork::AwaitThreads() { + if (support_enabled_) { + thread_state_->AwaitThreads(); + } +} + +internal::ExecCtxState* Fork::exec_ctx_state_ = nullptr; +internal::ThreadState* Fork::thread_state_ = nullptr; +bool Fork::support_enabled_ = false; +bool Fork::override_enabled_ = false; +Fork::child_postfork_func Fork::reset_child_polling_engine_ = nullptr; +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/gprpp/fork.h b/Sources/CgRPC/src/core/lib/gprpp/fork.h new file mode 100644 index 000000000..5a7404f0d --- /dev/null +++ b/Sources/CgRPC/src/core/lib/gprpp/fork.h @@ -0,0 +1,88 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_FORK_H +#define GRPC_CORE_LIB_GPRPP_FORK_H + +/* + * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK + * AROUND VERY SPECIFIC USE CASES. + */ + +namespace grpc_core { + +namespace internal { +class ExecCtxState; +class ThreadState; +} // namespace internal + +class Fork { + public: + typedef void (*child_postfork_func)(void); + + static void GlobalInit(); + static void GlobalShutdown(); + + // Returns true if fork suppport is enabled, false otherwise + static bool Enabled(); + + // Increment the count of active ExecCtxs. + // Will block until a pending fork is complete if one is in progress. + static void IncExecCtxCount(); + + // Decrement the count of active ExecCtxs + static void DecExecCtxCount(); + + // Provide a function that will be invoked in the child's postfork handler to + // reset the polling engine's internal state. + static void SetResetChildPollingEngineFunc( + child_postfork_func reset_child_polling_engine); + static child_postfork_func GetResetChildPollingEngineFunc(); + + // Check if there is a single active ExecCtx + // (the one used to invoke this function). If there are more, + // return false. Otherwise, return true and block creation of + // more ExecCtx s until AlloWExecCtx() is called + // + static bool BlockExecCtx(); + static void AllowExecCtx(); + + // Increment the count of active threads. + static void IncThreadCount(); + + // Decrement the count of active threads. + static void DecThreadCount(); + + // Await all core threads to be joined. + static void AwaitThreads(); + + // Test only: overrides environment variables/compile flags + // Must be called before grpc_init() + static void Enable(bool enable); + + private: + static internal::ExecCtxState* exec_ctx_state_; + static internal::ThreadState* thread_state_; + static bool support_enabled_; + static bool override_enabled_; + static child_postfork_func reset_child_polling_engine_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_FORK_H */ diff --git a/Sources/CgRPC/src/core/lib/gprpp/inlined_vector.h b/Sources/CgRPC/src/core/lib/gprpp/inlined_vector.h index f36f6cb70..66dc751a5 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/inlined_vector.h +++ b/Sources/CgRPC/src/core/lib/gprpp/inlined_vector.h @@ -22,6 +22,7 @@ #include #include +#include #include "src/core/lib/gprpp/memory.h" @@ -50,9 +51,33 @@ class InlinedVector { InlinedVector() { init_data(); } ~InlinedVector() { destroy_elements(); } - // For now, we do not support copying. - InlinedVector(const InlinedVector&) = delete; - InlinedVector& operator=(const InlinedVector&) = delete; + // copy constructor + InlinedVector(const InlinedVector& v) { + init_data(); + copy_from(v); + } + + InlinedVector& operator=(const InlinedVector& v) { + if (this != &v) { + clear(); + copy_from(v); + } + return *this; + } + + // move constructor + InlinedVector(InlinedVector&& v) { + init_data(); + move_from(v); + } + + InlinedVector& operator=(InlinedVector&& v) { + if (this != &v) { + clear(); + move_from(v); + } + return *this; + } T* data() { return dynamic_ != nullptr ? dynamic_ : reinterpret_cast(inline_); @@ -75,10 +100,7 @@ class InlinedVector { void reserve(size_t capacity) { if (capacity > capacity_) { T* new_dynamic = static_cast(gpr_malloc(sizeof(T) * capacity)); - for (size_t i = 0; i < size_; ++i) { - new (&new_dynamic[i]) T(std::move(data()[i])); - data()[i].~T(); - } + move_elements(data(), new_dynamic, size_); gpr_free(dynamic_); dynamic_ = new_dynamic; capacity_ = capacity; @@ -98,7 +120,17 @@ class InlinedVector { void push_back(T&& value) { emplace_back(std::move(value)); } + void pop_back() { + assert(!empty()); + size_t s = size(); + T& value = data()[s - 1]; + value.~T(); + size_--; + } + size_t size() const { return size_; } + bool empty() const { return size_ == 0; } + size_t capacity() const { return capacity_; } void clear() { @@ -107,6 +139,42 @@ class InlinedVector { } private: + void copy_from(const InlinedVector& v) { + // if v is allocated, make sure we have enough capacity. + if (v.dynamic_ != nullptr) { + reserve(v.capacity_); + } + // copy over elements + for (size_t i = 0; i < v.size_; ++i) { + new (&(data()[i])) T(v[i]); + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + } + + void move_from(InlinedVector& v) { + // if v is allocated, then we steal its dynamic array; otherwise, we + // move the elements individually. + if (v.dynamic_ != nullptr) { + dynamic_ = v.dynamic_; + } else { + move_elements(v.data(), data(), v.size_); + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + // null out the original + v.init_data(); + } + + static void move_elements(T* src, T* dst, size_t num_elements) { + for (size_t i = 0; i < num_elements; ++i) { + new (&dst[i]) T(std::move(src[i])); + src[i].~T(); + } + } + void init_data() { dynamic_ = nullptr; size_ = 0; diff --git a/Sources/CgRPC/src/core/lib/gprpp/memory.h b/Sources/CgRPC/src/core/lib/gprpp/memory.h index ba2f54667..b4b63ae77 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/memory.h +++ b/Sources/CgRPC/src/core/lib/gprpp/memory.h @@ -27,29 +27,32 @@ #include #include -namespace grpc_core { +// Add this to a class that want to use Delete(), but has a private or +// protected destructor. +#define GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE \ + template \ + friend void grpc_core::Delete(T*); +// Add this to a class that want to use New(), but has a private or +// protected constructor. +#define GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW \ + template \ + friend T* grpc_core::New(Args&&...); -// The alignment of memory returned by gpr_malloc(). -constexpr size_t kAlignmentForDefaultAllocationInBytes = 8; +namespace grpc_core { // Alternative to new, since we cannot use it (for fear of libstdc++) template inline T* New(Args&&... args) { - void* p = alignof(T) > kAlignmentForDefaultAllocationInBytes - ? gpr_malloc_aligned(sizeof(T), alignof(T)) - : gpr_malloc(sizeof(T)); + void* p = gpr_malloc(sizeof(T)); return new (p) T(std::forward(args)...); } // Alternative to delete, since we cannot use it (for fear of libstdc++) template inline void Delete(T* p) { + if (p == nullptr) return; p->~T(); - if (alignof(T) > kAlignmentForDefaultAllocationInBytes) { - gpr_free_aligned(p); - } else { - gpr_free(p); - } + gpr_free(p); } template diff --git a/Sources/CgRPC/src/core/lib/iomgr/network_status_tracker.cc b/Sources/CgRPC/src/core/lib/gprpp/mutex_lock.h similarity index 53% rename from Sources/CgRPC/src/core/lib/iomgr/network_status_tracker.cc rename to Sources/CgRPC/src/core/lib/gprpp/mutex_lock.h index d4b7f4a57..54751d5fe 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/network_status_tracker.cc +++ b/Sources/CgRPC/src/core/lib/gprpp/mutex_lock.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,21 +16,27 @@ * */ +#ifndef GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H +#define GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H + #include -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/network_status_tracker.h" +#include -void grpc_network_status_shutdown(void) {} +namespace grpc_core { -void grpc_network_status_init(void) { - // TODO(makarandd): Install callback with OS to monitor network status. -} +class MutexLock { + public: + explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu); } + ~MutexLock() { gpr_mu_unlock(mu_); } -void grpc_destroy_network_status_monitor() {} + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; -void grpc_network_status_register_endpoint(grpc_endpoint* ep) { (void)ep; } + private: + gpr_mu* const mu_; +}; -void grpc_network_status_unregister_endpoint(grpc_endpoint* ep) { (void)ep; } +} // namespace grpc_core -void grpc_network_status_shutdown_all_endpoints() {} +#endif /* GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H */ diff --git a/Sources/CgRPC/src/core/lib/gprpp/optional.h b/Sources/CgRPC/src/core/lib/gprpp/optional.h new file mode 100644 index 000000000..a8e3ce150 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/gprpp/optional.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_OPTIONAL_H +#define GRPC_CORE_LIB_GPRPP_OPTIONAL_H + +namespace grpc_core { + +/* A make-shift alternative for absl::Optional. This can be removed in favor of + * that once absl dependencies can be introduced. */ +template +class Optional { + public: + void set(const T& val) { + value_ = val; + set_ = true; + } + + bool has_value() const { return set_; } + + void reset() { set_ = false; } + + T value() const { return value_; } + + private: + T value_; + bool set_ = false; +}; + +} /* namespace grpc_core */ + +#endif /* GRPC_CORE_LIB_GPRPP_OPTIONAL_H */ diff --git a/Sources/CgRPC/src/core/lib/gprpp/orphanable.h b/Sources/CgRPC/src/core/lib/gprpp/orphanable.h index 73a73995c..9053c6011 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/orphanable.h +++ b/Sources/CgRPC/src/core/lib/gprpp/orphanable.h @@ -31,6 +31,7 @@ #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" namespace grpc_core { @@ -83,115 +84,48 @@ class InternallyRefCounted : public Orphanable { GRPC_ABSTRACT_BASE_CLASS protected: - // Allow Delete() to access destructor. - template - friend void Delete(T*); + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE // Allow RefCountedPtr<> to access Unref() and IncrementRefCount(). - friend class RefCountedPtr; - - InternallyRefCounted() { gpr_ref_init(&refs_, 1); } - virtual ~InternallyRefCounted() {} - - RefCountedPtr Ref() GRPC_MUST_USE_RESULT { - IncrementRefCount(); - return RefCountedPtr(static_cast(this)); - } - - void Unref() { - if (gpr_unref(&refs_)) { - Delete(static_cast(this)); - } - } - - private: - void IncrementRefCount() { gpr_ref(&refs_); } - - gpr_refcount refs_; -}; - -// An alternative version of the InternallyRefCounted base class that -// supports tracing. This is intended to be used in cases where the -// object will be handled both by idiomatic C++ code using smart -// pointers and legacy code that is manually calling Ref() and Unref(). -// Once all of our code is converted to idiomatic C++, we may be able to -// eliminate this class. -template -class InternallyRefCountedWithTracing : public Orphanable { - public: - // Not copyable nor movable. - InternallyRefCountedWithTracing(const InternallyRefCountedWithTracing&) = - delete; - InternallyRefCountedWithTracing& operator=( - const InternallyRefCountedWithTracing&) = delete; - - GRPC_ABSTRACT_BASE_CLASS - - protected: - // Allow Delete() to access destructor. template - friend void Delete(T*); - - // Allow RefCountedPtr<> to access Unref() and IncrementRefCount(). - friend class RefCountedPtr; - - InternallyRefCountedWithTracing() - : InternallyRefCountedWithTracing(static_cast(nullptr)) {} - - explicit InternallyRefCountedWithTracing(TraceFlag* trace_flag) - : trace_flag_(trace_flag) { - gpr_ref_init(&refs_, 1); - } - -#ifdef NDEBUG - explicit InternallyRefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) - : InternallyRefCountedWithTracing() {} -#endif + friend class RefCountedPtr; - virtual ~InternallyRefCountedWithTracing() {} + // TraceFlagT is defined to accept both DebugOnlyTraceFlag and TraceFlag. + // Note: RefCount tracing is only enabled on debug builds, even when a + // TraceFlag is used. + template + explicit InternallyRefCounted(TraceFlagT* trace_flag = nullptr) + : refs_(1, trace_flag) {} + virtual ~InternallyRefCounted() = default; RefCountedPtr Ref() GRPC_MUST_USE_RESULT { IncrementRefCount(); return RefCountedPtr(static_cast(this)); } - RefCountedPtr Ref(const DebugLocation& location, const char* reason) GRPC_MUST_USE_RESULT { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs + 1, reason); - } - return Ref(); + IncrementRefCount(location, reason); + return RefCountedPtr(static_cast(this)); } - // TODO(roth): Once all of our code is converted to C++ and can use - // RefCountedPtr<> instead of manual ref-counting, make the Unref() methods - // private, since they will only be used by RefCountedPtr<>, which is a - // friend of this class. - void Unref() { - if (gpr_unref(&refs_)) { + if (refs_.Unref()) { Delete(static_cast(this)); } } - void Unref(const DebugLocation& location, const char* reason) { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs - 1, reason); + if (refs_.Unref(location, reason)) { + Delete(static_cast(this)); } - Unref(); } private: - void IncrementRefCount() { gpr_ref(&refs_); } + void IncrementRefCount() { refs_.Ref(); } + void IncrementRefCount(const DebugLocation& location, const char* reason) { + refs_.Ref(location, reason); + } - TraceFlag* trace_flag_ = nullptr; - gpr_refcount refs_; + grpc_core::RefCount refs_; }; } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/gprpp/ref_counted.h b/Sources/CgRPC/src/core/lib/gprpp/ref_counted.h index c67e3f315..fa97ffcfe 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/ref_counted.h +++ b/Sources/CgRPC/src/core/lib/gprpp/ref_counted.h @@ -21,9 +21,12 @@ #include +#include #include #include +#include +#include #include #include "src/core/lib/debug/trace.h" @@ -34,62 +37,150 @@ namespace grpc_core { -// A base class for reference-counted objects. -// New objects should be created via New() and start with a refcount of 1. -// When the refcount reaches 0, the object will be deleted via Delete(). -// -// This will commonly be used by CRTP (curiously-recurring template pattern) -// e.g., class MyClass : public RefCounted -template -class RefCounted { +// PolymorphicRefCount enforces polymorphic destruction of RefCounted. +class PolymorphicRefCount { public: - RefCountedPtr Ref() GRPC_MUST_USE_RESULT { - IncrementRefCount(); - return RefCountedPtr(static_cast(this)); - } + GRPC_ABSTRACT_BASE_CLASS - // TODO(roth): Once all of our code is converted to C++ and can use - // RefCountedPtr<> instead of manual ref-counting, make this method - // private, since it will only be used by RefCountedPtr<>, which is a - // friend of this class. - void Unref() { - if (gpr_unref(&refs_)) { - Delete(static_cast(this)); - } - } + protected: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - // Not copyable nor movable. - RefCounted(const RefCounted&) = delete; - RefCounted& operator=(const RefCounted&) = delete; + virtual ~PolymorphicRefCount() = default; +}; +// NonPolymorphicRefCount does not enforce polymorphic destruction of +// RefCounted. Please refer to grpc_core::RefCounted for more details, and +// when in doubt use PolymorphicRefCount. +class NonPolymorphicRefCount { + public: GRPC_ABSTRACT_BASE_CLASS protected: - // Allow Delete() to access destructor. - template - friend void Delete(T*); + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - RefCounted() { gpr_ref_init(&refs_, 1); } + ~NonPolymorphicRefCount() = default; +}; - virtual ~RefCounted() {} +// RefCount is a simple atomic ref-count. +// +// This is a C++ implementation of gpr_refcount, with inline functions. Due to +// inline functions, this class is significantly more efficient than +// gpr_refcount and should be preferred over gpr_refcount whenever possible. +// +// TODO(soheil): Remove gpr_refcount after submitting the GRFC and the paragraph +// above. +class RefCount { + public: + using Value = intptr_t; + + // `init` is the initial refcount stored in this object. + // + // TraceFlagT is defined to accept both DebugOnlyTraceFlag and TraceFlag. + // Note: RefCount tracing is only enabled on debug builds, even when a + // TraceFlag is used. + template + constexpr explicit RefCount(Value init = 1, TraceFlagT* trace_flag = nullptr) + : +#ifndef NDEBUG + trace_flag_(trace_flag), +#endif + value_(init) { + } - private: - // Allow RefCountedPtr<> to access IncrementRefCount(). - friend class RefCountedPtr; + // Increases the ref-count by `n`. + void Ref(Value n = 1) { + GPR_ATM_INC_ADD_THEN(value_.fetch_add(n, std::memory_order_relaxed)); + } + void Ref(const DebugLocation& location, const char* reason, Value n = 1) { +#ifndef NDEBUG + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + const RefCount::Value old_refs = get(); + gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs + n, reason); + } +#endif + Ref(n); + } + + // Similar to Ref() with an assert on the ref-count being non-zero. + void RefNonZero() { +#ifndef NDEBUG + const Value prior = + GPR_ATM_INC_ADD_THEN(value_.fetch_add(1, std::memory_order_relaxed)); + assert(prior > 0); +#else + Ref(); +#endif + } + void RefNonZero(const DebugLocation& location, const char* reason) { +#ifndef NDEBUG + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + const RefCount::Value old_refs = get(); + gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs + 1, reason); + } +#endif + RefNonZero(); + } - void IncrementRefCount() { gpr_ref(&refs_); } + // Decrements the ref-count and returns true if the ref-count reaches 0. + bool Unref() { + const Value prior = + GPR_ATM_INC_ADD_THEN(value_.fetch_sub(1, std::memory_order_acq_rel)); + GPR_DEBUG_ASSERT(prior > 0); + return prior == 1; + } + bool Unref(const DebugLocation& location, const char* reason) { +#ifndef NDEBUG + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + const RefCount::Value old_refs = get(); + gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs - 1, reason); + } +#endif + return Unref(); + } - gpr_refcount refs_; + private: + Value get() const { return value_.load(std::memory_order_relaxed); } + +#ifndef NDEBUG + TraceFlag* trace_flag_; +#endif + std::atomic value_; }; -// An alternative version of the RefCounted base class that -// supports tracing. This is intended to be used in cases where the -// object will be handled both by idiomatic C++ code using smart -// pointers and legacy code that is manually calling Ref() and Unref(). -// Once all of our code is converted to idiomatic C++, we may be able to -// eliminate this class. -template -class RefCountedWithTracing { +// A base class for reference-counted objects. +// New objects should be created via New() and start with a refcount of 1. +// When the refcount reaches 0, the object will be deleted via Delete(). +// +// This will commonly be used by CRTP (curiously-recurring template pattern) +// e.g., class MyClass : public RefCounted +// +// Use PolymorphicRefCount and NonPolymorphicRefCount to select between +// different implementations of RefCounted. +// +// Note that NonPolymorphicRefCount does not support polymorphic destruction. +// So, use NonPolymorphicRefCount only when both of the following conditions +// are guaranteed to hold: +// (a) Child is a concrete leaf class in RefCounted, and +// (b) you are gauranteed to call Unref only on concrete leaf classes and not +// their parents. +// +// The following example is illegal, because calling Unref() will not call +// the dtor of Child. +// +// class Parent : public RefCounted {} +// class Child : public Parent {} +// +// Child* ch; +// ch->Unref(); +// +template +class RefCounted : public Impl { public: RefCountedPtr Ref() GRPC_MUST_USE_RESULT { IncrementRefCount(); @@ -98,70 +189,55 @@ class RefCountedWithTracing { RefCountedPtr Ref(const DebugLocation& location, const char* reason) GRPC_MUST_USE_RESULT { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs + 1, reason); - } - return Ref(); + IncrementRefCount(location, reason); + return RefCountedPtr(static_cast(this)); } // TODO(roth): Once all of our code is converted to C++ and can use - // RefCountedPtr<> instead of manual ref-counting, make the Unref() methods - // private, since they will only be used by RefCountedPtr<>, which is a + // RefCountedPtr<> instead of manual ref-counting, make this method + // private, since it will only be used by RefCountedPtr<>, which is a // friend of this class. - void Unref() { - if (gpr_unref(&refs_)) { + if (refs_.Unref()) { Delete(static_cast(this)); } } - void Unref(const DebugLocation& location, const char* reason) { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs - 1, reason); + if (refs_.Unref(location, reason)) { + Delete(static_cast(this)); } - Unref(); } // Not copyable nor movable. - RefCountedWithTracing(const RefCountedWithTracing&) = delete; - RefCountedWithTracing& operator=(const RefCountedWithTracing&) = delete; + RefCounted(const RefCounted&) = delete; + RefCounted& operator=(const RefCounted&) = delete; GRPC_ABSTRACT_BASE_CLASS protected: - // Allow Delete() to access destructor. - template - friend void Delete(T*); + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - RefCountedWithTracing() - : RefCountedWithTracing(static_cast(nullptr)) {} + // TraceFlagT is defined to accept both DebugOnlyTraceFlag and TraceFlag. + // Note: RefCount tracing is only enabled on debug builds, even when a + // TraceFlag is used. + template + explicit RefCounted(TraceFlagT* trace_flag = nullptr) + : refs_(1, trace_flag) {} - explicit RefCountedWithTracing(TraceFlag* trace_flag) - : trace_flag_(trace_flag) { - gpr_ref_init(&refs_, 1); - } - -#ifdef NDEBUG - explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) - : RefCountedWithTracing() {} -#endif - - virtual ~RefCountedWithTracing() {} + // Note: Depending on the Impl used, this dtor can be implicitly virtual. + ~RefCounted() = default; private: // Allow RefCountedPtr<> to access IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; - void IncrementRefCount() { gpr_ref(&refs_); } + void IncrementRefCount() { refs_.Ref(); } + void IncrementRefCount(const DebugLocation& location, const char* reason) { + refs_.Ref(location, reason); + } - TraceFlag* trace_flag_ = nullptr; - gpr_refcount refs_; + RefCount refs_; }; } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/gprpp/ref_counted_ptr.h b/Sources/CgRPC/src/core/lib/gprpp/ref_counted_ptr.h index 388e2ec41..19f38d7f0 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/ref_counted_ptr.h +++ b/Sources/CgRPC/src/core/lib/gprpp/ref_counted_ptr.h @@ -21,8 +21,10 @@ #include +#include #include +#include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/memory.h" namespace grpc_core { @@ -36,31 +38,64 @@ class RefCountedPtr { RefCountedPtr(std::nullptr_t) {} // If value is non-null, we take ownership of a ref to it. - explicit RefCountedPtr(T* value) { value_ = value; } + template + explicit RefCountedPtr(Y* value) { + value_ = value; + } - // Move support. + // Move ctors. RefCountedPtr(RefCountedPtr&& other) { value_ = other.value_; other.value_ = nullptr; } + template + RefCountedPtr(RefCountedPtr&& other) { + value_ = static_cast(other.value_); + other.value_ = nullptr; + } + + // Move assignment. RefCountedPtr& operator=(RefCountedPtr&& other) { - if (value_ != nullptr) value_->Unref(); - value_ = other.value_; + reset(other.value_); + other.value_ = nullptr; + return *this; + } + template + RefCountedPtr& operator=(RefCountedPtr&& other) { + reset(other.value_); other.value_ = nullptr; return *this; } - // Copy support. + // Copy ctors. RefCountedPtr(const RefCountedPtr& other) { if (other.value_ != nullptr) other.value_->IncrementRefCount(); value_ = other.value_; } + template + RefCountedPtr(const RefCountedPtr& other) { + static_assert(std::has_virtual_destructor::value, + "T does not have a virtual dtor"); + if (other.value_ != nullptr) other.value_->IncrementRefCount(); + value_ = static_cast(other.value_); + } + + // Copy assignment. RefCountedPtr& operator=(const RefCountedPtr& other) { // Note: Order of reffing and unreffing is important here in case value_ // and other.value_ are the same object. if (other.value_ != nullptr) other.value_->IncrementRefCount(); - if (value_ != nullptr) value_->Unref(); - value_ = other.value_; + reset(other.value_); + return *this; + } + template + RefCountedPtr& operator=(const RefCountedPtr& other) { + static_assert(std::has_virtual_destructor::value, + "T does not have a virtual dtor"); + // Note: Order of reffing and unreffing is important here in case value_ + // and other.value_ are the same object. + if (other.value_ != nullptr) other.value_->IncrementRefCount(); + reset(other.value_); return *this; } @@ -73,6 +108,26 @@ class RefCountedPtr { if (value_ != nullptr) value_->Unref(); value_ = value; } + void reset(const DebugLocation& location, const char* reason, + T* value = nullptr) { + if (value_ != nullptr) value_->Unref(location, reason); + value_ = value; + } + template + void reset(Y* value = nullptr) { + static_assert(std::has_virtual_destructor::value, + "T does not have a virtual dtor"); + if (value_ != nullptr) value_->Unref(); + value_ = static_cast(value); + } + template + void reset(const DebugLocation& location, const char* reason, + Y* value = nullptr) { + static_assert(std::has_virtual_destructor::value, + "T does not have a virtual dtor"); + if (value_ != nullptr) value_->Unref(location, reason); + value_ = static_cast(value); + } // TODO(roth): This method exists solely as a transition mechanism to allow // us to pass a ref to idiomatic C code that does not use RefCountedPtr<>. @@ -89,16 +144,34 @@ class RefCountedPtr { T& operator*() const { return *value_; } T* operator->() const { return value_; } - bool operator==(const RefCountedPtr& other) const { + template + bool operator==(const RefCountedPtr& other) const { return value_ == other.value_; } - bool operator==(const T* other) const { return value_ == other; } - bool operator!=(const RefCountedPtr& other) const { + + template + bool operator==(const Y* other) const { + return value_ == other; + } + + bool operator==(std::nullptr_t) const { return value_ == nullptr; } + + template + bool operator!=(const RefCountedPtr& other) const { return value_ != other.value_; } - bool operator!=(const T* other) const { return value_ != other; } + + template + bool operator!=(const Y* other) const { + return value_ != other; + } + + bool operator!=(std::nullptr_t) const { return value_ != nullptr; } private: + template + friend class RefCountedPtr; + T* value_ = nullptr; }; diff --git a/Sources/CgRPC/src/core/lib/gprpp/thd.h b/Sources/CgRPC/src/core/lib/gprpp/thd.h index 05c7ded45..caf0652c1 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/thd.h +++ b/Sources/CgRPC/src/core/lib/gprpp/thd.h @@ -111,9 +111,6 @@ class Thread { } }; - static void Init(); - static bool AwaitAll(gpr_timespec deadline); - private: Thread(const Thread&) = delete; Thread& operator=(const Thread&) = delete; diff --git a/Sources/CgRPC/src/core/lib/gprpp/thd_posix.cc b/Sources/CgRPC/src/core/lib/gprpp/thd_posix.cc index 2f6c2edca..2751b221a 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/thd_posix.cc +++ b/Sources/CgRPC/src/core/lib/gprpp/thd_posix.cc @@ -32,17 +32,12 @@ #include #include -#include "src/core/lib/gpr/fork.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/fork.h" #include "src/core/lib/gprpp/memory.h" namespace grpc_core { namespace { -gpr_mu g_mu; -gpr_cv g_cv; -int g_thread_count; -int g_awaiting_threads; - class ThreadInternalsPosix; struct thd_arg { ThreadInternalsPosix* thread; @@ -68,7 +63,7 @@ class ThreadInternalsPosix info->body = thd_body; info->arg = arg; info->name = thd_name; - inc_thd_count(); + grpc_core::Fork::IncThreadCount(); GPR_ASSERT(pthread_attr_init(&attr) == 0); GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) == @@ -103,17 +98,17 @@ class ThreadInternalsPosix gpr_mu_unlock(&arg.thread->mu_); (*arg.body)(arg.arg); - dec_thd_count(); + grpc_core::Fork::DecThreadCount(); return nullptr; }, info) == 0); GPR_ASSERT(pthread_attr_destroy(&attr) == 0); - if (!success) { + if (!(*success)) { /* don't use gpr_free, as this was allocated using malloc (see above) */ free(info); - dec_thd_count(); + grpc_core::Fork::DecThreadCount(); } }; @@ -132,29 +127,6 @@ class ThreadInternalsPosix void Join() override { pthread_join(pthread_id_, nullptr); } private: - /***************************************** - * Only used when fork support is enabled - */ - - static void inc_thd_count() { - if (grpc_fork_support_enabled()) { - gpr_mu_lock(&g_mu); - g_thread_count++; - gpr_mu_unlock(&g_mu); - } - } - - static void dec_thd_count() { - if (grpc_fork_support_enabled()) { - gpr_mu_lock(&g_mu); - g_thread_count--; - if (g_awaiting_threads && g_thread_count == 0) { - gpr_cv_signal(&g_cv); - } - gpr_mu_unlock(&g_mu); - } - } - gpr_mu mu_; gpr_cv ready_; bool started_; @@ -180,27 +152,6 @@ Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg, *success = outcome; } } - -void Thread::Init() { - gpr_mu_init(&g_mu); - gpr_cv_init(&g_cv); - g_thread_count = 0; - g_awaiting_threads = 0; -} - -bool Thread::AwaitAll(gpr_timespec deadline) { - gpr_mu_lock(&g_mu); - g_awaiting_threads = 1; - int res = 0; - while ((g_thread_count > 0) && - (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0)) { - res = gpr_cv_wait(&g_cv, &g_mu, deadline); - } - g_awaiting_threads = 0; - gpr_mu_unlock(&g_mu); - return res == 0; -} - } // namespace grpc_core // The following is in the external namespace as it is exposed as C89 API diff --git a/Sources/CgRPC/src/core/lib/gprpp/thd_windows.cc b/Sources/CgRPC/src/core/lib/gprpp/thd_windows.cc index 59ea02f3d..71584fd35 100644 --- a/Sources/CgRPC/src/core/lib/gprpp/thd_windows.cc +++ b/Sources/CgRPC/src/core/lib/gprpp/thd_windows.cc @@ -131,13 +131,6 @@ class ThreadInternalsWindows namespace grpc_core { -void Thread::Init() {} - -bool Thread::AwaitAll(gpr_timespec deadline) { - // TODO: Consider adding this if needed - return false; -} - Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg, bool* success) { bool outcome = false; diff --git a/Sources/CgRPC/src/core/lib/http/httpcli.cc b/Sources/CgRPC/src/core/lib/http/httpcli.cc index 12060074c..3bd7a2ce5 100644 --- a/Sources/CgRPC/src/core/lib/http/httpcli.cc +++ b/Sources/CgRPC/src/core/lib/http/httpcli.cc @@ -163,7 +163,7 @@ static void done_write(void* arg, grpc_error* error) { static void start_write(internal_request* req) { grpc_slice_ref_internal(req->request_text); grpc_slice_buffer_add(&req->outgoing, req->request_text); - grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write); + grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write, nullptr); } static void on_handshake_done(void* arg, grpc_endpoint* ep) { diff --git a/Sources/CgRPC/src/core/lib/http/httpcli_security_connector.cc b/Sources/CgRPC/src/core/lib/http/httpcli_security_connector.cc index 0b53d63e7..3f288e045 100644 --- a/Sources/CgRPC/src/core/lib/http/httpcli_security_connector.cc +++ b/Sources/CgRPC/src/core/lib/http/httpcli_security_connector.cc @@ -29,118 +29,124 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" #include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl_transport_security.h" -#include "src/core/tsi/transport_security_adapter.h" -typedef struct { - grpc_channel_security_connector base; - tsi_ssl_client_handshaker_factory* handshaker_factory; - char* secure_peer_name; -} grpc_httpcli_ssl_channel_security_connector; - -static void httpcli_ssl_destroy(grpc_security_connector* sc) { - grpc_httpcli_ssl_channel_security_connector* c = - reinterpret_cast(sc); - if (c->handshaker_factory != nullptr) { - tsi_ssl_client_handshaker_factory_unref(c->handshaker_factory); - c->handshaker_factory = nullptr; +class grpc_httpcli_ssl_channel_security_connector final + : public grpc_channel_security_connector { + public: + explicit grpc_httpcli_ssl_channel_security_connector(char* secure_peer_name) + : grpc_channel_security_connector( + /*url_scheme=*/nullptr, + /*channel_creds=*/nullptr, + /*request_metadata_creds=*/nullptr), + secure_peer_name_(secure_peer_name) {} + + ~grpc_httpcli_ssl_channel_security_connector() override { + if (handshaker_factory_ != nullptr) { + tsi_ssl_client_handshaker_factory_unref(handshaker_factory_); + } + if (secure_peer_name_ != nullptr) { + gpr_free(secure_peer_name_); + } + } + + tsi_result InitHandshakerFactory(const char* pem_root_certs, + const tsi_ssl_root_certs_store* root_store) { + tsi_ssl_client_handshaker_options options; + memset(&options, 0, sizeof(options)); + options.pem_root_certs = pem_root_certs; + options.root_store = root_store; + return tsi_create_ssl_client_handshaker_factory_with_options( + &options, &handshaker_factory_); } - if (c->secure_peer_name != nullptr) gpr_free(c->secure_peer_name); - gpr_free(sc); -} -static void httpcli_ssl_add_handshakers(grpc_channel_security_connector* sc, - grpc_handshake_manager* handshake_mgr) { - grpc_httpcli_ssl_channel_security_connector* c = - reinterpret_cast(sc); - tsi_handshaker* handshaker = nullptr; - if (c->handshaker_factory != nullptr) { - tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( - c->handshaker_factory, c->secure_peer_name, &handshaker); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override { + tsi_handshaker* handshaker = nullptr; + if (handshaker_factory_ != nullptr) { + tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( + handshaker_factory_, secure_peer_name_, &handshaker); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + } } + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(handshaker, this)); } - grpc_handshake_manager_add( - handshake_mgr, grpc_security_handshaker_create( - tsi_create_adapter_handshaker(handshaker), &sc->base)); -} -static void httpcli_ssl_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - grpc_httpcli_ssl_channel_security_connector* c = - reinterpret_cast(sc); - grpc_error* error = GRPC_ERROR_NONE; - - /* Check the peer name. */ - if (c->secure_peer_name != nullptr && - !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) { - char* msg; - gpr_asprintf(&msg, "Peer name %s is not in peer certificate", - c->secure_peer_name); - error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); - gpr_free(msg); + tsi_ssl_client_handshaker_factory* handshaker_factory() const { + return handshaker_factory_; } - GRPC_CLOSURE_SCHED(on_peer_checked, error); - tsi_peer_destruct(&peer); -} -static int httpcli_ssl_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - grpc_httpcli_ssl_channel_security_connector* c1 = - reinterpret_cast(sc1); - grpc_httpcli_ssl_channel_security_connector* c2 = - reinterpret_cast(sc2); - return strcmp(c1->secure_peer_name, c2->secure_peer_name); -} + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* /*auth_context*/, + grpc_closure* on_peer_checked) override { + grpc_error* error = GRPC_ERROR_NONE; + + /* Check the peer name. */ + if (secure_peer_name_ != nullptr && + !tsi_ssl_peer_matches_name(&peer, secure_peer_name_)) { + char* msg; + gpr_asprintf(&msg, "Peer name %s is not in peer certificate", + secure_peer_name_); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + } + GRPC_CLOSURE_SCHED(on_peer_checked, error); + tsi_peer_destruct(&peer); + } -static grpc_security_connector_vtable httpcli_ssl_vtable = { - httpcli_ssl_destroy, httpcli_ssl_check_peer, httpcli_ssl_cmp}; + int cmp(const grpc_security_connector* other_sc) const override { + auto* other = + reinterpret_cast( + other_sc); + return strcmp(secure_peer_name_, other->secure_peer_name_); + } -static grpc_security_status httpcli_ssl_channel_security_connector_create( - const char* pem_root_certs, const tsi_ssl_root_certs_store* root_store, - const char* secure_peer_name, grpc_channel_security_connector** sc) { - tsi_result result = TSI_OK; - grpc_httpcli_ssl_channel_security_connector* c; + bool check_call_host(const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) override { + *error = GRPC_ERROR_NONE; + return true; + } - if (secure_peer_name != nullptr && pem_root_certs == nullptr) { - gpr_log(GPR_ERROR, - "Cannot assert a secure peer name without a trust root."); - return GRPC_SECURITY_ERROR; + void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) override { + GRPC_ERROR_UNREF(error); } - c = static_cast( - gpr_zalloc(sizeof(grpc_httpcli_ssl_channel_security_connector))); + const char* secure_peer_name() const { return secure_peer_name_; } - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.vtable = &httpcli_ssl_vtable; - if (secure_peer_name != nullptr) { - c->secure_peer_name = gpr_strdup(secure_peer_name); + private: + tsi_ssl_client_handshaker_factory* handshaker_factory_ = nullptr; + char* secure_peer_name_; +}; + +static grpc_core::RefCountedPtr +httpcli_ssl_channel_security_connector_create( + const char* pem_root_certs, const tsi_ssl_root_certs_store* root_store, + const char* secure_peer_name) { + if (secure_peer_name != nullptr && pem_root_certs == nullptr) { + gpr_log(GPR_ERROR, + "Cannot assert a secure peer name without a trust root."); + return nullptr; } - tsi_ssl_client_handshaker_options options; - memset(&options, 0, sizeof(options)); - options.pem_root_certs = pem_root_certs; - options.root_store = root_store; - result = tsi_create_ssl_client_handshaker_factory_with_options( - &options, &c->handshaker_factory); + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + secure_peer_name == nullptr ? nullptr : gpr_strdup(secure_peer_name)); + tsi_result result = c->InitHandshakerFactory(pem_root_certs, root_store); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", tsi_result_to_string(result)); - httpcli_ssl_destroy(&c->base.base); - *sc = nullptr; - return GRPC_SECURITY_ERROR; + return nullptr; } - // We don't actually need a channel credentials object in this case, - // but we set it to a non-nullptr address so that we don't trigger - // assertions in grpc_channel_security_connector_cmp(). - c->base.channel_creds = (grpc_channel_credentials*)1; - c->base.add_handshakers = httpcli_ssl_add_handshakers; - *sc = &c->base; - return GRPC_SECURITY_OK; + return c; } /* handshaker */ @@ -148,11 +154,11 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create( typedef struct { void (*func)(void* arg, grpc_endpoint* endpoint); void* arg; - grpc_handshake_manager* handshake_mgr; + grpc_core::RefCountedPtr handshake_mgr; } on_done_closure; static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + auto* args = static_cast(arg); on_done_closure* c = static_cast(args->user_data); if (error != GRPC_ERROR_NONE) { const char* msg = grpc_error_string(error); @@ -165,14 +171,13 @@ static void on_handshake_done(void* arg, grpc_error* error) { gpr_free(args->read_buffer); c->func(c->arg, args->endpoint); } - grpc_handshake_manager_destroy(c->handshake_mgr); - gpr_free(c); + grpc_core::Delete(c); } static void ssl_handshake(void* arg, grpc_endpoint* tcp, const char* host, grpc_millis deadline, void (*on_done)(void* arg, grpc_endpoint* endpoint)) { - on_done_closure* c = static_cast(gpr_malloc(sizeof(*c))); + auto* c = grpc_core::New(); const char* pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); const tsi_ssl_root_certs_store* root_store = @@ -185,18 +190,20 @@ static void ssl_handshake(void* arg, grpc_endpoint* tcp, const char* host, } c->func = on_done; c->arg = arg; - grpc_channel_security_connector* sc = nullptr; - GPR_ASSERT(httpcli_ssl_channel_security_connector_create( - pem_root_certs, root_store, host, &sc) == GRPC_SECURITY_OK); - grpc_arg channel_arg = grpc_security_connector_to_arg(&sc->base); + grpc_core::RefCountedPtr sc = + httpcli_ssl_channel_security_connector_create(pem_root_certs, root_store, + host); + GPR_ASSERT(sc != nullptr); + grpc_arg channel_arg = grpc_security_connector_to_arg(sc.get()); grpc_channel_args args = {1, &channel_arg}; - c->handshake_mgr = grpc_handshake_manager_create(); - grpc_handshakers_add(HANDSHAKER_CLIENT, &args, c->handshake_mgr); - grpc_handshake_manager_do_handshake( - c->handshake_mgr, nullptr /* interested_parties */, tcp, - nullptr /* channel_args */, deadline, nullptr /* acceptor */, - on_handshake_done, c /* user_data */); - GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli"); + c->handshake_mgr = grpc_core::MakeRefCounted(); + grpc_core::HandshakerRegistry::AddHandshakers( + grpc_core::HANDSHAKER_CLIENT, &args, /*interested_parties=*/nullptr, + c->handshake_mgr.get()); + c->handshake_mgr->DoHandshake(tcp, /*channel_args=*/nullptr, deadline, + /*acceptor=*/nullptr, on_handshake_done, + /*user_data=*/c); + sc.reset(DEBUG_LOCATION, "httpcli"); } const grpc_httpcli_handshaker grpc_httpcli_ssl = {"https", ssl_handshake}; diff --git a/Sources/CgRPC/src/core/lib/http/parser.h b/Sources/CgRPC/src/core/lib/http/parser.h index 1d2e13e83..a8f47c96c 100644 --- a/Sources/CgRPC/src/core/lib/http/parser.h +++ b/Sources/CgRPC/src/core/lib/http/parser.h @@ -70,13 +70,13 @@ typedef struct grpc_http_request { /* A response */ typedef struct grpc_http_response { /* HTTP status code */ - int status; + int status = 0; /* Headers: count and key/values */ - size_t hdr_count; - grpc_http_header* hdrs; + size_t hdr_count = 0; + grpc_http_header* hdrs = nullptr; /* Body: length and contents; contents are NOT null-terminated */ - size_t body_length; - char* body; + size_t body_length = 0; + char* body = nullptr; } grpc_http_response; typedef struct { diff --git a/Sources/CgRPC/src/core/lib/iomgr/buffer_list.cc b/Sources/CgRPC/src/core/lib/iomgr/buffer_list.cc new file mode 100644 index 000000000..73915933e --- /dev/null +++ b/Sources/CgRPC/src/core/lib/iomgr/buffer_list.cc @@ -0,0 +1,303 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/buffer_list.h" +#include "src/core/lib/iomgr/port.h" + +#include + +#ifdef GRPC_LINUX_ERRQUEUE +#include +#include +#include + +#include "src/core/lib/gprpp/memory.h" + +namespace grpc_core { +namespace { +/** Fills gpr_timespec gts based on values from timespec ts */ +void fill_gpr_from_timestamp(gpr_timespec* gts, const struct timespec* ts) { + gts->tv_sec = ts->tv_sec; + gts->tv_nsec = static_cast(ts->tv_nsec); + gts->clock_type = GPR_CLOCK_REALTIME; +} + +void default_timestamps_callback(void* arg, grpc_core::Timestamps* ts, + grpc_error* shudown_err) { + gpr_log(GPR_DEBUG, "Timestamps callback has not been registered"); +} + +/** The saved callback function that will be invoked when we get all the + * timestamps that we are going to get for a TracedBuffer. */ +void (*timestamps_callback)(void*, grpc_core::Timestamps*, + grpc_error* shutdown_err) = + default_timestamps_callback; + +/* Used to extract individual opt stats from cmsg, so as to avoid troubles with + * unaligned reads */ +template +T read_unaligned(const void* ptr) { + T val; + memcpy(&val, ptr, sizeof(val)); + return val; +} + +/* Extracts opt stats from the tcp_info struct \a info to \a metrics */ +void extract_opt_stats_from_tcp_info(ConnectionMetrics* metrics, + const grpc_core::tcp_info* info) { + if (info == nullptr) { + return; + } + if (info->length > offsetof(grpc_core::tcp_info, tcpi_sndbuf_limited)) { + metrics->recurring_retrans.set(info->tcpi_retransmits); + metrics->is_delivery_rate_app_limited.set( + info->tcpi_delivery_rate_app_limited); + metrics->congestion_window.set(info->tcpi_snd_cwnd); + metrics->reordering.set(info->tcpi_reordering); + metrics->packet_retx.set(info->tcpi_total_retrans); + metrics->pacing_rate.set(info->tcpi_pacing_rate); + metrics->data_notsent.set(info->tcpi_notsent_bytes); + if (info->tcpi_min_rtt != UINT32_MAX) { + metrics->min_rtt.set(info->tcpi_min_rtt); + } + metrics->packet_sent.set(info->tcpi_data_segs_out); + metrics->delivery_rate.set(info->tcpi_delivery_rate); + metrics->busy_usec.set(info->tcpi_busy_time); + metrics->rwnd_limited_usec.set(info->tcpi_rwnd_limited); + metrics->sndbuf_limited_usec.set(info->tcpi_sndbuf_limited); + } + if (info->length > offsetof(grpc_core::tcp_info, tcpi_dsack_dups)) { + metrics->data_sent.set(info->tcpi_bytes_sent); + metrics->data_retx.set(info->tcpi_bytes_retrans); + metrics->packet_spurious_retx.set(info->tcpi_dsack_dups); + } +} + +/** Extracts opt stats from the given control message \a opt_stats to the + * connection metrics \a metrics */ +void extract_opt_stats_from_cmsg(ConnectionMetrics* metrics, + const cmsghdr* opt_stats) { + if (opt_stats == nullptr) { + return; + } + const auto* data = CMSG_DATA(opt_stats); + constexpr int64_t cmsg_hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr)); + const int64_t len = opt_stats->cmsg_len - cmsg_hdr_len; + int64_t offset = 0; + + while (offset < len) { + const auto* attr = reinterpret_cast(data + offset); + const void* val = data + offset + NLA_HDRLEN; + switch (attr->nla_type) { + case TCP_NLA_BUSY: { + metrics->busy_usec.set(read_unaligned(val)); + break; + } + case TCP_NLA_RWND_LIMITED: { + metrics->rwnd_limited_usec.set(read_unaligned(val)); + break; + } + case TCP_NLA_SNDBUF_LIMITED: { + metrics->sndbuf_limited_usec.set(read_unaligned(val)); + break; + } + case TCP_NLA_PACING_RATE: { + metrics->pacing_rate.set(read_unaligned(val)); + break; + } + case TCP_NLA_DELIVERY_RATE: { + metrics->delivery_rate.set(read_unaligned(val)); + break; + } + case TCP_NLA_DELIVERY_RATE_APP_LMT: { + metrics->is_delivery_rate_app_limited.set(read_unaligned(val)); + break; + } + case TCP_NLA_SND_CWND: { + metrics->congestion_window.set(read_unaligned(val)); + break; + } + case TCP_NLA_MIN_RTT: { + metrics->min_rtt.set(read_unaligned(val)); + break; + } + case TCP_NLA_SRTT: { + metrics->srtt.set(read_unaligned(val)); + break; + } + case TCP_NLA_RECUR_RETRANS: { + metrics->recurring_retrans.set(read_unaligned(val)); + break; + } + case TCP_NLA_BYTES_SENT: { + metrics->data_sent.set(read_unaligned(val)); + break; + } + case TCP_NLA_DATA_SEGS_OUT: { + metrics->packet_sent.set(read_unaligned(val)); + break; + } + case TCP_NLA_TOTAL_RETRANS: { + metrics->packet_retx.set(read_unaligned(val)); + break; + } + case TCP_NLA_DELIVERED: { + metrics->packet_delivered.set(read_unaligned(val)); + break; + } + case TCP_NLA_DELIVERED_CE: { + metrics->packet_delivered_ce.set(read_unaligned(val)); + break; + } + case TCP_NLA_BYTES_RETRANS: { + metrics->data_retx.set(read_unaligned(val)); + break; + } + case TCP_NLA_DSACK_DUPS: { + metrics->packet_spurious_retx.set(read_unaligned(val)); + break; + } + case TCP_NLA_REORDERING: { + metrics->reordering.set(read_unaligned(val)); + break; + } + case TCP_NLA_SND_SSTHRESH: { + metrics->snd_ssthresh.set(read_unaligned(val)); + break; + } + } + offset += NLA_ALIGN(attr->nla_len); + } +} + +static int get_socket_tcp_info(grpc_core::tcp_info* info, int fd) { + memset(info, 0, sizeof(*info)); + info->length = sizeof(*info) - sizeof(socklen_t); + return getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &(info->length)); +} +} /* namespace */ + +void TracedBuffer::AddNewEntry(TracedBuffer** head, uint32_t seq_no, int fd, + void* arg) { + GPR_DEBUG_ASSERT(head != nullptr); + TracedBuffer* new_elem = New(seq_no, arg); + /* Store the current time as the sendmsg time. */ + new_elem->ts_.sendmsg_time.time = gpr_now(GPR_CLOCK_REALTIME); + new_elem->ts_.scheduled_time.time = gpr_inf_past(GPR_CLOCK_REALTIME); + new_elem->ts_.sent_time.time = gpr_inf_past(GPR_CLOCK_REALTIME); + new_elem->ts_.acked_time.time = gpr_inf_past(GPR_CLOCK_REALTIME); + + if (get_socket_tcp_info(&new_elem->ts_.info, fd) == 0) { + extract_opt_stats_from_tcp_info(&new_elem->ts_.sendmsg_time.metrics, + &new_elem->ts_.info); + } + if (*head == nullptr) { + *head = new_elem; + return; + } + /* Append at the end. */ + TracedBuffer* ptr = *head; + while (ptr->next_ != nullptr) { + ptr = ptr->next_; + } + ptr->next_ = new_elem; +} + +void TracedBuffer::ProcessTimestamp(TracedBuffer** head, + struct sock_extended_err* serr, + struct cmsghdr* opt_stats, + struct scm_timestamping* tss) { + GPR_DEBUG_ASSERT(head != nullptr); + TracedBuffer* elem = *head; + TracedBuffer* next = nullptr; + while (elem != nullptr) { + /* The byte number refers to the sequence number of the last byte which this + * timestamp relates to. */ + if (serr->ee_data >= elem->seq_no_) { + switch (serr->ee_info) { + case SCM_TSTAMP_SCHED: + fill_gpr_from_timestamp(&(elem->ts_.scheduled_time.time), + &(tss->ts[0])); + extract_opt_stats_from_cmsg(&(elem->ts_.scheduled_time.metrics), + opt_stats); + elem = elem->next_; + break; + case SCM_TSTAMP_SND: + fill_gpr_from_timestamp(&(elem->ts_.sent_time.time), &(tss->ts[0])); + extract_opt_stats_from_cmsg(&(elem->ts_.sent_time.metrics), + opt_stats); + elem = elem->next_; + break; + case SCM_TSTAMP_ACK: + fill_gpr_from_timestamp(&(elem->ts_.acked_time.time), &(tss->ts[0])); + extract_opt_stats_from_cmsg(&(elem->ts_.acked_time.metrics), + opt_stats); + /* Got all timestamps. Do the callback and free this TracedBuffer. + * The thing below can be passed by value if we don't want the + * restriction on the lifetime. */ + timestamps_callback(elem->arg_, &(elem->ts_), GRPC_ERROR_NONE); + next = elem->next_; + Delete(elem); + *head = elem = next; + break; + default: + abort(); + } + } else { + break; + } + } +} + +void TracedBuffer::Shutdown(TracedBuffer** head, void* remaining, + grpc_error* shutdown_err) { + GPR_DEBUG_ASSERT(head != nullptr); + TracedBuffer* elem = *head; + while (elem != nullptr) { + timestamps_callback(elem->arg_, &(elem->ts_), shutdown_err); + auto* next = elem->next_; + Delete(elem); + elem = next; + } + *head = nullptr; + if (remaining != nullptr) { + timestamps_callback(remaining, nullptr, shutdown_err); + } + GRPC_ERROR_UNREF(shutdown_err); +} + +void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)) { + timestamps_callback = fn; +} +} /* namespace grpc_core */ + +#else /* GRPC_LINUX_ERRQUEUE */ + +namespace grpc_core { +void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)) { + gpr_log(GPR_DEBUG, "Timestamps callback is not enabled for this platform"); +} +} /* namespace grpc_core */ + +#endif /* GRPC_LINUX_ERRQUEUE */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/buffer_list.h b/Sources/CgRPC/src/core/lib/iomgr/buffer_list.h new file mode 100644 index 000000000..3dba15312 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/iomgr/buffer_list.h @@ -0,0 +1,165 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H +#define GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H + +#include + +#include "src/core/lib/iomgr/port.h" + +#include + +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/optional.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/internal_errqueue.h" + +namespace grpc_core { + +struct ConnectionMetrics { + /* Delivery rate in Bytes/s. */ + Optional delivery_rate; + /* If the delivery rate is limited by the application, this is set to true. */ + Optional is_delivery_rate_app_limited; + /* Total packets retransmitted. */ + Optional packet_retx; + /* Total packets retransmitted spuriously. This metric is smaller than or + equal to packet_retx. */ + Optional packet_spurious_retx; + /* Total packets sent. */ + Optional packet_sent; + /* Total packets delivered. */ + Optional packet_delivered; + /* Total packets delivered with ECE marked. This metric is smaller than or + equal to packet_delivered. */ + Optional packet_delivered_ce; + /* Total bytes lost so far. */ + Optional data_retx; + /* Total bytes sent so far. */ + Optional data_sent; + /* Total bytes in write queue but not sent. */ + Optional data_notsent; + /* Pacing rate of the connection in Bps */ + Optional pacing_rate; + /* Minimum RTT observed in usec. */ + Optional min_rtt; + /* Smoothed RTT in usec */ + Optional srtt; + /* Send congestion window. */ + Optional congestion_window; + /* Slow start threshold in packets. */ + Optional snd_ssthresh; + /* Maximum degree of reordering (i.e., maximum number of packets reodered) + on the connection. */ + Optional reordering; + /* Represents the number of recurring retransmissions of the first sequence + that is not acknowledged yet. */ + Optional recurring_retrans; + /* The cumulative time (in usec) that the transport protocol was busy + sending data. */ + Optional busy_usec; + /* The cumulative time (in usec) that the transport protocol was limited by + the receive window size. */ + Optional rwnd_limited_usec; + /* The cumulative time (in usec) that the transport protocol was limited by + the send buffer size. */ + Optional sndbuf_limited_usec; +}; + +struct Timestamp { + gpr_timespec time; + ConnectionMetrics metrics; /* Metrics collected with this timestamp */ +}; + +struct Timestamps { + Timestamp sendmsg_time; + Timestamp scheduled_time; + Timestamp sent_time; + Timestamp acked_time; + + uint32_t byte_offset; /* byte offset relative to the start of the RPC */ + +#ifdef GRPC_LINUX_ERRQUEUE + grpc_core::tcp_info info; /* tcp_info collected on sendmsg */ +#endif /* GRPC_LINUX_ERRQUEUE */ +}; + +/** TracedBuffer is a class to keep track of timestamps for a specific buffer in + * the TCP layer. We are only tracking timestamps for Linux kernels and hence + * this class would only be used by Linux platforms. For all other platforms, + * TracedBuffer would be an empty class. + * + * The timestamps collected are according to grpc_core::Timestamps declared + * above. + * + * A TracedBuffer list is kept track of using the head element of the list. If + * the head element of the list is nullptr, then the list is empty. + */ +#ifdef GRPC_LINUX_ERRQUEUE +class TracedBuffer { + public: + /** Add a new entry in the TracedBuffer list pointed to by head. Also saves + * sendmsg_time with the current timestamp. */ + static void AddNewEntry(grpc_core::TracedBuffer** head, uint32_t seq_no, + int fd, void* arg); + + /** Processes a received timestamp based on sock_extended_err and + * scm_timestamping structures. It will invoke the timestamps callback if the + * timestamp type is SCM_TSTAMP_ACK. */ + static void ProcessTimestamp(grpc_core::TracedBuffer** head, + struct sock_extended_err* serr, + struct cmsghdr* opt_stats, + struct scm_timestamping* tss); + + /** Cleans the list by calling the callback for each traced buffer in the list + * with timestamps that it has. */ + static void Shutdown(grpc_core::TracedBuffer** head, void* remaining, + grpc_error* shutdown_err); + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + + TracedBuffer(uint32_t seq_no, void* arg) + : seq_no_(seq_no), arg_(arg), next_(nullptr) {} + + uint32_t seq_no_; /* The sequence number for the last byte in the buffer */ + void* arg_; /* The arg to pass to timestamps_callback */ + grpc_core::Timestamps ts_; /* The timestamps corresponding to this buffer */ + grpc_core::TracedBuffer* next_; /* The next TracedBuffer in the list */ +}; +#else /* GRPC_LINUX_ERRQUEUE */ +class TracedBuffer { + public: + /* Dummy shutdown function */ + static void Shutdown(grpc_core::TracedBuffer** head, void* remaining, + grpc_error* shutdown_err) { + GRPC_ERROR_UNREF(shutdown_err); + } +}; +#endif /* GRPC_LINUX_ERRQUEUE */ + +/** Sets the callback function to call when timestamps for a write are + * collected. The callback does not own a reference to error. */ +void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)); + +}; /* namespace grpc_core */ + +#endif /* GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/call_combiner.cc b/Sources/CgRPC/src/core/lib/iomgr/call_combiner.cc index 00a839b64..6b5759a03 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/call_combiner.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/call_combiner.cc @@ -39,8 +39,57 @@ static gpr_atm encode_cancel_state_error(grpc_error* error) { return static_cast(1) | (gpr_atm)error; } +#ifdef GRPC_TSAN_ENABLED +static void tsan_closure(void* user_data, grpc_error* error) { + grpc_call_combiner* call_combiner = + static_cast(user_data); + // We ref-count the lock, and check if it's already taken. + // If it was taken, we should do nothing. Otherwise, we will mark it as + // locked. Note that if two different threads try to do this, only one of + // them will be able to mark the lock as acquired, while they both run their + // callbacks. In such cases (which should never happen for call_combiner), + // TSAN will correctly produce an error. + // + // TODO(soheil): This only covers the callbacks scheduled by + // grpc_call_combiner_(start|finish). If in the future, a + // callback gets scheduled using other mechanisms, we will need + // to add APIs to externally lock call combiners. + grpc_core::RefCountedPtr lock = + call_combiner->tsan_lock; + bool prev = false; + if (lock->taken.compare_exchange_strong(prev, true)) { + TSAN_ANNOTATE_RWLOCK_ACQUIRED(&lock->taken, true); + } else { + lock.reset(); + } + GRPC_CLOSURE_RUN(call_combiner->original_closure, GRPC_ERROR_REF(error)); + if (lock != nullptr) { + TSAN_ANNOTATE_RWLOCK_RELEASED(&lock->taken, true); + bool prev = true; + GPR_ASSERT(lock->taken.compare_exchange_strong(prev, false)); + } +} +#endif + +static void call_combiner_sched_closure(grpc_call_combiner* call_combiner, + grpc_closure* closure, + grpc_error* error) { +#ifdef GRPC_TSAN_ENABLED + call_combiner->original_closure = closure; + GRPC_CLOSURE_SCHED(&call_combiner->tsan_closure, error); +#else + GRPC_CLOSURE_SCHED(closure, error); +#endif +} + void grpc_call_combiner_init(grpc_call_combiner* call_combiner) { + gpr_atm_no_barrier_store(&call_combiner->cancel_state, 0); + gpr_atm_no_barrier_store(&call_combiner->size, 0); gpr_mpscq_init(&call_combiner->queue); +#ifdef GRPC_TSAN_ENABLED + GRPC_CLOSURE_INIT(&call_combiner->tsan_closure, tsan_closure, call_combiner, + grpc_schedule_on_exec_ctx); +#endif } void grpc_call_combiner_destroy(grpc_call_combiner* call_combiner) { @@ -85,7 +134,7 @@ void grpc_call_combiner_start(grpc_call_combiner* call_combiner, gpr_log(GPR_INFO, " EXECUTING IMMEDIATELY"); } // Queue was empty, so execute this closure immediately. - GRPC_CLOSURE_SCHED(closure, error); + call_combiner_sched_closure(call_combiner, closure, error); } else { if (grpc_call_combiner_trace.enabled()) { gpr_log(GPR_INFO, " QUEUING"); @@ -132,7 +181,8 @@ void grpc_call_combiner_stop(grpc_call_combiner* call_combiner DEBUG_ARGS, gpr_log(GPR_INFO, " EXECUTING FROM QUEUE: closure=%p error=%s", closure, grpc_error_string(closure->error_data.error)); } - GRPC_CLOSURE_SCHED(closure, closure->error_data.error); + call_combiner_sched_closure(call_combiner, closure, + closure->error_data.error); break; } } else if (grpc_call_combiner_trace.enabled()) { diff --git a/Sources/CgRPC/src/core/lib/iomgr/call_combiner.h b/Sources/CgRPC/src/core/lib/iomgr/call_combiner.h index 0ccd08ea5..4ec0044f0 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/call_combiner.h +++ b/Sources/CgRPC/src/core/lib/iomgr/call_combiner.h @@ -26,7 +26,11 @@ #include #include "src/core/lib/gpr/mpscq.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/dynamic_annotations.h" // A simple, lock-free mechanism for serializing activity related to a // single call. This is similar to a combiner but is more lightweight. @@ -39,14 +43,38 @@ extern grpc_core::TraceFlag grpc_call_combiner_trace; -typedef struct { - gpr_atm size; // size_t, num closures in queue or currently executing +struct grpc_call_combiner { + gpr_atm size = 0; // size_t, num closures in queue or currently executing gpr_mpscq queue; // Either 0 (if not cancelled and no cancellation closure set), // a grpc_closure* (if the lowest bit is 0), // or a grpc_error* (if the lowest bit is 1). - gpr_atm cancel_state; -} grpc_call_combiner; + gpr_atm cancel_state = 0; +#ifdef GRPC_TSAN_ENABLED + // A fake ref-counted lock that is kept alive after the destruction of + // grpc_call_combiner, when we are running the original closure. + // + // Ideally we want to lock and unlock the call combiner as a pointer, when the + // callback is called. However, original_closure is free to trigger + // anything on the call combiner (including destruction of grpc_call). + // Thus, we need a ref-counted structure that can outlive the call combiner. + struct TsanLock + : public grpc_core::RefCounted { + TsanLock() { TSAN_ANNOTATE_RWLOCK_CREATE(&taken); } + ~TsanLock() { TSAN_ANNOTATE_RWLOCK_DESTROY(&taken); } + + // To avoid double-locking by the same thread, we should acquire/release + // the lock only when taken is false. On each acquire taken must be set to + // true. + std::atomic taken{false}; + }; + grpc_core::RefCountedPtr tsan_lock = + grpc_core::MakeRefCounted(); + grpc_closure tsan_closure; + grpc_closure* original_closure; +#endif +}; // Assumes memory was initialized to zero. void grpc_call_combiner_init(grpc_call_combiner* call_combiner); @@ -101,7 +129,10 @@ void grpc_call_combiner_stop(grpc_call_combiner* call_combiner, /// If \a closure is NULL, then no closure will be invoked on /// cancellation; this effectively unregisters the previously set closure. /// However, most filters will not need to explicitly unregister their -/// callbacks, as this is done automatically when the call is destroyed. +/// callbacks, as this is done automatically when the call is destroyed. Filters +/// that schedule the cancellation closure on ExecCtx do not need to take a ref +/// on the call stack to guarantee closure liveness. This is done by explicitly +/// flushing ExecCtx after the unregistration during call destruction. void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner, grpc_closure* closure); @@ -109,4 +140,83 @@ void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner, void grpc_call_combiner_cancel(grpc_call_combiner* call_combiner, grpc_error* error); +namespace grpc_core { + +// Helper for running a list of closures in a call combiner. +// +// Each callback running in the call combiner will eventually be +// returned to the surface, at which point the surface will yield the +// call combiner. So when we are running in the call combiner and have +// more than one callback to return to the surface, we need to re-enter +// the call combiner for all but one of those callbacks. +class CallCombinerClosureList { + public: + CallCombinerClosureList() {} + + // Adds a closure to the list. The closure must eventually result in + // the call combiner being yielded. + void Add(grpc_closure* closure, grpc_error* error, const char* reason) { + closures_.emplace_back(closure, error, reason); + } + + // Runs all closures in the call combiner and yields the call combiner. + // + // All but one of the closures in the list will be scheduled via + // GRPC_CALL_COMBINER_START(), and the remaining closure will be + // scheduled via GRPC_CLOSURE_SCHED(), which will eventually result in + // yielding the call combiner. If the list is empty, then the call + // combiner will be yielded immediately. + void RunClosures(grpc_call_combiner* call_combiner) { + if (closures_.empty()) { + GRPC_CALL_COMBINER_STOP(call_combiner, "no closures to schedule"); + return; + } + for (size_t i = 1; i < closures_.size(); ++i) { + auto& closure = closures_[i]; + GRPC_CALL_COMBINER_START(call_combiner, closure.closure, closure.error, + closure.reason); + } + if (grpc_call_combiner_trace.enabled()) { + gpr_log(GPR_INFO, + "CallCombinerClosureList executing closure while already " + "holding call_combiner %p: closure=%p error=%s reason=%s", + call_combiner, closures_[0].closure, + grpc_error_string(closures_[0].error), closures_[0].reason); + } + // This will release the call combiner. + GRPC_CLOSURE_SCHED(closures_[0].closure, closures_[0].error); + closures_.clear(); + } + + // Runs all closures in the call combiner, but does NOT yield the call + // combiner. All closures will be scheduled via GRPC_CALL_COMBINER_START(). + void RunClosuresWithoutYielding(grpc_call_combiner* call_combiner) { + for (size_t i = 0; i < closures_.size(); ++i) { + auto& closure = closures_[i]; + GRPC_CALL_COMBINER_START(call_combiner, closure.closure, closure.error, + closure.reason); + } + closures_.clear(); + } + + size_t size() const { return closures_.size(); } + + private: + struct CallCombinerClosure { + grpc_closure* closure; + grpc_error* error; + const char* reason; + + CallCombinerClosure(grpc_closure* closure, grpc_error* error, + const char* reason) + : closure(closure), error(error), reason(reason) {} + }; + + // There are generally a maximum of 6 closures to run in the call + // combiner, one for each pending op. + InlinedVector closures_; +}; + +} // namespace grpc_core + #endif /* GRPC_CORE_LIB_IOMGR_CALL_COMBINER_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/closure.h b/Sources/CgRPC/src/core/lib/iomgr/closure.h index 34a494485..bde3437c0 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/closure.h +++ b/Sources/CgRPC/src/core/lib/iomgr/closure.h @@ -114,6 +114,7 @@ inline grpc_closure* grpc_closure_init(grpc_closure* closure, closure->cb = cb; closure->cb_arg = cb_arg; closure->scheduler = scheduler; + closure->error_data.error = GRPC_ERROR_NONE; #ifndef NDEBUG closure->scheduled = false; closure->file_initiated = nullptr; @@ -283,9 +284,10 @@ inline void grpc_closure_sched(grpc_closure* c, grpc_error* error) { if (c->scheduled) { gpr_log(GPR_ERROR, "Closure already scheduled. (closure: %p, created: [%s:%d], " - "previously scheduled at: [%s: %d] run?: %s", + "previously scheduled at: [%s: %d], newly scheduled at [%s: %d], " + "run?: %s", c, c->file_created, c->line_created, c->file_initiated, - c->line_initiated, c->run ? "true" : "false"); + c->line_initiated, file, line, c->run ? "true" : "false"); abort(); } c->scheduled = true; diff --git a/Sources/CgRPC/src/core/lib/iomgr/combiner.cc b/Sources/CgRPC/src/core/lib/iomgr/combiner.cc index 9429842eb..4fc4a9dcc 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/combiner.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/combiner.cc @@ -29,9 +29,10 @@ #include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/profiling/timers.h" -grpc_core::TraceFlag grpc_combiner_trace(false, "combiner"); +grpc_core::DebugOnlyTraceFlag grpc_combiner_trace(false, "combiner"); #define GRPC_COMBINER_TRACE(fn) \ do { \ @@ -63,11 +64,12 @@ struct grpc_combiner { gpr_refcount refs; }; +static void combiner_run(grpc_closure* closure, grpc_error* error); static void combiner_exec(grpc_closure* closure, grpc_error* error); static void combiner_finally_exec(grpc_closure* closure, grpc_error* error); static const grpc_closure_scheduler_vtable scheduler = { - combiner_exec, combiner_exec, "combiner:immediately"}; + combiner_run, combiner_exec, "combiner:immediately"}; static const grpc_closure_scheduler_vtable finally_scheduler = { combiner_finally_exec, combiner_finally_exec, "combiner:finally"}; @@ -81,8 +83,9 @@ grpc_combiner* grpc_combiner_create(void) { gpr_atm_no_barrier_store(&lock->state, STATE_UNORPHANED); gpr_mpscq_init(&lock->queue); grpc_closure_list_init(&lock->final_list); - GRPC_CLOSURE_INIT(&lock->offload, offload, lock, - grpc_executor_scheduler(GRPC_EXECUTOR_SHORT)); + GRPC_CLOSURE_INIT( + &lock->offload, offload, lock, + grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT)); GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p create", lock)); return lock; } @@ -227,8 +230,14 @@ bool grpc_combiner_continue_exec_ctx() { grpc_core::ExecCtx::Get()->IsReadyToFinish(), lock->time_to_execute_final_list)); + // offload only if all the following conditions are true: + // 1. the combiner is contended and has more than one closure to execute + // 2. the current execution context needs to finish as soon as possible + // 3. the DEFAULT executor is threaded + // 4. the current thread is not a worker for any background poller if (contended && grpc_core::ExecCtx::Get()->IsReadyToFinish() && - grpc_executor_is_threaded()) { + grpc_core::Executor::IsThreadedDefault() && + !grpc_iomgr_is_any_background_poller_thread()) { GPR_TIMER_MARK("offload_from_finished_exec_ctx", 0); // this execution context wants to move on: schedule remaining work to be // picked up on the executor @@ -343,6 +352,22 @@ static void combiner_finally_exec(grpc_closure* closure, grpc_error* error) { grpc_closure_list_append(&lock->final_list, closure, error); } +static void combiner_run(grpc_closure* closure, grpc_error* error) { + grpc_combiner* lock = COMBINER_FROM_CLOSURE_SCHEDULER(closure, scheduler); +#ifndef NDEBUG + closure->scheduled = false; + GRPC_COMBINER_TRACE(gpr_log( + GPR_DEBUG, + "Combiner:%p grpc_combiner_run closure:%p created [%s:%d] run [%s:%d]", + lock, closure, closure->file_created, closure->line_created, + closure->file_initiated, closure->line_initiated)); +#endif + GPR_ASSERT(grpc_core::ExecCtx::Get()->combiner_data()->active_combiner == + lock); + closure->cb(closure->cb_arg, error); + GRPC_ERROR_UNREF(error); +} + static void enqueue_finally(void* closure, grpc_error* error) { combiner_finally_exec(static_cast(closure), GRPC_ERROR_REF(error)); diff --git a/Sources/CgRPC/src/core/lib/iomgr/combiner.h b/Sources/CgRPC/src/core/lib/iomgr/combiner.h index 0d63e468d..3c947bf9d 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/combiner.h +++ b/Sources/CgRPC/src/core/lib/iomgr/combiner.h @@ -61,6 +61,6 @@ grpc_closure_scheduler* grpc_combiner_finally_scheduler(grpc_combiner* lock); bool grpc_combiner_continue_exec_ctx(); -extern grpc_core::TraceFlag grpc_combiner_trace; +extern grpc_core::DebugOnlyTraceFlag grpc_combiner_trace; #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/dynamic_annotations.h b/Sources/CgRPC/src/core/lib/iomgr/dynamic_annotations.h new file mode 100644 index 000000000..713928023 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/iomgr/dynamic_annotations.h @@ -0,0 +1,67 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_DYNAMIC_ANNOTATIONS_H +#define GRPC_CORE_LIB_IOMGR_DYNAMIC_ANNOTATIONS_H + +#include + +#ifdef GRPC_TSAN_ENABLED + +#define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) \ + AnnotateHappensBefore(__FILE__, __LINE__, (void*)(addr)) +#define TSAN_ANNOTATE_HAPPENS_AFTER(addr) \ + AnnotateHappensAfter(__FILE__, __LINE__, (void*)(addr)) +#define TSAN_ANNOTATE_RWLOCK_CREATE(addr) \ + AnnotateRWLockCreate(__FILE__, __LINE__, (void*)(addr)) +#define TSAN_ANNOTATE_RWLOCK_DESTROY(addr) \ + AnnotateRWLockDestroy(__FILE__, __LINE__, (void*)(addr)) +#define TSAN_ANNOTATE_RWLOCK_ACQUIRED(addr, is_w) \ + AnnotateRWLockAcquired(__FILE__, __LINE__, (void*)(addr), (is_w)) +#define TSAN_ANNOTATE_RWLOCK_RELEASED(addr, is_w) \ + AnnotateRWLockReleased(__FILE__, __LINE__, (void*)(addr), (is_w)) + +#ifdef __cplusplus +extern "C" { +#endif +void AnnotateHappensBefore(const char* file, int line, const volatile void* cv); +void AnnotateHappensAfter(const char* file, int line, const volatile void* cv); +void AnnotateRWLockCreate(const char* file, int line, + const volatile void* lock); +void AnnotateRWLockDestroy(const char* file, int line, + const volatile void* lock); +void AnnotateRWLockAcquired(const char* file, int line, + const volatile void* lock, long is_w); +void AnnotateRWLockReleased(const char* file, int line, + const volatile void* lock, long is_w); +#ifdef __cplusplus +} +#endif + +#else /* GRPC_TSAN_ENABLED */ + +#define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) +#define TSAN_ANNOTATE_HAPPENS_AFTER(addr) +#define TSAN_ANNOTATE_RWLOCK_CREATE(addr) +#define TSAN_ANNOTATE_RWLOCK_DESTROY(addr) +#define TSAN_ANNOTATE_RWLOCK_ACQUIRED(addr, is_w) +#define TSAN_ANNOTATE_RWLOCK_RELEASED(addr, is_w) + +#endif /* GRPC_TSAN_ENABLED */ + +#endif /* GRPC_CORE_LIB_IOMGR_DYNAMIC_ANNOTATIONS_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/endpoint.cc b/Sources/CgRPC/src/core/lib/iomgr/endpoint.cc index 92e793011..06316c603 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/endpoint.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/endpoint.cc @@ -28,8 +28,8 @@ void grpc_endpoint_read(grpc_endpoint* ep, grpc_slice_buffer* slices, } void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { - ep->vtable->write(ep, slices, cb); + grpc_closure* cb, void* arg) { + ep->vtable->write(ep, slices, cb, arg); } void grpc_endpoint_add_to_pollset(grpc_endpoint* ep, grpc_pollset* pollset) { @@ -61,3 +61,7 @@ int grpc_endpoint_get_fd(grpc_endpoint* ep) { return ep->vtable->get_fd(ep); } grpc_resource_user* grpc_endpoint_get_resource_user(grpc_endpoint* ep) { return ep->vtable->get_resource_user(ep); } + +bool grpc_endpoint_can_track_err(grpc_endpoint* ep) { + return ep->vtable->can_track_err(ep); +} diff --git a/Sources/CgRPC/src/core/lib/iomgr/endpoint.h b/Sources/CgRPC/src/core/lib/iomgr/endpoint.h index 15db1649f..79c8ece26 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/endpoint.h +++ b/Sources/CgRPC/src/core/lib/iomgr/endpoint.h @@ -33,10 +33,12 @@ typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; +class Timestamps; struct grpc_endpoint_vtable { void (*read)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb); - void (*write)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb); + void (*write)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb, + void* arg); void (*add_to_pollset)(grpc_endpoint* ep, grpc_pollset* pollset); void (*add_to_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); void (*delete_from_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); @@ -45,6 +47,7 @@ struct grpc_endpoint_vtable { grpc_resource_user* (*get_resource_user)(grpc_endpoint* ep); char* (*get_peer)(grpc_endpoint* ep); int (*get_fd)(grpc_endpoint* ep); + bool (*can_track_err)(grpc_endpoint* ep); }; /* When data is available on the connection, calls the callback with slices. @@ -70,9 +73,11 @@ int grpc_endpoint_get_fd(grpc_endpoint* ep); \a slices may be mutated at will by the endpoint until cb is called. No guarantee is made to the content of slices after a write EXCEPT that it is a valid slice buffer. + \a arg is platform specific. It is currently only used by TCP on linux + platforms as an argument that would be forwarded to the timestamps callback. */ void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb); + grpc_closure* cb, void* arg); /* Causes any pending and future read/write callbacks to run immediately with success==0 */ @@ -91,6 +96,8 @@ void grpc_endpoint_delete_from_pollset_set(grpc_endpoint* ep, grpc_resource_user* grpc_endpoint_get_resource_user(grpc_endpoint* endpoint); +bool grpc_endpoint_can_track_err(grpc_endpoint* ep); + struct grpc_endpoint { const grpc_endpoint_vtable* vtable; }; diff --git a/Sources/CgRPC/src/core/lib/iomgr/endpoint_pair_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/endpoint_pair_posix.cc index 49850ab3a..5c5c246f9 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/endpoint_pair_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/endpoint_pair_posix.cc @@ -59,11 +59,11 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char* name, grpc_core::ExecCtx exec_ctx; gpr_asprintf(&final_name, "%s:client", name); - p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), args, + p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name, false), args, "socketpair-server"); gpr_free(final_name); gpr_asprintf(&final_name, "%s:server", name); - p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), args, + p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name, false), args, "socketpair-client"); gpr_free(final_name); diff --git a/Sources/CgRPC/src/core/lib/iomgr/error.cc b/Sources/CgRPC/src/core/lib/iomgr/error.cc index 4088cf612..f4abad9b2 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/error.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/error.cc @@ -121,14 +121,8 @@ static const char* error_time_name(grpc_error_times key) { GPR_UNREACHABLE_CODE(return "unknown"); } -bool grpc_error_is_special(grpc_error* err) { - return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM || - err == GRPC_ERROR_CANCELLED; -} - #ifndef NDEBUG -grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) { - if (grpc_error_is_special(err)) return err; +grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line) { if (grpc_trace_error_refcount.enabled()) { gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err, gpr_atm_no_barrier_load(&err->atomics.refs.count), @@ -138,8 +132,7 @@ grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) { return err; } #else -grpc_error* grpc_error_ref(grpc_error* err) { - if (grpc_error_is_special(err)) return err; +grpc_error* grpc_error_do_ref(grpc_error* err) { gpr_ref(&err->atomics.refs); return err; } @@ -177,8 +170,7 @@ static void error_destroy(grpc_error* err) { } #ifndef NDEBUG -void grpc_error_unref(grpc_error* err, const char* file, int line) { - if (grpc_error_is_special(err)) return; +void grpc_error_do_unref(grpc_error* err, const char* file, int line) { if (grpc_trace_error_refcount.enabled()) { gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err, gpr_atm_no_barrier_load(&err->atomics.refs.count), @@ -189,8 +181,7 @@ void grpc_error_unref(grpc_error* err, const char* file, int line) { } } #else -void grpc_error_unref(grpc_error* err) { - if (grpc_error_is_special(err)) return; +void grpc_error_do_unref(grpc_error* err) { if (gpr_unref(&err->atomics.refs)) { error_destroy(err); } @@ -312,6 +303,16 @@ static void internal_add_error(grpc_error** err, grpc_error* new_err) { // It is very common to include and extra int and string in an error #define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) +static gpr_atm g_error_creation_allowed = true; + +void grpc_disable_error_creation() { + gpr_atm_no_barrier_store(&g_error_creation_allowed, false); +} + +void grpc_enable_error_creation() { + gpr_atm_no_barrier_store(&g_error_creation_allowed, true); +} + grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, grpc_error** referencing, size_t num_referencing) { @@ -326,6 +327,12 @@ grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, return GRPC_ERROR_OOM; } #ifndef NDEBUG + if (!gpr_atm_no_barrier_load(&g_error_creation_allowed)) { + gpr_log(GPR_ERROR, + "Error creation occurred when error creation was disabled [%s:%d]", + file, line); + abort(); + } if (grpc_trace_error_refcount.enabled()) { gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line); } @@ -438,28 +445,23 @@ grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which, } typedef struct { - grpc_error* error; grpc_status_code code; const char* msg; } special_error_status_map; -static special_error_status_map error_status_map[] = { - {GRPC_ERROR_NONE, GRPC_STATUS_OK, ""}, - {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"}, - {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"}, +static const special_error_status_map error_status_map[] = { + {GRPC_STATUS_OK, ""}, // GRPC_ERROR_NONE + {GRPC_STATUS_INVALID_ARGUMENT, ""}, // GRPC_ERROR_RESERVED_1 + {GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"}, // GRPC_ERROR_OOM + {GRPC_STATUS_INVALID_ARGUMENT, ""}, // GRPC_ERROR_RESERVED_2 + {GRPC_STATUS_CANCELLED, "Cancelled"}, // GRPC_ERROR_CANCELLED }; bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) { GPR_TIMER_SCOPE("grpc_error_get_int", 0); if (grpc_error_is_special(err)) { - if (which == GRPC_ERROR_INT_GRPC_STATUS) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { - if (error_status_map[i].error == err) { - if (p != nullptr) *p = error_status_map[i].code; - return true; - } - } - } - return false; + if (which != GRPC_ERROR_INT_GRPC_STATUS) return false; + *p = error_status_map[reinterpret_cast(err)].code; + return true; } uint8_t slot = err->ints[which]; if (slot != UINT8_MAX) { @@ -480,15 +482,10 @@ grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which, bool grpc_error_get_str(grpc_error* err, grpc_error_strs which, grpc_slice* str) { if (grpc_error_is_special(err)) { - if (which == GRPC_ERROR_STR_GRPC_MESSAGE) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { - if (error_status_map[i].error == err) { - *str = grpc_slice_from_static_string(error_status_map[i].msg); - return true; - } - } - } - return false; + if (which != GRPC_ERROR_STR_GRPC_MESSAGE) return false; + *str = grpc_slice_from_static_string( + error_status_map[reinterpret_cast(err)].msg); + return true; } uint8_t slot = err->strs[which]; if (slot != UINT8_MAX) { @@ -501,9 +498,24 @@ bool grpc_error_get_str(grpc_error* err, grpc_error_strs which, grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) { GPR_TIMER_SCOPE("grpc_error_add_child", 0); - grpc_error* new_err = copy_error_and_unref(src); - internal_add_error(&new_err, child); - return new_err; + if (src != GRPC_ERROR_NONE) { + if (child == GRPC_ERROR_NONE) { + /* \a child is empty. Simply return the ref to \a src */ + return src; + } else if (child != src) { + grpc_error* new_err = copy_error_and_unref(src); + internal_add_error(&new_err, child); + return new_err; + } else { + /* \a src and \a child are the same. Drop one of the references and return + * the other */ + GRPC_ERROR_UNREF(child); + return src; + } + } else { + /* \a src is empty. Simply return the ref to \a child */ + return child; + } } static const char* no_error_string = "\"No Error\""; @@ -757,7 +769,7 @@ grpc_error* grpc_os_error(const char* file, int line, int err, grpc_error_set_str( grpc_error_set_int( grpc_error_create(file, line, - grpc_slice_from_static_string("OS Error"), + grpc_slice_from_static_string(strerror(err)), nullptr, 0), GRPC_ERROR_INT_ERRNO, err), GRPC_ERROR_STR_OS_ERROR, diff --git a/Sources/CgRPC/src/core/lib/iomgr/error.h b/Sources/CgRPC/src/core/lib/iomgr/error.h index f8cae4da8..cb740d5b0 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/error.h +++ b/Sources/CgRPC/src/core/lib/iomgr/error.h @@ -120,8 +120,20 @@ typedef enum { /// polling engines) can safely use the lower bit for themselves. #define GRPC_ERROR_NONE ((grpc_error*)NULL) +#define GRPC_ERROR_RESERVED_1 ((grpc_error*)1) #define GRPC_ERROR_OOM ((grpc_error*)2) +#define GRPC_ERROR_RESERVED_2 ((grpc_error*)3) #define GRPC_ERROR_CANCELLED ((grpc_error*)4) +#define GRPC_ERROR_SPECIAL_MAX GRPC_ERROR_CANCELLED + +inline bool grpc_error_is_special(struct grpc_error* err) { + return err <= GRPC_ERROR_SPECIAL_MAX; +} + +// debug only toggles that allow for a sanity to check that ensures we will +// never create any errors in the per-RPC hotpath. +void grpc_disable_error_creation(); +void grpc_enable_error_creation(); const char* grpc_error_string(grpc_error* error); @@ -153,19 +165,37 @@ grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, errs, count) #ifndef NDEBUG -grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line); -void grpc_error_unref(grpc_error* err, const char* file, int line); +grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line); +void grpc_error_do_unref(grpc_error* err, const char* file, int line); +inline grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) { + if (grpc_error_is_special(err)) return err; + return grpc_error_do_ref(err, file, line); +} +inline void grpc_error_unref(grpc_error* err, const char* file, int line) { + if (grpc_error_is_special(err)) return; + grpc_error_do_unref(err, file, line); +} #define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__) #define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__) #else -grpc_error* grpc_error_ref(grpc_error* err); -void grpc_error_unref(grpc_error* err); +grpc_error* grpc_error_do_ref(grpc_error* err); +void grpc_error_do_unref(grpc_error* err); +inline grpc_error* grpc_error_ref(grpc_error* err) { + if (grpc_error_is_special(err)) return err; + return grpc_error_do_ref(err); +} +inline void grpc_error_unref(grpc_error* err) { + if (grpc_error_is_special(err)) return; + grpc_error_do_unref(err); +} #define GRPC_ERROR_REF(err) grpc_error_ref(err) #define GRPC_ERROR_UNREF(err) grpc_error_unref(err) #endif grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which, intptr_t value) GRPC_MUST_USE_RESULT; +/// It is an error to pass nullptr as `p`. Caller should allocate a dummy +/// intptr_t for `p`, even if the value of `p` is not used. bool grpc_error_get_int(grpc_error* error, grpc_error_ints which, intptr_t* p); /// This call takes ownership of the slice; the error is responsible for /// eventually unref-ing it. @@ -180,8 +210,16 @@ bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, /// error occurring. Allows root causing high level errors from lower level /// errors that contributed to them. The src error takes ownership of the /// child error. +/// +/// Edge Conditions - +/// 1) If either of \a src or \a child is GRPC_ERROR_NONE, returns a reference +/// to the other argument. 2) If both \a src and \a child are GRPC_ERROR_NONE, +/// returns GRPC_ERROR_NONE. 3) If \a src and \a child point to the same error, +/// returns a single reference. (Note that, 2 references should have been +/// received to the error in this case.) grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) GRPC_MUST_USE_RESULT; + grpc_error* grpc_os_error(const char* file, int line, int err, const char* call_name) GRPC_MUST_USE_RESULT; diff --git a/Sources/CgRPC/src/core/lib/iomgr/error_internal.h b/Sources/CgRPC/src/core/lib/iomgr/error_internal.h index 7fde347ab..802739601 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/error_internal.h +++ b/Sources/CgRPC/src/core/lib/iomgr/error_internal.h @@ -58,6 +58,4 @@ struct grpc_error { intptr_t arena[0]; }; -bool grpc_error_is_special(struct grpc_error* err); - #endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_epoll1_linux.cc b/Sources/CgRPC/src/core/lib/iomgr/ev_epoll1_linux.cc index e5db1be0e..9eb4c089d 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -131,19 +131,26 @@ static void epoll_set_shutdown() { * Fd Declarations */ +/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ +struct grpc_fork_fd_list { + grpc_fd* fd; + grpc_fd* next; + grpc_fd* prev; +}; + struct grpc_fd { int fd; grpc_core::ManualConstructor read_closure; grpc_core::ManualConstructor write_closure; + grpc_core::ManualConstructor error_closure; struct grpc_fd* freelist_next; - /* The pollset that last noticed that the fd is readable. The actual type - * stored in this is (grpc_pollset *) */ - gpr_atm read_notifier_pollset; - grpc_iomgr_object iomgr_object; + + /* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ + grpc_fork_fd_list* fork_fd_list; }; static void fd_global_init(void); @@ -186,9 +193,13 @@ struct grpc_pollset_worker { #define MAX_NEIGHBORHOODS 1024 typedef struct pollset_neighborhood { - gpr_mu mu; - grpc_pollset* active_root; - char pad[GPR_CACHELINE_SIZE]; + union { + char pad[GPR_CACHELINE_SIZE]; + struct { + gpr_mu mu; + grpc_pollset* active_root; + }; + }; } pollset_neighborhood; struct grpc_pollset { @@ -259,9 +270,17 @@ static bool append_error(grpc_error** composite, grpc_error* error, static grpc_fd* fd_freelist = nullptr; static gpr_mu fd_freelist_mu; +/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ +static grpc_fd* fork_fd_list_head = nullptr; +static gpr_mu fork_fd_list_mu; + static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } static void fd_global_shutdown(void) { + // TODO(guantaol): We don't have a reasonable explanation about this + // lock()/unlock() pattern. It can be a valid barrier if there is at most one + // pending lock() at this point. Otherwise, there is still a possibility of + // use-after-free race. Need to reason about the code and/or clean it up. gpr_mu_lock(&fd_freelist_mu); gpr_mu_unlock(&fd_freelist_mu); while (fd_freelist != nullptr) { @@ -272,7 +291,39 @@ static void fd_global_shutdown(void) { gpr_mu_destroy(&fd_freelist_mu); } -static grpc_fd* fd_create(int fd, const char* name) { +static void fork_fd_list_add_grpc_fd(grpc_fd* fd) { + if (grpc_core::Fork::Enabled()) { + gpr_mu_lock(&fork_fd_list_mu); + fd->fork_fd_list = + static_cast(gpr_malloc(sizeof(grpc_fork_fd_list))); + fd->fork_fd_list->next = fork_fd_list_head; + fd->fork_fd_list->prev = nullptr; + if (fork_fd_list_head != nullptr) { + fork_fd_list_head->fork_fd_list->prev = fd; + } + fork_fd_list_head = fd; + gpr_mu_unlock(&fork_fd_list_mu); + } +} + +static void fork_fd_list_remove_grpc_fd(grpc_fd* fd) { + if (grpc_core::Fork::Enabled()) { + gpr_mu_lock(&fork_fd_list_mu); + if (fork_fd_list_head == fd) { + fork_fd_list_head = fd->fork_fd_list->next; + } + if (fd->fork_fd_list->prev != nullptr) { + fd->fork_fd_list->prev->fork_fd_list->next = fd->fork_fd_list->next; + } + if (fd->fork_fd_list->next != nullptr) { + fd->fork_fd_list->next->fork_fd_list->prev = fd->fork_fd_list->prev; + } + gpr_free(fd->fork_fd_list); + gpr_mu_unlock(&fork_fd_list_mu); + } +} + +static grpc_fd* fd_create(int fd, const char* name, bool track_err) { grpc_fd* new_fd = nullptr; gpr_mu_lock(&fd_freelist_mu); @@ -286,18 +337,19 @@ static grpc_fd* fd_create(int fd, const char* name) { new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); new_fd->read_closure.Init(); new_fd->write_closure.Init(); + new_fd->error_closure.Init(); } - new_fd->fd = fd; new_fd->read_closure->InitEvent(); new_fd->write_closure->InitEvent(); - gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); + new_fd->error_closure->InitEvent(); new_fd->freelist_next = nullptr; char* fd_name; gpr_asprintf(&fd_name, "%s fd=%d", name, fd); grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); + fork_fd_list_add_grpc_fd(new_fd); #ifndef NDEBUG if (grpc_trace_fd_refcount.enabled()) { gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name); @@ -307,7 +359,13 @@ static grpc_fd* fd_create(int fd, const char* name) { struct epoll_event ev; ev.events = static_cast(EPOLLIN | EPOLLOUT | EPOLLET); - ev.data.ptr = new_fd; + /* Use the least significant bit of ev.data.ptr to store track_err. We expect + * the addresses to be word aligned. We need to store track_err to avoid + * synchronization issues when accessing it after receiving an event. + * Accessing fd would be a data race there because the fd might have been + * returned to the free list at that point. */ + ev.data.ptr = reinterpret_cast(reinterpret_cast(new_fd) | + (track_err ? 1 : 0)); if (epoll_ctl(g_epoll_set.epfd, EPOLL_CTL_ADD, fd, &ev) != 0) { gpr_log(GPR_ERROR, "epoll_ctl failed: %s", strerror(errno)); } @@ -327,6 +385,7 @@ static void fd_shutdown_internal(grpc_fd* fd, grpc_error* why, shutdown(fd->fd, SHUT_RDWR); } fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); + fd->error_closure->SetShutdown(GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } @@ -337,7 +396,7 @@ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { } static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason) { + const char* reason) { grpc_error* error = GRPC_ERROR_NONE; bool is_release_fd = (release_fd != nullptr); @@ -350,15 +409,17 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, descriptor fd->fd (but we still own the grpc_fd structure). */ if (is_release_fd) { *release_fd = fd->fd; - } else if (!already_closed) { + } else { close(fd->fd); } GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_REF(error)); grpc_iomgr_unregister_object(&fd->iomgr_object); + fork_fd_list_remove_grpc_fd(fd); fd->read_closure->DestroyEvent(); fd->write_closure->DestroyEvent(); + fd->error_closure->DestroyEvent(); gpr_mu_lock(&fd_freelist_mu); fd->freelist_next = fd_freelist; @@ -366,11 +427,6 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, gpr_mu_unlock(&fd_freelist_mu); } -static grpc_pollset* fd_get_read_notifier_pollset(grpc_fd* fd) { - gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); - return (grpc_pollset*)notifier; -} - static bool fd_is_shutdown(grpc_fd* fd) { return fd->read_closure->IsShutdown(); } @@ -383,14 +439,16 @@ static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { fd->write_closure->NotifyOn(closure); } -static void fd_become_readable(grpc_fd* fd, grpc_pollset* notifier) { - fd->read_closure->SetReady(); - /* Use release store to match with acquire load in fd_get_read_notifier */ - gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); +static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { + fd->error_closure->NotifyOn(closure); } +static void fd_become_readable(grpc_fd* fd) { fd->read_closure->SetReady(); } + static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } +static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); } + /******************************************************************************* * Pollset Definitions */ @@ -611,16 +669,25 @@ static grpc_error* process_epoll_events(grpc_pollset* pollset) { append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd), err_desc); } else { - grpc_fd* fd = static_cast(data_ptr); - bool cancel = (ev->events & (EPOLLERR | EPOLLHUP)) != 0; + grpc_fd* fd = reinterpret_cast( + reinterpret_cast(data_ptr) & ~static_cast(1)); + bool track_err = + reinterpret_cast(data_ptr) & static_cast(1); + bool cancel = (ev->events & EPOLLHUP) != 0; + bool error = (ev->events & EPOLLERR) != 0; bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0; bool write_ev = (ev->events & EPOLLOUT) != 0; + bool err_fallback = error && !track_err; + + if (error && !err_fallback) { + fd_has_errors(fd); + } - if (read_ev || cancel) { - fd_become_readable(fd, pollset); + if (read_ev || cancel || err_fallback) { + fd_become_readable(fd); } - if (write_ev || cancel) { + if (write_ev || cancel || err_fallback) { fd_become_writable(fd); } } @@ -1175,14 +1242,24 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag, * Event engine binding */ +static bool is_any_background_poller_thread(void) { return false; } + +static void shutdown_background_closure(void) {} + static void shutdown_engine(void) { fd_global_shutdown(); pollset_global_shutdown(); epoll_set_shutdown(); + if (grpc_core::Fork::Enabled()) { + gpr_mu_destroy(&fork_fd_list_mu); + grpc_core::Fork::SetResetChildPollingEngineFunc(nullptr); + } } static const grpc_event_engine_vtable vtable = { sizeof(grpc_pollset), + true, + false, fd_create, fd_wrapped_fd, @@ -1190,8 +1267,11 @@ static const grpc_event_engine_vtable vtable = { fd_shutdown, fd_notify_on_read, fd_notify_on_write, + fd_notify_on_error, + fd_become_readable, + fd_become_writable, + fd_has_errors, fd_is_shutdown, - fd_get_read_notifier_pollset, pollset_init, pollset_shutdown, @@ -1209,9 +1289,26 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + is_any_background_poller_thread, + shutdown_background_closure, shutdown_engine, }; +/* Called by the child process's post-fork handler to close open fds, including + * the global epoll fd. This allows gRPC to shutdown in the child process + * without interfering with connections or RPCs ongoing in the parent. */ +static void reset_event_manager_on_fork() { + gpr_mu_lock(&fork_fd_list_mu); + while (fork_fd_list_head != nullptr) { + close(fork_fd_list_head->fd); + fork_fd_list_head->fd = -1; + fork_fd_list_head = fork_fd_list_head->fork_fd_list->next; + } + gpr_mu_unlock(&fork_fd_list_mu); + shutdown_engine(); + grpc_init_epoll1_linux(true); +} + /* It is possible that GLIBC has epoll but the underlying kernel doesn't. * Create epoll_fd (epoll_set_init() takes care of that) to make sure epoll * support is available */ @@ -1233,16 +1330,21 @@ const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) { return nullptr; } + if (grpc_core::Fork::Enabled()) { + gpr_mu_init(&fork_fd_list_mu); + grpc_core::Fork::SetResetChildPollingEngineFunc( + reset_event_manager_on_fork); + } return &vtable; } #else /* defined(GRPC_LINUX_EPOLL) */ -#if defined(GRPC_POSIX_SOCKET) +#if defined(GRPC_POSIX_SOCKET_EV_EPOLL1) #include "src/core/lib/iomgr/ev_epoll1_linux.h" /* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return * NULL */ const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) { return nullptr; } -#endif /* defined(GRPC_POSIX_SOCKET) */ +#endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLL1) */ #endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_epollex_linux.cc b/Sources/CgRPC/src/core/lib/iomgr/ev_epollex_linux.cc index 65f1c912a..b6d13b44d 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/ev_epollex_linux.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,9 @@ #include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" @@ -63,6 +66,7 @@ // a keepalive ping timeout issue. We may want to revert https://github // .com/grpc/grpc/pull/14943 once we figure out the root cause. #define MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL 16 +#define MAX_FDS_IN_CACHE 32 grpc_core::DebugOnlyTraceFlag grpc_trace_pollable_refcount(false, "pollable_refcount"); @@ -90,8 +94,10 @@ struct pollable { int epfd; grpc_wakeup_fd wakeup; - // only for type fd... one ref to the owner fd - grpc_fd* owner_fd; + // The following are relevant only for type PO_FD + grpc_fd* owner_fd; // Set to the owner_fd if the type is PO_FD + gpr_mu owner_orphan_mu; // Synchronizes access to owner_orphaned field + bool owner_orphaned; // Is the owner fd orphaned grpc_pollset_set* pollset_set; pollable* next; @@ -146,29 +152,90 @@ static void pollable_unref(pollable* p, int line, const char* reason); */ struct grpc_fd { + grpc_fd(int fd, const char* name, bool track_err) + : fd(fd), track_err(track_err) { + gpr_mu_init(&orphan_mu); + gpr_mu_init(&pollable_mu); + read_closure.InitEvent(); + write_closure.InitEvent(); + error_closure.InitEvent(); + + char* fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&iomgr_object, fd_name); +#ifndef NDEBUG + if (grpc_trace_fd_refcount.enabled()) { + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, this, fd_name); + } +#endif + gpr_free(fd_name); + } + + // This is really the dtor, but the poller threads waking up from + // epoll_wait() may access the (read|write|error)_closure after destruction. + // Since the object will be added to the free pool, this behavior is + // not going to cause issues, except spurious events if the FD is reused + // while the race happens. + void destroy() { + grpc_iomgr_unregister_object(&iomgr_object); + + POLLABLE_UNREF(pollable_obj, "fd_pollable"); + pollset_fds.clear(); + gpr_mu_destroy(&pollable_mu); + gpr_mu_destroy(&orphan_mu); + + read_closure.DestroyEvent(); + write_closure.DestroyEvent(); + error_closure.DestroyEvent(); + + invalidate(); + } + +#ifndef NDEBUG + /* Since an fd is never really destroyed (i.e gpr_free() is not called), it is + * hard-to-debug cases where fd fields are accessed even after calling + * fd_destroy(). The following invalidates fd fields to make catching such + * errors easier */ + void invalidate() { + fd = -1; + gpr_atm_no_barrier_store(&refst, -1); + memset(&orphan_mu, -1, sizeof(orphan_mu)); + memset(&pollable_mu, -1, sizeof(pollable_mu)); + pollable_obj = nullptr; + on_done_closure = nullptr; + memset(&iomgr_object, -1, sizeof(iomgr_object)); + track_err = false; + } +#else + void invalidate() {} +#endif + int fd; - /* refst format: - bit 0 : 1=Active / 0=Orphaned - bits 1-n : refcount - Ref/Unref by two to avoid altering the orphaned bit */ - gpr_atm refst; + + // refst format: + // bit 0 : 1=Active / 0=Orphaned + // bits 1-n : refcount + // Ref/Unref by two to avoid altering the orphaned bit + gpr_atm refst = 1; gpr_mu orphan_mu; + // Protects pollable_obj and pollset_fds. gpr_mu pollable_mu; - pollable* pollable_obj; + grpc_core::InlinedVector pollset_fds; // Used in PO_MULTI. + pollable* pollable_obj = nullptr; // Used in PO_FD. - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; + grpc_core::LockfreeEvent read_closure; + grpc_core::LockfreeEvent write_closure; + grpc_core::LockfreeEvent error_closure; - struct grpc_fd* freelist_next; - grpc_closure* on_done_closure; - - /* The pollset that last noticed that the fd is readable. The actual type - * stored in this is (grpc_pollset *) */ - gpr_atm read_notifier_pollset; + struct grpc_fd* freelist_next = nullptr; + grpc_closure* on_done_closure = nullptr; grpc_iomgr_object iomgr_object; + + // Do we need to track EPOLLERR events separately? + bool track_err; }; static void fd_global_init(void); @@ -202,6 +269,7 @@ struct grpc_pollset_worker { struct grpc_pollset { gpr_mu mu; gpr_atm worker_count; + gpr_atm active_pollable_type; pollable* active_pollable; bool kicked_without_poller; grpc_closure* shutdown_closure; @@ -281,20 +349,15 @@ static void ref_by(grpc_fd* fd, int n) { GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } +/* Uninitialize and add to the freelist */ static void fd_destroy(void* arg, grpc_error* error) { grpc_fd* fd = static_cast(arg); + fd->destroy(); + /* Add the fd to the freelist */ - grpc_iomgr_unregister_object(&fd->iomgr_object); - POLLABLE_UNREF(fd->pollable_obj, "fd_pollable"); - gpr_mu_destroy(&fd->pollable_mu); - gpr_mu_destroy(&fd->orphan_mu); gpr_mu_lock(&fd_freelist_mu); fd->freelist_next = fd_freelist; fd_freelist = fd; - - fd->read_closure->DestroyEvent(); - fd->write_closure->DestroyEvent(); - gpr_mu_unlock(&fd_freelist_mu); } @@ -323,6 +386,10 @@ static void unref_by(grpc_fd* fd, int n) { static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } static void fd_global_shutdown(void) { + // TODO(guantaol): We don't have a reasonable explanation about this + // lock()/unlock() pattern. It can be a valid barrier if there is at most one + // pending lock() at this point. Otherwise, there is still a possibility of + // use-after-free race. Need to reason about the code and/or clean it up. gpr_mu_lock(&fd_freelist_mu); gpr_mu_unlock(&fd_freelist_mu); while (fd_freelist != nullptr) { @@ -333,7 +400,7 @@ static void fd_global_shutdown(void) { gpr_mu_destroy(&fd_freelist_mu); } -static grpc_fd* fd_create(int fd, const char* name) { +static grpc_fd* fd_create(int fd, const char* name, bool track_err) { grpc_fd* new_fd = nullptr; gpr_mu_lock(&fd_freelist_mu); @@ -345,32 +412,9 @@ static grpc_fd* fd_create(int fd, const char* name) { if (new_fd == nullptr) { new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); } - gpr_mu_init(&new_fd->pollable_mu); - gpr_mu_init(&new_fd->orphan_mu); - new_fd->pollable_obj = nullptr; - gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); - new_fd->fd = fd; - new_fd->read_closure->InitEvent(); - new_fd->write_closure->InitEvent(); - gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); - - new_fd->freelist_next = nullptr; - new_fd->on_done_closure = nullptr; - - char* fd_name; - gpr_asprintf(&fd_name, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); -#ifndef NDEBUG - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name); - } -#endif - gpr_free(fd_name); - return new_fd; + return new (new_fd) grpc_fd(fd, name, track_err); } static int fd_wrapped_fd(grpc_fd* fd) { @@ -379,24 +423,48 @@ static int fd_wrapped_fd(grpc_fd* fd) { } static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason) { - bool is_fd_closed = already_closed; + const char* reason) { + bool is_fd_closed = false; gpr_mu_lock(&fd->orphan_mu); + // Get the fd->pollable_obj and set the owner_orphaned on that pollable to + // true so that the pollable will no longer access its owner_fd field. + gpr_mu_lock(&fd->pollable_mu); + pollable* pollable_obj = fd->pollable_obj; + + if (pollable_obj) { + gpr_mu_lock(&pollable_obj->owner_orphan_mu); + pollable_obj->owner_orphaned = true; + } + fd->on_done_closure = on_done; /* If release_fd is not NULL, we should be relinquishing control of the file descriptor fd->fd (but we still own the grpc_fd structure). */ if (release_fd != nullptr) { + // Remove the FD from all epolls sets, before releasing it. + // Otherwise, we will receive epoll events after we release the FD. + epoll_event ev_fd; + memset(&ev_fd, 0, sizeof(ev_fd)); + if (release_fd != nullptr) { + if (pollable_obj != nullptr) { // For PO_FD. + epoll_ctl(pollable_obj->epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + for (size_t i = 0; i < fd->pollset_fds.size(); ++i) { // For PO_MULTI. + const int epfd = fd->pollset_fds[i]; + epoll_ctl(epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + } *release_fd = fd->fd; - } else if (!is_fd_closed) { + } else { close(fd->fd); is_fd_closed = true; } + // TODO(sreek): handle fd removal (where is_fd_closed=false) if (!is_fd_closed) { - gpr_log(GPR_DEBUG, "TODO: handle fd removal?"); + GRPC_FD_TRACE("epoll_fd %p (%d) was orphaned but not closed.", fd, fd->fd); } /* Remove the active status but keep referenced. We want this grpc_fd struct @@ -405,35 +473,62 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, GRPC_CLOSURE_SCHED(fd->on_done_closure, GRPC_ERROR_NONE); + if (pollable_obj) { + gpr_mu_unlock(&pollable_obj->owner_orphan_mu); + } + + gpr_mu_unlock(&fd->pollable_mu); gpr_mu_unlock(&fd->orphan_mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ } -static grpc_pollset* fd_get_read_notifier_pollset(grpc_fd* fd) { - gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); - return (grpc_pollset*)notifier; -} - static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return fd->read_closure.IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { - shutdown(fd->fd, SHUT_RDWR); - fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); + if (fd->read_closure.SetShutdown(GRPC_ERROR_REF(why))) { + if (shutdown(fd->fd, SHUT_RDWR)) { + if (errno != ENOTCONN) { + gpr_log(GPR_ERROR, "Error shutting down fd %d. errno: %d", + grpc_fd_wrapped_fd(fd), errno); + } + } + fd->write_closure.SetShutdown(GRPC_ERROR_REF(why)); + fd->error_closure.SetShutdown(GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(closure); + fd->read_closure.NotifyOn(closure); } static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(closure); + fd->write_closure.NotifyOn(closure); +} + +static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { + fd->error_closure.NotifyOn(closure); +} + +static bool fd_has_pollset(grpc_fd* fd, grpc_pollset* pollset) { + const int epfd = pollset->active_pollable->epfd; + grpc_core::MutexLock lock(&fd->pollable_mu); + for (size_t i = 0; i < fd->pollset_fds.size(); ++i) { + if (fd->pollset_fds[i] == epfd) { + return true; + } + } + return false; +} + +static void fd_add_pollset(grpc_fd* fd, grpc_pollset* pollset) { + const int epfd = pollset->active_pollable->epfd; + grpc_core::MutexLock lock(&fd->pollable_mu); + fd->pollset_fds.push_back(epfd); } /******************************************************************************* @@ -447,9 +542,13 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { if (epfd == -1) { return GRPC_OS_ERROR(errno, "epoll_create1"); } + GRPC_FD_TRACE("Pollable_create: created epfd: %d (type: %d)", epfd, type); *p = static_cast(gpr_malloc(sizeof(**p))); grpc_error* err = grpc_wakeup_fd_init(&(*p)->wakeup); if (err != GRPC_ERROR_NONE) { + GRPC_FD_TRACE( + "Pollable_create: closed epfd: %d (type: %d). wakeupfd_init error", + epfd, type); close(epfd); gpr_free(*p); *p = nullptr; @@ -460,6 +559,9 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { ev.data.ptr = (void*)(1 | (intptr_t) & (*p)->wakeup); if (epoll_ctl(epfd, EPOLL_CTL_ADD, (*p)->wakeup.read_fd, &ev) != 0) { err = GRPC_OS_ERROR(errno, "epoll_ctl"); + GRPC_FD_TRACE( + "Pollable_create: closed epfd: %d (type: %d). epoll_ctl error", epfd, + type); close(epfd); grpc_wakeup_fd_destroy(&(*p)->wakeup); gpr_free(*p); @@ -472,6 +574,8 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { gpr_mu_init(&(*p)->mu); (*p)->epfd = epfd; (*p)->owner_fd = nullptr; + gpr_mu_init(&(*p)->owner_orphan_mu); + (*p)->owner_orphaned = false; (*p)->pollset_set = nullptr; (*p)->next = (*p)->prev = *p; (*p)->root_worker = nullptr; @@ -506,8 +610,10 @@ static void pollable_unref(pollable* p, int line, const char* reason) { } #endif if (p != nullptr && gpr_unref(&p->refs)) { + GRPC_FD_TRACE("pollable_unref: Closing epfd: %d", p->epfd); close(p->epfd); grpc_wakeup_fd_destroy(&p->wakeup); + gpr_mu_destroy(&p->owner_orphan_mu); gpr_free(p); } } @@ -516,7 +622,6 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { grpc_error* error = GRPC_ERROR_NONE; static const char* err_desc = "pollable_add_fd"; const int epfd = p->epfd; - if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p); } @@ -524,7 +629,13 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { struct epoll_event ev_fd; ev_fd.events = static_cast(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE); - ev_fd.data.ptr = fd; + /* Use the second least significant bit of ev_fd.data.ptr to store track_err + * to avoid synchronization issues when accessing it after receiving an event. + * Accessing fd would be a data race there because the fd might have been + * returned to the free list at that point. */ + ev_fd.data.ptr = reinterpret_cast(reinterpret_cast(fd) | + (fd->track_err ? 2 : 0)); + GRPC_STATS_INC_SYSCALL_EPOLL_CTL(); if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->fd, &ev_fd) != 0) { switch (errno) { case EEXIST: @@ -581,7 +692,7 @@ static void pollset_maybe_finish_shutdown(grpc_pollset* pollset) { static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) { GPR_TIMER_SCOPE("kick_one_worker", 0); pollable* p = specific_worker->pollable_obj; - grpc_core::mu_guard lock(&p->mu); + grpc_core::MutexLock lock(&p->mu); GPR_ASSERT(specific_worker != nullptr); if (specific_worker->kicked) { if (grpc_polling_trace.enabled()) { @@ -690,6 +801,7 @@ static grpc_error* pollset_kick_all(grpc_pollset* pollset) { static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { gpr_mu_init(&pollset->mu); gpr_atm_no_barrier_store(&pollset->worker_count, 0); + gpr_atm_no_barrier_store(&pollset->active_pollable_type, PO_EMPTY); pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset"); pollset->kicked_without_poller = false; pollset->shutdown_closure = nullptr; @@ -710,24 +822,21 @@ static int poll_deadline_to_millis_timeout(grpc_millis millis) { return static_cast(delta); } -static void fd_become_readable(grpc_fd* fd, grpc_pollset* notifier) { - fd->read_closure->SetReady(); +static void fd_become_readable(grpc_fd* fd) { fd->read_closure.SetReady(); } - /* Note, it is possible that fd_become_readable might be called twice with - different 'notifier's when an fd becomes readable and it is in two epoll - sets (This can happen briefly during polling island merges). In such cases - it does not really matter which notifer is set as the read_notifier_pollset - (They would both point to the same polling island anyway) */ - /* Use release store to match with acquire load in fd_get_read_notifier */ - gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); -} +static void fd_become_writable(grpc_fd* fd) { fd->write_closure.SetReady(); } -static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } +static void fd_has_errors(grpc_fd* fd) { fd->error_closure.SetReady(); } -static grpc_error* fd_get_or_become_pollable(grpc_fd* fd, pollable** p) { +/* Get the pollable_obj attached to this fd. If none is attached, create a new + * pollable object (of type PO_FD), attach it to the fd and return it + * + * Note that if a pollable object is already attached to the fd, it may be of + * either PO_FD or PO_MULTI type */ +static grpc_error* get_fd_pollable(grpc_fd* fd, pollable** p) { gpr_mu_lock(&fd->pollable_mu); grpc_error* error = GRPC_ERROR_NONE; - static const char* err_desc = "fd_get_or_become_pollable"; + static const char* err_desc = "get_fd_pollable"; if (fd->pollable_obj == nullptr) { if (append_error(&error, pollable_create(PO_FD, &fd->pollable_obj), err_desc)) { @@ -792,20 +901,28 @@ static grpc_error* pollable_process_events(grpc_pollset* pollset, (intptr_t)data_ptr)), err_desc); } else { - grpc_fd* fd = static_cast(data_ptr); - bool cancel = (ev->events & (EPOLLERR | EPOLLHUP)) != 0; + grpc_fd* fd = + reinterpret_cast(reinterpret_cast(data_ptr) & ~2); + bool track_err = reinterpret_cast(data_ptr) & 2; + bool cancel = (ev->events & EPOLLHUP) != 0; + bool error = (ev->events & EPOLLERR) != 0; bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0; bool write_ev = (ev->events & EPOLLOUT) != 0; + bool err_fallback = error && !track_err; + if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "PS:%p got fd %p: cancel=%d read=%d " "write=%d", pollset, fd, cancel, read_ev, write_ev); } - if (read_ev || cancel) { - fd_become_readable(fd, pollset); + if (error && !err_fallback) { + fd_has_errors(fd); + } + if (read_ev || cancel || err_fallback) { + fd_become_readable(fd); } - if (write_ev || cancel) { + if (write_ev || cancel || err_fallback) { fd_become_writable(fd); } } @@ -1010,7 +1127,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, #endif if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, - "PS:%p work hdl=%p worker=%p now=%" PRIdPTR " deadline=%" PRIdPTR + "PS:%p work hdl=%p worker=%p now=%" PRId64 " deadline=%" PRId64 " kwp=%d pollable=%p", pollset, worker_hdl, WORKER_PTR, grpc_core::ExecCtx::Get()->Now(), deadline, pollset->kicked_without_poller, pollset->active_pollable); @@ -1056,7 +1173,7 @@ static grpc_error* pollset_transition_pollable_from_empty_to_fd_locked( } append_error(&error, pollset_kick_all(pollset), err_desc); POLLABLE_UNREF(pollset->active_pollable, "pollset"); - append_error(&error, fd_get_or_become_pollable(fd, &pollset->active_pollable), + append_error(&error, get_fd_pollable(fd, &pollset->active_pollable), err_desc); return error; } @@ -1100,9 +1217,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { error = pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd); break; case PO_FD: - gpr_mu_lock(&po_at_start->owner_fd->orphan_mu); - if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) & - 1) == 0) { + gpr_mu_lock(&po_at_start->owner_orphan_mu); + if (po_at_start->owner_orphaned) { error = pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd); } else { @@ -1110,7 +1226,7 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { error = pollset_transition_pollable_from_fd_to_multi_locked(pollset, fd); } - gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu); + gpr_mu_unlock(&po_at_start->owner_orphan_mu); break; case PO_MULTI: error = pollable_add_fd(pollset->active_pollable, fd); @@ -1120,6 +1236,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { POLLABLE_UNREF(pollset->active_pollable, "pollset"); pollset->active_pollable = po_at_start; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); POLLABLE_UNREF(po_at_start, "pollset_add_fd"); } return error; @@ -1146,16 +1264,17 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, append_error(&error, pollset_kick_all(pollset), err_desc); break; case PO_FD: - gpr_mu_lock(&po_at_start->owner_fd->orphan_mu); - if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) & - 1) == 0) { + gpr_mu_lock(&po_at_start->owner_orphan_mu); + if (po_at_start->owner_orphaned) { + // Unlock before Unref'ing the pollable + gpr_mu_unlock(&po_at_start->owner_orphan_mu); POLLABLE_UNREF(pollset->active_pollable, "pollset"); error = pollable_create(PO_MULTI, &pollset->active_pollable); } else { error = pollset_transition_pollable_from_fd_to_multi_locked(pollset, nullptr); + gpr_mu_unlock(&po_at_start->owner_orphan_mu); } - gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu); break; case PO_MULTI: break; @@ -1165,6 +1284,8 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, pollset->active_pollable = po_at_start; *pollable_obj = nullptr; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); *pollable_obj = POLLABLE_REF(pollset->active_pollable, "pollset_set"); POLLABLE_UNREF(po_at_start, "pollset_as_multipollable"); } @@ -1173,9 +1294,23 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { GPR_TIMER_SCOPE("pollset_add_fd", 0); - gpr_mu_lock(&pollset->mu); + + // We never transition from PO_MULTI to other modes (i.e., PO_FD or PO_EMOPTY) + // and, thus, it is safe to simply store and check whether the FD has already + // been added to the active pollable previously. + if (gpr_atm_acq_load(&pollset->active_pollable_type) == PO_MULTI && + fd_has_pollset(fd, pollset)) { + return; + } + + grpc_core::MutexLock lock(&pollset->mu); grpc_error* error = pollset_add_fd_locked(pollset, fd); - gpr_mu_unlock(&pollset->mu); + + // If we are in PO_MULTI mode, we should update the pollsets of the FD. + if (gpr_atm_no_barrier_load(&pollset->active_pollable_type) == PO_MULTI) { + fd_add_pollset(fd, pollset); + } + GRPC_LOG_IF_ERROR("pollset_add_fd", error); } @@ -1385,7 +1520,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a, gpr_mu_unlock(b_mu); } // try to do the least copying possible - // TODO(ctiller): there's probably a better heuristic here + // TODO(sreek): there's probably a better heuristic here const size_t a_size = a->fd_count + a->pollset_count; const size_t b_size = b->fd_count + b->pollset_count; if (b_size > a_size) { @@ -1440,6 +1575,10 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag, * Event engine binding */ +static bool is_any_background_poller_thread(void) { return false; } + +static void shutdown_background_closure(void) {} + static void shutdown_engine(void) { fd_global_shutdown(); pollset_global_shutdown(); @@ -1447,6 +1586,8 @@ static void shutdown_engine(void) { static const grpc_event_engine_vtable vtable = { sizeof(grpc_pollset), + true, + false, fd_create, fd_wrapped_fd, @@ -1454,8 +1595,11 @@ static const grpc_event_engine_vtable vtable = { fd_shutdown, fd_notify_on_read, fd_notify_on_write, + fd_notify_on_error, + fd_become_readable, + fd_become_writable, + fd_has_errors, fd_is_shutdown, - fd_get_read_notifier_pollset, pollset_init, pollset_shutdown, @@ -1473,6 +1617,8 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + is_any_background_poller_thread, + shutdown_background_closure, shutdown_engine, }; @@ -1500,7 +1646,7 @@ const grpc_event_engine_vtable* grpc_init_epollex_linux( } #else /* defined(GRPC_LINUX_EPOLL_CREATE1) */ -#if defined(GRPC_POSIX_SOCKET) +#if defined(GRPC_POSIX_SOCKET_EV_EPOLLEX) #include "src/core/lib/iomgr/ev_epollex_linux.h" /* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means epoll_create1 is not available. Return NULL */ @@ -1508,6 +1654,6 @@ const grpc_event_engine_vtable* grpc_init_epollex_linux( bool explicitly_requested) { return nullptr; } -#endif /* defined(GRPC_POSIX_SOCKET) */ +#endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLLEX) */ #endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_epollsig_linux.cc b/Sources/CgRPC/src/core/lib/iomgr/ev_epollsig_linux.cc deleted file mode 100644 index 494bc71c1..000000000 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_epollsig_linux.cc +++ /dev/null @@ -1,1735 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/iomgr/port.h" - -#include -#include - -/* This polling engine is only relevant on linux kernels supporting epoll() */ -#ifdef GRPC_LINUX_EPOLL_CREATE1 - -#include "src/core/lib/iomgr/ev_epollsig_linux.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "src/core/lib/debug/stats.h" -#include "src/core/lib/gpr/tls.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/iomgr/block_annotate.h" -#include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/iomgr/lockfree_event.h" -#include "src/core/lib/iomgr/timer.h" -#include "src/core/lib/iomgr/wakeup_fd_posix.h" -#include "src/core/lib/profiling/timers.h" - -#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker*)1) - -#define GRPC_POLLING_TRACE(...) \ - if (grpc_polling_trace.enabled()) { \ - gpr_log(GPR_INFO, __VA_ARGS__); \ - } - -static int grpc_wakeup_signal = -1; -static bool is_grpc_wakeup_signal_initialized = false; - -/* Implements the function defined in grpc_posix.h. This function might be - * called before even calling grpc_init() to set either a different signal to - * use. If signum == -1, then the use of signals is disabled */ -void grpc_use_signal(int signum) { - grpc_wakeup_signal = signum; - is_grpc_wakeup_signal_initialized = true; - - if (grpc_wakeup_signal < 0) { - gpr_log(GPR_INFO, - "Use of signals is disabled. Epoll engine will not be used"); - } else { - gpr_log(GPR_INFO, "epoll engine will be using signal: %d", - grpc_wakeup_signal); - } -} - -struct polling_island; - -typedef enum { - POLL_OBJ_FD, - POLL_OBJ_POLLSET, - POLL_OBJ_POLLSET_SET -} poll_obj_type; - -typedef struct poll_obj { -#ifndef NDEBUG - poll_obj_type obj_type; -#endif - gpr_mu mu; - struct polling_island* pi; -} poll_obj; - -const char* poll_obj_string(poll_obj_type po_type) { - switch (po_type) { - case POLL_OBJ_FD: - return "fd"; - case POLL_OBJ_POLLSET: - return "pollset"; - case POLL_OBJ_POLLSET_SET: - return "pollset_set"; - } - - GPR_UNREACHABLE_CODE(return "UNKNOWN"); -} - - /******************************************************************************* - * Fd Declarations - */ - -#define FD_FROM_PO(po) ((grpc_fd*)(po)) - -struct grpc_fd { - poll_obj po; - - int fd; - /* refst format: - bit 0 : 1=Active / 0=Orphaned - bits 1-n : refcount - Ref/Unref by two to avoid altering the orphaned bit */ - gpr_atm refst; - - /* The fd is either closed or we relinquished control of it. In either - cases, this indicates that the 'fd' on this structure is no longer - valid */ - bool orphaned; - - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; - - struct grpc_fd* freelist_next; - grpc_closure* on_done_closure; - - /* The pollset that last noticed that the fd is readable. The actual type - * stored in this is (grpc_pollset *) */ - gpr_atm read_notifier_pollset; - - grpc_iomgr_object iomgr_object; -}; - -/* Reference counting for fds */ -#ifndef NDEBUG -static void fd_ref(grpc_fd* fd, const char* reason, const char* file, int line); -static void fd_unref(grpc_fd* fd, const char* reason, const char* file, - int line); -#define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__) -#define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__) -#else -static void fd_ref(grpc_fd* fd); -static void fd_unref(grpc_fd* fd); -#define GRPC_FD_REF(fd, reason) fd_ref(fd) -#define GRPC_FD_UNREF(fd, reason) fd_unref(fd) -#endif - -static void fd_global_init(void); -static void fd_global_shutdown(void); - -/******************************************************************************* - * Polling island Declarations - */ - -#ifndef NDEBUG - -#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) -#define PI_UNREF(p, r) pi_unref_dbg((p), (r), __FILE__, __LINE__) - -#else - -#define PI_ADD_REF(p, r) pi_add_ref((p)) -#define PI_UNREF(p, r) pi_unref((p)) - -#endif - -/* This is also used as grpc_workqueue (by directly casing it) */ -typedef struct polling_island { - gpr_mu mu; - /* Ref count. Use PI_ADD_REF() and PI_UNREF() macros to increment/decrement - the refcount. - Once the ref count becomes zero, this structure is destroyed which means - we should ensure that there is never a scenario where a PI_ADD_REF() is - racing with a PI_UNREF() that just made the ref_count zero. */ - gpr_atm ref_count; - - /* Pointer to the polling_island this merged into. - * merged_to value is only set once in polling_island's lifetime (and that too - * only if the island is merged with another island). Because of this, we can - * use gpr_atm type here so that we can do atomic access on this and reduce - * lock contention on 'mu' mutex. - * - * Note that if this field is not NULL (i.e not 0), all the remaining fields - * (except mu and ref_count) are invalid and must be ignored. */ - gpr_atm merged_to; - - /* Number of threads currently polling on this island */ - gpr_atm poller_count; - - /* The fd of the underlying epoll set */ - int epoll_fd; - - /* The file descriptors in the epoll set */ - size_t fd_cnt; - size_t fd_capacity; - grpc_fd** fds; -} polling_island; - -/******************************************************************************* - * Pollset Declarations - */ -struct grpc_pollset_worker { - /* Thread id of this worker */ - pthread_t pt_id; - - /* Used to prevent a worker from getting kicked multiple times */ - gpr_atm is_kicked; - struct grpc_pollset_worker* next; - struct grpc_pollset_worker* prev; -}; - -struct grpc_pollset { - poll_obj po; - - grpc_pollset_worker root_worker; - bool kicked_without_pollers; - - bool shutting_down; /* Is the pollset shutting down ? */ - bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ - grpc_closure* shutdown_done; /* Called after after shutdown is complete */ -}; - -/******************************************************************************* - * Pollset-set Declarations - */ -struct grpc_pollset_set { - poll_obj po; -}; - -/******************************************************************************* - * Common helpers - */ - -static bool append_error(grpc_error** composite, grpc_error* error, - const char* desc) { - if (error == GRPC_ERROR_NONE) return true; - if (*composite == GRPC_ERROR_NONE) { - *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); - } - *composite = grpc_error_add_child(*composite, error); - return false; -} - -/******************************************************************************* - * Polling island Definitions - */ - -/* The wakeup fd that is used to wake up all threads in a Polling island. This - is useful in the polling island merge operation where we need to wakeup all - the threads currently polling the smaller polling island (so that they can - start polling the new/merged polling island) - - NOTE: This fd is initialized to be readable and MUST NOT be consumed i.e the - threads that woke up MUST NOT call grpc_wakeup_fd_consume_wakeup() */ -static grpc_wakeup_fd polling_island_wakeup_fd; - -/* The polling island being polled right now. - See comments in workqueue_maybe_wakeup for why this is tracked. */ -static __thread polling_island* g_current_thread_polling_island; - -/* Forward declaration */ -static void polling_island_delete(polling_island* pi); - -#ifdef GRPC_TSAN -/* Currently TSAN may incorrectly flag data races between epoll_ctl and - epoll_wait for any grpc_fd structs that are added to the epoll set via - epoll_ctl and are returned (within a very short window) via epoll_wait(). - - To work-around this race, we establish a happens-before relation between - the code just-before epoll_ctl() and the code after epoll_wait() by using - this atomic */ -gpr_atm g_epoll_sync; -#endif /* defined(GRPC_TSAN) */ - -static void pi_add_ref(polling_island* pi); -static void pi_unref(polling_island* pi); - -#ifndef NDEBUG -static void pi_add_ref_dbg(polling_island* pi, const char* reason, - const char* file, int line) { - if (grpc_polling_trace.enabled()) { - gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count); - gpr_log(GPR_INFO, - "Add ref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR - " (%s) - (%s, %d)", - pi, old_cnt, old_cnt + 1, reason, file, line); - } - pi_add_ref(pi); -} - -static void pi_unref_dbg(polling_island* pi, const char* reason, - const char* file, int line) { - if (grpc_polling_trace.enabled()) { - gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count); - gpr_log(GPR_INFO, - "Unref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR - " (%s) - (%s, %d)", - pi, old_cnt, (old_cnt - 1), reason, file, line); - } - pi_unref(pi); -} -#endif - -static void pi_add_ref(polling_island* pi) { - gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1); -} - -static void pi_unref(polling_island* pi) { - /* If ref count went to zero, delete the polling island. - Note that this deletion not be done under a lock. Once the ref count goes - to zero, we are guaranteed that no one else holds a reference to the - polling island (and that there is no racing pi_add_ref() call either). - - Also, if we are deleting the polling island and the merged_to field is - non-empty, we should remove a ref to the merged_to polling island - */ - if (1 == gpr_atm_full_fetch_add(&pi->ref_count, -1)) { - polling_island* next = (polling_island*)gpr_atm_acq_load(&pi->merged_to); - polling_island_delete(pi); - if (next != nullptr) { - PI_UNREF(next, "pi_delete"); /* Recursive call */ - } - } -} - -/* The caller is expected to hold pi->mu lock before calling this function */ -static void polling_island_add_fds_locked(polling_island* pi, grpc_fd** fds, - size_t fd_count, bool add_fd_refs, - grpc_error** error) { - int err; - size_t i; - struct epoll_event ev; - char* err_msg; - const char* err_desc = "polling_island_add_fds"; - -#ifdef GRPC_TSAN - /* See the definition of g_epoll_sync for more context */ - gpr_atm_rel_store(&g_epoll_sync, (gpr_atm)0); -#endif /* defined(GRPC_TSAN) */ - - for (i = 0; i < fd_count; i++) { - ev.events = static_cast(EPOLLIN | EPOLLOUT | EPOLLET); - ev.data.ptr = fds[i]; - err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, fds[i]->fd, &ev); - - if (err < 0) { - if (errno != EEXIST) { - gpr_asprintf( - &err_msg, - "epoll_ctl (epoll_fd: %d) add fd: %d failed with error: %d (%s)", - pi->epoll_fd, fds[i]->fd, errno, strerror(errno)); - append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); - gpr_free(err_msg); - } - - continue; - } - - if (pi->fd_cnt == pi->fd_capacity) { - pi->fd_capacity = GPR_MAX(pi->fd_capacity + 8, pi->fd_cnt * 3 / 2); - pi->fds = static_cast( - gpr_realloc(pi->fds, sizeof(grpc_fd*) * pi->fd_capacity)); - } - - pi->fds[pi->fd_cnt++] = fds[i]; - if (add_fd_refs) { - GRPC_FD_REF(fds[i], "polling_island"); - } - } -} - -/* The caller is expected to hold pi->mu before calling this */ -static void polling_island_add_wakeup_fd_locked(polling_island* pi, - grpc_wakeup_fd* wakeup_fd, - grpc_error** error) { - struct epoll_event ev; - int err; - char* err_msg; - const char* err_desc = "polling_island_add_wakeup_fd"; - - ev.events = static_cast(EPOLLIN | EPOLLET); - ev.data.ptr = wakeup_fd; - err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, - GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), &ev); - if (err < 0 && errno != EEXIST) { - gpr_asprintf(&err_msg, - "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with " - "error: %d (%s)", - pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), errno, - strerror(errno)); - append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); - gpr_free(err_msg); - } -} - -/* The caller is expected to hold pi->mu lock before calling this function */ -static void polling_island_remove_all_fds_locked(polling_island* pi, - bool remove_fd_refs, - grpc_error** error) { - int err; - size_t i; - char* err_msg; - const char* err_desc = "polling_island_remove_fds"; - - for (i = 0; i < pi->fd_cnt; i++) { - err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, pi->fds[i]->fd, nullptr); - if (err < 0 && errno != ENOENT) { - gpr_asprintf(&err_msg, - "epoll_ctl (epoll_fd: %d) delete fds[%zu]: %d failed with " - "error: %d (%s)", - pi->epoll_fd, i, pi->fds[i]->fd, errno, strerror(errno)); - append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); - gpr_free(err_msg); - } - - if (remove_fd_refs) { - GRPC_FD_UNREF(pi->fds[i], "polling_island"); - } - } - - pi->fd_cnt = 0; -} - -/* The caller is expected to hold pi->mu lock before calling this function */ -static void polling_island_remove_fd_locked(polling_island* pi, grpc_fd* fd, - bool is_fd_closed, - grpc_error** error) { - int err; - size_t i; - char* err_msg; - const char* err_desc = "polling_island_remove_fd"; - - /* If fd is already closed, then it would have been automatically been removed - from the epoll set */ - if (!is_fd_closed) { - err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, fd->fd, nullptr); - if (err < 0 && errno != ENOENT) { - gpr_asprintf( - &err_msg, - "epoll_ctl (epoll_fd: %d) del fd: %d failed with error: %d (%s)", - pi->epoll_fd, fd->fd, errno, strerror(errno)); - append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); - gpr_free(err_msg); - } - } - - for (i = 0; i < pi->fd_cnt; i++) { - if (pi->fds[i] == fd) { - pi->fds[i] = pi->fds[--pi->fd_cnt]; - GRPC_FD_UNREF(fd, "polling_island"); - break; - } - } -} - -/* Might return NULL in case of an error */ -static polling_island* polling_island_create(grpc_fd* initial_fd, - grpc_error** error) { - polling_island* pi = nullptr; - const char* err_desc = "polling_island_create"; - - *error = GRPC_ERROR_NONE; - - pi = static_cast(gpr_malloc(sizeof(*pi))); - gpr_mu_init(&pi->mu); - pi->fd_cnt = 0; - pi->fd_capacity = 0; - pi->fds = nullptr; - pi->epoll_fd = -1; - - gpr_atm_rel_store(&pi->ref_count, 0); - gpr_atm_rel_store(&pi->poller_count, 0); - gpr_atm_rel_store(&pi->merged_to, (gpr_atm) nullptr); - - pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC); - - if (pi->epoll_fd < 0) { - append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc); - goto done; - } - - if (initial_fd != nullptr) { - polling_island_add_fds_locked(pi, &initial_fd, 1, true, error); - } - -done: - if (*error != GRPC_ERROR_NONE) { - polling_island_delete(pi); - pi = nullptr; - } - return pi; -} - -static void polling_island_delete(polling_island* pi) { - GPR_ASSERT(pi->fd_cnt == 0); - - if (pi->epoll_fd >= 0) { - close(pi->epoll_fd); - } - gpr_mu_destroy(&pi->mu); - gpr_free(pi->fds); - gpr_free(pi); -} - -/* Attempts to gets the last polling island in the linked list (liked by the - * 'merged_to' field). Since this does not lock the polling island, there are no - * guarantees that the island returned is the last island */ -static polling_island* polling_island_maybe_get_latest(polling_island* pi) { - polling_island* next = (polling_island*)gpr_atm_acq_load(&pi->merged_to); - while (next != nullptr) { - pi = next; - next = (polling_island*)gpr_atm_acq_load(&pi->merged_to); - } - - return pi; -} - -/* Gets the lock on the *latest* polling island i.e the last polling island in - the linked list (linked by the 'merged_to' field). Call gpr_mu_unlock on the - returned polling island's mu. - Usage: To lock/unlock polling island "pi", do the following: - polling_island *pi_latest = polling_island_lock(pi); - ... - ... critical section .. - ... - gpr_mu_unlock(&pi_latest->mu); // NOTE: use pi_latest->mu. NOT pi->mu */ -static polling_island* polling_island_lock(polling_island* pi) { - polling_island* next = nullptr; - - while (true) { - next = (polling_island*)gpr_atm_acq_load(&pi->merged_to); - if (next == nullptr) { - /* Looks like 'pi' is the last node in the linked list but unless we check - this by holding the pi->mu lock, we cannot be sure (i.e without the - pi->mu lock, we don't prevent island merges). - To be absolutely sure, check once more by holding the pi->mu lock */ - gpr_mu_lock(&pi->mu); - next = (polling_island*)gpr_atm_acq_load(&pi->merged_to); - if (next == nullptr) { - /* pi is infact the last node and we have the pi->mu lock. we're done */ - break; - } - - /* pi->merged_to is not NULL i.e pi isn't the last node anymore. pi->mu - * isn't the lock we are interested in. Continue traversing the list */ - gpr_mu_unlock(&pi->mu); - } - - pi = next; - } - - return pi; -} - -/* Gets the lock on the *latest* polling islands in the linked lists pointed by - *p and *q (and also updates *p and *q to point to the latest polling islands) - - This function is needed because calling the following block of code to obtain - locks on polling islands (*p and *q) is prone to deadlocks. - { - polling_island_lock(*p, true); - polling_island_lock(*q, true); - } - - Usage/example: - polling_island *p1; - polling_island *p2; - .. - polling_island_lock_pair(&p1, &p2); - .. - .. Critical section with both p1 and p2 locked - .. - // Release locks: Always call polling_island_unlock_pair() to release locks - polling_island_unlock_pair(p1, p2); -*/ -static void polling_island_lock_pair(polling_island** p, polling_island** q) { - polling_island* pi_1 = *p; - polling_island* pi_2 = *q; - polling_island* next_1 = nullptr; - polling_island* next_2 = nullptr; - - /* The algorithm is simple: - - Go to the last polling islands in the linked lists *pi_1 and *pi_2 (and - keep updating pi_1 and pi_2) - - Then obtain locks on the islands by following a lock order rule of - locking polling_island with lower address first - Special case: Before obtaining the locks, check if pi_1 and pi_2 are - pointing to the same island. If that is the case, we can just call - polling_island_lock() - - After obtaining both the locks, double check that the polling islands - are still the last polling islands in their respective linked lists - (this is because there might have been polling island merges before - we got the lock) - - If the polling islands are the last islands, we are done. If not, - release the locks and continue the process from the first step */ - while (true) { - next_1 = (polling_island*)gpr_atm_acq_load(&pi_1->merged_to); - while (next_1 != nullptr) { - pi_1 = next_1; - next_1 = (polling_island*)gpr_atm_acq_load(&pi_1->merged_to); - } - - next_2 = (polling_island*)gpr_atm_acq_load(&pi_2->merged_to); - while (next_2 != nullptr) { - pi_2 = next_2; - next_2 = (polling_island*)gpr_atm_acq_load(&pi_2->merged_to); - } - - if (pi_1 == pi_2) { - pi_1 = pi_2 = polling_island_lock(pi_1); - break; - } - - if (pi_1 < pi_2) { - gpr_mu_lock(&pi_1->mu); - gpr_mu_lock(&pi_2->mu); - } else { - gpr_mu_lock(&pi_2->mu); - gpr_mu_lock(&pi_1->mu); - } - - next_1 = (polling_island*)gpr_atm_acq_load(&pi_1->merged_to); - next_2 = (polling_island*)gpr_atm_acq_load(&pi_2->merged_to); - if (next_1 == nullptr && next_2 == nullptr) { - break; - } - - gpr_mu_unlock(&pi_1->mu); - gpr_mu_unlock(&pi_2->mu); - } - - *p = pi_1; - *q = pi_2; -} - -static void polling_island_unlock_pair(polling_island* p, polling_island* q) { - if (p == q) { - gpr_mu_unlock(&p->mu); - } else { - gpr_mu_unlock(&p->mu); - gpr_mu_unlock(&q->mu); - } -} - -static polling_island* polling_island_merge(polling_island* p, - polling_island* q, - grpc_error** error) { - /* Get locks on both the polling islands */ - polling_island_lock_pair(&p, &q); - - if (p != q) { - /* Make sure that p points to the polling island with fewer fds than q */ - if (p->fd_cnt > q->fd_cnt) { - GPR_SWAP(polling_island*, p, q); - } - - /* Merge p with q i.e move all the fds from p (The one with fewer fds) to q - Note that the refcounts on the fds being moved will not change here. - This is why the last param in the following two functions is 'false') */ - polling_island_add_fds_locked(q, p->fds, p->fd_cnt, false, error); - polling_island_remove_all_fds_locked(p, false, error); - - /* Wakeup all the pollers (if any) on p so that they pickup this change */ - polling_island_add_wakeup_fd_locked(p, &polling_island_wakeup_fd, error); - - /* Add the 'merged_to' link from p --> q */ - gpr_atm_rel_store(&p->merged_to, (gpr_atm)q); - PI_ADD_REF(q, "pi_merge"); /* To account for the new incoming ref from p */ - } - /* else if p == q, nothing needs to be done */ - - polling_island_unlock_pair(p, q); - - /* Return the merged polling island (Note that no merge would have happened - if p == q which is ok) */ - return q; -} - -static grpc_error* polling_island_global_init() { - grpc_error* error = GRPC_ERROR_NONE; - - error = grpc_wakeup_fd_init(&polling_island_wakeup_fd); - if (error == GRPC_ERROR_NONE) { - error = grpc_wakeup_fd_wakeup(&polling_island_wakeup_fd); - } - - return error; -} - -static void polling_island_global_shutdown() { - grpc_wakeup_fd_destroy(&polling_island_wakeup_fd); -} - -/******************************************************************************* - * Fd Definitions - */ - -/* We need to keep a freelist not because of any concerns of malloc performance - * but instead so that implementations with multiple threads in (for example) - * epoll_wait deal with the race between pollset removal and incoming poll - * notifications. - * - * The problem is that the poller ultimately holds a reference to this - * object, so it is very difficult to know when is safe to free it, at least - * without some expensive synchronization. - * - * If we keep the object freelisted, in the worst case losing this race just - * becomes a spurious read notification on a reused fd. - */ - -/* The alarm system needs to be able to wakeup 'some poller' sometimes - * (specifically when a new alarm needs to be triggered earlier than the next - * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a - * case occurs. */ - -static grpc_fd* fd_freelist = nullptr; -static gpr_mu fd_freelist_mu; - -#ifndef NDEBUG -#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) -#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) -static void ref_by(grpc_fd* fd, int n, const char* reason, const char* file, - int line) { - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, - "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]", - fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst), - gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); - } -#else -#define REF_BY(fd, n, reason) ref_by(fd, n) -#define UNREF_BY(fd, n, reason) unref_by(fd, n) -static void ref_by(grpc_fd* fd, int n) { -#endif - GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); -} - -#ifndef NDEBUG -static void unref_by(grpc_fd* fd, int n, const char* reason, const char* file, - int line) { - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, - "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]", - fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst), - gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); - } -#else -static void unref_by(grpc_fd* fd, int n) { -#endif - gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); - if (old == n) { - /* Add the fd to the freelist */ - gpr_mu_lock(&fd_freelist_mu); - fd->freelist_next = fd_freelist; - fd_freelist = fd; - grpc_iomgr_unregister_object(&fd->iomgr_object); - - fd->read_closure->DestroyEvent(); - fd->write_closure->DestroyEvent(); - - gpr_mu_unlock(&fd_freelist_mu); - } else { - GPR_ASSERT(old > n); - } -} - -/* Increment refcount by two to avoid changing the orphan bit */ -#ifndef NDEBUG -static void fd_ref(grpc_fd* fd, const char* reason, const char* file, - int line) { - ref_by(fd, 2, reason, file, line); -} - -static void fd_unref(grpc_fd* fd, const char* reason, const char* file, - int line) { - unref_by(fd, 2, reason, file, line); -} -#else -static void fd_ref(grpc_fd* fd) { ref_by(fd, 2); } -static void fd_unref(grpc_fd* fd) { unref_by(fd, 2); } -#endif - -static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } - -static void fd_global_shutdown(void) { - gpr_mu_lock(&fd_freelist_mu); - gpr_mu_unlock(&fd_freelist_mu); - while (fd_freelist != nullptr) { - grpc_fd* fd = fd_freelist; - fd_freelist = fd_freelist->freelist_next; - gpr_mu_destroy(&fd->po.mu); - gpr_free(fd); - } - gpr_mu_destroy(&fd_freelist_mu); -} - -static grpc_fd* fd_create(int fd, const char* name) { - grpc_fd* new_fd = nullptr; - - gpr_mu_lock(&fd_freelist_mu); - if (fd_freelist != nullptr) { - new_fd = fd_freelist; - fd_freelist = fd_freelist->freelist_next; - } - gpr_mu_unlock(&fd_freelist_mu); - - if (new_fd == nullptr) { - new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); - gpr_mu_init(&new_fd->po.mu); - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); - } - - /* Note: It is not really needed to get the new_fd->po.mu lock here. If this - * is a newly created fd (or an fd we got from the freelist), no one else - * would be holding a lock to it anyway. */ - gpr_mu_lock(&new_fd->po.mu); - new_fd->po.pi = nullptr; -#ifndef NDEBUG - new_fd->po.obj_type = POLL_OBJ_FD; -#endif - - gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); - new_fd->fd = fd; - new_fd->orphaned = false; - new_fd->read_closure->InitEvent(); - new_fd->write_closure->InitEvent(); - gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); - - new_fd->freelist_next = nullptr; - new_fd->on_done_closure = nullptr; - - gpr_mu_unlock(&new_fd->po.mu); - - char* fd_name; - gpr_asprintf(&fd_name, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); - gpr_free(fd_name); - return new_fd; -} - -static int fd_wrapped_fd(grpc_fd* fd) { - int ret_fd = -1; - gpr_mu_lock(&fd->po.mu); - if (!fd->orphaned) { - ret_fd = fd->fd; - } - gpr_mu_unlock(&fd->po.mu); - - return ret_fd; -} - -static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason) { - grpc_error* error = GRPC_ERROR_NONE; - polling_island* unref_pi = nullptr; - - gpr_mu_lock(&fd->po.mu); - fd->on_done_closure = on_done; - - /* Remove the active status but keep referenced. We want this grpc_fd struct - to be alive (and not added to freelist) until the end of this function */ - REF_BY(fd, 1, reason); - - /* Remove the fd from the polling island: - - Get a lock on the latest polling island (i.e the last island in the - linked list pointed by fd->po.pi). This is the island that - would actually contain the fd - - Remove the fd from the latest polling island - - Unlock the latest polling island - - Set fd->po.pi to NULL (but remove the ref on the polling island - before doing this.) */ - if (fd->po.pi != nullptr) { - polling_island* pi_latest = polling_island_lock(fd->po.pi); - polling_island_remove_fd_locked(pi_latest, fd, already_closed, &error); - gpr_mu_unlock(&pi_latest->mu); - - unref_pi = fd->po.pi; - fd->po.pi = nullptr; - } - - /* If release_fd is not NULL, we should be relinquishing control of the file - descriptor fd->fd (but we still own the grpc_fd structure). */ - if (release_fd != nullptr) { - *release_fd = fd->fd; - } else { - close(fd->fd); - } - - fd->orphaned = true; - - GRPC_CLOSURE_SCHED(fd->on_done_closure, GRPC_ERROR_REF(error)); - - gpr_mu_unlock(&fd->po.mu); - UNREF_BY(fd, 2, reason); /* Drop the reference */ - if (unref_pi != nullptr) { - /* Unref stale polling island here, outside the fd lock above. - The polling island owns a workqueue which owns an fd, and unreffing - inside the lock can cause an eventual lock loop that makes TSAN very - unhappy. */ - PI_UNREF(unref_pi, "fd_orphan"); - } - if (error != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "fd_orphan: %s", msg); - } - GRPC_ERROR_UNREF(error); -} - -static grpc_pollset* fd_get_read_notifier_pollset(grpc_fd* fd) { - gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); - return (grpc_pollset*)notifier; -} - -static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); -} - -/* Might be called multiple times */ -static void fd_shutdown(grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { - shutdown(fd->fd, SHUT_RDWR); - fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); - } - GRPC_ERROR_UNREF(why); -} - -static void fd_notify_on_read(grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(closure); -} - -static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(closure); -} - -/******************************************************************************* - * Pollset Definitions - */ -GPR_TLS_DECL(g_current_thread_pollset); -GPR_TLS_DECL(g_current_thread_worker); -static __thread bool g_initialized_sigmask; -static __thread sigset_t g_orig_sigmask; - -static void sig_handler(int sig_num) { -#ifdef GRPC_EPOLL_DEBUG - gpr_log(GPR_INFO, "Received signal %d", sig_num); -#endif -} - -static void poller_kick_init() { signal(grpc_wakeup_signal, sig_handler); } - -/* Global state management */ -static grpc_error* pollset_global_init(void) { - gpr_tls_init(&g_current_thread_pollset); - gpr_tls_init(&g_current_thread_worker); - poller_kick_init(); - return GRPC_ERROR_NONE; -} - -static void pollset_global_shutdown(void) { - gpr_tls_destroy(&g_current_thread_pollset); - gpr_tls_destroy(&g_current_thread_worker); -} - -static grpc_error* pollset_worker_kick(grpc_pollset_worker* worker) { - grpc_error* err = GRPC_ERROR_NONE; - - /* Kick the worker only if it was not already kicked */ - if (gpr_atm_no_barrier_cas(&worker->is_kicked, static_cast(0), - static_cast(1))) { - GRPC_POLLING_TRACE( - "pollset_worker_kick: Kicking worker: %p (thread id: %ld)", - (void*)worker, (long int)worker->pt_id); - int err_num = pthread_kill(worker->pt_id, grpc_wakeup_signal); - if (err_num != 0) { - err = GRPC_OS_ERROR(err_num, "pthread_kill"); - } - } - return err; -} - -/* Return 1 if the pollset has active threads in pollset_work (pollset must - * be locked) */ -static int pollset_has_workers(grpc_pollset* p) { - return p->root_worker.next != &p->root_worker; -} - -static void remove_worker(grpc_pollset* p, grpc_pollset_worker* worker) { - worker->prev->next = worker->next; - worker->next->prev = worker->prev; -} - -static grpc_pollset_worker* pop_front_worker(grpc_pollset* p) { - if (pollset_has_workers(p)) { - grpc_pollset_worker* w = p->root_worker.next; - remove_worker(p, w); - return w; - } else { - return nullptr; - } -} - -static void push_back_worker(grpc_pollset* p, grpc_pollset_worker* worker) { - worker->next = &p->root_worker; - worker->prev = worker->next->prev; - worker->prev->next = worker->next->prev = worker; -} - -static void push_front_worker(grpc_pollset* p, grpc_pollset_worker* worker) { - worker->prev = &p->root_worker; - worker->next = worker->prev->next; - worker->prev->next = worker->next->prev = worker; -} - -/* p->mu must be held before calling this function */ -static grpc_error* pollset_kick(grpc_pollset* p, - grpc_pollset_worker* specific_worker) { - GPR_TIMER_SCOPE("pollset_kick", 0); - grpc_error* error = GRPC_ERROR_NONE; - GRPC_STATS_INC_POLLSET_KICK(); - const char* err_desc = "Kick Failure"; - grpc_pollset_worker* worker = specific_worker; - if (worker != nullptr) { - if (worker == GRPC_POLLSET_KICK_BROADCAST) { - if (pollset_has_workers(p)) { - GPR_TIMER_SCOPE("pollset_kick.broadcast", 0); - for (worker = p->root_worker.next; worker != &p->root_worker; - worker = worker->next) { - if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { - append_error(&error, pollset_worker_kick(worker), err_desc); - } - } - } else { - p->kicked_without_pollers = true; - } - } else { - GPR_TIMER_MARK("kicked_specifically", 0); - if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { - append_error(&error, pollset_worker_kick(worker), err_desc); - } - } - } else if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)p) { - /* Since worker == NULL, it means that we can kick "any" worker on this - pollset 'p'. If 'p' happens to be the same pollset this thread is - currently polling (i.e in pollset_work() function), then there is no need - to kick any other worker since the current thread can just absorb the - kick. This is the reason why we enter this case only when - g_current_thread_pollset is != p */ - - GPR_TIMER_MARK("kick_anonymous", 0); - worker = pop_front_worker(p); - if (worker != nullptr) { - GPR_TIMER_MARK("finally_kick", 0); - push_back_worker(p, worker); - append_error(&error, pollset_worker_kick(worker), err_desc); - } else { - GPR_TIMER_MARK("kicked_no_pollers", 0); - p->kicked_without_pollers = true; - } - } - - GRPC_LOG_IF_ERROR("pollset_kick", GRPC_ERROR_REF(error)); - return error; -} - -static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { - gpr_mu_init(&pollset->po.mu); - *mu = &pollset->po.mu; - pollset->po.pi = nullptr; -#ifndef NDEBUG - pollset->po.obj_type = POLL_OBJ_POLLSET; -#endif - - pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; - pollset->kicked_without_pollers = false; - - pollset->shutting_down = false; - pollset->finish_shutdown_called = false; - pollset->shutdown_done = nullptr; -} - -static int poll_deadline_to_millis_timeout(grpc_millis millis) { - if (millis == GRPC_MILLIS_INF_FUTURE) return -1; - grpc_millis delta = millis - grpc_core::ExecCtx::Get()->Now(); - if (delta > INT_MAX) - return INT_MAX; - else if (delta < 0) - return 0; - else - return static_cast(delta); -} - -static void fd_become_readable(grpc_fd* fd, grpc_pollset* notifier) { - fd->read_closure->SetReady(); - - /* Note, it is possible that fd_become_readable might be called twice with - different 'notifier's when an fd becomes readable and it is in two epoll - sets (This can happen briefly during polling island merges). In such cases - it does not really matter which notifer is set as the read_notifier_pollset - (They would both point to the same polling island anyway) */ - /* Use release store to match with acquire load in fd_get_read_notifier */ - gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); -} - -static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } - -static void pollset_release_polling_island(grpc_pollset* ps, - const char* reason) { - if (ps->po.pi != nullptr) { - PI_UNREF(ps->po.pi, reason); - } - ps->po.pi = nullptr; -} - -static void finish_shutdown_locked(grpc_pollset* pollset) { - /* The pollset cannot have any workers if we are at this stage */ - GPR_ASSERT(!pollset_has_workers(pollset)); - - pollset->finish_shutdown_called = true; - - /* Release the ref and set pollset->po.pi to NULL */ - pollset_release_polling_island(pollset, "ps_shutdown"); - GRPC_CLOSURE_SCHED(pollset->shutdown_done, GRPC_ERROR_NONE); -} - -/* pollset->po.mu lock must be held by the caller before calling this */ -static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) { - GPR_TIMER_SCOPE("pollset_shutdown", 0); - GPR_ASSERT(!pollset->shutting_down); - pollset->shutting_down = true; - pollset->shutdown_done = closure; - pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); - - /* If the pollset has any workers, we cannot call finish_shutdown_locked() - because it would release the underlying polling island. In such a case, we - let the last worker call finish_shutdown_locked() from pollset_work() */ - if (!pollset_has_workers(pollset)) { - GPR_ASSERT(!pollset->finish_shutdown_called); - GPR_TIMER_MARK("pollset_shutdown.finish_shutdown_locked", 0); - finish_shutdown_locked(pollset); - } -} - -/* pollset_shutdown is guaranteed to be called before pollset_destroy. So other - * than destroying the mutexes, there is nothing special that needs to be done - * here */ -static void pollset_destroy(grpc_pollset* pollset) { - GPR_ASSERT(!pollset_has_workers(pollset)); - gpr_mu_destroy(&pollset->po.mu); -} - -#define GRPC_EPOLL_MAX_EVENTS 100 -/* Note: sig_mask contains the signal mask to use *during* epoll_wait() */ -static void pollset_work_and_unlock(grpc_pollset* pollset, - grpc_pollset_worker* worker, int timeout_ms, - sigset_t* sig_mask, grpc_error** error) { - GPR_TIMER_SCOPE("pollset_work_and_unlock", 0); - struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS]; - int epoll_fd = -1; - int ep_rv; - polling_island* pi = nullptr; - char* err_msg; - const char* err_desc = "pollset_work_and_unlock"; - - /* We need to get the epoll_fd to wait on. The epoll_fd is in inside the - latest polling island pointed by pollset->po.pi - - Since epoll_fd is immutable, we can read it without obtaining the polling - island lock. There is however a possibility that the polling island (from - which we got the epoll_fd) got merged with another island while we are - in this function. This is still okay because in such a case, we will wakeup - right-away from epoll_wait() and pick up the latest polling_island the next - this function (i.e pollset_work_and_unlock()) is called */ - - if (pollset->po.pi == nullptr) { - pollset->po.pi = polling_island_create(nullptr, error); - if (pollset->po.pi == nullptr) { - return; /* Fatal error. We cannot continue */ - } - - PI_ADD_REF(pollset->po.pi, "ps"); - GRPC_POLLING_TRACE("pollset_work: pollset: %p created new pi: %p", - (void*)pollset, (void*)pollset->po.pi); - } - - pi = polling_island_maybe_get_latest(pollset->po.pi); - epoll_fd = pi->epoll_fd; - - /* Update the pollset->po.pi since the island being pointed by - pollset->po.pi maybe older than the one pointed by pi) */ - if (pollset->po.pi != pi) { - /* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the - polling island to be deleted */ - PI_ADD_REF(pi, "ps"); - PI_UNREF(pollset->po.pi, "ps"); - pollset->po.pi = pi; - } - - /* Add an extra ref so that the island does not get destroyed (which means - the epoll_fd won't be closed) while we are are doing an epoll_wait() on the - epoll_fd */ - PI_ADD_REF(pi, "ps_work"); - gpr_mu_unlock(&pollset->po.mu); - - gpr_atm_no_barrier_fetch_add(&pi->poller_count, 1); - g_current_thread_polling_island = pi; - - GRPC_SCHEDULING_START_BLOCKING_REGION; - GRPC_STATS_INC_SYSCALL_POLL(); - ep_rv = - epoll_pwait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms, sig_mask); - GRPC_SCHEDULING_END_BLOCKING_REGION; - if (ep_rv < 0) { - if (errno != EINTR) { - gpr_asprintf(&err_msg, - "epoll_wait() epoll fd: %d failed with error: %d (%s)", - epoll_fd, errno, strerror(errno)); - append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); - } else { - /* We were interrupted. Save an interation by doing a zero timeout - epoll_wait to see if there are any other events of interest */ - GRPC_POLLING_TRACE("pollset_work: pollset: %p, worker: %p received kick", - (void*)pollset, (void*)worker); - ep_rv = epoll_wait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0); - } - } - -#ifdef GRPC_TSAN - /* See the definition of g_poll_sync for more details */ - gpr_atm_acq_load(&g_epoll_sync); -#endif /* defined(GRPC_TSAN) */ - - for (int i = 0; i < ep_rv; ++i) { - void* data_ptr = ep_ev[i].data.ptr; - if (data_ptr == &polling_island_wakeup_fd) { - GRPC_POLLING_TRACE( - "pollset_work: pollset: %p, worker: %p polling island (epoll_fd: " - "%d) got merged", - (void*)pollset, (void*)worker, epoll_fd); - /* This means that our polling island is merged with a different - island. We do not have to do anything here since the subsequent call - to the function pollset_work_and_unlock() will pick up the correct - epoll_fd */ - } else { - grpc_fd* fd = static_cast(data_ptr); - int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP); - int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI); - int write_ev = ep_ev[i].events & EPOLLOUT; - if (read_ev || cancel) { - fd_become_readable(fd, pollset); - } - if (write_ev || cancel) { - fd_become_writable(fd); - } - } - } - - g_current_thread_polling_island = nullptr; - gpr_atm_no_barrier_fetch_add(&pi->poller_count, -1); - - GPR_ASSERT(pi != nullptr); - - /* Before leaving, release the extra ref we added to the polling island. It - is important to use "pi" here (i.e our old copy of pollset->po.pi - that we got before releasing the polling island lock). This is because - pollset->po.pi pointer might get udpated in other parts of the - code when there is an island merge while we are doing epoll_wait() above */ - PI_UNREF(pi, "ps_work"); -} - -/* pollset->po.mu lock must be held by the caller before calling this. - The function pollset_work() may temporarily release the lock (pollset->po.mu) - during the course of its execution but it will always re-acquire the lock and - ensure that it is held by the time the function returns */ -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker_hdl, - grpc_millis deadline) { - GPR_TIMER_SCOPE("pollset_work", 0); - grpc_error* error = GRPC_ERROR_NONE; - int timeout_ms = poll_deadline_to_millis_timeout(deadline); - - sigset_t new_mask; - - grpc_pollset_worker worker; - worker.next = worker.prev = nullptr; - worker.pt_id = pthread_self(); - gpr_atm_no_barrier_store(&worker.is_kicked, (gpr_atm)0); - - if (worker_hdl) *worker_hdl = &worker; - - gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); - gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); - - if (pollset->kicked_without_pollers) { - /* If the pollset was kicked without pollers, pretend that the current - worker got the kick and skip polling. A kick indicates that there is some - work that needs attention like an event on the completion queue or an - alarm */ - GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0); - pollset->kicked_without_pollers = 0; - } else if (!pollset->shutting_down) { - /* We use the posix-signal with number 'grpc_wakeup_signal' for waking up - (i.e 'kicking') a worker in the pollset. A 'kick' is a way to inform the - worker that there is some pending work that needs immediate attention - (like an event on the completion queue, or a polling island merge that - results in a new epoll-fd to wait on) and that the worker should not - spend time waiting in epoll_pwait(). - - A worker can be kicked anytime from the point it is added to the pollset - via push_front_worker() (or push_back_worker()) to the point it is - removed via remove_worker(). - If the worker is kicked before/during it calls epoll_pwait(), it should - immediately exit from epoll_wait(). If the worker is kicked after it - returns from epoll_wait(), then nothing really needs to be done. - - To accomplish this, we mask 'grpc_wakeup_signal' on this thread at all - times *except* when it is in epoll_pwait(). This way, the worker never - misses acting on a kick */ - - if (!g_initialized_sigmask) { - sigemptyset(&new_mask); - sigaddset(&new_mask, grpc_wakeup_signal); - pthread_sigmask(SIG_BLOCK, &new_mask, &g_orig_sigmask); - sigdelset(&g_orig_sigmask, grpc_wakeup_signal); - g_initialized_sigmask = true; - /* new_mask: The new thread mask which blocks 'grpc_wakeup_signal'. - This is the mask used at all times *except during - epoll_wait()*" - g_orig_sigmask: The thread mask which allows 'grpc_wakeup_signal' and - this is the mask to use *during epoll_wait()* - - The new_mask is set on the worker before it is added to the pollset - (i.e before it can be kicked) */ - } - - push_front_worker(pollset, &worker); /* Add worker to pollset */ - - pollset_work_and_unlock(pollset, &worker, timeout_ms, &g_orig_sigmask, - &error); - grpc_core::ExecCtx::Get()->Flush(); - - gpr_mu_lock(&pollset->po.mu); - - /* Note: There is no need to reset worker.is_kicked to 0 since we are no - longer going to use this worker */ - remove_worker(pollset, &worker); - } - - /* If we are the last worker on the pollset (i.e pollset_has_workers() is - false at this point) and the pollset is shutting down, we may have to - finish the shutdown process by calling finish_shutdown_locked(). - See pollset_shutdown() for more details. - - Note: Continuing to access pollset here is safe; it is the caller's - responsibility to not destroy a pollset when it has outstanding calls to - pollset_work() */ - if (pollset->shutting_down && !pollset_has_workers(pollset) && - !pollset->finish_shutdown_called) { - GPR_TIMER_MARK("pollset_work.finish_shutdown_locked", 0); - finish_shutdown_locked(pollset); - - gpr_mu_unlock(&pollset->po.mu); - grpc_core::ExecCtx::Get()->Flush(); - gpr_mu_lock(&pollset->po.mu); - } - - if (worker_hdl) *worker_hdl = nullptr; - - gpr_tls_set(&g_current_thread_pollset, (intptr_t)0); - gpr_tls_set(&g_current_thread_worker, (intptr_t)0); - - GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); - return error; -} - -static void add_poll_object(poll_obj* bag, poll_obj_type bag_type, - poll_obj* item, poll_obj_type item_type) { - GPR_TIMER_SCOPE("add_poll_object", 0); - -#ifndef NDEBUG - GPR_ASSERT(item->obj_type == item_type); - GPR_ASSERT(bag->obj_type == bag_type); -#endif - - grpc_error* error = GRPC_ERROR_NONE; - polling_island* pi_new = nullptr; - - gpr_mu_lock(&bag->mu); - gpr_mu_lock(&item->mu); - -retry: - /* - * 1) If item->pi and bag->pi are both non-NULL and equal, do nothing - * 2) If item->pi and bag->pi are both NULL, create a new polling island (with - * a refcount of 2) and point item->pi and bag->pi to the new island - * 3) If exactly one of item->pi or bag->pi is NULL, update it to point to - * the other's non-NULL pi - * 4) Finally if item->pi and bag-pi are non-NULL and not-equal, merge the - * polling islands and update item->pi and bag->pi to point to the new - * island - */ - - /* Early out if we are trying to add an 'fd' to a 'bag' but the fd is already - * orphaned */ - if (item_type == POLL_OBJ_FD && (FD_FROM_PO(item))->orphaned) { - gpr_mu_unlock(&item->mu); - gpr_mu_unlock(&bag->mu); - return; - } - - if (item->pi == bag->pi) { - pi_new = item->pi; - if (pi_new == nullptr) { - /* GPR_ASSERT(item->pi == bag->pi == NULL) */ - - /* If we are adding an fd to a bag (i.e pollset or pollset_set), then - * we need to do some extra work to make TSAN happy */ - if (item_type == POLL_OBJ_FD) { - /* Unlock before creating a new polling island: the polling island will - create a workqueue which creates a file descriptor, and holding an fd - lock here can eventually cause a loop to appear to TSAN (making it - unhappy). We don't think it's a real loop (there's an epoch point - where that loop possibility disappears), but the advantages of - keeping TSAN happy outweigh any performance advantage we might have - by keeping the lock held. */ - gpr_mu_unlock(&item->mu); - pi_new = polling_island_create(FD_FROM_PO(item), &error); - gpr_mu_lock(&item->mu); - - /* Need to reverify any assumptions made between the initial lock and - getting to this branch: if they've changed, we need to throw away our - work and figure things out again. */ - if (item->pi != nullptr) { - GRPC_POLLING_TRACE( - "add_poll_object: Raced creating new polling island. pi_new: %p " - "(fd: %d, %s: %p)", - (void*)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type), - (void*)bag); - /* No need to lock 'pi_new' here since this is a new polling island - and no one has a reference to it yet */ - polling_island_remove_all_fds_locked(pi_new, true, &error); - - /* Ref and unref so that the polling island gets deleted during unref - */ - PI_ADD_REF(pi_new, "dance_of_destruction"); - PI_UNREF(pi_new, "dance_of_destruction"); - goto retry; - } - } else { - pi_new = polling_island_create(nullptr, &error); - } - - GRPC_POLLING_TRACE( - "add_poll_object: Created new polling island. pi_new: %p (%s: %p, " - "%s: %p)", - (void*)pi_new, poll_obj_string(item_type), (void*)item, - poll_obj_string(bag_type), (void*)bag); - } else { - GRPC_POLLING_TRACE( - "add_poll_object: Same polling island. pi: %p (%s, %s)", - (void*)pi_new, poll_obj_string(item_type), poll_obj_string(bag_type)); - } - } else if (item->pi == nullptr) { - /* GPR_ASSERT(bag->pi != NULL) */ - /* Make pi_new point to latest pi*/ - pi_new = polling_island_lock(bag->pi); - - if (item_type == POLL_OBJ_FD) { - grpc_fd* fd = FD_FROM_PO(item); - polling_island_add_fds_locked(pi_new, &fd, 1, true, &error); - } - - gpr_mu_unlock(&pi_new->mu); - GRPC_POLLING_TRACE( - "add_poll_obj: item->pi was NULL. pi_new: %p (item(%s): %p, " - "bag(%s): %p)", - (void*)pi_new, poll_obj_string(item_type), (void*)item, - poll_obj_string(bag_type), (void*)bag); - } else if (bag->pi == nullptr) { - /* GPR_ASSERT(item->pi != NULL) */ - /* Make pi_new to point to latest pi */ - pi_new = polling_island_lock(item->pi); - gpr_mu_unlock(&pi_new->mu); - GRPC_POLLING_TRACE( - "add_poll_obj: bag->pi was NULL. pi_new: %p (item(%s): %p, " - "bag(%s): %p)", - (void*)pi_new, poll_obj_string(item_type), (void*)item, - poll_obj_string(bag_type), (void*)bag); - } else { - pi_new = polling_island_merge(item->pi, bag->pi, &error); - GRPC_POLLING_TRACE( - "add_poll_obj: polling islands merged. pi_new: %p (item(%s): %p, " - "bag(%s): %p)", - (void*)pi_new, poll_obj_string(item_type), (void*)item, - poll_obj_string(bag_type), (void*)bag); - } - - /* At this point, pi_new is the polling island that both item->pi and bag->pi - MUST be pointing to */ - - if (item->pi != pi_new) { - PI_ADD_REF(pi_new, poll_obj_string(item_type)); - if (item->pi != nullptr) { - PI_UNREF(item->pi, poll_obj_string(item_type)); - } - item->pi = pi_new; - } - - if (bag->pi != pi_new) { - PI_ADD_REF(pi_new, poll_obj_string(bag_type)); - if (bag->pi != nullptr) { - PI_UNREF(bag->pi, poll_obj_string(bag_type)); - } - bag->pi = pi_new; - } - - gpr_mu_unlock(&item->mu); - gpr_mu_unlock(&bag->mu); - - GRPC_LOG_IF_ERROR("add_poll_object", error); -} - -static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { - add_poll_object(&pollset->po, POLL_OBJ_POLLSET, &fd->po, POLL_OBJ_FD); -} - -/******************************************************************************* - * Pollset-set Definitions - */ - -static grpc_pollset_set* pollset_set_create(void) { - grpc_pollset_set* pss = - static_cast(gpr_malloc(sizeof(*pss))); - gpr_mu_init(&pss->po.mu); - pss->po.pi = nullptr; -#ifndef NDEBUG - pss->po.obj_type = POLL_OBJ_POLLSET_SET; -#endif - return pss; -} - -static void pollset_set_destroy(grpc_pollset_set* pss) { - gpr_mu_destroy(&pss->po.mu); - - if (pss->po.pi != nullptr) { - PI_UNREF(pss->po.pi, "pss_destroy"); - } - - gpr_free(pss); -} - -static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) { - add_poll_object(&pss->po, POLL_OBJ_POLLSET_SET, &fd->po, POLL_OBJ_FD); -} - -static void pollset_set_del_fd(grpc_pollset_set* pss, grpc_fd* fd) { - /* Nothing to do */ -} - -static void pollset_set_add_pollset(grpc_pollset_set* pss, grpc_pollset* ps) { - add_poll_object(&pss->po, POLL_OBJ_POLLSET_SET, &ps->po, POLL_OBJ_POLLSET); -} - -static void pollset_set_del_pollset(grpc_pollset_set* pss, grpc_pollset* ps) { - /* Nothing to do */ -} - -static void pollset_set_add_pollset_set(grpc_pollset_set* bag, - grpc_pollset_set* item) { - add_poll_object(&bag->po, POLL_OBJ_POLLSET_SET, &item->po, - POLL_OBJ_POLLSET_SET); -} - -static void pollset_set_del_pollset_set(grpc_pollset_set* bag, - grpc_pollset_set* item) { - /* Nothing to do */ -} - -/* Test helper functions - * */ -void* grpc_fd_get_polling_island(grpc_fd* fd) { - polling_island* pi; - - gpr_mu_lock(&fd->po.mu); - pi = fd->po.pi; - gpr_mu_unlock(&fd->po.mu); - - return pi; -} - -void* grpc_pollset_get_polling_island(grpc_pollset* ps) { - polling_island* pi; - - gpr_mu_lock(&ps->po.mu); - pi = ps->po.pi; - gpr_mu_unlock(&ps->po.mu); - - return pi; -} - -bool grpc_are_polling_islands_equal(void* p, void* q) { - polling_island* p1 = static_cast(p); - polling_island* p2 = static_cast(q); - - /* Note: polling_island_lock_pair() may change p1 and p2 to point to the - latest polling islands in their respective linked lists */ - polling_island_lock_pair(&p1, &p2); - polling_island_unlock_pair(p1, p2); - - return p1 == p2; -} - -/******************************************************************************* - * Event engine binding - */ - -static void shutdown_engine(void) { - fd_global_shutdown(); - pollset_global_shutdown(); - polling_island_global_shutdown(); -} - -static const grpc_event_engine_vtable vtable = { - sizeof(grpc_pollset), - - fd_create, - fd_wrapped_fd, - fd_orphan, - fd_shutdown, - fd_notify_on_read, - fd_notify_on_write, - fd_is_shutdown, - fd_get_read_notifier_pollset, - - pollset_init, - pollset_shutdown, - pollset_destroy, - pollset_work, - pollset_kick, - pollset_add_fd, - - pollset_set_create, - pollset_set_destroy, - pollset_set_add_pollset, - pollset_set_del_pollset, - pollset_set_add_pollset_set, - pollset_set_del_pollset_set, - pollset_set_add_fd, - pollset_set_del_fd, - - shutdown_engine, -}; - -/* It is possible that GLIBC has epoll but the underlying kernel doesn't. - * Create a dummy epoll_fd to make sure epoll support is available */ -static bool is_epoll_available() { - int fd = epoll_create1(EPOLL_CLOEXEC); - if (fd < 0) { - gpr_log( - GPR_ERROR, - "epoll_create1 failed with error: %d. Not using epoll polling engine", - fd); - return false; - } - close(fd); - return true; -} - -const grpc_event_engine_vtable* grpc_init_epollsig_linux( - bool explicit_request) { - /* If use of signals is disabled, we cannot use epoll engine*/ - if (is_grpc_wakeup_signal_initialized && grpc_wakeup_signal < 0) { - gpr_log(GPR_ERROR, "Skipping epollsig because use of signals is disabled."); - return nullptr; - } - - if (!grpc_has_wakeup_fd()) { - gpr_log(GPR_ERROR, "Skipping epollsig because of no wakeup fd."); - return nullptr; - } - - if (!is_epoll_available()) { - gpr_log(GPR_ERROR, "Skipping epollsig because epoll is unavailable."); - return nullptr; - } - - if (!is_grpc_wakeup_signal_initialized) { - if (explicit_request) { - grpc_use_signal(SIGRTMIN + 6); - } else { - gpr_log(GPR_ERROR, - "Skipping epollsig because uninitialized wakeup signal."); - return nullptr; - } - } - - fd_global_init(); - - if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { - return nullptr; - } - - if (!GRPC_LOG_IF_ERROR("polling_island_global_init", - polling_island_global_init())) { - return nullptr; - } - - return &vtable; -} - -#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */ -#if defined(GRPC_POSIX_SOCKET) -#include "src/core/lib/iomgr/ev_epollsig_linux.h" -/* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means - epoll_create1 is not available. Return NULL */ -const grpc_event_engine_vtable* grpc_init_epollsig_linux( - bool explicit_request) { - return nullptr; -} -#endif /* defined(GRPC_POSIX_SOCKET) */ - -void grpc_use_signal(int signum) {} -#endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_poll_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/ev_poll_posix.cc index 504787e65..c47920641 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_poll_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/ev_poll_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_EV_POLL #include "src/core/lib/iomgr/ev_poll_posix.h" @@ -60,6 +60,19 @@ typedef struct grpc_fd_watcher { grpc_fd* fd; } grpc_fd_watcher; +typedef struct grpc_cached_wakeup_fd grpc_cached_wakeup_fd; + +/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ +struct grpc_fork_fd_list { + /* Only one of fd or cached_wakeup_fd will be set. The unused field will be + set to nullptr. */ + grpc_fd* fd; + grpc_cached_wakeup_fd* cached_wakeup_fd; + + grpc_fork_fd_list* next; + grpc_fork_fd_list* prev; +}; + struct grpc_fd { int fd; /* refst format: @@ -109,10 +122,17 @@ struct grpc_fd { grpc_iomgr_object iomgr_object; - /* The pollset that last noticed and notified that the fd is readable */ - grpc_pollset* read_notifier_pollset; + /* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ + grpc_fork_fd_list* fork_fd_list; }; +/* True when GRPC_ENABLE_FORK_SUPPORT=1. We do not support fork with poll-cv */ +static bool track_fds_for_fork = false; + +/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ +static grpc_fork_fd_list* fork_fd_list_head = nullptr; +static gpr_mu fork_fd_list_mu; + /* Begin polling on an fd. Registers that the given pollset is interested in this fd - so that if read or writability interest changes, the pollset can be kicked to pick up that @@ -131,8 +151,7 @@ static uint32_t fd_begin_poll(grpc_fd* fd, grpc_pollset* pollset, MUST NOT be called with a pollset lock taken if got_read or got_write are 1, also does the become_{readable,writable} as appropriate. */ -static void fd_end_poll(grpc_fd_watcher* rec, int got_read, int got_write, - grpc_pollset* read_notifier_pollset); +static void fd_end_poll(grpc_fd_watcher* rec, int got_read, int got_write); /* Return 1 if this fd is orphaned, 0 otherwise */ static bool fd_is_orphaned(grpc_fd* fd); @@ -160,6 +179,9 @@ static void fd_unref(grpc_fd* fd); typedef struct grpc_cached_wakeup_fd { grpc_wakeup_fd fd; struct grpc_cached_wakeup_fd* next; + + /* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */ + grpc_fork_fd_list* fork_fd_list; } grpc_cached_wakeup_fd; struct grpc_pollset_worker { @@ -285,9 +307,61 @@ poll_hash_table poll_cache; grpc_cv_fd_table g_cvfds; /******************************************************************************* - * fd_posix.c + * functions to track opened fds. No-ops unless track_fds_for_fork is true. */ +static void fork_fd_list_remove_node(grpc_fork_fd_list* node) { + if (track_fds_for_fork) { + gpr_mu_lock(&fork_fd_list_mu); + if (fork_fd_list_head == node) { + fork_fd_list_head = node->next; + } + if (node->prev != nullptr) { + node->prev->next = node->next; + } + if (node->next != nullptr) { + node->next->prev = node->prev; + } + gpr_free(node); + gpr_mu_unlock(&fork_fd_list_mu); + } +} + +static void fork_fd_list_add_node(grpc_fork_fd_list* node) { + gpr_mu_lock(&fork_fd_list_mu); + node->next = fork_fd_list_head; + node->prev = nullptr; + if (fork_fd_list_head != nullptr) { + fork_fd_list_head->prev = node; + } + fork_fd_list_head = node; + gpr_mu_unlock(&fork_fd_list_mu); +} + +static void fork_fd_list_add_grpc_fd(grpc_fd* fd) { + if (track_fds_for_fork) { + fd->fork_fd_list = + static_cast(gpr_malloc(sizeof(grpc_fork_fd_list))); + fd->fork_fd_list->fd = fd; + fd->fork_fd_list->cached_wakeup_fd = nullptr; + fork_fd_list_add_node(fd->fork_fd_list); + } +} + +static void fork_fd_list_add_wakeup_fd(grpc_cached_wakeup_fd* fd) { + if (track_fds_for_fork) { + fd->fork_fd_list = + static_cast(gpr_malloc(sizeof(grpc_fork_fd_list))); + fd->fork_fd_list->cached_wakeup_fd = fd; + fd->fork_fd_list->fd = nullptr; + fork_fd_list_add_node(fd->fork_fd_list); + } +} + + /******************************************************************************* + * fd_posix.c + */ + #ifndef NDEBUG #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) @@ -323,6 +397,7 @@ static void unref_by(grpc_fd* fd, int n) { if (old == n) { gpr_mu_destroy(&fd->mu); grpc_iomgr_unregister_object(&fd->iomgr_object); + fork_fd_list_remove_node(fd->fork_fd_list); if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error); gpr_free(fd); } else { @@ -330,7 +405,8 @@ static void unref_by(grpc_fd* fd, int n) { } } -static grpc_fd* fd_create(int fd, const char* name) { +static grpc_fd* fd_create(int fd, const char* name, bool track_err) { + GPR_DEBUG_ASSERT(track_err == false); grpc_fd* r = static_cast(gpr_malloc(sizeof(*r))); gpr_mu_init(&r->mu); gpr_atm_rel_store(&r->refst, 1); @@ -345,12 +421,12 @@ static grpc_fd* fd_create(int fd, const char* name) { r->closed = 0; r->released = 0; gpr_atm_no_barrier_store(&r->pollhup, 0); - r->read_notifier_pollset = nullptr; char* name2; gpr_asprintf(&name2, "%s fd=%d", name, fd); grpc_iomgr_register_object(&r->iomgr_object, name2); gpr_free(name2); + fork_fd_list_add_grpc_fd(r); return r; } @@ -358,17 +434,6 @@ static bool fd_is_orphaned(grpc_fd* fd) { return (gpr_atm_acq_load(&fd->refst) & 1) == 0; } -/* Return the read-notifier pollset */ -static grpc_pollset* fd_get_read_notifier_pollset(grpc_fd* fd) { - grpc_pollset* notifier = nullptr; - - gpr_mu_lock(&fd->mu); - notifier = fd->read_notifier_pollset; - gpr_mu_unlock(&fd->mu); - - return notifier; -} - static grpc_error* pollset_kick_locked(grpc_fd_watcher* watcher) { gpr_mu_lock(&watcher->pollset->mu); GPR_ASSERT(watcher->worker); @@ -424,14 +489,12 @@ static int fd_wrapped_fd(grpc_fd* fd) { } static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason) { + const char* reason) { fd->on_done_closure = on_done; fd->released = release_fd != nullptr; if (release_fd != nullptr) { *release_fd = fd->fd; fd->released = true; - } else if (already_closed) { - fd->released = true; } gpr_mu_lock(&fd->mu); REF_BY(fd, 1, reason); /* remove active status, but keep referenced */ @@ -513,11 +576,6 @@ static int set_ready_locked(grpc_fd* fd, grpc_closure** st) { } } -static void set_read_notifier_pollset_locked( - grpc_fd* fd, grpc_pollset* read_notifier_pollset) { - fd->read_notifier_pollset = read_notifier_pollset; -} - static void fd_shutdown(grpc_fd* fd, grpc_error* why) { gpr_mu_lock(&fd->mu); /* only shutdown once */ @@ -553,6 +611,31 @@ static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { gpr_mu_unlock(&fd->mu); } +static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { + if (grpc_polling_trace.enabled()) { + gpr_log(GPR_ERROR, "Polling engine does not support tracking errors."); + } + GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_CANCELLED); +} + +static void fd_set_readable(grpc_fd* fd) { + gpr_mu_lock(&fd->mu); + set_ready_locked(fd, &fd->read_closure); + gpr_mu_unlock(&fd->mu); +} + +static void fd_set_writable(grpc_fd* fd) { + gpr_mu_lock(&fd->mu); + set_ready_locked(fd, &fd->write_closure); + gpr_mu_unlock(&fd->mu); +} + +static void fd_set_error(grpc_fd* fd) { + if (grpc_polling_trace.enabled()) { + gpr_log(GPR_ERROR, "Polling engine does not support tracking errors."); + } +} + static uint32_t fd_begin_poll(grpc_fd* fd, grpc_pollset* pollset, grpc_pollset_worker* worker, uint32_t read_mask, uint32_t write_mask, grpc_fd_watcher* watcher) { @@ -604,8 +687,7 @@ static uint32_t fd_begin_poll(grpc_fd* fd, grpc_pollset* pollset, return mask; } -static void fd_end_poll(grpc_fd_watcher* watcher, int got_read, int got_write, - grpc_pollset* read_notifier_pollset) { +static void fd_end_poll(grpc_fd_watcher* watcher, int got_read, int got_write) { int was_polling = 0; int kick = 0; grpc_fd* fd = watcher->fd; @@ -641,9 +723,6 @@ static void fd_end_poll(grpc_fd_watcher* watcher, int got_read, int got_write, if (set_ready_locked(fd, &fd->read_closure)) { kick = 1; } - if (read_notifier_pollset != nullptr) { - set_read_notifier_pollset_locked(fd, read_notifier_pollset); - } } if (got_write) { if (set_ready_locked(fd, &fd->write_closure)) { @@ -823,6 +902,7 @@ static void pollset_destroy(grpc_pollset* pollset) { GPR_ASSERT(!pollset_has_workers(pollset)); while (pollset->local_wakeup_cache) { grpc_cached_wakeup_fd* next = pollset->local_wakeup_cache->next; + fork_fd_list_remove_node(pollset->local_wakeup_cache->fork_fd_list); grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd); gpr_free(pollset->local_wakeup_cache); pollset->local_wakeup_cache = next; @@ -896,6 +976,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, worker.wakeup_fd = static_cast( gpr_malloc(sizeof(*worker.wakeup_fd))); error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd); + fork_fd_list_add_wakeup_fd(worker.wakeup_fd); if (error != GRPC_ERROR_NONE) { GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); return error; @@ -993,16 +1074,16 @@ static grpc_error* pollset_work(grpc_pollset* pollset, for (i = 1; i < pfd_count; i++) { if (watchers[i].fd == nullptr) { - fd_end_poll(&watchers[i], 0, 0, nullptr); + fd_end_poll(&watchers[i], 0, 0); } else { // Wake up all the file descriptors, if we have an invalid one // we can identify it on the next pollset_work() - fd_end_poll(&watchers[i], 1, 1, pollset); + fd_end_poll(&watchers[i], 1, 1); } } } else if (r == 0) { for (i = 1; i < pfd_count; i++) { - fd_end_poll(&watchers[i], 0, 0, nullptr); + fd_end_poll(&watchers[i], 0, 0); } } else { if (pfds[0].revents & POLLIN_CHECK) { @@ -1014,7 +1095,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, } for (i = 1; i < pfd_count; i++) { if (watchers[i].fd == nullptr) { - fd_end_poll(&watchers[i], 0, 0, nullptr); + fd_end_poll(&watchers[i], 0, 0); } else { if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "%p got_event: %d r:%d w:%d [%d]", pollset, @@ -1028,7 +1109,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, gpr_atm_no_barrier_store(&watchers[i].fd->pollhup, 1); } fd_end_poll(&watchers[i], pfds[i].revents & POLLIN_CHECK, - pfds[i].revents & POLLOUT_CHECK, pollset); + pfds[i].revents & POLLOUT_CHECK); } } } @@ -1701,15 +1782,25 @@ static void global_cv_fd_table_shutdown() { * event engine binding */ +static bool is_any_background_poller_thread(void) { return false; } + +static void shutdown_background_closure(void) {} + static void shutdown_engine(void) { pollset_global_shutdown(); if (grpc_cv_wakeup_fds_enabled()) { global_cv_fd_table_shutdown(); } + if (track_fds_for_fork) { + gpr_mu_destroy(&fork_fd_list_mu); + grpc_core::Fork::SetResetChildPollingEngineFunc(nullptr); + } } static const grpc_event_engine_vtable vtable = { sizeof(grpc_pollset), + false, + false, fd_create, fd_wrapped_fd, @@ -1717,8 +1808,11 @@ static const grpc_event_engine_vtable vtable = { fd_shutdown, fd_notify_on_read, fd_notify_on_write, + fd_notify_on_error, + fd_set_readable, + fd_set_writable, + fd_set_error, fd_is_shutdown, - fd_get_read_notifier_pollset, pollset_init, pollset_shutdown, @@ -1736,9 +1830,31 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + is_any_background_poller_thread, + shutdown_background_closure, shutdown_engine, }; +/* Called by the child process's post-fork handler to close open fds, including + * worker wakeup fds. This allows gRPC to shutdown in the child process without + * interfering with connections or RPCs ongoing in the parent. */ +static void reset_event_manager_on_fork() { + gpr_mu_lock(&fork_fd_list_mu); + while (fork_fd_list_head != nullptr) { + if (fork_fd_list_head->fd != nullptr) { + close(fork_fd_list_head->fd->fd); + fork_fd_list_head->fd->fd = -1; + } else { + close(fork_fd_list_head->cached_wakeup_fd->fd.read_fd); + fork_fd_list_head->cached_wakeup_fd->fd.read_fd = -1; + close(fork_fd_list_head->cached_wakeup_fd->fd.write_fd); + fork_fd_list_head->cached_wakeup_fd->fd.write_fd = -1; + } + fork_fd_list_head = fork_fd_list_head->next; + } + gpr_mu_unlock(&fork_fd_list_mu); +} + const grpc_event_engine_vtable* grpc_init_poll_posix(bool explicit_request) { if (!grpc_has_wakeup_fd()) { gpr_log(GPR_ERROR, "Skipping poll because of no wakeup fd."); @@ -1747,6 +1863,12 @@ const grpc_event_engine_vtable* grpc_init_poll_posix(bool explicit_request) { if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { return nullptr; } + if (grpc_core::Fork::Enabled()) { + track_fds_for_fork = true; + gpr_mu_init(&fork_fd_list_mu); + grpc_core::Fork::SetResetChildPollingEngineFunc( + reset_event_manager_on_fork); + } return &vtable; } @@ -1761,4 +1883,4 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(bool explicit_request) { return &vtable; } -#endif +#endif /* GRPC_POSIX_SOCKET_EV_POLL */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/ev_posix.cc index 4ea63fc6e..fb2e70eee 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/ev_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_EV #include "src/core/lib/iomgr/ev_posix.h" @@ -35,11 +35,14 @@ #include "src/core/lib/gpr/useful.h" #include "src/core/lib/iomgr/ev_epoll1_linux.h" #include "src/core/lib/iomgr/ev_epollex_linux.h" -#include "src/core/lib/iomgr/ev_epollsig_linux.h" #include "src/core/lib/iomgr/ev_poll_posix.h" +#include "src/core/lib/iomgr/internal_errqueue.h" grpc_core::TraceFlag grpc_polling_trace(false, "polling"); /* Disabled by default */ + +/* Traces fd create/close operations */ +grpc_core::TraceFlag grpc_fd_trace(false, "fd_trace"); grpc_core::DebugOnlyTraceFlag grpc_trace_fd_refcount(false, "fd_refcount"); grpc_core::DebugOnlyTraceFlag grpc_polling_api_trace(false, "polling_api"); @@ -56,7 +59,14 @@ grpc_core::DebugOnlyTraceFlag grpc_polling_api_trace(false, "polling_api"); /** Default poll() function - a pointer so that it can be overridden by some * tests */ +#ifndef GPR_AIX grpc_poll_function_type grpc_poll_function = poll; +#else +int aix_poll(struct pollfd fds[], nfds_t nfds, int timeout) { + return poll(fds, nfds, timeout); +} +grpc_poll_function_type grpc_poll_function = aix_poll; +#endif grpc_wakeup_fd grpc_global_wakeup_fd; @@ -98,10 +108,28 @@ const grpc_event_engine_vtable* init_non_polling(bool explicit_request) { } } // namespace -static const event_engine_factory g_factories[] = { - {"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux}, - {"epollsig", grpc_init_epollsig_linux}, {"poll", grpc_init_poll_posix}, - {"poll-cv", grpc_init_poll_cv_posix}, {"none", init_non_polling}, +#define ENGINE_HEAD_CUSTOM "head_custom" +#define ENGINE_TAIL_CUSTOM "tail_custom" + +// The global array of event-engine factories. Each entry is a pair with a name +// and an event-engine generator function (nullptr if there is no generator +// registered for this name). The middle entries are the engines predefined by +// open-source gRPC. The head entries represent an opportunity for specific +// high-priority custom pollers to be added by the initializer plugins of +// custom-built gRPC libraries. The tail entries represent the same, but for +// low-priority custom pollers. The actual poller selected is either the first +// available one in the list if no specific poller is requested, or the first +// specific poller that is requested by name in the GRPC_POLL_STRATEGY +// environment variable if that variable is set (which should be a +// comma-separated list of one or more event engine names) +static event_engine_factory g_factories[] = { + {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr}, + {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr}, + {"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux}, + {"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix}, + {"none", init_non_polling}, {ENGINE_TAIL_CUSTOM, nullptr}, + {ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr}, + {ENGINE_TAIL_CUSTOM, nullptr}, }; static void add(const char* beg, const char* end, char*** ss, size_t* ns) { @@ -135,7 +163,7 @@ static bool is(const char* want, const char* have) { static void try_engine(const char* engine) { for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) { - if (is(engine, g_factories[i].name)) { + if (g_factories[i].factory != nullptr && is(engine, g_factories[i].name)) { if ((g_event_engine = g_factories[i].factory( 0 == strcmp(engine, g_factories[i].name)))) { g_poll_strategy_name = g_factories[i].name; @@ -146,14 +174,32 @@ static void try_engine(const char* engine) { } } -/* This should be used for testing purposes ONLY */ -void grpc_set_event_engine_test_only( - const grpc_event_engine_vtable* ev_engine) { - g_event_engine = ev_engine; -} +/* Call this before calling grpc_event_engine_init() */ +void grpc_register_event_engine_factory(const char* name, + event_engine_factory_fn factory, + bool add_at_head) { + const char* custom_match = + add_at_head ? ENGINE_HEAD_CUSTOM : ENGINE_TAIL_CUSTOM; + + // Overwrite an existing registration if already registered + for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) { + if (0 == strcmp(name, g_factories[i].name)) { + g_factories[i].factory = factory; + return; + } + } -const grpc_event_engine_vtable* grpc_get_event_engine_test_only() { - return g_event_engine; + // Otherwise fill in an available custom slot + for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) { + if (0 == strcmp(g_factories[i].name, custom_match)) { + g_factories[i].name = name; + g_factories[i].factory = factory; + return; + } + } + + // Otherwise fail + GPR_ASSERT(false); } /* Call this only after calling grpc_event_engine_init() */ @@ -190,9 +236,23 @@ void grpc_event_engine_shutdown(void) { g_event_engine = nullptr; } -grpc_fd* grpc_fd_create(int fd, const char* name) { - GRPC_POLLING_API_TRACE("fd_create(%d, %s)", fd, name); - return g_event_engine->fd_create(fd, name); +bool grpc_event_engine_can_track_errors(void) { + /* Only track errors if platform supports errqueue. */ + if (grpc_core::kernel_supports_errqueue()) { + return g_event_engine->can_track_err; + } + return false; +} + +bool grpc_event_engine_run_in_background(void) { + return g_event_engine->run_in_background; +} + +grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err) { + GRPC_POLLING_API_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); + GRPC_FD_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); + return g_event_engine->fd_create( + fd, name, track_err && grpc_event_engine_can_track_errors()); } int grpc_fd_wrapped_fd(grpc_fd* fd) { @@ -200,15 +260,17 @@ int grpc_fd_wrapped_fd(grpc_fd* fd) { } void grpc_fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason) { - GRPC_POLLING_API_TRACE("fd_orphan(%d, %p, %p, %d, %s)", - grpc_fd_wrapped_fd(fd), on_done, release_fd, - already_closed, reason); - g_event_engine->fd_orphan(fd, on_done, release_fd, already_closed, reason); + const char* reason) { + GRPC_POLLING_API_TRACE("fd_orphan(%d, %p, %p, %s)", grpc_fd_wrapped_fd(fd), + on_done, release_fd, reason); + GRPC_FD_TRACE("grpc_fd_orphan, fd:%d closed", grpc_fd_wrapped_fd(fd)); + + g_event_engine->fd_orphan(fd, on_done, release_fd, reason); } void grpc_fd_shutdown(grpc_fd* fd, grpc_error* why) { GRPC_POLLING_API_TRACE("fd_shutdown(%d)", grpc_fd_wrapped_fd(fd)); + GRPC_FD_TRACE("fd_shutdown(%d)", grpc_fd_wrapped_fd(fd)); g_event_engine->fd_shutdown(fd, why); } @@ -224,6 +286,16 @@ void grpc_fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { g_event_engine->fd_notify_on_write(fd, closure); } +void grpc_fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { + g_event_engine->fd_notify_on_error(fd, closure); +} + +void grpc_fd_set_readable(grpc_fd* fd) { g_event_engine->fd_set_readable(fd); } + +void grpc_fd_set_writable(grpc_fd* fd) { g_event_engine->fd_set_writable(fd); } + +void grpc_fd_set_error(grpc_fd* fd) { g_event_engine->fd_set_error(fd); } + static size_t pollset_size(void) { return g_event_engine->pollset_size; } static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { @@ -244,10 +316,10 @@ static void pollset_destroy(grpc_pollset* pollset) { static grpc_error* pollset_work(grpc_pollset* pollset, grpc_pollset_worker** worker, grpc_millis deadline) { - GRPC_POLLING_API_TRACE("pollset_work(%p, %" PRIdPTR ") begin", pollset, + GRPC_POLLING_API_TRACE("pollset_work(%p, %" PRId64 ") begin", pollset, deadline); grpc_error* err = g_event_engine->pollset_work(pollset, worker, deadline); - GRPC_POLLING_API_TRACE("pollset_work(%p, %" PRIdPTR ") end", pollset, + GRPC_POLLING_API_TRACE("pollset_work(%p, %" PRId64 ") end", pollset, deadline); return err; } @@ -327,4 +399,12 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) { g_event_engine->pollset_set_del_fd(pollset_set, fd); } -#endif // GRPC_POSIX_SOCKET +bool grpc_is_any_background_poller_thread(void) { + return g_event_engine->is_any_background_poller_thread(); +} + +void grpc_shutdown_background_closure(void) { + g_event_engine->shutdown_background_closure(); +} + +#endif // GRPC_POSIX_SOCKET_EV diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_posix.h b/Sources/CgRPC/src/core/lib/iomgr/ev_posix.h index 6a5129a74..94ac9fdba 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_posix.h +++ b/Sources/CgRPC/src/core/lib/iomgr/ev_posix.h @@ -29,22 +29,33 @@ #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" +extern grpc_core::TraceFlag grpc_fd_trace; /* Disabled by default */ extern grpc_core::TraceFlag grpc_polling_trace; /* Disabled by default */ +#define GRPC_FD_TRACE(format, ...) \ + if (grpc_fd_trace.enabled()) { \ + gpr_log(GPR_INFO, "(fd-trace) " format, __VA_ARGS__); \ + } + typedef struct grpc_fd grpc_fd; typedef struct grpc_event_engine_vtable { size_t pollset_size; + bool can_track_err; + bool run_in_background; - grpc_fd* (*fd_create)(int fd, const char* name); + grpc_fd* (*fd_create)(int fd, const char* name, bool track_err); int (*fd_wrapped_fd)(grpc_fd* fd); void (*fd_orphan)(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason); + const char* reason); void (*fd_shutdown)(grpc_fd* fd, grpc_error* why); void (*fd_notify_on_read)(grpc_fd* fd, grpc_closure* closure); void (*fd_notify_on_write)(grpc_fd* fd, grpc_closure* closure); + void (*fd_notify_on_error)(grpc_fd* fd, grpc_closure* closure); + void (*fd_set_readable)(grpc_fd* fd); + void (*fd_set_writable)(grpc_fd* fd); + void (*fd_set_error)(grpc_fd* fd); bool (*fd_is_shutdown)(grpc_fd* fd); - grpc_pollset* (*fd_get_read_notifier_pollset)(grpc_fd* fd); void (*pollset_init)(grpc_pollset* pollset, gpr_mu** mu); void (*pollset_shutdown)(grpc_pollset* pollset, grpc_closure* closure); @@ -69,19 +80,41 @@ typedef struct grpc_event_engine_vtable { void (*pollset_set_add_fd)(grpc_pollset_set* pollset_set, grpc_fd* fd); void (*pollset_set_del_fd)(grpc_pollset_set* pollset_set, grpc_fd* fd); + bool (*is_any_background_poller_thread)(void); + void (*shutdown_background_closure)(void); void (*shutdown_engine)(void); } grpc_event_engine_vtable; +/* register a new event engine factory */ +void grpc_register_event_engine_factory( + const char* name, const grpc_event_engine_vtable* (*factory)(bool), + bool add_at_head); + void grpc_event_engine_init(void); void grpc_event_engine_shutdown(void); /* Return the name of the poll strategy */ const char* grpc_get_poll_strategy_name(); +/* Returns true if polling engine can track errors separately, false otherwise. + * If this is true, fd can be created with track_err set. After this, error + * events will be reported using fd_notify_on_error. If it is not set, errors + * will continue to be reported through fd_notify_on_read and + * fd_notify_on_write. + */ +bool grpc_event_engine_can_track_errors(); + +/* Returns true if polling engine runs in the background, false otherwise. + * Currently only 'epollbg' runs in the background. + */ +bool grpc_event_engine_run_in_background(); + /* Create a wrapped file descriptor. Requires fd is a non-blocking file descriptor. + \a track_err if true means that error events would be tracked separately + using grpc_fd_notify_on_error. Currently, valid only for linux systems. This takes ownership of closing fd. */ -grpc_fd* grpc_fd_create(int fd, const char* name); +grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err); /* Return the wrapped fd, or -1 if it has been released or closed. */ int grpc_fd_wrapped_fd(grpc_fd* fd); @@ -94,7 +127,7 @@ int grpc_fd_wrapped_fd(grpc_fd* fd); notify_on_write. MUST NOT be called with a pollset lock taken */ void grpc_fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, - bool already_closed, const char* reason); + const char* reason); /* Has grpc_fd_shutdown been called on an fd? */ bool grpc_fd_is_shutdown(grpc_fd* fd); @@ -120,8 +153,24 @@ void grpc_fd_notify_on_read(grpc_fd* fd, grpc_closure* closure); /* Exactly the same semantics as above, except based on writable events. */ void grpc_fd_notify_on_write(grpc_fd* fd, grpc_closure* closure); -/* Return the read notifier pollset from the fd */ -grpc_pollset* grpc_fd_get_read_notifier_pollset(grpc_fd* fd); +/* Exactly the same semantics as above, except based on error events. track_err + * needs to have been set on grpc_fd_create */ +void grpc_fd_notify_on_error(grpc_fd* fd, grpc_closure* closure); + +/* Forcibly set the fd to be readable, resulting in the closure registered with + * grpc_fd_notify_on_read being invoked. + */ +void grpc_fd_set_readable(grpc_fd* fd); + +/* Forcibly set the fd to be writable, resulting in the closure registered with + * grpc_fd_notify_on_write being invoked. + */ +void grpc_fd_set_writable(grpc_fd* fd); + +/* Forcibly set the fd to have errored, resulting in the closure registered with + * grpc_fd_notify_on_error being invoked. + */ +void grpc_fd_set_error(grpc_fd* fd); /* pollset_posix functions */ @@ -133,13 +182,14 @@ void grpc_pollset_add_fd(grpc_pollset* pollset, struct grpc_fd* fd); void grpc_pollset_set_add_fd(grpc_pollset_set* pollset_set, grpc_fd* fd); void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd); +/* Returns true if the caller is a worker thread for any background poller. */ +bool grpc_is_any_background_poller_thread(); + +/* Shut down all the closures registered in the background poller. */ +void grpc_shutdown_background_closure(); + /* override to allow tests to hook poll() usage */ typedef int (*grpc_poll_function_type)(struct pollfd*, nfds_t, int); extern grpc_poll_function_type grpc_poll_function; -/* WARNING: The following two functions should be used for testing purposes - * ONLY */ -void grpc_set_event_engine_test_only(const grpc_event_engine_vtable*); -const grpc_event_engine_vtable* grpc_get_event_engine_test_only(); - #endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.cc b/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.cc index 2f544b20a..f45def433 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.cc @@ -53,24 +53,31 @@ static void exec_ctx_sched(grpc_closure* closure, grpc_error* error) { static gpr_timespec g_start_time; -static gpr_atm timespec_to_atm_round_down(gpr_timespec ts) { +// For debug of the timer manager crash only. +// TODO (mxyan): remove after bug is fixed. +#ifdef GRPC_DEBUG_TIMER_MANAGER +extern int64_t g_start_time_sec; +extern int64_t g_start_time_nsec; +#endif // GRPC_DEBUG_TIMER_MANAGER + +static grpc_millis timespec_to_millis_round_down(gpr_timespec ts) { ts = gpr_time_sub(ts, g_start_time); double x = GPR_MS_PER_SEC * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec) / GPR_NS_PER_MS; if (x < 0) return 0; - if (x > GPR_ATM_MAX) return GPR_ATM_MAX; - return static_cast(x); + if (x > GRPC_MILLIS_INF_FUTURE) return GRPC_MILLIS_INF_FUTURE; + return static_cast(x); } -static gpr_atm timespec_to_atm_round_up(gpr_timespec ts) { +static grpc_millis timespec_to_millis_round_up(gpr_timespec ts) { ts = gpr_time_sub(ts, g_start_time); double x = GPR_MS_PER_SEC * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec) / GPR_NS_PER_MS + static_cast(GPR_NS_PER_SEC - 1) / static_cast(GPR_NS_PER_SEC); if (x < 0) return 0; - if (x > GPR_ATM_MAX) return GPR_ATM_MAX; - return static_cast(x); + if (x > GRPC_MILLIS_INF_FUTURE) return GRPC_MILLIS_INF_FUTURE; + return static_cast(x); } gpr_timespec grpc_millis_to_timespec(grpc_millis millis, @@ -92,12 +99,12 @@ gpr_timespec grpc_millis_to_timespec(grpc_millis millis, } grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec ts) { - return timespec_to_atm_round_down( + return timespec_to_millis_round_down( gpr_convert_clock_type(ts, g_start_time.clock_type)); } grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec ts) { - return timespec_to_atm_round_up( + return timespec_to_millis_round_up( gpr_convert_clock_type(ts, g_start_time.clock_type)); } @@ -108,9 +115,22 @@ grpc_closure_scheduler* grpc_schedule_on_exec_ctx = &exec_ctx_scheduler; namespace grpc_core { GPR_TLS_CLASS_DEF(ExecCtx::exec_ctx_); +GPR_TLS_CLASS_DEF(ApplicationCallbackExecCtx::callback_exec_ctx_); + +// WARNING: for testing purposes only! +void ExecCtx::TestOnlyGlobalInit(gpr_timespec new_val) { + g_start_time = new_val; + gpr_tls_init(&exec_ctx_); +} void ExecCtx::GlobalInit(void) { g_start_time = gpr_now(GPR_CLOCK_MONOTONIC); + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. +#ifdef GRPC_DEBUG_TIMER_MANAGER + g_start_time_sec = g_start_time.tv_sec; + g_start_time_nsec = g_start_time.tv_nsec; +#endif gpr_tls_init(&exec_ctx_); } @@ -138,7 +158,7 @@ bool ExecCtx::Flush() { grpc_millis ExecCtx::Now() { if (!now_is_valid_) { - now_ = timespec_to_atm_round_down(gpr_now(GPR_CLOCK_MONOTONIC)); + now_ = timespec_to_millis_round_down(gpr_now(GPR_CLOCK_MONOTONIC)); now_is_valid_ = true; } return now_; diff --git a/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.h b/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.h index 72d0ae58c..daf019c41 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.h +++ b/Sources/CgRPC/src/core/lib/iomgr/exec_ctx.h @@ -21,21 +21,22 @@ #include +#include #include #include #include #include "src/core/lib/gpr/tls.h" +#include "src/core/lib/gprpp/fork.h" #include "src/core/lib/iomgr/closure.h" -typedef gpr_atm grpc_millis; +typedef int64_t grpc_millis; -#define GRPC_MILLIS_INF_FUTURE GPR_ATM_MAX -#define GRPC_MILLIS_INF_PAST GPR_ATM_MIN +#define GRPC_MILLIS_INF_FUTURE INT64_MAX +#define GRPC_MILLIS_INF_PAST INT64_MIN -/** A workqueue represents a list of work to be executed asynchronously. - Forward declared here to avoid a circular dependency with workqueue.h. */ -typedef struct grpc_workqueue grpc_workqueue; +/** A combiner represents a list of work to be executed later. + Forward declared here to avoid a circular dependency with combiner.h. */ typedef struct grpc_combiner grpc_combiner; /* This exec_ctx is ready to return: either pre-populated, or cached as soon as @@ -44,6 +45,13 @@ typedef struct grpc_combiner grpc_combiner; /* The exec_ctx's thread is (potentially) owned by a call or channel: care should be given to not delete said call/channel from this exec_ctx */ #define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2 +/* This exec ctx was initialized by an internal thread, and should not + be counted by fork handlers */ +#define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 4 + +/* This application callback exec ctx was initialized by an internal thread, and + should not be counted by fork handlers */ +#define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 1 extern grpc_closure_scheduler* grpc_schedule_on_exec_ctx; @@ -54,8 +62,8 @@ grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec timespec); namespace grpc_core { /** Execution context. * A bag of data that collects information along a callstack. - * It is created on the stack at public API entry points, and stored internally - * as a thread-local variable. + * It is created on the stack at core entry points (public API or iomgr), and + * stored internally as a thread-local variable. * * Generally, to create an exec_ctx instance, add the following line at the top * of the public API entry point or at the start of a thread's work function : @@ -66,7 +74,7 @@ namespace grpc_core { * grpc_core::ExecCtx::Get() * * Specific responsibilities (this may grow in the future): - * - track a list of work that needs to be delayed until the top of the + * - track a list of core work that needs to be delayed until the base of the * call stack (this provides a convenient mechanism to run callbacks * without worrying about locking issues) * - provide a decision maker (via IsReadyToFinish) that provides a @@ -76,32 +84,51 @@ namespace grpc_core { * CONVENTIONS: * - Instance of this must ALWAYS be constructed on the stack, never * heap allocated. - * - Exactly one instance of ExecCtx must be created per thread. Instances must - * always be called exec_ctx. * - Do not pass exec_ctx as a parameter to a function. Always access it using - * grpc_core::ExecCtx::Get() + * grpc_core::ExecCtx::Get(). + * - NOTE: In the future, the convention is likely to change to allow only one + * ExecCtx on a thread's stack at the same time. The TODO below + * discusses this plan in more detail. + * + * TODO(yashykt): Only allow one "active" ExecCtx on a thread at the same time. + * Stage 1: If a new one is created on the stack, it should just + * pass-through to the underlying ExecCtx deeper in the thread's + * stack. + * Stage 2: Assert if a 2nd one is ever created on the stack + * since that implies a core re-entry outside of application + * callbacks. */ class ExecCtx { public: /** Default Constructor */ - ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { Set(this); } + ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { + grpc_core::Fork::IncExecCtxCount(); + Set(this); + } /** Parameterised Constructor */ - ExecCtx(uintptr_t fl) : flags_(fl) { Set(this); } + ExecCtx(uintptr_t fl) : flags_(fl) { + if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) { + grpc_core::Fork::IncExecCtxCount(); + } + Set(this); + } /** Destructor */ virtual ~ExecCtx() { flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED; Flush(); Set(last_exec_ctx_); + if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) { + grpc_core::Fork::DecExecCtxCount(); + } } /** Disallow copy and assignment operators */ ExecCtx(const ExecCtx&) = delete; ExecCtx& operator=(const ExecCtx&) = delete; - /** Return starting_cpu */ unsigned starting_cpu() const { return starting_cpu_; } struct CombinerData { @@ -128,12 +155,14 @@ class ExecCtx { /** Flush any work that has been enqueued onto this grpc_exec_ctx. * Caller must guarantee that no interfering locks are held. - * Returns true if work was performed, false otherwise. */ + * Returns true if work was performed, false otherwise. + */ bool Flush(); /** Returns true if we'd like to leave this execution context as soon as -possible: useful for deciding whether to do something more or not depending -on outside context */ + * possible: useful for deciding whether to do something more or not + * depending on outside context. + */ bool IsReadyToFinish() { if ((flags_ & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) { if (CheckReadyToFinish()) { @@ -147,12 +176,14 @@ on outside context */ } /** Returns the stored current time relative to start if valid, - * otherwise refreshes the stored time, sets it valid and returns the new - * value */ + * otherwise refreshes the stored time, sets it valid and returns the new + * value. + */ grpc_millis Now(); /** Invalidates the stored time value. A new time value will be set on calling - * Now() */ + * Now(). + */ void InvalidateNow() { now_is_valid_ = false; } /** To be used only by shutdown code in iomgr */ @@ -162,20 +193,22 @@ on outside context */ } /** To be used only for testing. - * Sets the now value + * Sets the now value. */ void TestOnlySetNow(grpc_millis new_val) { now_ = new_val; now_is_valid_ = true; } - /** Global initialization for ExecCtx. Called by iomgr */ + static void TestOnlyGlobalInit(gpr_timespec new_val); + + /** Global initialization for ExecCtx. Called by iomgr. */ static void GlobalInit(void); - /** Global shutdown for ExecCtx. Called by iomgr */ + /** Global shutdown for ExecCtx. Called by iomgr. */ static void GlobalShutdown(void) { gpr_tls_destroy(&exec_ctx_); } - /** Gets pointer to current exec_ctx */ + /** Gets pointer to current exec_ctx. */ static ExecCtx* Get() { return reinterpret_cast(gpr_tls_get(&exec_ctx_)); } @@ -185,18 +218,19 @@ on outside context */ } protected: - /** Check if ready to finish */ + /** Check if ready to finish. */ virtual bool CheckReadyToFinish() { return false; } - /** Disallow delete on ExecCtx */ + /** Disallow delete on ExecCtx. */ static void operator delete(void* p) { abort(); } private: - /** Set exec_ctx_ to exec_ctx */ + /** Set exec_ctx_ to exec_ctx. */ grpc_closure_list closure_list_ = GRPC_CLOSURE_LIST_INIT; CombinerData combiner_data_ = {nullptr, nullptr}; uintptr_t flags_; + unsigned starting_cpu_ = gpr_cpu_current_cpu(); bool now_is_valid_ = false; @@ -205,6 +239,122 @@ on outside context */ GPR_TLS_CLASS_DECL(exec_ctx_); ExecCtx* last_exec_ctx_ = Get(); }; + +/** Application-callback execution context. + * A bag of data that collects information along a callstack. + * It is created on the stack at core entry points, and stored internally + * as a thread-local variable. + * + * There are three key differences between this structure and ExecCtx: + * 1. ApplicationCallbackExecCtx builds a list of application-level + * callbacks, but ExecCtx builds a list of internal callbacks to invoke. + * 2. ApplicationCallbackExecCtx invokes its callbacks only at destruction; + * there is no explicit Flush method. + * 3. If more than one ApplicationCallbackExecCtx is created on the thread's + * stack, only the one closest to the base of the stack is actually + * active and this is the only one that enqueues application callbacks. + * (Unlike ExecCtx, it is not feasible to prevent multiple of these on the + * stack since the executing application callback may itself enter core. + * However, the new one created will just pass callbacks through to the + * base one and those will not be executed until the return to the + * destructor of the base one, preventing unlimited stack growth.) + * + * This structure exists because application callbacks may themselves cause a + * core re-entry (e.g., through a public API call) and if that call in turn + * causes another application-callback, there could be arbitrarily growing + * stacks of core re-entries. Instead, any application callbacks instead should + * not be invoked until other core work is done and other application callbacks + * have completed. To accomplish this, any application callback should be + * enqueued using grpc_core::ApplicationCallbackExecCtx::Enqueue . + * + * CONVENTIONS: + * - Instances of this must ALWAYS be constructed on the stack, never + * heap allocated. + * - Instances of this are generally constructed before ExecCtx when needed. + * The only exception is for ExecCtx's that are explicitly flushed and + * that survive beyond the scope of the function that can cause application + * callbacks to be invoked (e.g., in the timer thread). + * + * Generally, core entry points that may trigger application-level callbacks + * will have the following declarations: + * + * grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + * grpc_core::ExecCtx exec_ctx; + * + * This ordering is important to make sure that the ApplicationCallbackExecCtx + * is destroyed after the ExecCtx (to prevent the re-entry problem described + * above, as well as making sure that ExecCtx core callbacks are invoked first) + * + */ + +class ApplicationCallbackExecCtx { + public: + /** Default Constructor */ + ApplicationCallbackExecCtx() { Set(this, flags_); } + + /** Parameterised Constructor */ + ApplicationCallbackExecCtx(uintptr_t fl) : flags_(fl) { Set(this, flags_); } + + ~ApplicationCallbackExecCtx() { + if (reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)) == this) { + while (head_ != nullptr) { + auto* f = head_; + head_ = f->internal_next; + if (f->internal_next == nullptr) { + tail_ = nullptr; + } + (*f->functor_run)(f, f->internal_success); + } + gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(nullptr)); + if (!(GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) { + grpc_core::Fork::DecExecCtxCount(); + } + } else { + GPR_DEBUG_ASSERT(head_ == nullptr); + GPR_DEBUG_ASSERT(tail_ == nullptr); + } + } + + static void Set(ApplicationCallbackExecCtx* exec_ctx, uintptr_t flags) { + if (reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)) == nullptr) { + if (!(GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags)) { + grpc_core::Fork::IncExecCtxCount(); + } + gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(exec_ctx)); + } + } + + static void Enqueue(grpc_experimental_completion_queue_functor* functor, + int is_success) { + functor->internal_success = is_success; + functor->internal_next = nullptr; + + auto* ctx = reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)); + + if (ctx->head_ == nullptr) { + ctx->head_ = functor; + } + if (ctx->tail_ != nullptr) { + ctx->tail_->internal_next = functor; + } + ctx->tail_ = functor; + } + + /** Global initialization for ApplicationCallbackExecCtx. Called by init. */ + static void GlobalInit(void) { gpr_tls_init(&callback_exec_ctx_); } + + /** Global shutdown for ApplicationCallbackExecCtx. Called by init. */ + static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); } + + private: + uintptr_t flags_{0u}; + grpc_experimental_completion_queue_functor* head_{nullptr}; + grpc_experimental_completion_queue_functor* tail_{nullptr}; + GPR_TLS_CLASS_DECL(callback_exec_ctx_); +}; } // namespace grpc_core #endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/executor.cc b/Sources/CgRPC/src/core/lib/iomgr/executor.cc index f19f8cf20..2ad8972fc 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/executor.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/executor.cc @@ -28,52 +28,107 @@ #include #include "src/core/lib/debug/stats.h" -#include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/exec_ctx.h" #define MAX_DEPTH 2 -typedef struct { - gpr_mu mu; - gpr_cv cv; - grpc_closure_list elems; - size_t depth; - bool shutdown; - bool queued_long_job; - grpc_core::Thread thd; -} thread_state; - -static thread_state* g_thread_state; -static size_t g_max_threads; -static gpr_atm g_cur_threads; -static gpr_spinlock g_adding_thread_lock = GPR_SPINLOCK_STATIC_INITIALIZER; +#define EXECUTOR_TRACE(format, ...) \ + if (executor_trace.enabled()) { \ + gpr_log(GPR_INFO, "EXECUTOR " format, __VA_ARGS__); \ + } + +#define EXECUTOR_TRACE0(str) \ + if (executor_trace.enabled()) { \ + gpr_log(GPR_INFO, "EXECUTOR " str); \ + } + +namespace grpc_core { +namespace { GPR_TLS_DECL(g_this_thread_state); -grpc_core::TraceFlag executor_trace(false, "executor"); +Executor* executors[static_cast(ExecutorType::NUM_EXECUTORS)]; + +void default_enqueue_short(grpc_closure* closure, grpc_error* error) { + executors[static_cast(ExecutorType::DEFAULT)]->Enqueue( + closure, error, true /* is_short */); +} -static void executor_thread(void* arg); +void default_enqueue_long(grpc_closure* closure, grpc_error* error) { + executors[static_cast(ExecutorType::DEFAULT)]->Enqueue( + closure, error, false /* is_short */); +} + +void resolver_enqueue_short(grpc_closure* closure, grpc_error* error) { + executors[static_cast(ExecutorType::RESOLVER)]->Enqueue( + closure, error, true /* is_short */); +} + +void resolver_enqueue_long(grpc_closure* closure, grpc_error* error) { + executors[static_cast(ExecutorType::RESOLVER)]->Enqueue( + closure, error, false /* is_short */); +} -static size_t run_closures(grpc_closure_list list) { +const grpc_closure_scheduler_vtable + vtables_[static_cast(ExecutorType::NUM_EXECUTORS)] + [static_cast(ExecutorJobType::NUM_JOB_TYPES)] = { + {{&default_enqueue_short, &default_enqueue_short, + "def-ex-short"}, + {&default_enqueue_long, &default_enqueue_long, "def-ex-long"}}, + {{&resolver_enqueue_short, &resolver_enqueue_short, + "res-ex-short"}, + {&resolver_enqueue_long, &resolver_enqueue_long, + "res-ex-long"}}}; + +grpc_closure_scheduler + schedulers_[static_cast(ExecutorType::NUM_EXECUTORS)] + [static_cast(ExecutorJobType::NUM_JOB_TYPES)] = { + {{&vtables_[static_cast(ExecutorType::DEFAULT)] + [static_cast(ExecutorJobType::SHORT)]}, + {&vtables_[static_cast(ExecutorType::DEFAULT)] + [static_cast(ExecutorJobType::LONG)]}}, + {{&vtables_[static_cast(ExecutorType::RESOLVER)] + [static_cast(ExecutorJobType::SHORT)]}, + {&vtables_[static_cast(ExecutorType::RESOLVER)] + [static_cast(ExecutorJobType::LONG)]}}}; + +} // namespace + +TraceFlag executor_trace(false, "executor"); + +Executor::Executor(const char* name) : name_(name) { + adding_thread_lock_ = GPR_SPINLOCK_STATIC_INITIALIZER; + gpr_atm_rel_store(&num_threads_, 0); + max_threads_ = GPR_MAX(1, 2 * gpr_cpu_num_cores()); +} + +void Executor::Init() { SetThreading(true); } + +size_t Executor::RunClosures(const char* executor_name, + grpc_closure_list list) { size_t n = 0; + // In the executor, the ExecCtx for the thread is declared in the executor + // thread itself, but this is the point where we could start seeing + // application-level callbacks. No need to create a new ExecCtx, though, + // since there already is one and it is flushed (but not destructed) in this + // function itself. + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx( + GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD); + grpc_closure* c = list.head; while (c != nullptr) { grpc_closure* next = c->next_data.next; grpc_error* error = c->error_data.error; - if (executor_trace.enabled()) { -#ifndef NDEBUG - gpr_log(GPR_DEBUG, "EXECUTOR: run %p [created by %s:%d]", c, - c->file_created, c->line_created); -#else - gpr_log(GPR_INFO, "EXECUTOR: run %p", c); -#endif - } #ifndef NDEBUG + EXECUTOR_TRACE("(%s) run %p [created by %s:%d]", executor_name, c, + c->file_created, c->line_created); c->scheduled = false; +#else + EXECUTOR_TRACE("(%s) run %p", executor_name, c); #endif c->cb(c->cb_arg, error); GRPC_ERROR_UNREF(error); @@ -85,217 +140,329 @@ static size_t run_closures(grpc_closure_list list) { return n; } -bool grpc_executor_is_threaded() { - return gpr_atm_no_barrier_load(&g_cur_threads) > 0; +bool Executor::IsThreaded() const { + return gpr_atm_acq_load(&num_threads_) > 0; } -void grpc_executor_set_threading(bool threading) { - gpr_atm cur_threads = gpr_atm_no_barrier_load(&g_cur_threads); +void Executor::SetThreading(bool threading) { + gpr_atm curr_num_threads = gpr_atm_acq_load(&num_threads_); + EXECUTOR_TRACE("(%s) SetThreading(%d) begin", name_, threading); + if (threading) { - if (cur_threads > 0) return; - g_max_threads = GPR_MAX(1, 2 * gpr_cpu_num_cores()); - gpr_atm_no_barrier_store(&g_cur_threads, 1); + if (curr_num_threads > 0) { + EXECUTOR_TRACE("(%s) SetThreading(true). curr_num_threads == 0", name_); + return; + } + + GPR_ASSERT(num_threads_ == 0); + gpr_atm_rel_store(&num_threads_, 1); gpr_tls_init(&g_this_thread_state); - g_thread_state = static_cast( - gpr_zalloc(sizeof(thread_state) * g_max_threads)); - for (size_t i = 0; i < g_max_threads; i++) { - gpr_mu_init(&g_thread_state[i].mu); - gpr_cv_init(&g_thread_state[i].cv); - g_thread_state[i].thd = grpc_core::Thread(); - g_thread_state[i].elems = GRPC_CLOSURE_LIST_INIT; + thd_state_ = static_cast( + gpr_zalloc(sizeof(ThreadState) * max_threads_)); + + for (size_t i = 0; i < max_threads_; i++) { + gpr_mu_init(&thd_state_[i].mu); + gpr_cv_init(&thd_state_[i].cv); + thd_state_[i].id = i; + thd_state_[i].name = name_; + thd_state_[i].thd = grpc_core::Thread(); + thd_state_[i].elems = GRPC_CLOSURE_LIST_INIT; } - g_thread_state[0].thd = - grpc_core::Thread("grpc_executor", executor_thread, &g_thread_state[0]); - g_thread_state[0].thd.Start(); - } else { - if (cur_threads == 0) return; - for (size_t i = 0; i < g_max_threads; i++) { - gpr_mu_lock(&g_thread_state[i].mu); - g_thread_state[i].shutdown = true; - gpr_cv_signal(&g_thread_state[i].cv); - gpr_mu_unlock(&g_thread_state[i].mu); + thd_state_[0].thd = + grpc_core::Thread(name_, &Executor::ThreadMain, &thd_state_[0]); + thd_state_[0].thd.Start(); + } else { // !threading + if (curr_num_threads == 0) { + EXECUTOR_TRACE("(%s) SetThreading(false). curr_num_threads == 0", name_); + return; } - /* ensure no thread is adding a new thread... once this is past, then - no thread will try to add a new one either (since shutdown is true) */ - gpr_spinlock_lock(&g_adding_thread_lock); - gpr_spinlock_unlock(&g_adding_thread_lock); - for (gpr_atm i = 0; i < g_cur_threads; i++) { - g_thread_state[i].thd.Join(); + + for (size_t i = 0; i < max_threads_; i++) { + gpr_mu_lock(&thd_state_[i].mu); + thd_state_[i].shutdown = true; + gpr_cv_signal(&thd_state_[i].cv); + gpr_mu_unlock(&thd_state_[i].mu); } - gpr_atm_no_barrier_store(&g_cur_threads, 0); - for (size_t i = 0; i < g_max_threads; i++) { - gpr_mu_destroy(&g_thread_state[i].mu); - gpr_cv_destroy(&g_thread_state[i].cv); - run_closures(g_thread_state[i].elems); + + /* Ensure no thread is adding a new thread. Once this is past, then no + * thread will try to add a new one either (since shutdown is true) */ + gpr_spinlock_lock(&adding_thread_lock_); + gpr_spinlock_unlock(&adding_thread_lock_); + + curr_num_threads = gpr_atm_no_barrier_load(&num_threads_); + for (gpr_atm i = 0; i < curr_num_threads; i++) { + thd_state_[i].thd.Join(); + EXECUTOR_TRACE("(%s) Thread %" PRIdPTR " of %" PRIdPTR " joined", name_, + i + 1, curr_num_threads); } - gpr_free(g_thread_state); + + gpr_atm_rel_store(&num_threads_, 0); + for (size_t i = 0; i < max_threads_; i++) { + gpr_mu_destroy(&thd_state_[i].mu); + gpr_cv_destroy(&thd_state_[i].cv); + RunClosures(thd_state_[i].name, thd_state_[i].elems); + } + + gpr_free(thd_state_); gpr_tls_destroy(&g_this_thread_state); } -} -void grpc_executor_init() { - gpr_atm_no_barrier_store(&g_cur_threads, 0); - grpc_executor_set_threading(true); + EXECUTOR_TRACE("(%s) SetThreading(%d) done", name_, threading); } -void grpc_executor_shutdown() { grpc_executor_set_threading(false); } +void Executor::Shutdown() { SetThreading(false); } -static void executor_thread(void* arg) { - thread_state* ts = static_cast(arg); - gpr_tls_set(&g_this_thread_state, (intptr_t)ts); +void Executor::ThreadMain(void* arg) { + ThreadState* ts = static_cast(arg); + gpr_tls_set(&g_this_thread_state, reinterpret_cast(ts)); - grpc_core::ExecCtx exec_ctx(0); + grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD); size_t subtract_depth = 0; for (;;) { - if (executor_trace.enabled()) { - gpr_log(GPR_INFO, "EXECUTOR[%d]: step (sub_depth=%" PRIdPTR ")", - static_cast(ts - g_thread_state), subtract_depth); - } + EXECUTOR_TRACE("(%s) [%" PRIdPTR "]: step (sub_depth=%" PRIdPTR ")", + ts->name, ts->id, subtract_depth); + gpr_mu_lock(&ts->mu); ts->depth -= subtract_depth; + // Wait for closures to be enqueued or for the executor to be shutdown while (grpc_closure_list_empty(ts->elems) && !ts->shutdown) { ts->queued_long_job = false; gpr_cv_wait(&ts->cv, &ts->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); } + if (ts->shutdown) { - if (executor_trace.enabled()) { - gpr_log(GPR_INFO, "EXECUTOR[%d]: shutdown", - static_cast(ts - g_thread_state)); - } + EXECUTOR_TRACE("(%s) [%" PRIdPTR "]: shutdown", ts->name, ts->id); gpr_mu_unlock(&ts->mu); break; } + GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED(); - grpc_closure_list exec = ts->elems; + grpc_closure_list closures = ts->elems; ts->elems = GRPC_CLOSURE_LIST_INIT; gpr_mu_unlock(&ts->mu); - if (executor_trace.enabled()) { - gpr_log(GPR_INFO, "EXECUTOR[%d]: execute", - static_cast(ts - g_thread_state)); - } + + EXECUTOR_TRACE("(%s) [%" PRIdPTR "]: execute", ts->name, ts->id); grpc_core::ExecCtx::Get()->InvalidateNow(); - subtract_depth = run_closures(exec); + subtract_depth = RunClosures(ts->name, closures); } } -static void executor_push(grpc_closure* closure, grpc_error* error, - bool is_short) { +void Executor::Enqueue(grpc_closure* closure, grpc_error* error, + bool is_short) { bool retry_push; if (is_short) { GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS(); } else { GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS(); } + do { retry_push = false; size_t cur_thread_count = - static_cast(gpr_atm_no_barrier_load(&g_cur_threads)); + static_cast(gpr_atm_acq_load(&num_threads_)); + + // If the number of threads is zero(i.e either the executor is not threaded + // or already shutdown), then queue the closure on the exec context itself if (cur_thread_count == 0) { - if (executor_trace.enabled()) { #ifndef NDEBUG - gpr_log(GPR_DEBUG, "EXECUTOR: schedule %p (created %s:%d) inline", - closure, closure->file_created, closure->line_created); + EXECUTOR_TRACE("(%s) schedule %p (created %s:%d) inline", name_, closure, + closure->file_created, closure->line_created); #else - gpr_log(GPR_INFO, "EXECUTOR: schedule %p inline", closure); + EXECUTOR_TRACE("(%s) schedule %p inline", name_, closure); #endif - } grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(), closure, error); return; } - thread_state* ts = (thread_state*)gpr_tls_get(&g_this_thread_state); + + ThreadState* ts = (ThreadState*)gpr_tls_get(&g_this_thread_state); if (ts == nullptr) { - ts = &g_thread_state[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(), - cur_thread_count)]; + ts = &thd_state_[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(), + cur_thread_count)]; } else { GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF(); } - thread_state* orig_ts = ts; - bool try_new_thread; + ThreadState* orig_ts = ts; + bool try_new_thread = false; + for (;;) { - if (executor_trace.enabled()) { #ifndef NDEBUG - gpr_log( - GPR_DEBUG, - "EXECUTOR: try to schedule %p (%s) (created %s:%d) to thread %d", - closure, is_short ? "short" : "long", closure->file_created, - closure->line_created, static_cast(ts - g_thread_state)); + EXECUTOR_TRACE( + "(%s) try to schedule %p (%s) (created %s:%d) to thread " + "%" PRIdPTR, + name_, closure, is_short ? "short" : "long", closure->file_created, + closure->line_created, ts->id); #else - gpr_log(GPR_INFO, "EXECUTOR: try to schedule %p (%s) to thread %d", - closure, is_short ? "short" : "long", - (int)(ts - g_thread_state)); + EXECUTOR_TRACE("(%s) try to schedule %p (%s) to thread %" PRIdPTR, name_, + closure, is_short ? "short" : "long", ts->id); #endif - } + gpr_mu_lock(&ts->mu); if (ts->queued_long_job) { // if there's a long job queued, we never queue anything else to this // queue (since long jobs can take 'infinite' time and we need to - // guarantee no starvation) - // ... spin through queues and try again + // guarantee no starvation). Spin through queues and try again gpr_mu_unlock(&ts->mu); - size_t idx = static_cast(ts - g_thread_state); - ts = &g_thread_state[(idx + 1) % cur_thread_count]; + size_t idx = ts->id; + ts = &thd_state_[(idx + 1) % cur_thread_count]; if (ts == orig_ts) { + // We cycled through all the threads. Retry enqueue again by creating + // a new thread + // + // TODO (sreek): There is a potential issue here. We are + // unconditionally setting try_new_thread to true here. What if the + // executor is shutdown OR if cur_thread_count is already equal to + // max_threads ? + // (Fortunately, this is not an issue yet (as of july 2018) because + // there is only one instance of long job in gRPC and hence we will + // not hit this code path) retry_push = true; try_new_thread = true; break; } - continue; + + continue; // Try the next thread-state } + + // == Found the thread state (i.e thread) to enqueue this closure! == + + // Also, if this thread has been waiting for closures, wake it up. + // - If grpc_closure_list_empty() is true and the Executor is not + // shutdown, it means that the thread must be waiting in ThreadMain() + // - Note that gpr_cv_signal() won't immediately wakeup the thread. That + // happens after we release the mutex &ts->mu a few lines below if (grpc_closure_list_empty(ts->elems) && !ts->shutdown) { GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED(); gpr_cv_signal(&ts->cv); } + grpc_closure_list_append(&ts->elems, closure, error); + + // If we already queued more than MAX_DEPTH number of closures on this + // thread, use this as a hint to create more threads ts->depth++; try_new_thread = ts->depth > MAX_DEPTH && - cur_thread_count < g_max_threads && !ts->shutdown; - if (!is_short) ts->queued_long_job = true; + cur_thread_count < max_threads_ && !ts->shutdown; + + ts->queued_long_job = !is_short; + gpr_mu_unlock(&ts->mu); break; } - if (try_new_thread && gpr_spinlock_trylock(&g_adding_thread_lock)) { - cur_thread_count = - static_cast(gpr_atm_no_barrier_load(&g_cur_threads)); - if (cur_thread_count < g_max_threads) { - gpr_atm_no_barrier_store(&g_cur_threads, cur_thread_count + 1); - - g_thread_state[cur_thread_count].thd = - grpc_core::Thread("grpc_executor", executor_thread, - &g_thread_state[cur_thread_count]); - g_thread_state[cur_thread_count].thd.Start(); + + if (try_new_thread && gpr_spinlock_trylock(&adding_thread_lock_)) { + cur_thread_count = static_cast(gpr_atm_acq_load(&num_threads_)); + if (cur_thread_count < max_threads_) { + // Increment num_threads (safe to do a store instead of a cas because we + // always increment num_threads under the 'adding_thread_lock') + gpr_atm_rel_store(&num_threads_, cur_thread_count + 1); + + thd_state_[cur_thread_count].thd = grpc_core::Thread( + name_, &Executor::ThreadMain, &thd_state_[cur_thread_count]); + thd_state_[cur_thread_count].thd.Start(); } - gpr_spinlock_unlock(&g_adding_thread_lock); + gpr_spinlock_unlock(&adding_thread_lock_); } + if (retry_push) { GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES(); } } while (retry_push); } -static void executor_push_short(grpc_closure* closure, grpc_error* error) { - executor_push(closure, error, true); +// Executor::InitAll() and Executor::ShutdownAll() functions are called in the +// the grpc_init() and grpc_shutdown() code paths which are protected by a +// global mutex. So it is okay to assume that these functions are thread-safe +void Executor::InitAll() { + EXECUTOR_TRACE0("Executor::InitAll() enter"); + + // Return if Executor::InitAll() is already called earlier + if (executors[static_cast(ExecutorType::DEFAULT)] != nullptr) { + GPR_ASSERT(executors[static_cast(ExecutorType::RESOLVER)] != + nullptr); + return; + } + + executors[static_cast(ExecutorType::DEFAULT)] = + grpc_core::New("default-executor"); + executors[static_cast(ExecutorType::RESOLVER)] = + grpc_core::New("resolver-executor"); + + executors[static_cast(ExecutorType::DEFAULT)]->Init(); + executors[static_cast(ExecutorType::RESOLVER)]->Init(); + + EXECUTOR_TRACE0("Executor::InitAll() done"); +} + +grpc_closure_scheduler* Executor::Scheduler(ExecutorType executor_type, + ExecutorJobType job_type) { + return &schedulers_[static_cast(executor_type)] + [static_cast(job_type)]; +} + +grpc_closure_scheduler* Executor::Scheduler(ExecutorJobType job_type) { + return Executor::Scheduler(ExecutorType::DEFAULT, job_type); +} + +void Executor::ShutdownAll() { + EXECUTOR_TRACE0("Executor::ShutdownAll() enter"); + + // Return if Executor:SshutdownAll() is already called earlier + if (executors[static_cast(ExecutorType::DEFAULT)] == nullptr) { + GPR_ASSERT(executors[static_cast(ExecutorType::RESOLVER)] == + nullptr); + return; + } + + executors[static_cast(ExecutorType::DEFAULT)]->Shutdown(); + executors[static_cast(ExecutorType::RESOLVER)]->Shutdown(); + + // Delete the executor objects. + // + // NOTE: It is important to call Shutdown() on all executors first before + // calling Delete() because it is possible for one executor (that is not + // shutdown yet) to call Enqueue() on a different executor which is already + // shutdown. This is legal and in such cases, the Enqueue() operation + // effectively "fails" and enqueues that closure on the calling thread's + // exec_ctx. + // + // By ensuring that all executors are shutdown first, we are also ensuring + // that no thread is active across all executors. + + grpc_core::Delete( + executors[static_cast(ExecutorType::DEFAULT)]); + grpc_core::Delete( + executors[static_cast(ExecutorType::RESOLVER)]); + executors[static_cast(ExecutorType::DEFAULT)] = nullptr; + executors[static_cast(ExecutorType::RESOLVER)] = nullptr; + + EXECUTOR_TRACE0("Executor::ShutdownAll() done"); } -static void executor_push_long(grpc_closure* closure, grpc_error* error) { - executor_push(closure, error, false); +bool Executor::IsThreaded(ExecutorType executor_type) { + GPR_ASSERT(executor_type < ExecutorType::NUM_EXECUTORS); + return executors[static_cast(executor_type)]->IsThreaded(); } -static const grpc_closure_scheduler_vtable executor_vtable_short = { - executor_push_short, executor_push_short, "executor"}; -static grpc_closure_scheduler executor_scheduler_short = { - &executor_vtable_short}; +bool Executor::IsThreadedDefault() { + return Executor::IsThreaded(ExecutorType::DEFAULT); +} -static const grpc_closure_scheduler_vtable executor_vtable_long = { - executor_push_long, executor_push_long, "executor"}; -static grpc_closure_scheduler executor_scheduler_long = {&executor_vtable_long}; +void Executor::SetThreadingAll(bool enable) { + EXECUTOR_TRACE("Executor::SetThreadingAll(%d) called", enable); + for (size_t i = 0; i < static_cast(ExecutorType::NUM_EXECUTORS); + i++) { + executors[i]->SetThreading(enable); + } +} -grpc_closure_scheduler* grpc_executor_scheduler( - grpc_executor_job_length length) { - return length == GRPC_EXECUTOR_SHORT ? &executor_scheduler_short - : &executor_scheduler_long; +void Executor::SetThreadingDefault(bool enable) { + EXECUTOR_TRACE("Executor::SetThreadingDefault(%d) called", enable); + executors[static_cast(ExecutorType::DEFAULT)]->SetThreading(enable); } + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/iomgr/executor.h b/Sources/CgRPC/src/core/lib/iomgr/executor.h index 68d540af5..9e472279b 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/executor.h +++ b/Sources/CgRPC/src/core/lib/iomgr/executor.h @@ -21,30 +21,101 @@ #include +#include "src/core/lib/gpr/spinlock.h" +#include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/closure.h" -typedef enum { - GRPC_EXECUTOR_SHORT, - GRPC_EXECUTOR_LONG -} grpc_executor_job_length; +namespace grpc_core { -/** Initialize the global executor. - * - * This mechanism is meant to outsource work (grpc_closure instances) to a - * thread, for those cases where blocking isn't an option but there isn't a - * non-blocking solution available. */ -void grpc_executor_init(); +struct ThreadState { + gpr_mu mu; + size_t id; // For debugging purposes + const char* name; // Thread state name + gpr_cv cv; + grpc_closure_list elems; + size_t depth; // Number of closures in the closure list + bool shutdown; + bool queued_long_job; + grpc_core::Thread thd; +}; + +enum class ExecutorType { + DEFAULT = 0, + RESOLVER, + + NUM_EXECUTORS // Add new values above this +}; + +enum class ExecutorJobType { + SHORT = 0, + LONG, + NUM_JOB_TYPES // Add new values above this +}; + +class Executor { + public: + Executor(const char* executor_name); + + void Init(); + + /** Is the executor multi-threaded? */ + bool IsThreaded() const; + + /* Enable/disable threading - must be called after Init and Shutdown() */ + void SetThreading(bool threading); + + /** Shutdown the executor, running all pending work as part of the call */ + void Shutdown(); + + /** Enqueue the closure onto the executor. is_short is true if the closure is + * a short job (i.e expected to not block and complete quickly) */ + void Enqueue(grpc_closure* closure, grpc_error* error, bool is_short); + + // TODO(sreek): Currently we have two executors (available globally): The + // default executor and the resolver executor. + // + // Some of the functions below operate on the DEFAULT executor only while some + // operate of ALL the executors. This is a bit confusing and should be cleaned + // up in future (where we make all the following functions take ExecutorType + // and/or JobType) + + // Initialize ALL the executors + static void InitAll(); + + // Shutdown ALL the executors + static void ShutdownAll(); + + // Set the threading mode for ALL the executors + static void SetThreadingAll(bool enable); + + // Set the threading mode for ALL the executors + static void SetThreadingDefault(bool enable); + + // Get the DEFAULT executor scheduler for the given job_type + static grpc_closure_scheduler* Scheduler(ExecutorJobType job_type); + + // Get the executor scheduler for a given executor_type and a job_type + static grpc_closure_scheduler* Scheduler(ExecutorType executor_type, + ExecutorJobType job_type); + + // Return if a given executor is running in threaded mode (i.e if + // SetThreading(true) was called previously on that executor) + static bool IsThreaded(ExecutorType executor_type); -grpc_closure_scheduler* grpc_executor_scheduler(grpc_executor_job_length); + // Return if the DEFAULT executor is threaded + static bool IsThreadedDefault(); -/** Shutdown the executor, running all pending work as part of the call */ -void grpc_executor_shutdown(); + private: + static size_t RunClosures(const char* executor_name, grpc_closure_list list); + static void ThreadMain(void* arg); -/** Is the executor multi-threaded? */ -bool grpc_executor_is_threaded(); + const char* name_; + ThreadState* thd_state_; + size_t max_threads_; + gpr_atm num_threads_; + gpr_spinlock adding_thread_lock_; +}; -/* enable/disable threading - must be called after grpc_executor_init and before - grpc_executor_shutdown */ -void grpc_executor_set_threading(bool enable); +} // namespace grpc_core #endif /* GRPC_CORE_LIB_IOMGR_EXECUTOR_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/fork_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/fork_posix.cc index f8645ab15..7f8fb7e82 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/fork_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/fork_posix.cc @@ -25,63 +25,88 @@ #include #include +#include #include #include "src/core/lib/gpr/env.h" -#include "src/core/lib/gpr/fork.h" +#include "src/core/lib/gprpp/fork.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/timer_manager.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" -#include "src/core/lib/surface/init.h" /* * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK * AROUND VERY SPECIFIC USE CASES. */ +namespace { +bool skipped_handler = true; +bool registered_handlers = false; +} // namespace + void grpc_prefork() { - if (!grpc_fork_support_enabled()) { + skipped_handler = true; + // This may be called after core shuts down, so verify initialized before + // instantiating an ExecCtx. + if (!grpc_is_initialized()) { + return; + } + grpc_core::ExecCtx exec_ctx; + if (!grpc_core::Fork::Enabled()) { gpr_log(GPR_ERROR, "Fork support not enabled; try running with the " "environment variable GRPC_ENABLE_FORK_SUPPORT=1"); return; } - if (grpc_is_initialized()) { - grpc_core::ExecCtx exec_ctx; - grpc_timer_manager_set_threading(false); - grpc_executor_set_threading(false); - grpc_core::ExecCtx::Get()->Flush(); - if (!grpc_core::Thread::AwaitAll( - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(3, GPR_TIMESPAN)))) { - gpr_log(GPR_ERROR, "gRPC thread still active! Cannot fork!"); - } + if (strcmp(grpc_get_poll_strategy_name(), "epoll1") != 0 && + strcmp(grpc_get_poll_strategy_name(), "poll") != 0) { + gpr_log(GPR_INFO, + "Fork support is only compatible with the epoll1 and poll polling " + "strategies"); + } + if (!grpc_core::Fork::BlockExecCtx()) { + gpr_log(GPR_INFO, + "Other threads are currently calling into gRPC, skipping fork() " + "handlers"); + return; } + grpc_timer_manager_set_threading(false); + grpc_core::Executor::SetThreadingAll(false); + grpc_core::ExecCtx::Get()->Flush(); + grpc_core::Fork::AwaitThreads(); + skipped_handler = false; } void grpc_postfork_parent() { - if (grpc_is_initialized()) { - grpc_timer_manager_set_threading(true); + if (!skipped_handler) { + grpc_core::Fork::AllowExecCtx(); grpc_core::ExecCtx exec_ctx; - grpc_executor_set_threading(true); + grpc_timer_manager_set_threading(true); + grpc_core::Executor::SetThreadingAll(true); } } void grpc_postfork_child() { - if (grpc_is_initialized()) { - grpc_timer_manager_set_threading(true); + if (!skipped_handler) { + grpc_core::Fork::AllowExecCtx(); grpc_core::ExecCtx exec_ctx; - grpc_executor_set_threading(true); - grpc_core::ExecCtx::Get()->Flush(); + grpc_core::Fork::child_postfork_func reset_polling_engine = + grpc_core::Fork::GetResetChildPollingEngineFunc(); + if (reset_polling_engine != nullptr) { + reset_polling_engine(); + } + grpc_timer_manager_set_threading(true); + grpc_core::Executor::SetThreadingAll(true); } } void grpc_fork_handlers_auto_register() { - if (grpc_fork_support_enabled()) { + if (grpc_core::Fork::Enabled() & !registered_handlers) { #ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK pthread_atfork(grpc_prefork, grpc_postfork_parent, grpc_postfork_child); + registered_handlers = true; #endif // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK } } diff --git a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_filter.h b/Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex.h similarity index 56% rename from Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_filter.h rename to Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex.h index b459a8ec5..ed9612dcb 100644 --- a/Sources/CgRPC/src/core/ext/filters/load_reporting/server_load_reporting_filter.h +++ b/Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2015 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,15 @@ * */ -#ifndef GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_FILTER_H -#define GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_FILTER_H +#ifndef GRPC_CORE_LIB_IOMGR_GRPC_IF_NAMETOINDEX_H +#define GRPC_CORE_LIB_IOMGR_GRPC_IF_NAMETOINDEX_H #include -#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" -#include "src/core/lib/channel/channel_stack.h" +#include -extern const grpc_channel_filter grpc_server_load_reporting_filter; +/* Returns the interface index corresponding to the interface "name" provided. + * Returns non-zero upon success, and zero upon failure. */ +uint32_t grpc_if_nametoindex(char* name); -#endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_FILTER_H \ - */ +#endif /* GRPC_CORE_LIB_IOMGR_GRPC_IF_NAMETOINDEX_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/ev_epollsig_linux.h b/Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc similarity index 54% rename from Sources/CgRPC/src/core/lib/iomgr/ev_epollsig_linux.h rename to Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc index 2ba2f0a63..f1ba20dce 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/ev_epollsig_linux.h +++ b/Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2016 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,20 +16,27 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H -#define GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H - #include -#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/port.h" -const grpc_event_engine_vtable* grpc_init_epollsig_linux(bool explicit_request); +#if GRPC_IF_NAMETOINDEX == 1 && defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) + +#include "src/core/lib/iomgr/grpc_if_nametoindex.h" + +#include +#include + +#include -#ifdef GRPC_LINUX_EPOLL_CREATE1 -void* grpc_fd_get_polling_island(grpc_fd* fd); -void* grpc_pollset_get_polling_island(grpc_pollset* ps); -bool grpc_are_polling_islands_equal(void* p, void* q); -#endif /* defined(GRPC_LINUX_EPOLL_CREATE1) */ +uint32_t grpc_if_nametoindex(char* name) { + uint32_t out = if_nametoindex(name); + if (out == 0) { + gpr_log(GPR_DEBUG, "if_nametoindex failed for name %s. errno %d", name, + errno); + } + return out; +} -#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H */ +#endif /* GRPC_IF_NAMETOINDEX == 1 && \ + defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/network_status_tracker.h b/Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc similarity index 57% rename from Sources/CgRPC/src/core/lib/iomgr/network_status_tracker.h rename to Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc index 198877f60..08644cccf 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/network_status_tracker.h +++ b/Sources/CgRPC/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc @@ -16,17 +16,23 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H -#define GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H #include -#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/port.h" -void grpc_network_status_init(void); -void grpc_network_status_shutdown(void); +#if GRPC_IF_NAMETOINDEX == 0 || !defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) -void grpc_network_status_register_endpoint(grpc_endpoint* ep); -void grpc_network_status_unregister_endpoint(grpc_endpoint* ep); -void grpc_network_status_shutdown_all_endpoints(); +#include "src/core/lib/iomgr/grpc_if_nametoindex.h" -#endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */ +#include + +uint32_t grpc_if_nametoindex(char* name) { + gpr_log(GPR_DEBUG, + "Not attempting to convert interface name %s to index for current " + "platform.", + name); + return 0; +} + +#endif /* GRPC_IF_NAMETOINDEX == 0 || \ + !defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/internal_errqueue.cc b/Sources/CgRPC/src/core/lib/iomgr/internal_errqueue.cc new file mode 100644 index 000000000..982d709f0 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/iomgr/internal_errqueue.cc @@ -0,0 +1,69 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" + +#include +#include "src/core/lib/iomgr/internal_errqueue.h" + +#ifdef GRPC_POSIX_SOCKET_TCP + +#include +#include +#include +#include + +namespace grpc_core { +static bool errqueue_supported = false; + +bool kernel_supports_errqueue() { return errqueue_supported; } + +void grpc_errqueue_init() { +/* Both-compile time and run-time linux kernel versions should be atleast 4.0.0 + */ +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) + struct utsname buffer; + if (uname(&buffer) != 0) { + gpr_log(GPR_ERROR, "uname: %s", strerror(errno)); + return; + } + char* release = buffer.release; + if (release == nullptr) { + return; + } + + if (strtol(release, nullptr, 10) >= 4) { + errqueue_supported = true; + } else { + gpr_log(GPR_DEBUG, "ERRQUEUE support not enabled"); + } +#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(4, 0, 0) */ +#endif /* LINUX_VERSION_CODE */ +} +} /* namespace grpc_core */ + +#else + +namespace grpc_core { +void grpc_errqueue_init() {} +} /* namespace grpc_core */ + +#endif /* GRPC_POSIX_SOCKET_TCP */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/internal_errqueue.h b/Sources/CgRPC/src/core/lib/iomgr/internal_errqueue.h new file mode 100644 index 000000000..b9fe41176 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/iomgr/internal_errqueue.h @@ -0,0 +1,191 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This file contains constants defined in and + * so as to allow collecting network timestamps in the + * kernel. This file allows tcp_posix.cc to compile on platforms that do not + * have and . + */ + +#ifndef GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H +#define GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H + +#include + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_POSIX_SOCKET_TCP + +#include +#include + +#ifdef GRPC_LINUX_ERRQUEUE +#include +#include +#include +#include +#endif /* GRPC_LINUX_ERRQUEUE */ + +namespace grpc_core { + +#ifdef GRPC_LINUX_ERRQUEUE + +/* Redefining scm_timestamping in the same way that defines + * it, so that code compiles on systems that don't have it. */ +struct scm_timestamping { + struct timespec ts[3]; +}; +/* Also redefine timestamp types */ +/* The timestamp type for when the driver passed skb to NIC, or HW. */ +constexpr int SCM_TSTAMP_SND = 0; +/* The timestamp type for when data entered the packet scheduler. */ +constexpr int SCM_TSTAMP_SCHED = 1; +/* The timestamp type for when data acknowledged by peer. */ +constexpr int SCM_TSTAMP_ACK = 2; + +/* Control message type containing OPT_STATS */ +#ifndef SCM_TIMESTAMPING_OPT_STATS +#define SCM_TIMESTAMPING_OPT_STATS 54 +#endif + +/* Redefine required constants from */ +constexpr uint32_t SOF_TIMESTAMPING_TX_SOFTWARE = 1u << 1; +constexpr uint32_t SOF_TIMESTAMPING_SOFTWARE = 1u << 4; +constexpr uint32_t SOF_TIMESTAMPING_OPT_ID = 1u << 7; +constexpr uint32_t SOF_TIMESTAMPING_TX_SCHED = 1u << 8; +constexpr uint32_t SOF_TIMESTAMPING_TX_ACK = 1u << 9; +constexpr uint32_t SOF_TIMESTAMPING_OPT_TSONLY = 1u << 11; +constexpr uint32_t SOF_TIMESTAMPING_OPT_STATS = 1u << 12; + +constexpr uint32_t kTimestampingSocketOptions = + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_OPT_TSONLY | SOF_TIMESTAMPING_OPT_STATS; +constexpr uint32_t kTimestampingRecordingOptions = + SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_TX_ACK; + +/* Netlink attribute types used for TCP opt stats. */ +enum TCPOptStats { + TCP_NLA_PAD, + TCP_NLA_BUSY, /* Time (usec) busy sending data. */ + TCP_NLA_RWND_LIMITED, /* Time (usec) limited by receive window. */ + TCP_NLA_SNDBUF_LIMITED, /* Time (usec) limited by send buffer. */ + TCP_NLA_DATA_SEGS_OUT, /* Data pkts sent including retransmission. */ + TCP_NLA_TOTAL_RETRANS, /* Data pkts retransmitted. */ + TCP_NLA_PACING_RATE, /* Pacing rate in Bps. */ + TCP_NLA_DELIVERY_RATE, /* Delivery rate in Bps. */ + TCP_NLA_SND_CWND, /* Sending congestion window. */ + TCP_NLA_REORDERING, /* Reordering metric. */ + TCP_NLA_MIN_RTT, /* minimum RTT. */ + TCP_NLA_RECUR_RETRANS, /* Recurring retransmits for the current pkt. */ + TCP_NLA_DELIVERY_RATE_APP_LMT, /* Delivery rate application limited? */ + TCP_NLA_SNDQ_SIZE, /* Data (bytes) pending in send queue */ + TCP_NLA_CA_STATE, /* ca_state of socket */ + TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */ + TCP_NLA_DELIVERED, /* Data pkts delivered incl. out-of-order */ + TCP_NLA_DELIVERED_CE, /* Like above but only ones w/ CE marks */ + TCP_NLA_BYTES_SENT, /* Data bytes sent including retransmission */ + TCP_NLA_BYTES_RETRANS, /* Data bytes retransmitted */ + TCP_NLA_DSACK_DUPS, /* DSACK blocks received */ + TCP_NLA_REORD_SEEN, /* reordering events seen */ + TCP_NLA_SRTT, /* smoothed RTT in usecs */ +}; + +/* tcp_info from from linux/tcp.h */ +struct tcp_info { + uint8_t tcpi_state; + uint8_t tcpi_ca_state; + uint8_t tcpi_retransmits; + uint8_t tcpi_probes; + uint8_t tcpi_backoff; + uint8_t tcpi_options; + uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + uint8_t tcpi_delivery_rate_app_limited : 1; + uint32_t tcpi_rto; + uint32_t tcpi_ato; + uint32_t tcpi_snd_mss; + uint32_t tcpi_rcv_mss; + uint32_t tcpi_unacked; + uint32_t tcpi_sacked; + uint32_t tcpi_lost; + uint32_t tcpi_retrans; + uint32_t tcpi_fackets; + /* Times. */ + uint32_t tcpi_last_data_sent; + uint32_t tcpi_last_ack_sent; /* Not remembered, sorry. */ + uint32_t tcpi_last_data_recv; + uint32_t tcpi_last_ack_recv; + /* Metrics. */ + uint32_t tcpi_pmtu; + uint32_t tcpi_rcv_ssthresh; + uint32_t tcpi_rtt; + uint32_t tcpi_rttvar; + uint32_t tcpi_snd_ssthresh; + uint32_t tcpi_snd_cwnd; + uint32_t tcpi_advmss; + uint32_t tcpi_reordering; + uint32_t tcpi_rcv_rtt; + uint32_t tcpi_rcv_space; + uint32_t tcpi_total_retrans; + uint64_t tcpi_pacing_rate; + uint64_t tcpi_max_pacing_rate; + uint64_t tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */ + uint64_t tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */ + + uint32_t tcpi_segs_out; /* RFC4898 tcpEStatsPerfSegsOut */ + uint32_t tcpi_segs_in; /* RFC4898 tcpEStatsPerfSegsIn */ + uint32_t tcpi_notsent_bytes; + uint32_t tcpi_min_rtt; + + uint32_t tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */ + uint32_t tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */ + + uint64_t tcpi_delivery_rate; + uint64_t tcpi_busy_time; /* Time (usec) busy sending data */ + uint64_t tcpi_rwnd_limited; /* Time (usec) limited by receive window */ + uint64_t tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */ + + uint32_t tcpi_delivered; + uint32_t tcpi_delivered_ce; + uint64_t tcpi_bytes_sent; /* RFC4898 tcpEStatsPerfHCDataOctetsOut */ + uint64_t tcpi_bytes_retrans; /* RFC4898 tcpEStatsPerfOctetsRetrans */ + uint32_t tcpi_dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups */ + uint32_t tcpi_reord_seen; /* reordering events seen */ + socklen_t length; /* Length of struct returned by kernel */ +}; + +#ifndef TCP_INFO +#define TCP_INFO 11 +#endif +#endif /* GRPC_LINUX_ERRQUEUE */ + +/* Returns true if kernel is capable of supporting errqueue and timestamping. + * Currently allowing only linux kernels above 4.0.0 + */ +bool kernel_supports_errqueue(); + +} /* namespace grpc_core */ + +#endif /* GRPC_POSIX_SOCKET_TCP */ + +namespace grpc_core { +/* Initializes errqueue support */ +void grpc_errqueue_init(); +} /* namespace grpc_core */ + +#endif /* GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/iocp_windows.cc b/Sources/CgRPC/src/core/lib/iomgr/iocp_windows.cc index ce7723103..ad325fe21 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iocp_windows.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/iocp_windows.cc @@ -89,10 +89,15 @@ grpc_iocp_work_status grpc_iocp_work(grpc_millis deadline) { } else { abort(); } - success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, - FALSE, &flags); - info->bytes_transfered = bytes; - info->wsa_error = success ? 0 : WSAGetLastError(); + if (socket->shutdown_called) { + info->bytes_transfered = 0; + info->wsa_error = WSA_OPERATION_ABORTED; + } else { + success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, + FALSE, &flags); + info->bytes_transfered = bytes; + info->wsa_error = success ? 0 : WSAGetLastError(); + } GPR_ASSERT(overlapped == &info->overlapped); grpc_socket_become_ready(socket, info); return GRPC_IOCP_WORK_WORK; diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr.cc b/Sources/CgRPC/src/core/lib/iomgr/iomgr.cc index 468814eae..33153d9cc 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr.cc @@ -33,10 +33,11 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/iomgr/buffer_list.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/internal_errqueue.h" #include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer_manager.h" @@ -51,12 +52,12 @@ void grpc_iomgr_init() { g_shutdown = 0; gpr_mu_init(&g_mu); gpr_cv_init(&g_rcv); - grpc_executor_init(); + grpc_core::Executor::InitAll(); grpc_timer_list_init(); g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.name = (char*)"root"; - grpc_network_status_init(); grpc_iomgr_platform_init(); + grpc_core::grpc_errqueue_init(); } void grpc_iomgr_start() { grpc_timer_manager_init(); } @@ -70,6 +71,8 @@ static size_t count_objects(void) { return n; } +size_t grpc_iomgr_count_objects_for_testing(void) { return count_objects(); } + static void dump_objects(const char* kind) { grpc_iomgr_object* obj; for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { @@ -85,7 +88,7 @@ void grpc_iomgr_shutdown() { { grpc_timer_manager_shutdown(); grpc_iomgr_platform_flush(); - grpc_executor_shutdown(); + grpc_core::Executor::ShutdownAll(); gpr_mu_lock(&g_mu); g_shutdown = 1; @@ -147,11 +150,18 @@ void grpc_iomgr_shutdown() { gpr_mu_unlock(&g_mu); grpc_iomgr_platform_shutdown(); - grpc_network_status_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); } +void grpc_iomgr_shutdown_background_closure() { + grpc_iomgr_platform_shutdown_background_closure(); +} + +bool grpc_iomgr_is_any_background_poller_thread() { + return grpc_iomgr_platform_is_any_background_poller_thread(); +} + void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name) { obj->name = gpr_strdup(name); gpr_mu_lock(&g_mu); diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr.h b/Sources/CgRPC/src/core/lib/iomgr/iomgr.h index e6d66e545..74775de81 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr.h +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr.h @@ -23,6 +23,8 @@ #include "src/core/lib/iomgr/port.h" +#include + /** Initializes the iomgr. */ void grpc_iomgr_init(); @@ -33,4 +35,19 @@ void grpc_iomgr_start(); * exec_ctx. */ void grpc_iomgr_shutdown(); +/** Signals the intention to shutdown all the closures registered in the + * background poller. */ +void grpc_iomgr_shutdown_background_closure(); + +/* Returns true if polling engine runs in the background, false otherwise. + * Currently only 'epollbg' runs in the background. + */ +bool grpc_iomgr_run_in_background(); + +/** Returns true if the caller is a worker thread for any background poller. */ +bool grpc_iomgr_is_any_background_poller_thread(); + +/* Exposed only for testing */ +size_t grpc_iomgr_count_objects_for_testing(); + #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr_custom.cc b/Sources/CgRPC/src/core/lib/iomgr/iomgr_custom.cc index d34c8e7cd..3d07f1abe 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr_custom.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr_custom.cc @@ -34,15 +34,21 @@ gpr_thd_id g_init_thread; static void iomgr_platform_init(void) { grpc_core::ExecCtx exec_ctx; - grpc_executor_set_threading(false); + grpc_core::Executor::SetThreadingAll(false); g_init_thread = gpr_thd_currentid(); grpc_pollset_global_init(); } static void iomgr_platform_flush(void) {} static void iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); } +static void iomgr_platform_shutdown_background_closure(void) {} +static bool iomgr_platform_is_any_background_poller_thread(void) { + return false; +} static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_custom_iomgr_init(grpc_socket_vtable* socket, grpc_custom_resolver_vtable* resolver, diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.cc b/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.cc index 32dbabb79..e68b1cf58 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.cc @@ -41,3 +41,11 @@ void grpc_iomgr_platform_init() { iomgr_platform_vtable->init(); } void grpc_iomgr_platform_flush() { iomgr_platform_vtable->flush(); } void grpc_iomgr_platform_shutdown() { iomgr_platform_vtable->shutdown(); } + +void grpc_iomgr_platform_shutdown_background_closure() { + iomgr_platform_vtable->shutdown_background_closure(); +} + +bool grpc_iomgr_platform_is_any_background_poller_thread() { + return iomgr_platform_vtable->is_any_background_poller_thread(); +} diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.h b/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.h index b011d9c7b..2250ad9a1 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.h +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr_internal.h @@ -35,6 +35,8 @@ typedef struct grpc_iomgr_platform_vtable { void (*init)(void); void (*flush)(void); void (*shutdown)(void); + void (*shutdown_background_closure)(void); + bool (*is_any_background_poller_thread)(void); } grpc_iomgr_platform_vtable; void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name); @@ -52,6 +54,12 @@ void grpc_iomgr_platform_flush(void); /** tear down all platform specific global iomgr structures */ void grpc_iomgr_platform_shutdown(void); +/** shut down all the closures registered in the background poller */ +void grpc_iomgr_platform_shutdown_background_closure(void); + +/** return true is the caller is a worker thread for any background poller */ +bool grpc_iomgr_platform_is_any_background_poller_thread(void); + bool grpc_iomgr_abort_on_leaks(void); #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/iomgr_posix.cc index 66c9cb7ff..690e81f3b 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_IOMGR #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/ev_posix.h" @@ -51,8 +51,18 @@ static void iomgr_platform_shutdown(void) { grpc_wakeup_fd_global_destroy(); } +static void iomgr_platform_shutdown_background_closure(void) { + grpc_shutdown_background_closure(); +} + +static bool iomgr_platform_is_any_background_poller_thread(void) { + return grpc_is_any_background_poller_thread(); +} + static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_set_default_iomgr_platform() { grpc_set_tcp_client_impl(&grpc_posix_tcp_client_vtable); @@ -64,4 +74,8 @@ void grpc_set_default_iomgr_platform() { grpc_set_iomgr_platform_vtable(&vtable); } -#endif /* GRPC_POSIX_SOCKET */ +bool grpc_iomgr_run_in_background() { + return grpc_event_engine_run_in_background(); +} + +#endif /* GRPC_POSIX_SOCKET_IOMGR */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/iomgr_windows.cc b/Sources/CgRPC/src/core/lib/iomgr/iomgr_windows.cc index cdef89cbf..e517a6cae 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/iomgr_windows.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/iomgr_windows.cc @@ -71,8 +71,16 @@ static void iomgr_platform_shutdown(void) { winsock_shutdown(); } +static void iomgr_platform_shutdown_background_closure(void) {} + +static bool iomgr_platform_is_any_background_poller_thread(void) { + return false; +} + static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_set_default_iomgr_platform() { grpc_set_tcp_client_impl(&grpc_windows_tcp_client_vtable); @@ -84,4 +92,6 @@ void grpc_set_default_iomgr_platform() { grpc_set_iomgr_platform_vtable(&vtable); } +bool grpc_iomgr_run_in_background() { return false; } + #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/is_epollexclusive_available.cc b/Sources/CgRPC/src/core/lib/iomgr/is_epollexclusive_available.cc index 036b77866..8df6a66e6 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/is_epollexclusive_available.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/is_epollexclusive_available.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/Sources/CgRPC/src/core/lib/iomgr/lockfree_event.cc b/Sources/CgRPC/src/core/lib/iomgr/lockfree_event.cc index 5b6b79fa9..085fea40a 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/lockfree_event.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/lockfree_event.cc @@ -89,7 +89,11 @@ void LockfreeEvent::DestroyEvent() { void LockfreeEvent::NotifyOn(grpc_closure* closure) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(&state_); + /* This load needs to be an acquire load because this can be a shutdown + * error that we might need to reference. Adding acquire semantics makes + * sure that the shutdown error has been initialized properly before us + * referencing it. */ + gpr_atm curr = gpr_atm_acq_load(&state_); if (grpc_polling_trace.enabled()) { gpr_log(GPR_ERROR, "LockfreeEvent::NotifyOn: %p curr=%p closure=%p", this, (void*)curr, closure); diff --git a/Sources/CgRPC/src/core/lib/iomgr/polling_entity.cc b/Sources/CgRPC/src/core/lib/iomgr/polling_entity.cc index 9f164f65b..dea07cae5 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/polling_entity.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/polling_entity.cc @@ -61,8 +61,11 @@ bool grpc_polling_entity_is_empty(const grpc_polling_entity* pollent) { void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent, grpc_pollset_set* pss_dst) { if (pollent->tag == GRPC_POLLS_POLLSET) { - GPR_ASSERT(pollent->pollent.pollset != nullptr); - grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset); + // CFStream does not use file destriptors. When CFStream is used, the fd + // pollset is possible to be null. + if (pollent->pollent.pollset != nullptr) { + grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset); + } } else if (pollent->tag == GRPC_POLLS_POLLSET_SET) { GPR_ASSERT(pollent->pollent.pollset_set != nullptr); grpc_pollset_set_add_pollset_set(pss_dst, pollent->pollent.pollset_set); @@ -75,8 +78,14 @@ void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent, void grpc_polling_entity_del_from_pollset_set(grpc_polling_entity* pollent, grpc_pollset_set* pss_dst) { if (pollent->tag == GRPC_POLLS_POLLSET) { +#ifdef GRPC_CFSTREAM + if (pollent->pollent.pollset != nullptr) { + grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset); + } +#else GPR_ASSERT(pollent->pollent.pollset != nullptr); grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset); +#endif } else if (pollent->tag == GRPC_POLLS_POLLSET_SET) { GPR_ASSERT(pollent->pollent.pollset_set != nullptr); grpc_pollset_set_del_pollset_set(pss_dst, pollent->pollent.pollset_set); diff --git a/Sources/CgRPC/src/core/lib/iomgr/polling_entity.h b/Sources/CgRPC/src/core/lib/iomgr/polling_entity.h index a95e08524..6f4c5bdd6 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/polling_entity.h +++ b/Sources/CgRPC/src/core/lib/iomgr/polling_entity.h @@ -34,13 +34,13 @@ typedef enum grpc_pollset_tag { * functions that accept a pollset XOR a pollset_set to do so through an * abstract interface. No ownership is taken. */ -typedef struct grpc_polling_entity { +struct grpc_polling_entity { union { - grpc_pollset* pollset; + grpc_pollset* pollset = nullptr; grpc_pollset_set* pollset_set; } pollent; - grpc_pollset_tag tag; -} grpc_polling_entity; + grpc_pollset_tag tag = GRPC_POLLS_NONE; +}; grpc_polling_entity grpc_polling_entity_create_from_pollset_set( grpc_pollset_set* pollset_set); diff --git a/Sources/CgRPC/src/core/lib/iomgr/pollset_custom.cc b/Sources/CgRPC/src/core/lib/iomgr/pollset_custom.cc index 04bd10405..70e8a4596 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/pollset_custom.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/pollset_custom.cc @@ -69,7 +69,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); gpr_mu_unlock(&pollset->mu); grpc_millis now = grpc_core::ExecCtx::Get()->Now(); - size_t timeout = 0; + grpc_millis timeout = 0; if (deadline > now) { timeout = deadline - now; } @@ -77,7 +77,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, // control back to the application grpc_core::ExecCtx* curr = grpc_core::ExecCtx::Get(); grpc_core::ExecCtx::Set(nullptr); - poller_vtable->poll(timeout); + poller_vtable->poll(static_cast(timeout)); grpc_core::ExecCtx::Set(curr); grpc_core::ExecCtx::Get()->InvalidateNow(); if (grpc_core::ExecCtx::Get()->HasWork()) { diff --git a/Sources/CgRPC/src/core/lib/iomgr/port.h b/Sources/CgRPC/src/core/lib/iomgr/port.h index a39701200..7b6ca1bc0 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/port.h +++ b/Sources/CgRPC/src/core/lib/iomgr/port.h @@ -60,6 +60,11 @@ #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) +#define GRPC_LINUX_ERRQUEUE 1 +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */ +#endif /* LINUX_VERSION_CODE */ #define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GRPC_POSIX_FORK 1 #define GRPC_POSIX_HOST_NAME_MAX 1 @@ -77,6 +82,11 @@ #define GRPC_LINUX_SOCKETUTILS 1 #endif #endif +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +#define GRPC_HAVE_TCP_USER_TIMEOUT +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) */ +#endif /* LINUX_VERSION_CODE */ #ifndef __GLIBC__ #define GRPC_LINUX_EPOLL 1 #define GRPC_LINUX_EPOLL_CREATE1 1 @@ -97,7 +107,26 @@ #define GRPC_MSG_IOVLEN_TYPE int #define GRPC_POSIX_FORK 1 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 +#ifdef GRPC_CFSTREAM +#define GRPC_CFSTREAM_IOMGR 1 +#define GRPC_CFSTREAM_CLIENT 1 +#define GRPC_CFSTREAM_ENDPOINT 1 +#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1 +#define GRPC_POSIX_SOCKET_EV 1 +#define GRPC_POSIX_SOCKET_EV_EPOLL1 1 +#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1 +#define GRPC_POSIX_SOCKET_EV_POLL 1 +#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1 +#define GRPC_POSIX_SOCKET_SOCKADDR 1 +#define GRPC_POSIX_SOCKET_SOCKET_FACTORY 1 +#define GRPC_POSIX_SOCKET_TCP 1 +#define GRPC_POSIX_SOCKET_TCP_CLIENT 1 +#define GRPC_POSIX_SOCKET_TCP_SERVER 1 +#define GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON 1 +#define GRPC_POSIX_SOCKET_UTILS_COMMON 1 +#else #define GRPC_POSIX_SOCKET 1 +#endif #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_SYSCONF 1 #define GRPC_POSIX_WAKEUP_FD 1 @@ -120,6 +149,18 @@ #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_WAKEUP_FD 1 +#elif defined(GPR_SOLARIS) +#define GRPC_HAVE_UNIX_SOCKET 1 +#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 +#define GRPC_POSIX_SOCKET 1 +#define GRPC_POSIX_SOCKETUTILS 1 +#define GRPC_POSIX_WAKEUP_FD 1 +#elif defined(GPR_AIX) +#define GRPC_HAVE_UNIX_SOCKET 1 +#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 +#define GRPC_POSIX_SOCKET 1 +#define GRPC_POSIX_SOCKETUTILS 1 +#define GRPC_POSIX_WAKEUP_FD 1 #elif defined(GPR_NACL) #define GRPC_HAVE_ARPA_NAMESER 1 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 @@ -131,12 +172,30 @@ #endif #if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \ - defined(GRPC_CUSTOM_SOCKET) != \ + defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_CFSTREAM) != \ 1 #error \ "Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET" #endif +#ifdef GRPC_POSIX_SOCKET +#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1 +#define GRPC_POSIX_SOCKET_EV 1 +#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1 +#define GRPC_POSIX_SOCKET_EV_POLL 1 +#define GRPC_POSIX_SOCKET_EV_EPOLL1 1 +#define GRPC_POSIX_SOCKET_IF_NAMETOINDEX 1 +#define GRPC_POSIX_SOCKET_IOMGR 1 +#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1 +#define GRPC_POSIX_SOCKET_SOCKADDR 1 +#define GRPC_POSIX_SOCKET_SOCKET_FACTORY 1 +#define GRPC_POSIX_SOCKET_TCP 1 +#define GRPC_POSIX_SOCKET_TCP_CLIENT 1 +#define GRPC_POSIX_SOCKET_TCP_SERVER 1 +#define GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON 1 +#define GRPC_POSIX_SOCKET_UTILS_COMMON 1 +#endif + #if defined(GRPC_POSIX_HOST_NAME_MAX) && defined(GRPC_POSIX_SYSCONF) #error "Cannot define both GRPC_POSIX_HOST_NAME_MAX and GRPC_POSIX_SYSCONF" #endif diff --git a/Sources/CgRPC/src/core/lib/iomgr/resolve_address.h b/Sources/CgRPC/src/core/lib/iomgr/resolve_address.h index fe0d83458..7016ffc31 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/resolve_address.h +++ b/Sources/CgRPC/src/core/lib/iomgr/resolve_address.h @@ -33,7 +33,7 @@ #include #endif -#ifdef GRPC_POSIX_SOCKET +#if defined(GRPC_POSIX_SOCKET) || defined(GRPC_CFSTREAM) #include #endif @@ -65,7 +65,7 @@ void grpc_set_resolver_impl(grpc_address_resolver_vtable* vtable); /* Asynchronously resolve addr. Use default_port if a port isn't designated in addr, otherwise use the port in addr. */ -/* TODO(ctiller): add a timeout here */ +/* TODO(apolcyn): add a timeout here */ void grpc_resolve_address(const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, diff --git a/Sources/CgRPC/src/core/lib/iomgr/resolve_address_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/resolve_address_posix.cc index a82075542..e6dd8f1ce 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/resolve_address_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/resolve_address_posix.cc @@ -19,7 +19,7 @@ #include #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_RESOLVE_ADDRESS #include "src/core/lib/iomgr/sockaddr.h" @@ -105,7 +105,7 @@ static grpc_error* posix_blocking_resolve_address( grpc_error_set_str( grpc_error_set_str( grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("OS Error"), + GRPC_ERROR_CREATE_FROM_STATIC_STRING(gai_strerror(s)), GRPC_ERROR_INT_ERRNO, s), GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(gai_strerror(s))), @@ -150,7 +150,7 @@ typedef struct { void* arg; } request; -/* Callback to be passed to grpc_executor to asynch-ify +/* Callback to be passed to grpc Executor to asynch-ify * grpc_blocking_resolve_address */ static void do_request_thread(void* rp, grpc_error* error) { request* r = static_cast(rp); @@ -166,8 +166,10 @@ static void posix_resolve_address(const char* name, const char* default_port, grpc_closure* on_done, grpc_resolved_addresses** addrs) { request* r = static_cast(gpr_malloc(sizeof(request))); - GRPC_CLOSURE_INIT(&r->request_closure, do_request_thread, r, - grpc_executor_scheduler(GRPC_EXECUTOR_SHORT)); + GRPC_CLOSURE_INIT( + &r->request_closure, do_request_thread, r, + grpc_core::Executor::Scheduler(grpc_core::ExecutorType::RESOLVER, + grpc_core::ExecutorJobType::SHORT)); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->on_done = on_done; diff --git a/Sources/CgRPC/src/core/lib/iomgr/resolve_address_windows.cc b/Sources/CgRPC/src/core/lib/iomgr/resolve_address_windows.cc index 71c92615a..64351c38a 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/resolve_address_windows.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/resolve_address_windows.cc @@ -151,8 +151,10 @@ static void windows_resolve_address(const char* name, const char* default_port, grpc_closure* on_done, grpc_resolved_addresses** addresses) { request* r = (request*)gpr_malloc(sizeof(request)); - GRPC_CLOSURE_INIT(&r->request_closure, do_request_thread, r, - grpc_executor_scheduler(GRPC_EXECUTOR_SHORT)); + GRPC_CLOSURE_INIT( + &r->request_closure, do_request_thread, r, + grpc_core::Executor::Scheduler(grpc_core::ExecutorType::RESOLVER, + grpc_core::ExecutorJobType::SHORT)); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->on_done = on_done; diff --git a/Sources/CgRPC/src/core/lib/iomgr/resource_quota.cc b/Sources/CgRPC/src/core/lib/iomgr/resource_quota.cc index 8cf4fe992..61c366098 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/resource_quota.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/resource_quota.cc @@ -90,12 +90,16 @@ struct grpc_resource_user { grpc_closure_list on_allocated; /* True if we are currently trying to allocate from the quota, false if not */ bool allocating; - /* How many bytes of allocations are outstanding */ + /* The amount of memory (in bytes) that has been requested from this user + * asynchronously but hasn't been granted yet. */ int64_t outstanding_allocations; /* True if we are currently trying to add ourselves to the non-free quota list, false otherwise */ bool added_to_free_pool; + /* The number of threads currently allocated to this resource user */ + gpr_atm num_threads_allocated; + /* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer */ grpc_closure* reclaimers[2]; @@ -132,15 +136,39 @@ struct grpc_resource_quota { int64_t size; /* Amount of free memory in the resource quota */ int64_t free_pool; + /* Used size of memory in the resource quota. Updated as soon as the resource + * users start to allocate or free the memory. */ + gpr_atm used; gpr_atm last_size; + /* Mutex to protect max_threads and num_threads_allocated */ + /* Note: We could have used gpr_atm for max_threads and num_threads_allocated + * and avoid having this mutex; but in that case, each invocation of the + * function grpc_resource_user_allocate_threads() would have had to do at + * least two atomic loads (for max_threads and num_threads_allocated) followed + * by a CAS (on num_threads_allocated). + * Moreover, we expect grpc_resource_user_allocate_threads() to be often + * called concurrently thereby increasing the chances of failing the CAS + * operation. This additional complexity is not worth the tiny perf gain we + * may (or may not) have by using atomics */ + gpr_mu thread_count_mu; + + /* Max number of threads allowed */ + int max_threads; + + /* Number of threads currently allocated via this resource_quota object */ + int num_threads_allocated; + /* Has rq_step been scheduled to occur? */ bool step_scheduled; + /* Are we currently reclaiming memory */ bool reclaiming; + /* Closure around rq_step */ grpc_closure rq_step_closure; + /* Closure around rq_reclamation_done */ grpc_closure rq_reclamation_done_closure; @@ -347,6 +375,7 @@ static bool rq_reclaim_from_per_user_free_pool( while ((resource_user = rulist_pop_head(resource_quota, GRPC_RULIST_NON_EMPTY_FREE_POOL))) { gpr_mu_lock(&resource_user->mu); + resource_user->added_to_free_pool = false; if (resource_user->free_pool > 0) { int64_t amt = resource_user->free_pool; resource_user->free_pool = 0; @@ -362,6 +391,13 @@ static bool rq_reclaim_from_per_user_free_pool( gpr_mu_unlock(&resource_user->mu); return true; } else { + if (grpc_resource_quota_trace.enabled()) { + gpr_log(GPR_INFO, + "RQ %s %s: failed to reclaim_from_per_user_free_pool; " + "free_pool = %" PRId64 "; rq_free_pool = %" PRId64, + resource_quota->name, resource_user->name, + resource_user->free_pool, resource_quota->free_pool); + } gpr_mu_unlock(&resource_user->mu); } } @@ -386,7 +422,7 @@ static bool rq_reclaim(grpc_resource_quota* resource_quota, bool destructive) { resource_quota->debug_only_last_reclaimer_resource_user = resource_user; resource_quota->debug_only_last_initiated_reclaimer = c; resource_user->reclaimers[destructive] = nullptr; - GRPC_CLOSURE_RUN(c, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(c, GRPC_ERROR_NONE); return true; } @@ -524,6 +560,11 @@ static void ru_shutdown(void* ru, grpc_error* error) { static void ru_destroy(void* ru, grpc_error* error) { grpc_resource_user* resource_user = static_cast(ru); GPR_ASSERT(gpr_atm_no_barrier_load(&resource_user->refs) == 0); + // Free all the remaining thread quota + grpc_resource_user_free_threads(resource_user, + static_cast(gpr_atm_no_barrier_load( + &resource_user->num_threads_allocated))); + for (int i = 0; i < GRPC_RULIST_COUNT; i++) { rulist_remove(resource_user, static_cast(i)); } @@ -593,7 +634,11 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { resource_quota->combiner = grpc_combiner_create(); resource_quota->free_pool = INT64_MAX; resource_quota->size = INT64_MAX; + resource_quota->used = 0; gpr_atm_no_barrier_store(&resource_quota->last_size, GPR_ATM_MAX); + gpr_mu_init(&resource_quota->thread_count_mu); + resource_quota->max_threads = INT_MAX; + resource_quota->num_threads_allocated = 0; resource_quota->step_scheduled = false; resource_quota->reclaiming = false; gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0); @@ -616,8 +661,11 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) { if (gpr_unref(&resource_quota->refs)) { + // No outstanding thread quota + GPR_ASSERT(resource_quota->num_threads_allocated == 0); GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota"); gpr_free(resource_quota->name); + gpr_mu_destroy(&resource_quota->thread_count_mu); gpr_free(resource_quota); } } @@ -646,6 +694,15 @@ double grpc_resource_quota_get_memory_pressure( (static_cast(MEMORY_USAGE_ESTIMATION_MAX)); } +/* Public API */ +void grpc_resource_quota_set_max_threads(grpc_resource_quota* resource_quota, + int new_max_threads) { + GPR_ASSERT(new_max_threads >= 0); + gpr_mu_lock(&resource_quota->thread_count_mu); + resource_quota->max_threads = new_max_threads; + gpr_mu_unlock(&resource_quota->thread_count_mu); +} + /* Public API */ void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, size_t size) { @@ -669,7 +726,7 @@ size_t grpc_resource_quota_peek_size(grpc_resource_quota* resource_quota) { */ grpc_resource_quota* grpc_resource_quota_from_channel_args( - const grpc_channel_args* channel_args) { + const grpc_channel_args* channel_args, bool create) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { if (channel_args->args[i].type == GRPC_ARG_POINTER) { @@ -681,7 +738,7 @@ grpc_resource_quota* grpc_resource_quota_from_channel_args( } } } - return grpc_resource_quota_create(nullptr); + return create ? grpc_resource_quota_create(nullptr) : nullptr; } static void* rq_copy(void* rq) { @@ -731,6 +788,7 @@ grpc_resource_user* grpc_resource_user_create( grpc_closure_list_init(&resource_user->on_allocated); resource_user->allocating = false; resource_user->added_to_free_pool = false; + gpr_atm_no_barrier_store(&resource_user->num_threads_allocated, 0); resource_user->reclaimers[0] = nullptr; resource_user->reclaimers[1] = nullptr; resource_user->new_reclaimers[0] = nullptr; @@ -785,33 +843,102 @@ void grpc_resource_user_shutdown(grpc_resource_user* resource_user) { } } -void grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size, - grpc_closure* optional_on_done) { - gpr_mu_lock(&resource_user->mu); +bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, + int thread_count) { + GPR_ASSERT(thread_count >= 0); + bool is_success = false; + gpr_mu_lock(&resource_user->resource_quota->thread_count_mu); + grpc_resource_quota* rq = resource_user->resource_quota; + if (rq->num_threads_allocated + thread_count <= rq->max_threads) { + rq->num_threads_allocated += thread_count; + gpr_atm_no_barrier_fetch_add(&resource_user->num_threads_allocated, + thread_count); + is_success = true; + } + gpr_mu_unlock(&resource_user->resource_quota->thread_count_mu); + return is_success; +} + +void grpc_resource_user_free_threads(grpc_resource_user* resource_user, + int thread_count) { + GPR_ASSERT(thread_count >= 0); + gpr_mu_lock(&resource_user->resource_quota->thread_count_mu); + grpc_resource_quota* rq = resource_user->resource_quota; + rq->num_threads_allocated -= thread_count; + int old_count = static_cast(gpr_atm_no_barrier_fetch_add( + &resource_user->num_threads_allocated, -thread_count)); + if (old_count < thread_count || rq->num_threads_allocated < 0) { + gpr_log(GPR_ERROR, + "Releasing more threads (%d) than currently allocated (rq threads: " + "%d, ru threads: %d)", + thread_count, rq->num_threads_allocated + thread_count, old_count); + abort(); + } + gpr_mu_unlock(&resource_user->resource_quota->thread_count_mu); +} + +static void resource_user_alloc_locked(grpc_resource_user* resource_user, + size_t size, + grpc_closure* optional_on_done) { ru_ref_by(resource_user, static_cast(size)); resource_user->free_pool -= static_cast(size); - resource_user->outstanding_allocations += static_cast(size); if (grpc_resource_quota_trace.enabled()) { gpr_log(GPR_INFO, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64, resource_user->resource_quota->name, resource_user->name, size, resource_user->free_pool); } if (resource_user->free_pool < 0) { - grpc_closure_list_append(&resource_user->on_allocated, optional_on_done, - GRPC_ERROR_NONE); + if (optional_on_done != nullptr) { + resource_user->outstanding_allocations += static_cast(size); + grpc_closure_list_append(&resource_user->on_allocated, optional_on_done, + GRPC_ERROR_NONE); + } if (!resource_user->allocating) { resource_user->allocating = true; GRPC_CLOSURE_SCHED(&resource_user->allocate_closure, GRPC_ERROR_NONE); } } else { - resource_user->outstanding_allocations -= static_cast(size); GRPC_CLOSURE_SCHED(optional_on_done, GRPC_ERROR_NONE); } +} + +bool grpc_resource_user_safe_alloc(grpc_resource_user* resource_user, + size_t size) { + if (gpr_atm_no_barrier_load(&resource_user->shutdown)) return false; + gpr_mu_lock(&resource_user->mu); + grpc_resource_quota* resource_quota = resource_user->resource_quota; + bool cas_success; + do { + gpr_atm used = gpr_atm_no_barrier_load(&resource_quota->used); + gpr_atm new_used = used + size; + if (static_cast(new_used) > + grpc_resource_quota_peek_size(resource_quota)) { + gpr_mu_unlock(&resource_user->mu); + return false; + } + cas_success = gpr_atm_full_cas(&resource_quota->used, used, new_used); + } while (!cas_success); + resource_user_alloc_locked(resource_user, size, nullptr); + gpr_mu_unlock(&resource_user->mu); + return true; +} + +void grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size, + grpc_closure* optional_on_done) { + // TODO(juanlishen): Maybe return immediately if shutting down. Deferring this + // because some tests become flaky after the change. + gpr_mu_lock(&resource_user->mu); + grpc_resource_quota* resource_quota = resource_user->resource_quota; + gpr_atm_no_barrier_fetch_add(&resource_quota->used, size); + resource_user_alloc_locked(resource_user, size, optional_on_done); gpr_mu_unlock(&resource_user->mu); } void grpc_resource_user_free(grpc_resource_user* resource_user, size_t size) { gpr_mu_lock(&resource_user->mu); + grpc_resource_quota* resource_quota = resource_user->resource_quota; + gpr_atm prior = gpr_atm_no_barrier_fetch_add(&resource_quota->used, -size); + GPR_ASSERT(prior >= static_cast(size)); bool was_zero_or_negative = resource_user->free_pool <= 0; resource_user->free_pool += static_cast(size); if (grpc_resource_quota_trace.enabled()) { @@ -862,6 +989,12 @@ void grpc_resource_user_slice_allocator_init( void grpc_resource_user_alloc_slices( grpc_resource_user_slice_allocator* slice_allocator, size_t length, size_t count, grpc_slice_buffer* dest) { + if (gpr_atm_no_barrier_load(&slice_allocator->resource_user->shutdown)) { + GRPC_CLOSURE_SCHED( + &slice_allocator->on_allocated, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource user shutdown")); + return; + } slice_allocator->length = length; slice_allocator->count = count; slice_allocator->dest = dest; diff --git a/Sources/CgRPC/src/core/lib/iomgr/resource_quota.h b/Sources/CgRPC/src/core/lib/iomgr/resource_quota.h index 937daf872..1c79b52e3 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/resource_quota.h +++ b/Sources/CgRPC/src/core/lib/iomgr/resource_quota.h @@ -65,11 +65,16 @@ extern grpc_core::TraceFlag grpc_resource_quota_trace; +// TODO(juanlishen): This is a hack. We need to do real accounting instead of +// hard coding. +constexpr size_t GRPC_RESOURCE_QUOTA_CALL_SIZE = 15 * 1024; +constexpr size_t GRPC_RESOURCE_QUOTA_CHANNEL_SIZE = 50 * 1024; + grpc_resource_quota* grpc_resource_quota_ref_internal( grpc_resource_quota* resource_quota); void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota); grpc_resource_quota* grpc_resource_quota_from_channel_args( - const grpc_channel_args* channel_args); + const grpc_channel_args* channel_args, bool create = true); /* Return a number indicating current memory pressure: 0.0 ==> no memory usage @@ -93,11 +98,37 @@ void grpc_resource_user_ref(grpc_resource_user* resource_user); void grpc_resource_user_unref(grpc_resource_user* resource_user); void grpc_resource_user_shutdown(grpc_resource_user* resource_user); -/* Allocate from the resource user (and its quota). - If optional_on_done is NULL, then allocate immediately. This may push the - quota over-limit, at which point reclamation will kick in. - If optional_on_done is non-NULL, it will be scheduled when the allocation has - been granted by the quota. */ +/* Attempts to get quota from the resource_user to create 'thread_count' number + * of threads. Returns true if successful (i.e the caller is now free to create + * 'thread_count' number of threads) or false if quota is not available */ +bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, + int thread_count); +/* Releases 'thread_count' worth of quota back to the resource user. The quota + * should have been previously obtained successfully by calling + * grpc_resource_user_allocate_threads(). + * + * Note: There need not be an exact one-to-one correspondence between + * grpc_resource_user_allocate_threads() and grpc_resource_user_free_threads() + * calls. The only requirement is that the number of threads allocated should + * all be eventually released */ +void grpc_resource_user_free_threads(grpc_resource_user* resource_user, + int thread_count); + +/* Allocates from the resource user 'size' worth of memory if this won't exceed + * the resource quota's total size. Returns whether the allocation is done + * successfully. If allocated successfully, the memory should be freed by the + * caller eventually. */ +bool grpc_resource_user_safe_alloc(grpc_resource_user* resource_user, + size_t size); +/* Allocates from the resource user 'size' worth of memory. + * If optional_on_done is NULL, then allocate immediately. This may push the + * quota over-limit, at which point reclamation will kick in. The caller is + * always responsible to free the memory eventually. + * If optional_on_done is non-NULL, it will be scheduled without error when the + * allocation has been granted by the quota, and the caller is responsible to + * free the memory eventually. Or it may be scheduled with an error, in which + * case the caller fails to allocate the memory and shouldn't free the memory. + */ void grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size, grpc_closure* optional_on_done); /* Release memory back to the quota */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/sockaddr_posix.h b/Sources/CgRPC/src/core/lib/iomgr/sockaddr_posix.h index 5b18bbc46..3cedd9082 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/sockaddr_posix.h +++ b/Sources/CgRPC/src/core/lib/iomgr/sockaddr_posix.h @@ -23,7 +23,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_SOCKADDR #include #include #include diff --git a/Sources/CgRPC/src/core/lib/iomgr/sockaddr_utils.cc b/Sources/CgRPC/src/core/lib/iomgr/sockaddr_utils.cc index 1b66dceb1..0839bdfef 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/sockaddr_utils.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/sockaddr_utils.cc @@ -217,6 +217,7 @@ void grpc_string_to_sockaddr(grpc_resolved_address* out, char* addr, int port) { } char* grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) { + if (resolved_addr->len == 0) return nullptr; grpc_resolved_address addr_normalized; if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) { resolved_addr = &addr_normalized; diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_factory_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/socket_factory_posix.cc index 1d1e36c0e..57137769c 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_factory_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_factory_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_SOCKET_FACTORY #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/useful.h" diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.cc b/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.cc index b9b8eaf4a..a448c9f61 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.cc @@ -57,7 +57,7 @@ int grpc_socket_mutator_compare(grpc_socket_mutator* a, void grpc_socket_mutator_unref(grpc_socket_mutator* mutator) { if (gpr_unref(&mutator->refcount)) { - mutator->vtable->destory(mutator); + mutator->vtable->destroy(mutator); } } diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.h b/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.h index 6c7781c51..8742a3ba6 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.h +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_mutator.h @@ -33,7 +33,7 @@ typedef struct { /** Compare socket mutator \a a and \a b */ int (*compare)(grpc_socket_mutator* a, grpc_socket_mutator* b); /** Destroys the socket mutator instance */ - void (*destory)(grpc_socket_mutator* mutator); + void (*destroy)(grpc_socket_mutator* mutator); } grpc_socket_mutator_vtable; /** The Socket Mutator interface allows changes on socket options */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_utils.h b/Sources/CgRPC/src/core/lib/iomgr/socket_utils.h index cf1a7be64..14bb081e9 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_utils.h +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_utils.h @@ -23,12 +23,21 @@ #include +// TODO(juanlishen): The following functions might be simple enough to implement +// ourselves, so that they don't cause any portability hassle. + /* A wrapper for htons on POSIX and Windows */ uint16_t grpc_htons(uint16_t hostshort); /* A wrapper for ntohs on POSIX and WINDOWS */ uint16_t grpc_ntohs(uint16_t netshort); +/* A wrapper for htonl on POSIX and Windows */ +uint32_t grpc_htonl(uint32_t hostlong); + +/* A wrapper for ntohl on POSIX and WINDOWS */ +uint32_t grpc_ntohl(uint32_t netlong); + /* A wrapper for inet_pton on POSIX and WINDOWS */ int grpc_inet_pton(int af, const char* src, void* dst); diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_common_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_common_posix.cc index 04a176773..4c337a052 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON #include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" @@ -41,6 +41,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/sockaddr.h" @@ -222,6 +223,101 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { return GRPC_ERROR_NONE; } +/* The default values for TCP_USER_TIMEOUT are currently configured to be in + * line with the default values of KEEPALIVE_TIMEOUT as proposed in + * https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */ +#define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */ +#define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */ + +static int g_default_client_tcp_user_timeout_ms = + DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS; +static int g_default_server_tcp_user_timeout_ms = + DEFAULT_SERVER_TCP_USER_TIMEOUT_MS; +static bool g_default_client_tcp_user_timeout_enabled = false; +static bool g_default_server_tcp_user_timeout_enabled = true; + +void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) { + if (is_client) { + g_default_client_tcp_user_timeout_enabled = enable; + if (timeout > 0) { + g_default_client_tcp_user_timeout_ms = timeout; + } + } else { + g_default_server_tcp_user_timeout_enabled = enable; + if (timeout > 0) { + g_default_server_tcp_user_timeout_ms = timeout; + } + } +} + +/* Set TCP_USER_TIMEOUT */ +grpc_error* grpc_set_socket_tcp_user_timeout( + int fd, const grpc_channel_args* channel_args, bool is_client) { +#ifdef GRPC_HAVE_TCP_USER_TIMEOUT + bool enable; + int timeout; + if (is_client) { + enable = g_default_client_tcp_user_timeout_enabled; + timeout = g_default_client_tcp_user_timeout_ms; + } else { + enable = g_default_server_tcp_user_timeout_enabled; + timeout = g_default_server_tcp_user_timeout_ms; + } + if (channel_args) { + for (unsigned int i = 0; i < channel_args->num_args; i++) { + if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX}); + /* Continue using default if value is 0 */ + if (value == 0) { + continue; + } + /* Disable if value is INT_MAX */ + enable = value != INT_MAX; + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX}); + /* Continue using default if value is 0 */ + if (value == 0) { + continue; + } + timeout = value; + } + } + } + if (enable) { + extern grpc_core::TraceFlag grpc_tcp_trace; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "Enabling TCP_USER_TIMEOUT with a timeout of %d ms", + timeout); + } + int newval; + socklen_t len = sizeof(newval); + if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, + sizeof(timeout))) { + gpr_log(GPR_ERROR, "setsockopt(TCP_USER_TIMEOUT) %s", strerror(errno)); + return GRPC_ERROR_NONE; + } + if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { + gpr_log(GPR_ERROR, "getsockopt(TCP_USER_TIMEOUT) %s", strerror(errno)); + return GRPC_ERROR_NONE; + } + if (newval != timeout) { + /* Do not fail on failing to set TCP_USER_TIMEOUT for now. */ + gpr_log(GPR_ERROR, "Failed to set TCP_USER_TIMEOUT"); + return GRPC_ERROR_NONE; + } + } +#else + extern grpc_core::TraceFlag grpc_tcp_trace; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform"); + } +#endif /* GRPC_HAVE_TCP_USER_TIMEOUT */ + return GRPC_ERROR_NONE; +} + /* set a socket using a grpc_socket_mutator */ grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) { GPR_ASSERT(mutator); @@ -339,6 +435,10 @@ uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); } uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); } +uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); } + +uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); } + int grpc_inet_pton(int af, const char* src, void* dst) { return inet_pton(af, src, dst); } diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_posix.h b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_posix.h index b3fd58a53..71a304dc4 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_posix.h +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_posix.h @@ -53,6 +53,13 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency); /* set SO_REUSEPORT */ grpc_error* grpc_set_socket_reuse_port(int fd, int reuse); +/* Configure the default values for TCP_USER_TIMEOUT */ +void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client); + +/* Set TCP_USER_TIMEOUT */ +grpc_error* grpc_set_socket_tcp_user_timeout( + int fd, const grpc_channel_args* channel_args, bool is_client); + /* Returns true if this system can create AF_INET6 sockets bound to ::1. The value is probed once, and cached for the life of the process. diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_uv.cc b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_uv.cc index 7eba40c46..b5f96b52d 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_uv.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_uv.cc @@ -33,6 +33,10 @@ uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); } uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); } +uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); } + +uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); } + int grpc_inet_pton(int af, const char* src, void* dst) { return inet_pton(af, src, dst); } diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_windows.cc b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_windows.cc index 3e7b5b812..9137ab98e 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_utils_windows.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_utils_windows.cc @@ -31,6 +31,10 @@ uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); } uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); } +uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); } + +uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); } + int grpc_inet_pton(int af, const char* src, void* dst) { return inet_pton(af, src, dst); } diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_windows.cc b/Sources/CgRPC/src/core/lib/iomgr/socket_windows.cc index 2e2340958..999c6646a 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_windows.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_windows.cc @@ -36,6 +36,7 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" +#include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) { @@ -51,6 +52,10 @@ grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) { return r; } +SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket) { + return socket->socket; +} + /* Schedule a shutdown of the socket operations. Will call the pending operations to abort them. We need to do that this way because of the various callsites of that function, which happens to be in various @@ -148,4 +153,32 @@ void grpc_socket_become_ready(grpc_winsocket* socket, if (should_destroy) destroy(socket); } +static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; +static bool g_ipv6_loopback_available = false; + +static void probe_ipv6_once(void) { + SOCKET s = socket(AF_INET6, SOCK_STREAM, 0); + g_ipv6_loopback_available = 0; + if (s == INVALID_SOCKET) { + gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); + } else { + grpc_sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ + if (bind(s, reinterpret_cast(&addr), sizeof(addr)) == 0) { + g_ipv6_loopback_available = 1; + } else { + gpr_log(GPR_INFO, + "Disabling AF_INET6 sockets because ::1 is not available."); + } + closesocket(s); + } +} + +int grpc_ipv6_loopback_available(void) { + gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); + return g_ipv6_loopback_available; +} + #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/socket_windows.h b/Sources/CgRPC/src/core/lib/iomgr/socket_windows.h index 7bd01eded..46d7d5835 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/socket_windows.h +++ b/Sources/CgRPC/src/core/lib/iomgr/socket_windows.h @@ -92,6 +92,8 @@ typedef struct grpc_winsocket { it will be responsible for closing it. */ grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name); +SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket); + /* Initiate an asynchronous shutdown of the socket. Will call off any pending operation to cancel them. */ void grpc_winsocket_shutdown(grpc_winsocket* socket); @@ -108,6 +110,10 @@ void grpc_socket_notify_on_read(grpc_winsocket* winsocket, void grpc_socket_become_ready(grpc_winsocket* winsocket, grpc_winsocket_callback_info* ci); +/* Returns true if this system can create AF_INET6 sockets bound to ::1. + The value is probed once, and cached for the life of the process. */ +int grpc_ipv6_loopback_available(void); + #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_client_custom.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_client_custom.cc index 932c79ea0..73344b18d 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_client_custom.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_client_custom.cc @@ -81,9 +81,8 @@ static void on_alarm(void* acp, grpc_error* error) { } } -static void custom_connect_callback(grpc_custom_socket* socket, - grpc_error* error) { - grpc_core::ExecCtx exec_ctx; +static void custom_connect_callback_internal(grpc_custom_socket* socket, + grpc_error* error) { grpc_custom_tcp_connect* connect = socket->connector; int done; grpc_closure* closure = connect->closure; @@ -100,6 +99,18 @@ static void custom_connect_callback(grpc_custom_socket* socket, GRPC_CLOSURE_SCHED(closure, error); } +static void custom_connect_callback(grpc_custom_socket* socket, + grpc_error* error) { + if (grpc_core::ExecCtx::Get() == nullptr) { + /* If we are being run on a thread which does not have an exec_ctx created + * yet, we should create one. */ + grpc_core::ExecCtx exec_ctx; + custom_connect_callback_internal(socket, error); + } else { + custom_connect_callback_internal(socket, error); + } +} + static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep, grpc_pollset_set* interested_parties, const grpc_channel_args* channel_args, @@ -140,12 +151,12 @@ static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep, socket, connect->addr_name); } - grpc_custom_socket_vtable->connect( - socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len, - custom_connect_callback); GRPC_CLOSURE_INIT(&connect->on_alarm, on_alarm, socket, grpc_schedule_on_exec_ctx); grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm); + grpc_custom_socket_vtable->connect( + socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len, + custom_connect_callback); } grpc_tcp_client_vtable custom_tcp_client_vtable = {tcp_connect}; diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_client_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_client_posix.cc index 6144d389f..0bff74e88 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_client_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_client_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_TCP_CLIENT #include "src/core/lib/iomgr/tcp_client_posix.h" @@ -45,6 +45,7 @@ #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "src/core/lib/slice/slice_internal.h" extern grpc_core::TraceFlag grpc_tcp_trace; @@ -75,6 +76,11 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, if (!grpc_is_unix_socket(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_reuse_addr(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_tcp_user_timeout(fd, channel_args, + true /* is_client */); + if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); if (err != GRPC_ERROR_NONE) goto error; @@ -210,8 +216,7 @@ static void on_writable(void* acp, grpc_error* error) { finish: if (fd != nullptr) { grpc_pollset_set_del_fd(ac->interested_parties, fd); - grpc_fd_orphan(fd, nullptr, nullptr, false /* already_closed */, - "tcp_client_orphan"); + grpc_fd_orphan(fd, nullptr, nullptr, "tcp_client_orphan"); fd = nullptr; } done = (--ac->refs == 0); @@ -233,7 +238,7 @@ static void on_writable(void* acp, grpc_error* error) { error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_str_slice /* takes ownership */); } else { - grpc_slice_unref(addr_str_slice); + grpc_slice_unref_internal(addr_str_slice); } if (done) { // This is safe even outside the lock, because "done", the sentinel, is @@ -279,7 +284,7 @@ grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args, } addr_str = grpc_sockaddr_to_uri(mapped_addr); gpr_asprintf(&name, "tcp-client:%s", addr_str); - *fdobj = grpc_fd_create(fd, name); + *fdobj = grpc_fd_create(fd, name, true); gpr_free(name); gpr_free(addr_str); return GRPC_ERROR_NONE; @@ -304,8 +309,7 @@ void grpc_tcp_client_create_from_prepared_fd( return; } if (errno != EWOULDBLOCK && errno != EINPROGRESS) { - grpc_fd_orphan(fdobj, nullptr, nullptr, false /* already_closed */, - "tcp_client_connect_error"); + grpc_fd_orphan(fdobj, nullptr, nullptr, "tcp_client_connect_error"); GRPC_CLOSURE_SCHED(closure, GRPC_OS_ERROR(errno, "connect")); return; } diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_custom.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_custom.cc index b3b293401..1e5696e12 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_custom.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_custom.cc @@ -31,7 +31,6 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr_custom.h" -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_custom.h" @@ -141,7 +140,7 @@ static void call_read_cb(custom_tcp_endpoint* tcp, grpc_error* error) { TCP_UNREF(tcp, "read"); tcp->read_slices = nullptr; tcp->read_cb = nullptr; - GRPC_CLOSURE_RUN(cb, error); + GRPC_CLOSURE_SCHED(cb, error); } static void custom_read_callback(grpc_custom_socket* socket, size_t nread, @@ -221,7 +220,7 @@ static void custom_write_callback(grpc_custom_socket* socket, } static void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* write_slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep; GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); @@ -309,7 +308,6 @@ static void custom_close_callback(grpc_custom_socket* socket) { } static void endpoint_destroy(grpc_endpoint* ep) { - grpc_network_status_unregister_endpoint(ep); custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep; grpc_custom_socket_vtable->close(tcp->socket, custom_close_callback); } @@ -326,6 +324,8 @@ static grpc_resource_user* endpoint_get_resource_user(grpc_endpoint* ep) { static int endpoint_get_fd(grpc_endpoint* ep) { return -1; } +static bool endpoint_can_track_err(grpc_endpoint* ep) { return false; } + static grpc_endpoint_vtable vtable = {endpoint_read, endpoint_write, endpoint_add_to_pollset, @@ -335,7 +335,8 @@ static grpc_endpoint_vtable vtable = {endpoint_read, endpoint_destroy, endpoint_get_resource_user, endpoint_get_peer, - endpoint_get_fd}; + endpoint_get_fd, + endpoint_can_track_err}; grpc_endpoint* custom_tcp_endpoint_create(grpc_custom_socket* socket, grpc_resource_quota* resource_quota, @@ -358,8 +359,6 @@ grpc_endpoint* custom_tcp_endpoint_create(grpc_custom_socket* socket, tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); grpc_resource_user_slice_allocator_init( &tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp); - /* Tell network status tracking code about the new endpoint */ - grpc_network_status_register_endpoint(&tcp->base); return &tcp->base; } diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.cc index 153be05e8..13ceffc69 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.cc @@ -20,13 +20,15 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_TCP -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/tcp_posix.h" #include +#include +#include #include +#include #include #include #include @@ -45,6 +47,7 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/iomgr/buffer_list.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/profiling/timers.h" @@ -70,7 +73,9 @@ struct grpc_tcp { grpc_endpoint base; grpc_fd* em_fd; int fd; - bool finished_edge; + /* Used by the endpoint read function to distinguish the very first read call + * from the rest */ + bool is_first_read; double target_length; double bytes_read_this_round; gpr_refcount refcount; @@ -94,17 +99,42 @@ struct grpc_tcp { grpc_closure read_done_closure; grpc_closure write_done_closure; + grpc_closure error_closure; char* peer_string; grpc_resource_user* resource_user; grpc_resource_user_slice_allocator slice_allocator; + + grpc_core::TracedBuffer* tb_head; /* List of traced buffers */ + gpr_mu tb_mu; /* Lock for access to list of traced buffers */ + + /* grpc_endpoint_write takes an argument which if non-null means that the + * transport layer wants the TCP layer to collect timestamps for this write. + * This arg is forwarded to the timestamps callback function when the ACK + * timestamp is received from the kernel. This arg is a (void *) which allows + * users of this API to pass in a pointer to any kind of structure. This + * structure could actually be a tag or any book-keeping object that the user + * can use to distinguish between different traced writes. The only + * requirement from the TCP endpoint layer is that this arg should be non-null + * if the user wants timestamps for the write. */ + void* outgoing_buffer_arg; + /* A counter which starts at 0. It is initialized the first time the socket + * options for collecting timestamps are set, and is incremented with each + * byte sent. */ + int bytes_counter; + bool socket_ts_enabled; /* True if timestamping options are set on the socket + */ + bool ts_capable; /* Cache whether we can set timestamping options */ + gpr_atm stop_error_notification; /* Set to 1 if we do not want to be notified + on errors anymore */ }; struct backup_poller { gpr_mu* pollset_mu; grpc_closure run_poller; }; + } // namespace #define BACKUP_POLLER_POLLSET(b) ((grpc_pollset*)((b) + 1)) @@ -165,7 +195,7 @@ static void run_poller(void* bp, grpc_error* error_ignored) { static void drop_uncovered(grpc_tcp* tcp) { backup_poller* p = (backup_poller*)gpr_atm_acq_load(&g_backup_poller); gpr_atm old_count = - gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, -1); + gpr_atm_full_fetch_add(&g_uncovered_notifications_pending, -1); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "BACKUP_POLLER:%p uncover cnt %d->%d", p, static_cast(old_count), static_cast(old_count) - 1); @@ -173,6 +203,13 @@ static void drop_uncovered(grpc_tcp* tcp) { GPR_ASSERT(old_count != 1); } +// gRPC API considers a Write operation to be done the moment it clears ‘flow +// control’ i.e., not necessarily sent on the wire. This means that the +// application MIGHT not call `grpc_completion_queue_next/pluck` in a timely +// manner when its `Write()` API is acked. +// +// We need to ensure that the fd is 'covered' (i.e being monitored by some +// polling thread and progress is made) and hence add it to a backup poller here static void cover_self(grpc_tcp* tcp) { backup_poller* p; gpr_atm old_count = @@ -190,10 +227,10 @@ static void cover_self(grpc_tcp* tcp) { } grpc_pollset_init(BACKUP_POLLER_POLLSET(p), &p->pollset_mu); gpr_atm_rel_store(&g_backup_poller, (gpr_atm)p); - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_INIT(&p->run_poller, run_poller, p, - grpc_executor_scheduler(GRPC_EXECUTOR_LONG)), - GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(GRPC_CLOSURE_INIT(&p->run_poller, run_poller, p, + grpc_core::Executor::Scheduler( + grpc_core::ExecutorJobType::LONG)), + GRPC_ERROR_NONE); } else { while ((p = (backup_poller*)gpr_atm_acq_load(&g_backup_poller)) == nullptr) { @@ -222,10 +259,17 @@ static void notify_on_write(grpc_tcp* tcp) { if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "TCP:%p notify_on_write", tcp); } - cover_self(tcp); - GRPC_CLOSURE_INIT(&tcp->write_done_closure, - tcp_drop_uncovered_then_handle_write, tcp, - grpc_schedule_on_exec_ctx); + if (grpc_event_engine_run_in_background()) { + // If there is a polling engine always running in the background, there is + // no need to run the backup poller. + GRPC_CLOSURE_INIT(&tcp->write_done_closure, tcp_handle_write, tcp, + grpc_schedule_on_exec_ctx); + } else { + cover_self(tcp); + GRPC_CLOSURE_INIT(&tcp->write_done_closure, + tcp_drop_uncovered_then_handle_write, tcp, + grpc_schedule_on_exec_ctx); + } grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_done_closure); } @@ -295,10 +339,18 @@ static void tcp_shutdown(grpc_endpoint* ep, grpc_error* why) { static void tcp_free(grpc_tcp* tcp) { grpc_fd_orphan(tcp->em_fd, tcp->release_fd_cb, tcp->release_fd, - false /* already_closed */, "tcp_unref_orphan"); + "tcp_unref_orphan"); grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); gpr_free(tcp->peer_string); + /* The lock is not really necessary here, since all refs have been released */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; + gpr_mu_destroy(&tcp->tb_mu); gpr_free(tcp); } @@ -341,9 +393,12 @@ static void tcp_ref(grpc_tcp* tcp) { gpr_ref(&tcp->refcount); } #endif static void tcp_destroy(grpc_endpoint* ep) { - grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = reinterpret_cast(ep); grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); + if (grpc_event_engine_can_track_errors()) { + gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); + grpc_fd_set_error(tcp->em_fd); + } TCP_UNREF(tcp, "destroy"); } @@ -354,19 +409,21 @@ static void call_read_cb(grpc_tcp* tcp, grpc_error* error) { gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg); size_t i; const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "read: error=%s", str); - - for (i = 0; i < tcp->incoming_buffer->count; i++) { - char* dump = grpc_dump_slice(tcp->incoming_buffer->slices[i], - GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump); - gpr_free(dump); + gpr_log(GPR_INFO, "READ %p (peer=%s) error=%s", tcp, tcp->peer_string, str); + + if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + for (i = 0; i < tcp->incoming_buffer->count; i++) { + char* dump = grpc_dump_slice(tcp->incoming_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "DATA: %s", dump); + gpr_free(dump); + } } } tcp->read_cb = nullptr; tcp->incoming_buffer = nullptr; - GRPC_CLOSURE_RUN(cb, error); + GRPC_CLOSURE_SCHED(cb, error); } #define MAX_READ_IOVEC 4 @@ -377,7 +434,6 @@ static void tcp_do_read(grpc_tcp* tcp) { ssize_t read_bytes; size_t i; - GPR_ASSERT(!tcp->finished_edge); GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); for (i = 0; i < tcp->incoming_buffer->count; i++) { @@ -426,7 +482,9 @@ static void tcp_do_read(grpc_tcp* tcp) { GRPC_STATS_INC_TCP_READ_SIZE(read_bytes); add_to_estimate(tcp, static_cast(read_bytes)); GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); - if (static_cast(read_bytes) < tcp->incoming_buffer->length) { + if (static_cast(read_bytes) == tcp->incoming_buffer->length) { + finish_estimate(tcp); + } else if (static_cast(read_bytes) < tcp->incoming_buffer->length) { grpc_slice_buffer_trim_end( tcp->incoming_buffer, tcp->incoming_buffer->length - static_cast(read_bytes), @@ -456,7 +514,7 @@ static void tcp_read_allocation_done(void* tcpp, grpc_error* error) { static void tcp_continue_read(grpc_tcp* tcp) { size_t target_read_size = get_target_read_size(tcp); - if (tcp->incoming_buffer->length < target_read_size && + if (tcp->incoming_buffer->length < target_read_size / 2 && tcp->incoming_buffer->count < MAX_READ_IOVEC) { if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "TCP:%p alloc_slices", tcp); @@ -473,7 +531,6 @@ static void tcp_continue_read(grpc_tcp* tcp) { static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error) { grpc_tcp* tcp = static_cast(arg); - GPR_ASSERT(!tcp->finished_edge); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, grpc_error_string(error)); } @@ -497,21 +554,291 @@ static void tcp_read(grpc_endpoint* ep, grpc_slice_buffer* incoming_buffer, grpc_slice_buffer_reset_and_unref_internal(incoming_buffer); grpc_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer); TCP_REF(tcp, "read"); - if (tcp->finished_edge) { - tcp->finished_edge = false; + if (tcp->is_first_read) { + /* Endpoint read called for the very first time. Register read callback with + * the polling engine */ + tcp->is_first_read = false; notify_on_read(tcp); } else { + /* Not the first time. We may or may not have more bytes available. In any + * case call tcp->read_done_closure (i.e tcp_handle_read()) which does the + * right thing (i.e calls tcp_do_read() which either reads the available + * bytes or calls notify_on_read() to be notified when new bytes become + * available */ GRPC_CLOSURE_SCHED(&tcp->read_done_closure, GRPC_ERROR_NONE); } } +/* A wrapper around sendmsg. It sends \a msg over \a fd and returns the number + * of bytes sent. */ +ssize_t tcp_send(int fd, const struct msghdr* msg) { + GPR_TIMER_SCOPE("sendmsg", 1); + ssize_t sent_length; + do { + /* TODO(klempner): Cork if this is a partial write */ + GRPC_STATS_INC_SYSCALL_WRITE(); + sent_length = sendmsg(fd, msg, SENDMSG_FLAGS); + } while (sent_length < 0 && errno == EINTR); + return sent_length; +} + +/** This is to be called if outgoing_buffer_arg is not null. On linux platforms, + * this will call sendmsg with socket options set to collect timestamps inside + * the kernel. On return, sent_length is set to the return value of the sendmsg + * call. Returns false if setting the socket options failed. This is not + * implemented for non-linux platforms currently, and crashes out. + */ +static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, + size_t sending_length, + ssize_t* sent_length); + +/** The callback function to be invoked when we get an error on the socket. */ +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error); + +#ifdef GRPC_LINUX_ERRQUEUE + +static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, + size_t sending_length, + ssize_t* sent_length) { + if (!tcp->socket_ts_enabled) { + uint32_t opt = grpc_core::kTimestampingSocketOptions; + if (setsockopt(tcp->fd, SOL_SOCKET, SO_TIMESTAMPING, + static_cast(&opt), sizeof(opt)) != 0) { + grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Failed to set timestamping options on the socket."); + } + return false; + } + tcp->bytes_counter = -1; + tcp->socket_ts_enabled = true; + } + /* Set control message to indicate that you want timestamps. */ + union { + char cmsg_buf[CMSG_SPACE(sizeof(uint32_t))]; + struct cmsghdr align; + } u; + cmsghdr* cmsg = reinterpret_cast(u.cmsg_buf); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPING; + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); + *reinterpret_cast(CMSG_DATA(cmsg)) = + grpc_core::kTimestampingRecordingOptions; + msg->msg_control = u.cmsg_buf; + msg->msg_controllen = CMSG_SPACE(sizeof(uint32_t)); + + /* If there was an error on sendmsg the logic in tcp_flush will handle it. */ + ssize_t length = tcp_send(tcp->fd, msg); + *sent_length = length; + /* Only save timestamps if all the bytes were taken by sendmsg. */ + if (sending_length == static_cast(length)) { + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::AddNewEntry( + &tcp->tb_head, static_cast(tcp->bytes_counter + length), + tcp->fd, tcp->outgoing_buffer_arg); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; + } + return true; +} + +/** Reads \a cmsg to derive timestamps from the control messages. If a valid + * timestamp is found, the traced buffer list is updated with this timestamp. + * The caller of this function should be looping on the control messages found + * in \a msg. \a cmsg should point to the control message that the caller wants + * processed. + * On return, a pointer to a control message is returned. On the next iteration, + * CMSG_NXTHDR(msg, ret_val) should be passed as \a cmsg. */ +struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg, + struct cmsghdr* cmsg) { + auto next_cmsg = CMSG_NXTHDR(msg, cmsg); + cmsghdr* opt_stats = nullptr; + if (next_cmsg == nullptr) { + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Received timestamp without extended error"); + } + return cmsg; + } + + /* Check if next_cmsg is an OPT_STATS msg */ + if (next_cmsg->cmsg_level == SOL_SOCKET && + next_cmsg->cmsg_type == SCM_TIMESTAMPING_OPT_STATS) { + opt_stats = next_cmsg; + next_cmsg = CMSG_NXTHDR(msg, opt_stats); + if (next_cmsg == nullptr) { + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Received timestamp without extended error"); + } + return opt_stats; + } + } + + if (!(next_cmsg->cmsg_level == SOL_IP || next_cmsg->cmsg_level == SOL_IPV6) || + !(next_cmsg->cmsg_type == IP_RECVERR || + next_cmsg->cmsg_type == IPV6_RECVERR)) { + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Unexpected control message"); + } + return cmsg; + } + + auto tss = + reinterpret_cast(CMSG_DATA(cmsg)); + auto serr = reinterpret_cast(CMSG_DATA(next_cmsg)); + if (serr->ee_errno != ENOMSG || + serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) { + gpr_log(GPR_ERROR, "Unexpected control message"); + return cmsg; + } + /* The error handling can potentially be done on another thread so we need + * to protect the traced buffer list. A lock free list might be better. Using + * a simple mutex for now. */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::ProcessTimestamp(&tcp->tb_head, serr, opt_stats, + tss); + gpr_mu_unlock(&tcp->tb_mu); + return next_cmsg; +} + +/** For linux platforms, reads the socket's error queue and processes error + * messages from the queue. + */ +static void process_errors(grpc_tcp* tcp) { + while (true) { + struct iovec iov; + iov.iov_base = nullptr; + iov.iov_len = 0; + struct msghdr msg; + msg.msg_name = nullptr; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 0; + msg.msg_flags = 0; + + /* Allocate enough space so we don't need to keep increasing this as size + * of OPT_STATS increase */ + constexpr size_t cmsg_alloc_space = + CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + + CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) + + CMSG_SPACE(32 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t))); + /* Allocate aligned space for cmsgs received along with timestamps */ + union { + char rbuf[cmsg_alloc_space]; + struct cmsghdr align; + } aligned_buf; + memset(&aligned_buf, 0, sizeof(aligned_buf)); + + msg.msg_control = aligned_buf.rbuf; + msg.msg_controllen = sizeof(aligned_buf.rbuf); + + int r, saved_errno; + do { + r = recvmsg(tcp->fd, &msg, MSG_ERRQUEUE); + saved_errno = errno; + } while (r < 0 && saved_errno == EINTR); + + if (r == -1 && saved_errno == EAGAIN) { + return; /* No more errors to process */ + } + if (r == -1) { + return; + } + if ((msg.msg_flags & MSG_CTRUNC) == 1) { + gpr_log(GPR_ERROR, "Error message was truncated."); + } + + if (msg.msg_controllen == 0) { + /* There was no control message found. It was probably spurious. */ + return; + } + bool seen = false; + for (auto cmsg = CMSG_FIRSTHDR(&msg); cmsg && cmsg->cmsg_len; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_TIMESTAMPING) { + /* Got a control message that is not a timestamp. Don't know how to + * handle this. */ + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, + "unknown control message cmsg_level:%d cmsg_type:%d", + cmsg->cmsg_level, cmsg->cmsg_type); + } + return; + } + cmsg = process_timestamp(tcp, &msg, cmsg); + seen = true; + } + if (!seen) { + return; + } + } +} + +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { + grpc_tcp* tcp = static_cast(arg); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, grpc_error_string(error)); + } + + if (error != GRPC_ERROR_NONE || + static_cast(gpr_atm_acq_load(&tcp->stop_error_notification))) { + /* We aren't going to register to hear on error anymore, so it is safe to + * unref. */ + TCP_UNREF(tcp, "error-tracking"); + return; + } + + /* We are still interested in collecting timestamps, so let's try reading + * them. */ + process_errors(tcp); + /* This might not a timestamps error. Set the read and write closures to be + * ready. */ + grpc_fd_set_readable(tcp->em_fd); + grpc_fd_set_writable(tcp->em_fd); + GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure); +} + +#else /* GRPC_LINUX_ERRQUEUE */ +static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, + size_t sending_length, + ssize_t* sent_length) { + gpr_log(GPR_ERROR, "Write with timestamps not supported for this platform"); + GPR_ASSERT(0); + return false; +} + +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { + gpr_log(GPR_ERROR, "Error handling is not supported for this platform"); + GPR_ASSERT(0); +} +#endif /* GRPC_LINUX_ERRQUEUE */ + +/* If outgoing_buffer_arg is filled, shuts down the list early, so that any + * release operations needed can be performed on the arg */ +void tcp_shutdown_buffer_list(grpc_tcp* tcp) { + if (tcp->outgoing_buffer_arg) { + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("TracedBuffer list shutdown")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; + } +} + /* returns true if done, false if pending; if returning true, *error is set */ +#if defined(IOV_MAX) && IOV_MAX < 1000 +#define MAX_WRITE_IOVEC IOV_MAX +#else #define MAX_WRITE_IOVEC 1000 +#endif static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; msg_iovlen_type iov_size; - ssize_t sent_length; + ssize_t sent_length = 0; size_t sending_length; size_t trailing; size_t unwind_slice_idx; @@ -545,19 +872,28 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = iov_size; - msg.msg_control = nullptr; - msg.msg_controllen = 0; msg.msg_flags = 0; + bool tried_sending_message = false; + if (tcp->outgoing_buffer_arg != nullptr) { + if (!tcp->ts_capable || + !tcp_write_with_timestamps(tcp, &msg, sending_length, &sent_length)) { + /* We could not set socket options to collect Fathom timestamps. + * Fallback on writing without timestamps. */ + tcp->ts_capable = false; + tcp_shutdown_buffer_list(tcp); + } else { + tried_sending_message = true; + } + } + if (!tried_sending_message) { + msg.msg_control = nullptr; + msg.msg_controllen = 0; - GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length); - GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size); + GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length); + GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size); - GPR_TIMER_SCOPE("sendmsg", 1); - do { - /* TODO(klempner): Cork if this is a partial write */ - GRPC_STATS_INC_SYSCALL_WRITE(); - sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS); - } while (sent_length < 0 && errno == EINTR); + sent_length = tcp_send(tcp->fd, &msg); + } if (sent_length < 0) { if (errno == EAGAIN) { @@ -572,15 +908,18 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { } else if (errno == EPIPE) { *error = tcp_annotate_error(GRPC_OS_ERROR(errno, "sendmsg"), tcp); grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); + tcp_shutdown_buffer_list(tcp); return true; } else { *error = tcp_annotate_error(GRPC_OS_ERROR(errno, "sendmsg"), tcp); grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); + tcp_shutdown_buffer_list(tcp); return true; } } GPR_ASSERT(tcp->outgoing_byte_idx == 0); + tcp->bytes_counter += sent_length; trailing = sending_length - static_cast(sent_length); while (trailing > 0) { size_t slice_length; @@ -595,7 +934,6 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { trailing -= slice_length; } } - if (outgoing_slice_idx == tcp->outgoing_buffer->count) { *error = GRPC_ERROR_NONE; grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); @@ -628,14 +966,13 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) { const char* str = grpc_error_string(error); gpr_log(GPR_INFO, "write: %s", str); } - - GRPC_CLOSURE_RUN(cb, error); + GRPC_CLOSURE_SCHED(cb, error); TCP_UNREF(tcp, "write"); } } static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { GPR_TIMER_SCOPE("tcp_write", 0); grpc_tcp* tcp = reinterpret_cast(ep); grpc_error* error = GRPC_ERROR_NONE; @@ -644,25 +981,33 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, size_t i; for (i = 0; i < buf->count; i++) { - char* data = - grpc_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); - gpr_free(data); + gpr_log(GPR_INFO, "WRITE %p (peer=%s)", tcp, tcp->peer_string); + if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + char* data = + grpc_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "DATA: %s", data); + gpr_free(data); + } } } GPR_ASSERT(tcp->write_cb == nullptr); + tcp->outgoing_buffer_arg = arg; if (buf->length == 0) { GRPC_CLOSURE_SCHED( cb, grpc_fd_is_shutdown(tcp->em_fd) ? tcp_annotate_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("EOF"), tcp) : GRPC_ERROR_NONE); + tcp_shutdown_buffer_list(tcp); return; } tcp->outgoing_buffer = buf; tcp->outgoing_byte_idx = 0; + if (arg) { + GPR_ASSERT(grpc_event_engine_can_track_errors()); + } if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); @@ -712,6 +1057,22 @@ static grpc_resource_user* tcp_get_resource_user(grpc_endpoint* ep) { return tcp->resource_user; } +static bool tcp_can_track_err(grpc_endpoint* ep) { + grpc_tcp* tcp = reinterpret_cast(ep); + if (!grpc_event_engine_can_track_errors()) { + return false; + } + struct sockaddr addr; + socklen_t len = sizeof(addr); + if (getsockname(tcp->fd, &addr, &len) < 0) { + return false; + } + if (addr.sa_family == AF_INET || addr.sa_family == AF_INET6) { + return true; + } + return false; +} + static const grpc_endpoint_vtable vtable = {tcp_read, tcp_write, tcp_add_to_pollset, @@ -721,7 +1082,8 @@ static const grpc_endpoint_vtable vtable = {tcp_read, tcp_destroy, tcp_get_resource_user, tcp_get_peer, - tcp_get_fd}; + tcp_get_fd, + tcp_can_track_err}; #define MAX_CHUNK_SIZE 32 * 1024 * 1024 @@ -778,7 +1140,12 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd, tcp->min_read_chunk_size = tcp_min_read_chunk_size; tcp->max_read_chunk_size = tcp_max_read_chunk_size; tcp->bytes_read_this_round = 0; - tcp->finished_edge = true; + /* Will be set to false by the very first endpoint read function */ + tcp->is_first_read = true; + tcp->bytes_counter = -1; + tcp->socket_ts_enabled = false; + tcp->ts_capable = true; + tcp->outgoing_buffer_arg = nullptr; /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); @@ -787,9 +1154,20 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd, tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); grpc_resource_user_slice_allocator_init( &tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp); - /* Tell network status tracker about new endpoint */ - grpc_network_status_register_endpoint(&tcp->base); grpc_resource_quota_unref_internal(resource_quota); + gpr_mu_init(&tcp->tb_mu); + tcp->tb_head = nullptr; + /* Start being notified on errors if event engine can track errors. */ + if (grpc_event_engine_can_track_errors()) { + /* Grab a ref to tcp so that we can safely access the tcp struct when + * processing errors. We unref when we no longer want to track errors + * separately. */ + TCP_REF(tcp, "error-tracking"); + gpr_atm_rel_store(&tcp->stop_error_notification, 0); + GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure); + } return &tcp->base; } @@ -802,13 +1180,17 @@ int grpc_tcp_fd(grpc_endpoint* ep) { void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, grpc_closure* done) { - grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = reinterpret_cast(ep); GPR_ASSERT(ep->vtable == &vtable); tcp->release_fd = fd; tcp->release_fd_cb = done; grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); + if (grpc_event_engine_can_track_errors()) { + /* Stop errors notification. */ + gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); + grpc_fd_set_error(tcp->em_fd); + } TCP_UNREF(tcp, "destroy"); } -#endif +#endif /* GRPC_POSIX_SOCKET_TCP */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.h b/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.h index af89bd24d..eff825cb9 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.h +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_posix.h @@ -31,7 +31,10 @@ #include +#include "src/core/lib/iomgr/port.h" + #include "src/core/lib/debug/trace.h" +#include "src/core/lib/iomgr/buffer_list.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/ev_posix.h" diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_server_posix.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_server_posix.cc index 524beba9a..824db07fb 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_server_posix.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_server_posix.cc @@ -25,7 +25,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_TCP_SERVER #include "src/core/lib/iomgr/tcp_server.h" @@ -150,7 +150,7 @@ static void deactivated_all_ports(grpc_tcp_server* s) { GRPC_CLOSURE_INIT(&sp->destroyed_closure, destroyed_port, s, grpc_schedule_on_exec_ctx); grpc_fd_orphan(sp->emfd, &sp->destroyed_closure, nullptr, - false /* already_closed */, "tcp_listener_shutdown"); + "tcp_listener_shutdown"); } gpr_mu_unlock(&s->mu); } else { @@ -187,11 +187,6 @@ static void on_read(void* arg, grpc_error* err) { goto error; } - read_notifier_pollset = - sp->server->pollsets[static_cast(gpr_atm_no_barrier_fetch_add( - &sp->server->next_pollset_to_assign, 1)) % - sp->server->pollset_count]; - /* loop until accept4 returns EAGAIN, and then re-arm notification */ for (;;) { grpc_resolved_address addr; @@ -231,7 +226,12 @@ static void on_read(void* arg, grpc_error* err) { gpr_log(GPR_INFO, "SERVER_CONNECT: incoming connection: %s", addr_str); } - grpc_fd* fdobj = grpc_fd_create(fd, name); + grpc_fd* fdobj = grpc_fd_create(fd, name, true); + + read_notifier_pollset = + sp->server->pollsets[static_cast(gpr_atm_no_barrier_fetch_add( + &sp->server->next_pollset_to_assign, 1)) % + sp->server->pollset_count]; grpc_pollset_add_fd(read_notifier_pollset, fdobj); @@ -346,7 +346,8 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) { err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode, &fd); if (err != GRPC_ERROR_NONE) return err; - err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port); + err = grpc_tcp_server_prepare_socket(listener->server, fd, &listener->addr, + true, &port); if (err != GRPC_ERROR_NONE) return err; listener->server->nports++; grpc_sockaddr_to_string(&addr_str, &listener->addr, 1); @@ -361,7 +362,7 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) { listener->sibling = sp; sp->server = listener->server; sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name); + sp->emfd = grpc_fd_create(fd, name, true); memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address)); sp->port = port; sp->port_index = listener->port_index; @@ -558,4 +559,4 @@ grpc_tcp_server_vtable grpc_posix_tcp_server_vtable = { tcp_server_shutdown_starting_add, tcp_server_unref, tcp_server_shutdown_listeners}; -#endif +#endif /* GRPC_POSIX_SOCKET_TCP_SERVER */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix.h b/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix.h index 34d68130c..dd199097b 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix.h +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix.h @@ -113,7 +113,7 @@ grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, int* out_port); /* Prepare a recently-created socket for listening. */ -grpc_error* grpc_tcp_server_prepare_socket(int fd, +grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server*, int fd, const grpc_resolved_address* addr, bool so_reuseport, int* port); /* Ruturn true if the platform supports ifaddrs */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index 9f4e58ca1..8d8d3f427 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#ifdef GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON #include "src/core/lib/iomgr/tcp_server_utils_posix.h" @@ -87,7 +87,7 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd, char* name; grpc_error* err = - grpc_tcp_server_prepare_socket(fd, addr, s->so_reuseport, &port); + grpc_tcp_server_prepare_socket(s, fd, addr, s->so_reuseport, &port); if (err == GRPC_ERROR_NONE) { GPR_ASSERT(port > 0); grpc_sockaddr_to_string(&addr_str, addr, 1); @@ -105,7 +105,7 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd, s->tail = sp; sp->server = s; sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name); + sp->emfd = grpc_fd_create(fd, name, true); memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); sp->port = port; sp->port_index = port_index; @@ -144,7 +144,7 @@ grpc_error* grpc_tcp_server_add_addr(grpc_tcp_server* s, } /* Prepare a recently-created socket for listening. */ -grpc_error* grpc_tcp_server_prepare_socket(int fd, +grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, const grpc_resolved_address* addr, bool so_reuseport, int* port) { grpc_resolved_address sockname_temp; @@ -166,10 +166,25 @@ grpc_error* grpc_tcp_server_prepare_socket(int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_tcp_user_timeout(fd, s->channel_args, + false /* is_client */); + if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); if (err != GRPC_ERROR_NONE) goto error; + if (s->channel_args) { + for (size_t i = 0; i < s->channel_args->num_args; i++) { + if (0 == strcmp(s->channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) { + GPR_ASSERT(s->channel_args->args[i].type == GRPC_ARG_POINTER); + grpc_socket_mutator* mutator = static_cast( + s->channel_args->args[i].value.pointer.p); + err = grpc_set_socket_with_mutator(fd, mutator); + if (err != GRPC_ERROR_NONE) goto error; + } + } + } + if (bind(fd, reinterpret_cast(const_cast(addr->addr)), addr->len) < 0) { err = GRPC_OS_ERROR(errno, "bind"); @@ -205,4 +220,4 @@ grpc_error* grpc_tcp_server_prepare_socket(int fd, return ret; } -#endif /* GRPC_POSIX_SOCKET */ +#endif /* GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_uv.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_uv.cc index 8d0e4a5e7..e53ff472f 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_uv.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_uv.cc @@ -33,7 +33,6 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr_custom.h" -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/resolve_address_custom.h" #include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/tcp_custom.h" diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.cc b/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.cc index 5d316d477..43817c5a0 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.cc @@ -24,7 +24,6 @@ #include -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/sockaddr_windows.h" #include @@ -42,6 +41,7 @@ #include "src/core/lib/iomgr/tcp_windows.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" #if defined(__MSYS__) && defined(GPR_ARCH_64) /* Nasty workaround for nasty bug when using the 64 bits msys compiler @@ -53,7 +53,7 @@ extern grpc_core::TraceFlag grpc_tcp_trace; -static grpc_error* set_non_block(SOCKET sock) { +grpc_error* grpc_tcp_set_non_block(SOCKET sock) { int status; uint32_t param = 1; DWORD ret; @@ -90,7 +90,7 @@ static grpc_error* enable_loopback_fast_path(SOCKET sock) { grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { grpc_error* err; - err = set_non_block(sock); + err = grpc_tcp_set_non_block(sock); if (err != GRPC_ERROR_NONE) return err; err = set_dualstack(sock); if (err != GRPC_ERROR_NONE) return err; @@ -112,7 +112,10 @@ typedef struct grpc_tcp { grpc_closure* read_cb; grpc_closure* write_cb; - grpc_slice read_slice; + + /* garbage after the last read */ + grpc_slice_buffer last_read_buffer; + grpc_slice_buffer* write_slices; grpc_slice_buffer* read_slices; @@ -131,6 +134,7 @@ static void tcp_free(grpc_tcp* tcp) { grpc_winsocket_destroy(tcp->socket); gpr_mu_destroy(&tcp->mu); gpr_free(tcp->peer_string); + grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error); gpr_free(tcp); @@ -179,9 +183,12 @@ static void on_read(void* tcpp, grpc_error* error) { grpc_tcp* tcp = (grpc_tcp*)tcpp; grpc_closure* cb = tcp->read_cb; grpc_winsocket* socket = tcp->socket; - grpc_slice sub; grpc_winsocket_callback_info* info = &socket->read_info; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p on_read", tcp); + } + GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE) { @@ -189,13 +196,35 @@ static void on_read(void* tcpp, grpc_error* error) { char* utf8_message = gpr_format_message(info->wsa_error); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(utf8_message); gpr_free(utf8_message); - grpc_slice_unref_internal(tcp->read_slice); + grpc_slice_buffer_reset_and_unref_internal(tcp->read_slices); } else { if (info->bytes_transfered != 0 && !tcp->shutting_down) { - sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - grpc_slice_buffer_add(tcp->read_slices, sub); + GPR_ASSERT((size_t)info->bytes_transfered <= tcp->read_slices->length); + if (static_cast(info->bytes_transfered) != + tcp->read_slices->length) { + grpc_slice_buffer_trim_end( + tcp->read_slices, + tcp->read_slices->length - + static_cast(info->bytes_transfered), + &tcp->last_read_buffer); + } + GPR_ASSERT((size_t)info->bytes_transfered == tcp->read_slices->length); + + if (grpc_tcp_trace.enabled()) { + size_t i; + for (i = 0; i < tcp->read_slices->count; i++) { + char* dump = grpc_dump_slice(tcp->read_slices->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, + dump); + gpr_free(dump); + } + } } else { - grpc_slice_unref_internal(tcp->read_slice); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p unref read_slice", tcp); + } + grpc_slice_buffer_reset_and_unref_internal(tcp->read_slices); error = tcp->shutting_down ? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "TCP stream shutting down", &tcp->shutdown_error, 1) @@ -209,6 +238,8 @@ static void on_read(void* tcpp, grpc_error* error) { GRPC_CLOSURE_SCHED(cb, error); } +#define DEFAULT_TARGET_READ_SIZE 8192 +#define MAX_WSABUF_COUNT 16 static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, grpc_closure* cb) { grpc_tcp* tcp = (grpc_tcp*)ep; @@ -217,7 +248,12 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, int status; DWORD bytes_read = 0; DWORD flags = 0; - WSABUF buffer; + WSABUF buffers[MAX_WSABUF_COUNT]; + size_t i; + + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p win_read", tcp); + } if (tcp->shutting_down) { GRPC_CLOSURE_SCHED( @@ -229,18 +265,27 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, tcp->read_cb = cb; tcp->read_slices = read_slices; grpc_slice_buffer_reset_and_unref_internal(read_slices); + grpc_slice_buffer_swap(read_slices, &tcp->last_read_buffer); - tcp->read_slice = GRPC_SLICE_MALLOC(8192); + if (tcp->read_slices->length < DEFAULT_TARGET_READ_SIZE / 2 && + tcp->read_slices->count < MAX_WSABUF_COUNT) { + // TODO(jtattermusch): slice should be allocated using resource quota + grpc_slice_buffer_add(tcp->read_slices, + GRPC_SLICE_MALLOC(DEFAULT_TARGET_READ_SIZE)); + } - buffer.len = (ULONG)GRPC_SLICE_LENGTH( - tcp->read_slice); // we know slice size fits in 32bit. - buffer.buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slice); + GPR_ASSERT(tcp->read_slices->count <= MAX_WSABUF_COUNT); + for (i = 0; i < tcp->read_slices->count; i++) { + buffers[i].len = (ULONG)GRPC_SLICE_LENGTH( + tcp->read_slices->slices[i]); // we know slice size fits in 32bit. + buffers[i].buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slices->slices[i]); + } TCP_REF(tcp, "read"); /* First let's try a synchronous, non-blocking read. */ - status = - WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL); + status = WSARecv(tcp->socket->socket, buffers, (DWORD)tcp->read_slices->count, + &bytes_read, &flags, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); /* Did we get data immediately ? Yay. */ @@ -252,8 +297,8 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, /* Otherwise, let's retry, by queuing a read. */ memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, - &info->overlapped, NULL); + status = WSARecv(tcp->socket->socket, buffers, (DWORD)tcp->read_slices->count, + &bytes_read, &flags, &info->overlapped, NULL); if (status != 0) { int wsa_error = WSAGetLastError(); @@ -275,6 +320,10 @@ static void on_write(void* tcpp, grpc_error* error) { grpc_winsocket_callback_info* info = &handle->write_info; grpc_closure* cb; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p on_write", tcp); + } + GRPC_ERROR_REF(error); gpr_mu_lock(&tcp->mu); @@ -296,18 +345,28 @@ static void on_write(void* tcpp, grpc_error* error) { /* Initiates a write. */ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { grpc_tcp* tcp = (grpc_tcp*)ep; grpc_winsocket* socket = tcp->socket; grpc_winsocket_callback_info* info = &socket->write_info; unsigned i; DWORD bytes_sent; int status; - WSABUF local_buffers[16]; + WSABUF local_buffers[MAX_WSABUF_COUNT]; WSABUF* allocated = NULL; WSABUF* buffers = local_buffers; size_t len; + if (grpc_tcp_trace.enabled()) { + size_t i; + for (i = 0; i < slices->count; i++) { + char* data = + grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); + gpr_free(data); + } + } + if (tcp->shutting_down) { GRPC_CLOSURE_SCHED( cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( @@ -410,8 +469,8 @@ static void win_shutdown(grpc_endpoint* ep, grpc_error* why) { } static void win_destroy(grpc_endpoint* ep) { - grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = (grpc_tcp*)ep; + grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); TCP_UNREF(tcp, "destroy"); } @@ -427,6 +486,8 @@ static grpc_resource_user* win_get_resource_user(grpc_endpoint* ep) { static int win_get_fd(grpc_endpoint* ep) { return -1; } +static bool win_can_track_err(grpc_endpoint* ep) { return false; } + static grpc_endpoint_vtable vtable = {win_read, win_write, win_add_to_pollset, @@ -436,7 +497,8 @@ static grpc_endpoint_vtable vtable = {win_read, win_destroy, win_get_resource_user, win_get_peer, - win_get_fd}; + win_get_fd, + win_can_track_err}; grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, grpc_channel_args* channel_args, @@ -460,9 +522,8 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, GRPC_CLOSURE_INIT(&tcp->on_read, on_read, tcp, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&tcp->on_write, on_write, tcp, grpc_schedule_on_exec_ctx); tcp->peer_string = gpr_strdup(peer_string); + grpc_slice_buffer_init(&tcp->last_read_buffer); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); - /* Tell network status tracking code about the new endpoint */ - grpc_network_status_register_endpoint(&tcp->base); grpc_resource_quota_unref_internal(resource_quota); return &tcp->base; diff --git a/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.h b/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.h index 161a545a2..04ef8102b 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.h +++ b/Sources/CgRPC/src/core/lib/iomgr/tcp_windows.h @@ -46,6 +46,8 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, grpc_error* grpc_tcp_prepare_socket(SOCKET sock); +grpc_error* grpc_tcp_set_non_block(SOCKET sock); + #endif #endif /* GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/timer.h b/Sources/CgRPC/src/core/lib/iomgr/timer.h index 5ff10d3ae..17e933b86 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/timer.h +++ b/Sources/CgRPC/src/core/lib/iomgr/timer.h @@ -28,7 +28,7 @@ #include "src/core/lib/iomgr/iomgr.h" typedef struct grpc_timer { - gpr_atm deadline; + grpc_millis deadline; uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */ bool pending; struct grpc_timer* next; @@ -61,10 +61,11 @@ typedef struct grpc_timer_vtable { /* Initialize *timer. When expired or canceled, closure will be called with error set to indicate if it expired (GRPC_ERROR_NONE) or was canceled - (GRPC_ERROR_CANCELLED). timer_cb is guaranteed to be called exactly once, and + (GRPC_ERROR_CANCELLED). *closure is guaranteed to be called exactly once, and application code should check the error to determine how it was invoked. The application callback is also responsible for maintaining information about - when to free up any user-level state. */ + when to free up any user-level state. Behavior is undefined for a deadline of + GRPC_MILLIS_INF_FUTURE. */ void grpc_timer_init(grpc_timer* timer, grpc_millis deadline, grpc_closure* closure); diff --git a/Sources/CgRPC/src/core/lib/iomgr/timer_generic.cc b/Sources/CgRPC/src/core/lib/iomgr/timer_generic.cc index de2256f7c..6a925add8 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/timer_generic.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/timer_generic.cc @@ -34,6 +34,7 @@ #include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/time_averaged_stats.h" #include "src/core/lib/iomgr/timer_heap.h" @@ -47,22 +48,22 @@ grpc_core::TraceFlag grpc_timer_trace(false, "timer"); grpc_core::TraceFlag grpc_timer_check_trace(false, "timer_check"); /* A "timer shard". Contains a 'heap' and a 'list' of timers. All timers with - * deadlines earlier than 'queue_deadline" cap are maintained in the heap and + * deadlines earlier than 'queue_deadline_cap' are maintained in the heap and * others are maintained in the list (unordered). This helps to keep the number * of elements in the heap low. * * The 'queue_deadline_cap' gets recomputed periodically based on the timer * stats maintained in 'stats' and the relevant timers are then moved from the - * 'list' to 'heap' + * 'list' to 'heap'. */ typedef struct { gpr_mu mu; grpc_time_averaged_stats stats; - /* All and only timers with deadlines <= this will be in the heap. */ - gpr_atm queue_deadline_cap; - /* The deadline of the next timer due in this shard */ - gpr_atm min_deadline; - /* Index of this timer_shard in the g_shard_queue */ + /* All and only timers with deadlines < this will be in the heap. */ + grpc_millis queue_deadline_cap; + /* The deadline of the next timer due in this shard. */ + grpc_millis min_deadline; + /* Index of this timer_shard in the g_shard_queue. */ uint32_t shard_queue_index; /* This holds all timers with deadlines < queue_deadline_cap. Timers in this list have the top bit of their deadline set to 0. */ @@ -84,7 +85,7 @@ static timer_shard** g_shard_queue; #ifndef NDEBUG -/* == Hash table for duplicate timer detection == */ +/* == DEBUG ONLY: hash table for duplicate timer detection == */ #define NUM_HASH_BUCKETS 1009 /* Prime number close to 1000 */ @@ -176,7 +177,7 @@ static void remove_from_ht(grpc_timer* t) { t->hash_table_next = nullptr; } -/* If a timer is added to a timer shard (either heap or a list), it cannot +/* If a timer is added to a timer shard (either heap or a list), it must * be pending. A timer is added to hash table only-if it is added to the * timer shard. * Therefore, if timer->pending is false, it cannot be in hash table */ @@ -209,15 +210,23 @@ static void validate_non_pending_timer(grpc_timer* t) { #endif +#if GPR_ARCH_64 +/* NOTE: TODO(sreek) - Currently the thread local storage support in grpc is + for intptr_t which means on 32-bit machines it is not wide enough to hold + grpc_millis which is 64-bit. Adding thread local support for 64 bit values + is a lot of work for very little gain. So we are currently restricting this + optimization to only 64 bit machines */ + /* Thread local variable that stores the deadline of the next timer the thread * has last-seen. This is an optimization to prevent the thread from checking * shared_mutables.min_timer (which requires acquiring shared_mutables.mu lock, * an expensive operation) */ GPR_TLS_DECL(g_last_seen_min_timer); +#endif struct shared_mutables { /* The deadline of the next timer due across all timer shards */ - gpr_atm min_timer; + grpc_millis min_timer; /* Allow only one run_some_expired_timers at once */ gpr_spinlock checker_mu; bool initialized; @@ -227,18 +236,18 @@ struct shared_mutables { static struct shared_mutables g_shared_mutables; -static gpr_atm saturating_add(gpr_atm a, gpr_atm b) { - if (a > GPR_ATM_MAX - b) { - return GPR_ATM_MAX; +static grpc_millis saturating_add(grpc_millis a, grpc_millis b) { + if (a > GRPC_MILLIS_INF_FUTURE - b) { + return GRPC_MILLIS_INF_FUTURE; } return a + b; } -static grpc_timer_check_result run_some_expired_timers(gpr_atm now, - gpr_atm* next, +static grpc_timer_check_result run_some_expired_timers(grpc_millis now, + grpc_millis* next, grpc_error* error); -static gpr_atm compute_min_deadline(timer_shard* shard) { +static grpc_millis compute_min_deadline(timer_shard* shard) { return grpc_timer_heap_is_empty(&shard->heap) ? saturating_add(shard->queue_deadline_cap, 1) : grpc_timer_heap_top(&shard->heap)->deadline; @@ -247,7 +256,7 @@ static gpr_atm compute_min_deadline(timer_shard* shard) { static void timer_list_init() { uint32_t i; - g_num_shards = GPR_MIN(1, 2 * gpr_cpu_num_cores()); + g_num_shards = GPR_CLAMP(2 * gpr_cpu_num_cores(), 1, 32); g_shards = static_cast(gpr_zalloc(g_num_shards * sizeof(*g_shards))); g_shard_queue = static_cast( @@ -257,8 +266,11 @@ static void timer_list_init() { g_shared_mutables.checker_mu = GPR_SPINLOCK_INITIALIZER; gpr_mu_init(&g_shared_mutables.mu); g_shared_mutables.min_timer = grpc_core::ExecCtx::Get()->Now(); + +#if GPR_ARCH_64 gpr_tls_init(&g_last_seen_min_timer); gpr_tls_set(&g_last_seen_min_timer, 0); +#endif for (i = 0; i < g_num_shards; i++) { timer_shard* shard = &g_shards[i]; @@ -279,7 +291,7 @@ static void timer_list_init() { static void timer_list_shutdown() { size_t i; run_some_expired_timers( - GPR_ATM_MAX, nullptr, + GRPC_MILLIS_INF_FUTURE, nullptr, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Timer list shutdown")); for (i = 0; i < g_num_shards; i++) { timer_shard* shard = &g_shards[i]; @@ -287,7 +299,11 @@ static void timer_list_shutdown() { grpc_timer_heap_destroy(&shard->heap); } gpr_mu_destroy(&g_shared_mutables.mu); + +#if GPR_ARCH_64 gpr_tls_destroy(&g_last_seen_min_timer); +#endif + gpr_free(g_shards); gpr_free(g_shard_queue); g_shared_mutables.initialized = false; @@ -346,7 +362,7 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline, #endif if (grpc_timer_trace.enabled()) { - gpr_log(GPR_INFO, "TIMER %p: SET %" PRIdPTR " now %" PRIdPTR " call %p[%p]", + gpr_log(GPR_INFO, "TIMER %p: SET %" PRId64 " now %" PRId64 " call %p[%p]", timer, deadline, grpc_core::ExecCtx::Get()->Now(), closure, closure->cb); } @@ -383,7 +399,7 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline, } if (grpc_timer_trace.enabled()) { gpr_log(GPR_INFO, - " .. add to shard %d with queue_deadline_cap=%" PRIdPTR + " .. add to shard %d with queue_deadline_cap=%" PRId64 " => is_first_timer=%s", static_cast(shard - g_shards), shard->queue_deadline_cap, is_first_timer ? "true" : "false"); @@ -404,15 +420,27 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline, if (is_first_timer) { gpr_mu_lock(&g_shared_mutables.mu); if (grpc_timer_trace.enabled()) { - gpr_log(GPR_INFO, " .. old shard min_deadline=%" PRIdPTR, + gpr_log(GPR_INFO, " .. old shard min_deadline=%" PRId64, shard->min_deadline); } if (deadline < shard->min_deadline) { - gpr_atm old_min_deadline = g_shard_queue[0]->min_deadline; + grpc_millis old_min_deadline = g_shard_queue[0]->min_deadline; shard->min_deadline = deadline; note_deadline_change(shard); if (shard->shard_queue_index == 0 && deadline < old_min_deadline) { - gpr_atm_no_barrier_store(&g_shared_mutables.min_timer, deadline); +#if GPR_ARCH_64 + // TODO: sreek - Using c-style cast here. static_cast<> gives an error + // (on mac platforms complaining that gpr_atm* is (long *) while + // (&g_shared_mutables.min_timer) is a (long long *). The cast should be + // safe since we know that both are pointer types and 64-bit wide. + gpr_atm_no_barrier_store((gpr_atm*)(&g_shared_mutables.min_timer), + deadline); +#else + // On 32-bit systems, gpr_atm_no_barrier_store does not work on 64-bit + // types (like grpc_millis). So all reads and writes to + // g_shared_mutables.min_timer varialbe under g_shared_mutables.mu + g_shared_mutables.min_timer = deadline; +#endif grpc_kick_poller(); } } @@ -421,8 +449,10 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline, } static void timer_consume_kick(void) { - /* force re-evaluation of last seeen min */ +#if GPR_ARCH_64 + /* Force re-evaluation of last seen min */ gpr_tls_set(&g_last_seen_min_timer, 0); +#endif } static void timer_cancel(grpc_timer* timer) { @@ -459,7 +489,7 @@ static void timer_cancel(grpc_timer* timer) { 'queue_deadline_cap') into into shard->heap. Returns 'true' if shard->heap has atleast ONE element REQUIRES: shard->mu locked */ -static int refill_heap(timer_shard* shard, gpr_atm now) { +static bool refill_heap(timer_shard* shard, grpc_millis now) { /* Compute the new queue window width and bound by the limits: */ double computed_deadline_delta = grpc_time_averaged_stats_update_average(&shard->stats) * @@ -472,10 +502,10 @@ static int refill_heap(timer_shard* shard, gpr_atm now) { /* Compute the new cap and put all timers under it into the queue: */ shard->queue_deadline_cap = saturating_add(GPR_MAX(now, shard->queue_deadline_cap), - static_cast(deadline_delta * 1000.0)); + static_cast(deadline_delta * 1000.0)); if (grpc_timer_check_trace.enabled()) { - gpr_log(GPR_INFO, " .. shard[%d]->queue_deadline_cap --> %" PRIdPTR, + gpr_log(GPR_INFO, " .. shard[%d]->queue_deadline_cap --> %" PRId64, static_cast(shard - g_shards), shard->queue_deadline_cap); } for (timer = shard->list.next; timer != &shard->list; timer = next) { @@ -483,7 +513,7 @@ static int refill_heap(timer_shard* shard, gpr_atm now) { if (timer->deadline < shard->queue_deadline_cap) { if (grpc_timer_check_trace.enabled()) { - gpr_log(GPR_INFO, " .. add timer with deadline %" PRIdPTR " to heap", + gpr_log(GPR_INFO, " .. add timer with deadline %" PRId64 " to heap", timer->deadline); } list_remove(timer); @@ -496,7 +526,7 @@ static int refill_heap(timer_shard* shard, gpr_atm now) { /* This pops the next non-cancelled timer with deadline <= now from the queue, or returns NULL if there isn't one. REQUIRES: shard->mu locked */ -static grpc_timer* pop_one(timer_shard* shard, gpr_atm now) { +static grpc_timer* pop_one(timer_shard* shard, grpc_millis now) { grpc_timer* timer; for (;;) { if (grpc_timer_check_trace.enabled()) { @@ -511,12 +541,12 @@ static grpc_timer* pop_one(timer_shard* shard, gpr_atm now) { timer = grpc_timer_heap_top(&shard->heap); if (grpc_timer_check_trace.enabled()) { gpr_log(GPR_INFO, - " .. check top timer deadline=%" PRIdPTR " now=%" PRIdPTR, + " .. check top timer deadline=%" PRId64 " now=%" PRId64, timer->deadline, now); } if (timer->deadline > now) return nullptr; if (grpc_timer_trace.enabled()) { - gpr_log(GPR_INFO, "TIMER %p: FIRE %" PRIdPTR "ms late via %s scheduler", + gpr_log(GPR_INFO, "TIMER %p: FIRE %" PRId64 "ms late via %s scheduler", timer, now - timer->deadline, timer->closure->scheduler->vtable->name); } @@ -527,8 +557,8 @@ static grpc_timer* pop_one(timer_shard* shard, gpr_atm now) { } /* REQUIRES: shard->mu unlocked */ -static size_t pop_timers(timer_shard* shard, gpr_atm now, - gpr_atm* new_min_deadline, grpc_error* error) { +static size_t pop_timers(timer_shard* shard, grpc_millis now, + grpc_millis* new_min_deadline, grpc_error* error) { size_t n = 0; grpc_timer* timer; gpr_mu_lock(&shard->mu); @@ -546,13 +576,27 @@ static size_t pop_timers(timer_shard* shard, gpr_atm now, return n; } -static grpc_timer_check_result run_some_expired_timers(gpr_atm now, - gpr_atm* next, +static grpc_timer_check_result run_some_expired_timers(grpc_millis now, + grpc_millis* next, grpc_error* error) { grpc_timer_check_result result = GRPC_TIMERS_NOT_CHECKED; - gpr_atm min_timer = gpr_atm_no_barrier_load(&g_shared_mutables.min_timer); +#if GPR_ARCH_64 + // TODO: sreek - Using c-style cast here. static_cast<> gives an error (on + // mac platforms complaining that gpr_atm* is (long *) while + // (&g_shared_mutables.min_timer) is a (long long *). The cast should be + // safe since we know that both are pointer types and 64-bit wide + grpc_millis min_timer = static_cast( + gpr_atm_no_barrier_load((gpr_atm*)(&g_shared_mutables.min_timer))); gpr_tls_set(&g_last_seen_min_timer, min_timer); +#else + // On 32-bit systems, gpr_atm_no_barrier_load does not work on 64-bit types + // (like grpc_millis). So all reads and writes to g_shared_mutables.min_timer + // are done under g_shared_mutables.mu + gpr_mu_lock(&g_shared_mutables.mu); + grpc_millis min_timer = g_shared_mutables.min_timer; + gpr_mu_unlock(&g_shared_mutables.mu); +#endif if (now < min_timer) { if (next != nullptr) *next = GPR_MIN(*next, min_timer); return GRPC_TIMERS_CHECKED_AND_EMPTY; @@ -563,14 +607,15 @@ static grpc_timer_check_result run_some_expired_timers(gpr_atm now, result = GRPC_TIMERS_CHECKED_AND_EMPTY; if (grpc_timer_check_trace.enabled()) { - gpr_log(GPR_INFO, " .. shard[%d]->min_deadline = %" PRIdPTR, + gpr_log(GPR_INFO, " .. shard[%d]->min_deadline = %" PRId64, static_cast(g_shard_queue[0] - g_shards), g_shard_queue[0]->min_deadline); } while (g_shard_queue[0]->min_deadline < now || - (now != GPR_ATM_MAX && g_shard_queue[0]->min_deadline == now)) { - gpr_atm new_min_deadline; + (now != GRPC_MILLIS_INF_FUTURE && + g_shard_queue[0]->min_deadline == now)) { + grpc_millis new_min_deadline; /* For efficiency, we pop as many available timers as we can from the shard. This may violate perfect timer deadline ordering, but that @@ -582,8 +627,8 @@ static grpc_timer_check_result run_some_expired_timers(gpr_atm now, if (grpc_timer_check_trace.enabled()) { gpr_log(GPR_INFO, " .. result --> %d" - ", shard[%d]->min_deadline %" PRIdPTR " --> %" PRIdPTR - ", now=%" PRIdPTR, + ", shard[%d]->min_deadline %" PRId64 " --> %" PRId64 + ", now=%" PRId64, result, static_cast(g_shard_queue[0] - g_shards), g_shard_queue[0]->min_deadline, new_min_deadline, now); } @@ -601,8 +646,19 @@ static grpc_timer_check_result run_some_expired_timers(gpr_atm now, *next = GPR_MIN(*next, g_shard_queue[0]->min_deadline); } - gpr_atm_no_barrier_store(&g_shared_mutables.min_timer, +#if GPR_ARCH_64 + // TODO: sreek - Using c-style cast here. static_cast<> gives an error (on + // mac platforms complaining that gpr_atm* is (long *) while + // (&g_shared_mutables.min_timer) is a (long long *). The cast should be + // safe since we know that both are pointer types and 64-bit wide + gpr_atm_no_barrier_store((gpr_atm*)(&g_shared_mutables.min_timer), g_shard_queue[0]->min_deadline); +#else + // On 32-bit systems, gpr_atm_no_barrier_store does not work on 64-bit + // types (like grpc_millis). So all reads and writes to + // g_shared_mutables.min_timer are done under g_shared_mutables.mu + g_shared_mutables.min_timer = g_shard_queue[0]->min_deadline; +#endif gpr_mu_unlock(&g_shared_mutables.mu); gpr_spinlock_unlock(&g_shared_mutables.checker_mu); } @@ -616,17 +672,28 @@ static grpc_timer_check_result timer_check(grpc_millis* next) { // prelude grpc_millis now = grpc_core::ExecCtx::Get()->Now(); +#if GPR_ARCH_64 /* fetch from a thread-local first: this avoids contention on a globally mutable cacheline in the common case */ grpc_millis min_timer = gpr_tls_get(&g_last_seen_min_timer); +#else + // On 32-bit systems, we currently do not have thread local support for 64-bit + // types. In this case, directly read from g_shared_mutables.min_timer. + // Also, note that on 32-bit systems, gpr_atm_no_barrier_store does not work + // on 64-bit types (like grpc_millis). So all reads and writes to + // g_shared_mutables.min_timer are done under g_shared_mutables.mu + gpr_mu_lock(&g_shared_mutables.mu); + grpc_millis min_timer = g_shared_mutables.min_timer; + gpr_mu_unlock(&g_shared_mutables.mu); +#endif + if (now < min_timer) { if (next != nullptr) { *next = GPR_MIN(*next, min_timer); } if (grpc_timer_check_trace.enabled()) { - gpr_log(GPR_INFO, - "TIMER CHECK SKIP: now=%" PRIdPTR " min_timer=%" PRIdPTR, now, - min_timer); + gpr_log(GPR_INFO, "TIMER CHECK SKIP: now=%" PRId64 " min_timer=%" PRId64, + now, min_timer); } return GRPC_TIMERS_CHECKED_AND_EMPTY; } @@ -642,13 +709,19 @@ static grpc_timer_check_result timer_check(grpc_millis* next) { if (next == nullptr) { next_str = gpr_strdup("NULL"); } else { - gpr_asprintf(&next_str, "%" PRIdPTR, *next); + gpr_asprintf(&next_str, "%" PRId64, *next); } +#if GPR_ARCH_64 gpr_log(GPR_INFO, - "TIMER CHECK BEGIN: now=%" PRIdPTR " next=%s tls_min=%" PRIdPTR - " glob_min=%" PRIdPTR, - now, next_str, gpr_tls_get(&g_last_seen_min_timer), - gpr_atm_no_barrier_load(&g_shared_mutables.min_timer)); + "TIMER CHECK BEGIN: now=%" PRId64 " next=%s tls_min=%" PRId64 + " glob_min=%" PRId64, + now, next_str, min_timer, + static_cast(gpr_atm_no_barrier_load( + (gpr_atm*)(&g_shared_mutables.min_timer)))); +#else + gpr_log(GPR_INFO, "TIMER CHECK BEGIN: now=%" PRId64 " next=%s min=%" PRId64, + now, next_str, min_timer); +#endif gpr_free(next_str); } // actual code @@ -660,7 +733,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) { if (next == nullptr) { next_str = gpr_strdup("NULL"); } else { - gpr_asprintf(&next_str, "%" PRIdPTR, *next); + gpr_asprintf(&next_str, "%" PRId64, *next); } gpr_log(GPR_INFO, "TIMER CHECK END: r=%d; next=%s", r, next_str); gpr_free(next_str); diff --git a/Sources/CgRPC/src/core/lib/iomgr/timer_heap.cc b/Sources/CgRPC/src/core/lib/iomgr/timer_heap.cc index 0c17d607e..2c6a59914 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/timer_heap.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/timer_heap.cc @@ -95,7 +95,7 @@ void grpc_timer_heap_init(grpc_timer_heap* heap) { void grpc_timer_heap_destroy(grpc_timer_heap* heap) { gpr_free(heap->timers); } -int grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer) { +bool grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer) { if (heap->timer_count == heap->timer_capacity) { heap->timer_capacity = GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2); @@ -122,7 +122,7 @@ void grpc_timer_heap_remove(grpc_timer_heap* heap, grpc_timer* timer) { note_changed_priority(heap, heap->timers[i]); } -int grpc_timer_heap_is_empty(grpc_timer_heap* heap) { +bool grpc_timer_heap_is_empty(grpc_timer_heap* heap) { return heap->timer_count == 0; } diff --git a/Sources/CgRPC/src/core/lib/iomgr/timer_heap.h b/Sources/CgRPC/src/core/lib/iomgr/timer_heap.h index 503365d4c..7b983e713 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/timer_heap.h +++ b/Sources/CgRPC/src/core/lib/iomgr/timer_heap.h @@ -29,8 +29,8 @@ typedef struct { uint32_t timer_capacity; } grpc_timer_heap; -/* return 1 if the new timer is the first timer in the heap */ -int grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer); +/* return true if the new timer is the first timer in the heap */ +bool grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer); void grpc_timer_heap_init(grpc_timer_heap* heap); void grpc_timer_heap_destroy(grpc_timer_heap* heap); @@ -39,6 +39,6 @@ void grpc_timer_heap_remove(grpc_timer_heap* heap, grpc_timer* timer); grpc_timer* grpc_timer_heap_top(grpc_timer_heap* heap); void grpc_timer_heap_pop(grpc_timer_heap* heap); -int grpc_timer_heap_is_empty(grpc_timer_heap* heap); +bool grpc_timer_heap_is_empty(grpc_timer_heap* heap); #endif /* GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H */ diff --git a/Sources/CgRPC/src/core/lib/iomgr/timer_manager.cc b/Sources/CgRPC/src/core/lib/iomgr/timer_manager.cc index 35e791456..4469db70d 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/timer_manager.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/timer_manager.cc @@ -61,6 +61,15 @@ static uint64_t g_timed_waiter_generation; static void timer_thread(void* completed_thread_ptr); +// For debug of the timer manager crash only. +// TODO (mxyan): remove after bug is fixed. +#ifdef GRPC_DEBUG_TIMER_MANAGER +extern int64_t g_timer_manager_init_count; +extern int64_t g_timer_manager_shutdown_count; +extern int64_t g_fork_count; +extern int64_t g_next_value; +#endif // GRPC_DEBUG_TIMER_MANAGER + static void gc_completed_threads(void) { if (g_completed_threads != nullptr) { completed_thread* to_gc = g_completed_threads; @@ -92,19 +101,29 @@ static void start_timer_thread_and_unlock(void) { void grpc_timer_manager_tick() { grpc_core::ExecCtx exec_ctx; - grpc_millis next = GRPC_MILLIS_INF_FUTURE; - grpc_timer_check(&next); + grpc_timer_check(nullptr); } static void run_some_timers() { + // In the case of timers, the ExecCtx for the thread is declared + // in the timer thread itself, but this is the point where we + // could start seeing application-level callbacks. No need to + // create a new ExecCtx, though, since there already is one and it is + // flushed (but not destructed) in this function itself + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx( + GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD); + // if there's something to execute... gpr_mu_lock(&g_mu); // remove a waiter from the pool, and start another thread if necessary --g_waiter_count; if (g_waiter_count == 0 && g_threaded) { + // The number of timer threads is always increasing until all the threads + // are stopped. In rare cases, if a large number of timers fire + // simultaneously, we may end up using a large number of threads. start_timer_thread_and_unlock(); } else { - // if there's no thread waiting with a timeout, kick an existing + // if there's no thread waiting with a timeout, kick an existing untimed // waiter so that the next deadline is not missed if (!g_has_timed_waiter) { if (grpc_timer_check_trace.enabled()) { @@ -172,7 +191,7 @@ static bool wait_until(grpc_millis next) { if (grpc_timer_check_trace.enabled()) { grpc_millis wait_time = next - grpc_core::ExecCtx::Get()->Now(); - gpr_log(GPR_INFO, "sleep for a %" PRIdPTR " milliseconds", wait_time); + gpr_log(GPR_INFO, "sleep for a %" PRId64 " milliseconds", wait_time); } } else { // g_timed_waiter == true && next >= g_timed_waiter_deadline next = GRPC_MILLIS_INF_FUTURE; @@ -183,6 +202,11 @@ static bool wait_until(grpc_millis next) { gpr_log(GPR_INFO, "sleep until kicked"); } + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. +#ifdef GRPC_DEBUG_TIMER_MANAGER + g_next_value = next; +#endif gpr_cv_wait(&g_cv_wait, &g_mu, grpc_millis_to_timespec(next, GPR_CLOCK_MONOTONIC)); @@ -235,7 +259,7 @@ static void timer_main_loop() { gpr_log(GPR_INFO, "timers not checked: expect another thread to"); } next = GRPC_MILLIS_INF_FUTURE; - /* fall through */ + // fallthrough case GRPC_TIMERS_CHECKED_AND_EMPTY: if (!wait_until(next)) { return; @@ -265,7 +289,7 @@ static void timer_thread_cleanup(completed_thread* ct) { static void timer_thread(void* completed_thread_ptr) { // this threads exec_ctx: we try to run things through to completion here // since it's easy to spin up new threads - grpc_core::ExecCtx exec_ctx(0); + grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD); timer_main_loop(); timer_thread_cleanup(static_cast(completed_thread_ptr)); @@ -277,7 +301,6 @@ static void start_threads(void) { g_threaded = true; start_timer_thread_and_unlock(); } else { - g_threaded = false; gpr_mu_unlock(&g_mu); } } @@ -285,6 +308,11 @@ static void start_threads(void) { void grpc_timer_manager_init(void) { gpr_mu_init(&g_mu); gpr_cv_init(&g_cv_wait); +#ifdef GRPC_DEBUG_TIMER_MANAGER + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. + g_timer_manager_init_count++; +#endif gpr_cv_init(&g_cv_shutdown); g_threaded = false; g_thread_count = 0; @@ -320,6 +348,11 @@ static void stop_threads(void) { } void grpc_timer_manager_shutdown(void) { +#ifdef GRPC_DEBUG_TIMER_MANAGER + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. + g_timer_manager_shutdown_count++; +#endif stop_threads(); gpr_mu_destroy(&g_mu); @@ -328,6 +361,11 @@ void grpc_timer_manager_shutdown(void) { } void grpc_timer_manager_set_threading(bool threaded) { +#ifdef GRPC_DEBUG_TIMER_MANAGER + // For debug of the timer manager crash only. + // TODO (mxyan): remove after bug is fixed. + g_fork_count++; +#endif if (threaded) { start_threads(); } else { diff --git a/Sources/CgRPC/src/core/lib/iomgr/timer_manager.h b/Sources/CgRPC/src/core/lib/iomgr/timer_manager.h index 3c4cdda2c..00dcdc461 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/timer_manager.h +++ b/Sources/CgRPC/src/core/lib/iomgr/timer_manager.h @@ -23,8 +23,8 @@ #include -/* Timer Manager tries to keep one thread waiting for the next timeout at all - times */ +/* Timer Manager tries to keep only one thread waiting for the next timeout at + all times, and thus effectively preventing the thundering herd problem. */ void grpc_timer_manager_init(void); void grpc_timer_manager_shutdown(void); diff --git a/Sources/CgRPC/src/core/lib/iomgr/udp_server.cc b/Sources/CgRPC/src/core/lib/iomgr/udp_server.cc index 51d17eb17..5f8865ca5 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/udp_server.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/udp_server.cc @@ -152,7 +152,7 @@ GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd, grpc_sockaddr_to_string(&addr_str, addr, 1); gpr_asprintf(&name, "udp-server-listener:%s", addr_str); gpr_free(addr_str); - emfd_ = grpc_fd_create(fd, name); + emfd_ = grpc_fd_create(fd, name, true); memcpy(&addr_, addr, sizeof(grpc_resolved_address)); GPR_ASSERT(emfd_); gpr_free(name); @@ -300,8 +300,7 @@ void GrpcUdpListener::OrphanFd() { grpc_schedule_on_exec_ctx); /* Because at this point, all listening sockets have been shutdown already, no * need to call OnFdAboutToOrphan() to notify the handler again. */ - grpc_fd_orphan(emfd_, &destroyed_closure_, nullptr, - false /* already_closed */, "udp_listener_shutdown"); + grpc_fd_orphan(emfd_, &destroyed_closure_, nullptr, "udp_listener_shutdown"); } void grpc_udp_server_destroy(grpc_udp_server* s, grpc_closure* on_done) { @@ -482,8 +481,9 @@ void GrpcUdpListener::OnRead(grpc_error* error, void* do_read_arg) { if (udp_handler_->Read()) { /* There maybe more packets to read. Schedule read_more_cb_ closure to run * after finishing this event loop. */ - GRPC_CLOSURE_INIT(&do_read_closure_, do_read, do_read_arg, - grpc_executor_scheduler(GRPC_EXECUTOR_LONG)); + GRPC_CLOSURE_INIT( + &do_read_closure_, do_read, do_read_arg, + grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::LONG)); GRPC_CLOSURE_SCHED(&do_read_closure_, GRPC_ERROR_NONE); } else { /* Finish reading all the packets, re-arm the notification event so we can @@ -543,8 +543,9 @@ void GrpcUdpListener::OnCanWrite(grpc_error* error, void* do_write_arg) { } /* Schedule actual write in another thread. */ - GRPC_CLOSURE_INIT(&do_write_closure_, do_write, do_write_arg, - grpc_executor_scheduler(GRPC_EXECUTOR_LONG)); + GRPC_CLOSURE_INIT( + &do_write_closure_, do_write, do_write_arg, + grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::LONG)); GRPC_CLOSURE_SCHED(&do_write_closure_, GRPC_ERROR_NONE); } diff --git a/Sources/CgRPC/src/core/lib/iomgr/wakeup_fd_eventfd.cc b/Sources/CgRPC/src/core/lib/iomgr/wakeup_fd_eventfd.cc index dcf7dab71..d68c9ada1 100644 --- a/Sources/CgRPC/src/core/lib/iomgr/wakeup_fd_eventfd.cc +++ b/Sources/CgRPC/src/core/lib/iomgr/wakeup_fd_eventfd.cc @@ -32,12 +32,11 @@ #include "src/core/lib/profiling/timers.h" static grpc_error* eventfd_create(grpc_wakeup_fd* fd_info) { - int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - if (efd < 0) { + fd_info->read_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + fd_info->write_fd = -1; + if (fd_info->read_fd < 0) { return GRPC_OS_ERROR(errno, "eventfd"); } - fd_info->read_fd = efd; - fd_info->write_fd = -1; return GRPC_ERROR_NONE; } diff --git a/Sources/CgRPC/src/core/lib/json/json.cc b/Sources/CgRPC/src/core/lib/json/json.cc index 816241bbf..2ed45fe55 100644 --- a/Sources/CgRPC/src/core/lib/json/json.cc +++ b/Sources/CgRPC/src/core/lib/json/json.cc @@ -18,10 +18,12 @@ #include +#include #include #include #include +#include #include "src/core/lib/json/json.h" @@ -33,29 +35,28 @@ grpc_json* grpc_json_create(grpc_json_type type) { } void grpc_json_destroy(grpc_json* json) { + if (json == nullptr) return; while (json->child) { grpc_json_destroy(json->child); } - if (json->next) { json->next->prev = json->prev; } - if (json->prev) { json->prev->next = json->next; } else if (json->parent) { json->parent->child = json->next; } - if (json->owns_value) { gpr_free((void*)json->value); } - gpr_free(json); } grpc_json* grpc_json_link_child(grpc_json* parent, grpc_json* child, grpc_json* sibling) { + // link child up to parent + child->parent = parent; // first child case. if (parent->child == nullptr) { GPR_ASSERT(sibling == nullptr); @@ -79,8 +80,15 @@ grpc_json* grpc_json_create_child(grpc_json* sibling, grpc_json* parent, grpc_json* child = grpc_json_create(type); grpc_json_link_child(parent, child, sibling); child->owns_value = owns_value; - child->parent = parent; child->value = value; child->key = key; return child; } + +grpc_json* grpc_json_add_number_string_child(grpc_json* parent, grpc_json* it, + const char* name, int64_t num) { + char* num_str; + gpr_asprintf(&num_str, "%" PRId64, num); + return grpc_json_create_child(it, parent, name, num_str, GRPC_JSON_STRING, + true); +} diff --git a/Sources/CgRPC/src/core/lib/json/json.h b/Sources/CgRPC/src/core/lib/json/json.h index f93b43048..8173845c7 100644 --- a/Sources/CgRPC/src/core/lib/json/json.h +++ b/Sources/CgRPC/src/core/lib/json/json.h @@ -91,4 +91,9 @@ grpc_json* grpc_json_create_child(grpc_json* sibling, grpc_json* parent, const char* key, const char* value, grpc_json_type type, bool owns_value); +/* Creates a child json string object from the integer num, then links the + json object into the parent's json tree */ +grpc_json* grpc_json_add_number_string_child(grpc_json* parent, grpc_json* it, + const char* name, int64_t num); + #endif /* GRPC_CORE_LIB_JSON_JSON_H */ diff --git a/Sources/CgRPC/src/core/lib/security/context/security_context.cc b/Sources/CgRPC/src/core/lib/security/context/security_context.cc index 14051a3f0..8443ee069 100644 --- a/Sources/CgRPC/src/core/lib/security/context/security_context.cc +++ b/Sources/CgRPC/src/core/lib/security/context/security_context.cc @@ -21,7 +21,10 @@ #include #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/arena.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" @@ -49,13 +52,11 @@ grpc_call_error grpc_call_set_credentials(grpc_call* call, ctx = static_cast( grpc_call_context_get(call, GRPC_CONTEXT_SECURITY)); if (ctx == nullptr) { - ctx = grpc_client_security_context_create(); - ctx->creds = grpc_call_credentials_ref(creds); + ctx = grpc_client_security_context_create(grpc_call_get_arena(call), creds); grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx, grpc_client_security_context_destroy); } else { - grpc_call_credentials_unref(ctx->creds); - ctx->creds = grpc_call_credentials_ref(creds); + ctx->creds = creds != nullptr ? creds->Ref() : nullptr; } return GRPC_CALL_OK; @@ -65,123 +66,83 @@ grpc_auth_context* grpc_call_auth_context(grpc_call* call) { void* sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY); GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call)); if (sec_ctx == nullptr) return nullptr; - return grpc_call_is_client(call) - ? GRPC_AUTH_CONTEXT_REF( - ((grpc_client_security_context*)sec_ctx)->auth_context, - "grpc_call_auth_context client") - : GRPC_AUTH_CONTEXT_REF( - ((grpc_server_security_context*)sec_ctx)->auth_context, - "grpc_call_auth_context server"); + if (grpc_call_is_client(call)) { + auto* sc = static_cast(sec_ctx); + if (sc->auth_context == nullptr) { + return nullptr; + } else { + return sc->auth_context + ->Ref(DEBUG_LOCATION, "grpc_call_auth_context client") + .release(); + } + } else { + auto* sc = static_cast(sec_ctx); + if (sc->auth_context == nullptr) { + return nullptr; + } else { + return sc->auth_context + ->Ref(DEBUG_LOCATION, "grpc_call_auth_context server") + .release(); + } + } } void grpc_auth_context_release(grpc_auth_context* context) { GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context)); - GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref"); + if (context == nullptr) return; + context->Unref(DEBUG_LOCATION, "grpc_auth_context_unref"); } /* --- grpc_client_security_context --- */ +grpc_client_security_context::~grpc_client_security_context() { + auth_context.reset(DEBUG_LOCATION, "client_security_context"); + if (extension.instance != nullptr && extension.destroy != nullptr) { + extension.destroy(extension.instance); + } +} -grpc_client_security_context* grpc_client_security_context_create(void) { - return static_cast( - gpr_zalloc(sizeof(grpc_client_security_context))); +grpc_client_security_context* grpc_client_security_context_create( + gpr_arena* arena, grpc_call_credentials* creds) { + return new (gpr_arena_alloc(arena, sizeof(grpc_client_security_context))) + grpc_client_security_context(creds != nullptr ? creds->Ref() : nullptr); } void grpc_client_security_context_destroy(void* ctx) { grpc_core::ExecCtx exec_ctx; grpc_client_security_context* c = static_cast(ctx); - grpc_call_credentials_unref(c->creds); - GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context"); - if (c->extension.instance != nullptr && c->extension.destroy != nullptr) { - c->extension.destroy(c->extension.instance); - } - gpr_free(ctx); + c->~grpc_client_security_context(); } /* --- grpc_server_security_context --- */ +grpc_server_security_context::~grpc_server_security_context() { + auth_context.reset(DEBUG_LOCATION, "server_security_context"); + if (extension.instance != nullptr && extension.destroy != nullptr) { + extension.destroy(extension.instance); + } +} -grpc_server_security_context* grpc_server_security_context_create(void) { - return static_cast( - gpr_zalloc(sizeof(grpc_server_security_context))); +grpc_server_security_context* grpc_server_security_context_create( + gpr_arena* arena) { + return new (gpr_arena_alloc(arena, sizeof(grpc_server_security_context))) + grpc_server_security_context(); } void grpc_server_security_context_destroy(void* ctx) { grpc_server_security_context* c = static_cast(ctx); - GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context"); - if (c->extension.instance != nullptr && c->extension.destroy != nullptr) { - c->extension.destroy(c->extension.instance); - } - gpr_free(ctx); + c->~grpc_server_security_context(); } /* --- grpc_auth_context --- */ static grpc_auth_property_iterator empty_iterator = {nullptr, 0, nullptr}; -grpc_auth_context* grpc_auth_context_create(grpc_auth_context* chained) { - grpc_auth_context* ctx = - static_cast(gpr_zalloc(sizeof(grpc_auth_context))); - gpr_ref_init(&ctx->refcount, 1); - if (chained != nullptr) { - ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained"); - ctx->peer_identity_property_name = - ctx->chained->peer_identity_property_name; - } - return ctx; -} - -#ifndef NDEBUG -grpc_auth_context* grpc_auth_context_ref(grpc_auth_context* ctx, - const char* file, int line, - const char* reason) { - if (ctx == nullptr) return nullptr; - if (grpc_trace_auth_context_refcount.enabled()) { - gpr_atm val = gpr_atm_no_barrier_load(&ctx->refcount.count); - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "AUTH_CONTEXT:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", ctx, val, - val + 1, reason); - } -#else -grpc_auth_context* grpc_auth_context_ref(grpc_auth_context* ctx) { - if (ctx == nullptr) return nullptr; -#endif - gpr_ref(&ctx->refcount); - return ctx; -} - -#ifndef NDEBUG -void grpc_auth_context_unref(grpc_auth_context* ctx, const char* file, int line, - const char* reason) { - if (ctx == nullptr) return; - if (grpc_trace_auth_context_refcount.enabled()) { - gpr_atm val = gpr_atm_no_barrier_load(&ctx->refcount.count); - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "AUTH_CONTEXT:%p unref %" PRIdPTR " -> %" PRIdPTR " %s", ctx, val, - val - 1, reason); - } -#else -void grpc_auth_context_unref(grpc_auth_context* ctx) { - if (ctx == nullptr) return; -#endif - if (gpr_unref(&ctx->refcount)) { - size_t i; - GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained"); - if (ctx->properties.array != nullptr) { - for (i = 0; i < ctx->properties.count; i++) { - grpc_auth_property_reset(&ctx->properties.array[i]); - } - gpr_free(ctx->properties.array); - } - gpr_free(ctx); - } -} - const char* grpc_auth_context_peer_identity_property_name( const grpc_auth_context* ctx) { GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1, (ctx)); - return ctx->peer_identity_property_name; + return ctx->peer_identity_property_name(); } int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context* ctx, @@ -197,13 +158,13 @@ int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context* ctx, name != nullptr ? name : "NULL"); return 0; } - ctx->peer_identity_property_name = prop->name; + ctx->set_peer_identity_property_name(prop->name); return 1; } int grpc_auth_context_peer_is_authenticated(const grpc_auth_context* ctx) { GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx)); - return ctx->peer_identity_property_name == nullptr ? 0 : 1; + return ctx->is_authenticated(); } grpc_auth_property_iterator grpc_auth_context_property_iterator( @@ -219,16 +180,17 @@ const grpc_auth_property* grpc_auth_property_iterator_next( grpc_auth_property_iterator* it) { GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it)); if (it == nullptr || it->ctx == nullptr) return nullptr; - while (it->index == it->ctx->properties.count) { - if (it->ctx->chained == nullptr) return nullptr; - it->ctx = it->ctx->chained; + while (it->index == it->ctx->properties().count) { + if (it->ctx->chained() == nullptr) return nullptr; + it->ctx = it->ctx->chained(); it->index = 0; } if (it->name == nullptr) { - return &it->ctx->properties.array[it->index++]; + return &it->ctx->properties().array[it->index++]; } else { - while (it->index < it->ctx->properties.count) { - const grpc_auth_property* prop = &it->ctx->properties.array[it->index++]; + while (it->index < it->ctx->properties().count) { + const grpc_auth_property* prop = + &it->ctx->properties().array[it->index++]; GPR_ASSERT(prop->name != nullptr); if (strcmp(it->name, prop->name) == 0) { return prop; @@ -255,49 +217,56 @@ grpc_auth_property_iterator grpc_auth_context_peer_identity( GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx)); if (ctx == nullptr) return empty_iterator; return grpc_auth_context_find_properties_by_name( - ctx, ctx->peer_identity_property_name); + ctx, ctx->peer_identity_property_name()); } -static void ensure_auth_context_capacity(grpc_auth_context* ctx) { - if (ctx->properties.count == ctx->properties.capacity) { - ctx->properties.capacity = - GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2); - ctx->properties.array = static_cast( - gpr_realloc(ctx->properties.array, - ctx->properties.capacity * sizeof(grpc_auth_property))); +void grpc_auth_context::ensure_capacity() { + if (properties_.count == properties_.capacity) { + properties_.capacity = + GPR_MAX(properties_.capacity + 8, properties_.capacity * 2); + properties_.array = static_cast(gpr_realloc( + properties_.array, properties_.capacity * sizeof(grpc_auth_property))); } } +void grpc_auth_context::add_property(const char* name, const char* value, + size_t value_length) { + ensure_capacity(); + grpc_auth_property* prop = &properties_.array[properties_.count++]; + prop->name = gpr_strdup(name); + prop->value = static_cast(gpr_malloc(value_length + 1)); + memcpy(prop->value, value, value_length); + prop->value[value_length] = '\0'; + prop->value_length = value_length; +} + void grpc_auth_context_add_property(grpc_auth_context* ctx, const char* name, const char* value, size_t value_length) { - grpc_auth_property* prop; GRPC_API_TRACE( "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, " "value_length=%lu)", 6, (ctx, name, (int)value_length, (int)value_length, value, (unsigned long)value_length)); - ensure_auth_context_capacity(ctx); - prop = &ctx->properties.array[ctx->properties.count++]; + ctx->add_property(name, value, value_length); +} + +void grpc_auth_context::add_cstring_property(const char* name, + const char* value) { + ensure_capacity(); + grpc_auth_property* prop = &properties_.array[properties_.count++]; prop->name = gpr_strdup(name); - prop->value = static_cast(gpr_malloc(value_length + 1)); - memcpy(prop->value, value, value_length); - prop->value[value_length] = '\0'; - prop->value_length = value_length; + prop->value = gpr_strdup(value); + prop->value_length = strlen(value); } void grpc_auth_context_add_cstring_property(grpc_auth_context* ctx, const char* name, const char* value) { - grpc_auth_property* prop; GRPC_API_TRACE( "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3, (ctx, name, value)); - ensure_auth_context_capacity(ctx); - prop = &ctx->properties.array[ctx->properties.count++]; - prop->name = gpr_strdup(name); - prop->value = gpr_strdup(value); - prop->value_length = strlen(value); + ctx->add_cstring_property(name, value); } void grpc_auth_property_reset(grpc_auth_property* property) { @@ -307,12 +276,17 @@ void grpc_auth_property_reset(grpc_auth_property* property) { } static void auth_context_pointer_arg_destroy(void* p) { - GRPC_AUTH_CONTEXT_UNREF((grpc_auth_context*)p, "auth_context_pointer_arg"); + if (p != nullptr) { + static_cast(p)->Unref(DEBUG_LOCATION, + "auth_context_pointer_arg"); + } } static void* auth_context_pointer_arg_copy(void* p) { - return GRPC_AUTH_CONTEXT_REF((grpc_auth_context*)p, - "auth_context_pointer_arg"); + auto* ctx = static_cast(p); + return ctx == nullptr + ? nullptr + : ctx->Ref(DEBUG_LOCATION, "auth_context_pointer_arg").release(); } static int auth_context_pointer_cmp(void* a, void* b) { return GPR_ICMP(a, b); } diff --git a/Sources/CgRPC/src/core/lib/security/context/security_context.h b/Sources/CgRPC/src/core/lib/security/context/security_context.h index e782e4f28..b43ee5e62 100644 --- a/Sources/CgRPC/src/core/lib/security/context/security_context.h +++ b/Sources/CgRPC/src/core/lib/security/context/security_context.h @@ -21,87 +21,123 @@ #include +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/security/credentials/credentials.h" extern grpc_core::DebugOnlyTraceFlag grpc_trace_auth_context_refcount; +struct gpr_arena; + /* --- grpc_auth_context --- High level authentication context object. Can optionally be chained. */ /* Property names are always NULL terminated. */ -typedef struct { - grpc_auth_property* array; - size_t count; - size_t capacity; -} grpc_auth_property_array; - -struct grpc_auth_context { - struct grpc_auth_context* chained; - grpc_auth_property_array properties; - gpr_refcount refcount; - const char* peer_identity_property_name; - grpc_pollset* pollset; +struct grpc_auth_property_array { + grpc_auth_property* array = nullptr; + size_t count = 0; + size_t capacity = 0; }; -/* Creation. */ -grpc_auth_context* grpc_auth_context_create(grpc_auth_context* chained); - -/* Refcounting. */ -#ifndef NDEBUG -#define GRPC_AUTH_CONTEXT_REF(p, r) \ - grpc_auth_context_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_AUTH_CONTEXT_UNREF(p, r) \ - grpc_auth_context_unref((p), __FILE__, __LINE__, (r)) -grpc_auth_context* grpc_auth_context_ref(grpc_auth_context* policy, - const char* file, int line, - const char* reason); -void grpc_auth_context_unref(grpc_auth_context* policy, const char* file, - int line, const char* reason); -#else -#define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p)) -#define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p)) -grpc_auth_context* grpc_auth_context_ref(grpc_auth_context* policy); -void grpc_auth_context_unref(grpc_auth_context* policy); -#endif - void grpc_auth_property_reset(grpc_auth_property* property); +// This type is forward declared as a C struct and we cannot define it as a +// class. Otherwise, compiler will complain about type mismatch due to +// -Wmismatched-tags. +struct grpc_auth_context + : public grpc_core::RefCounted { + public: + explicit grpc_auth_context( + grpc_core::RefCountedPtr chained) + : grpc_core::RefCounted( + &grpc_trace_auth_context_refcount), + chained_(std::move(chained)) { + if (chained_ != nullptr) { + peer_identity_property_name_ = chained_->peer_identity_property_name_; + } + } + + ~grpc_auth_context() { + chained_.reset(DEBUG_LOCATION, "chained"); + if (properties_.array != nullptr) { + for (size_t i = 0; i < properties_.count; i++) { + grpc_auth_property_reset(&properties_.array[i]); + } + gpr_free(properties_.array); + } + } + + const grpc_auth_context* chained() const { return chained_.get(); } + const grpc_auth_property_array& properties() const { return properties_; } + + bool is_authenticated() const { + return peer_identity_property_name_ != nullptr; + } + const char* peer_identity_property_name() const { + return peer_identity_property_name_; + } + void set_peer_identity_property_name(const char* name) { + peer_identity_property_name_ = name; + } + + void ensure_capacity(); + void add_property(const char* name, const char* value, size_t value_length); + void add_cstring_property(const char* name, const char* value); + + private: + grpc_core::RefCountedPtr chained_; + grpc_auth_property_array properties_; + const char* peer_identity_property_name_ = nullptr; +}; + /* --- grpc_security_context_extension --- Extension to the security context that may be set in a filter and accessed later by a higher level method on a grpc_call object. */ -typedef struct { - void* instance; - void (*destroy)(void*); -} grpc_security_context_extension; +struct grpc_security_context_extension { + void* instance = nullptr; + void (*destroy)(void*) = nullptr; +}; /* --- grpc_client_security_context --- Internal client-side security context. */ -typedef struct { - grpc_call_credentials* creds; - grpc_auth_context* auth_context; +struct grpc_client_security_context { + explicit grpc_client_security_context( + grpc_core::RefCountedPtr creds) + : creds(std::move(creds)) {} + ~grpc_client_security_context(); + + grpc_core::RefCountedPtr creds; + grpc_core::RefCountedPtr auth_context; grpc_security_context_extension extension; -} grpc_client_security_context; +}; -grpc_client_security_context* grpc_client_security_context_create(void); +grpc_client_security_context* grpc_client_security_context_create( + gpr_arena* arena, grpc_call_credentials* creds); void grpc_client_security_context_destroy(void* ctx); /* --- grpc_server_security_context --- Internal server-side security context. */ -typedef struct { - grpc_auth_context* auth_context; +struct grpc_server_security_context { + grpc_server_security_context() = default; + ~grpc_server_security_context(); + + grpc_core::RefCountedPtr auth_context; grpc_security_context_extension extension; -} grpc_server_security_context; +}; -grpc_server_security_context* grpc_server_security_context_create(void); +grpc_server_security_context* grpc_server_security_context_create( + gpr_arena* arena); void grpc_server_security_context_destroy(void* ctx); /* --- Channel args for auth context --- */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.cc index fa05d901b..9a3379030 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.cc @@ -28,45 +28,52 @@ #include #include "src/core/lib/security/credentials/alts/check_gcp_environment.h" -#include "src/core/lib/security/security_connector/alts_security_connector.h" +#include "src/core/lib/security/security_connector/alts/alts_security_connector.h" #define GRPC_CREDENTIALS_TYPE_ALTS "Alts" -#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal:8080" +#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal.:8080" -static void alts_credentials_destruct(grpc_channel_credentials* creds) { - grpc_alts_credentials* alts_creds = - reinterpret_cast(creds); - grpc_alts_credentials_options_destroy(alts_creds->options); - gpr_free(alts_creds->handshaker_service_url); -} - -static void alts_server_credentials_destruct(grpc_server_credentials* creds) { - grpc_alts_server_credentials* alts_creds = - reinterpret_cast(creds); - grpc_alts_credentials_options_destroy(alts_creds->options); - gpr_free(alts_creds->handshaker_service_url); +grpc_alts_credentials::grpc_alts_credentials( + const grpc_alts_credentials_options* options, + const char* handshaker_service_url) + : grpc_channel_credentials(GRPC_CREDENTIALS_TYPE_ALTS), + options_(grpc_alts_credentials_options_copy(options)), + handshaker_service_url_(handshaker_service_url == nullptr + ? gpr_strdup(GRPC_ALTS_HANDSHAKER_SERVICE_URL) + : gpr_strdup(handshaker_service_url)) {} + +grpc_alts_credentials::~grpc_alts_credentials() { + grpc_alts_credentials_options_destroy(options_); + gpr_free(handshaker_service_url_); } -static grpc_security_status alts_create_security_connector( - grpc_channel_credentials* creds, - grpc_call_credentials* request_metadata_creds, const char* target_name, - const grpc_channel_args* args, grpc_channel_security_connector** sc, +grpc_core::RefCountedPtr +grpc_alts_credentials::create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target_name, const grpc_channel_args* args, grpc_channel_args** new_args) { return grpc_alts_channel_security_connector_create( - creds, request_metadata_creds, target_name, sc); + this->Ref(), std::move(call_creds), target_name); } -static grpc_security_status alts_server_create_security_connector( - grpc_server_credentials* creds, grpc_server_security_connector** sc) { - return grpc_alts_server_security_connector_create(creds, sc); +grpc_alts_server_credentials::grpc_alts_server_credentials( + const grpc_alts_credentials_options* options, + const char* handshaker_service_url) + : grpc_server_credentials(GRPC_CREDENTIALS_TYPE_ALTS), + options_(grpc_alts_credentials_options_copy(options)), + handshaker_service_url_(handshaker_service_url == nullptr + ? gpr_strdup(GRPC_ALTS_HANDSHAKER_SERVICE_URL) + : gpr_strdup(handshaker_service_url)) {} + +grpc_core::RefCountedPtr +grpc_alts_server_credentials::create_security_connector() { + return grpc_alts_server_security_connector_create(this->Ref()); } -static const grpc_channel_credentials_vtable alts_credentials_vtable = { - alts_credentials_destruct, alts_create_security_connector, - /*duplicate_without_call_credentials=*/nullptr}; - -static const grpc_server_credentials_vtable alts_server_credentials_vtable = { - alts_server_credentials_destruct, alts_server_create_security_connector}; +grpc_alts_server_credentials::~grpc_alts_server_credentials() { + grpc_alts_credentials_options_destroy(options_); + gpr_free(handshaker_service_url_); +} grpc_channel_credentials* grpc_alts_credentials_create_customized( const grpc_alts_credentials_options* options, @@ -74,17 +81,7 @@ grpc_channel_credentials* grpc_alts_credentials_create_customized( if (!enable_untrusted_alts && !grpc_alts_is_running_on_gcp()) { return nullptr; } - auto creds = static_cast( - gpr_zalloc(sizeof(grpc_alts_credentials))); - creds->options = grpc_alts_credentials_options_copy(options); - creds->handshaker_service_url = - handshaker_service_url == nullptr - ? gpr_strdup(GRPC_ALTS_HANDSHAKER_SERVICE_URL) - : gpr_strdup(handshaker_service_url); - creds->base.type = GRPC_CREDENTIALS_TYPE_ALTS; - creds->base.vtable = &alts_credentials_vtable; - gpr_ref_init(&creds->base.refcount, 1); - return &creds->base; + return grpc_core::New(options, handshaker_service_url); } grpc_server_credentials* grpc_alts_server_credentials_create_customized( @@ -93,17 +90,8 @@ grpc_server_credentials* grpc_alts_server_credentials_create_customized( if (!enable_untrusted_alts && !grpc_alts_is_running_on_gcp()) { return nullptr; } - auto creds = static_cast( - gpr_zalloc(sizeof(grpc_alts_server_credentials))); - creds->options = grpc_alts_credentials_options_copy(options); - creds->handshaker_service_url = - handshaker_service_url == nullptr - ? gpr_strdup(GRPC_ALTS_HANDSHAKER_SERVICE_URL) - : gpr_strdup(handshaker_service_url); - creds->base.type = GRPC_CREDENTIALS_TYPE_ALTS; - creds->base.vtable = &alts_server_credentials_vtable; - gpr_ref_init(&creds->base.refcount, 1); - return &creds->base; + return grpc_core::New(options, + handshaker_service_url); } grpc_channel_credentials* grpc_alts_credentials_create( diff --git a/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.h index 810117f2b..cc6d5222b 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/alts/alts_credentials.h @@ -27,18 +27,45 @@ #include "src/core/lib/security/credentials/credentials.h" /* Main struct for grpc ALTS channel credential. */ -typedef struct grpc_alts_credentials { - grpc_channel_credentials base; - grpc_alts_credentials_options* options; - char* handshaker_service_url; -} grpc_alts_credentials; +class grpc_alts_credentials final : public grpc_channel_credentials { + public: + grpc_alts_credentials(const grpc_alts_credentials_options* options, + const char* handshaker_service_url); + ~grpc_alts_credentials() override; + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target_name, const grpc_channel_args* args, + grpc_channel_args** new_args) override; + + const grpc_alts_credentials_options* options() const { return options_; } + grpc_alts_credentials_options* mutable_options() { return options_; } + const char* handshaker_service_url() const { return handshaker_service_url_; } + + private: + grpc_alts_credentials_options* options_; + char* handshaker_service_url_; +}; /* Main struct for grpc ALTS server credential. */ -typedef struct grpc_alts_server_credentials { - grpc_server_credentials base; - grpc_alts_credentials_options* options; - char* handshaker_service_url; -} grpc_alts_server_credentials; +class grpc_alts_server_credentials final : public grpc_server_credentials { + public: + grpc_alts_server_credentials(const grpc_alts_credentials_options* options, + const char* handshaker_service_url); + ~grpc_alts_server_credentials() override; + + grpc_core::RefCountedPtr + create_security_connector() override; + + const grpc_alts_credentials_options* options() const { return options_; } + grpc_alts_credentials_options* mutable_options() { return options_; } + const char* handshaker_service_url() const { return handshaker_service_url_; } + + private: + grpc_alts_credentials_options* options_; + char* handshaker_service_url_; +}; /** * This method creates an ALTS channel credential object with customized diff --git a/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc b/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc index 7c4d7a71c..8454fd755 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc @@ -41,8 +41,9 @@ namespace internal { bool check_bios_data(const char* bios_data_file) { char* bios_data = read_bios_file(bios_data_file); - bool result = (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE)) || - (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GCE)); + bool result = + bios_data && ((!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE)) || + (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GCE))); gpr_free(bios_data); return result; } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc b/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc index d97681b86..b71f66a53 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc @@ -25,8 +25,8 @@ #include bool grpc_alts_is_running_on_gcp() { - gpr_log(GPR_ERROR, - "Platforms other than Linux and Windows are not supported"); + gpr_log(GPR_INFO, + "ALTS: Platforms other than Linux and Windows are not supported"); return false; } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc b/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc index 0a39c6c48..118d18d11 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc @@ -72,7 +72,8 @@ static void target_service_account_destroy( static const grpc_alts_credentials_options_vtable vtable = { alts_client_options_copy, alts_client_options_destroy}; -grpc_alts_credentials_options* grpc_alts_credentials_client_options_create() { +grpc_alts_credentials_options* grpc_alts_credentials_client_options_create( + void) { auto client_options = static_cast( gpr_zalloc(sizeof(grpc_alts_credentials_client_options))); client_options->base.vtable = &vtable; diff --git a/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc b/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc index 62aa7a620..1a59c4567 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc @@ -36,7 +36,8 @@ static void alts_server_options_destroy( static const grpc_alts_credentials_options_vtable vtable = { alts_server_options_copy, alts_server_options_destroy}; -grpc_alts_credentials_options* grpc_alts_credentials_server_options_create() { +grpc_alts_credentials_options* grpc_alts_credentials_server_options_create( + void) { grpc_alts_credentials_server_options* server_options = static_cast( gpr_zalloc(sizeof(*server_options))); diff --git a/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.cc index b8f409260..586bbed77 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.cc @@ -20,8 +20,10 @@ #include "src/core/lib/security/credentials/composite/composite_credentials.h" -#include +#include +#include +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/surface/api_trace.h" @@ -31,35 +33,44 @@ /* -- Composite call credentials. -- */ -typedef struct { +static void composite_call_metadata_cb(void* arg, grpc_error* error); + +namespace { +struct grpc_composite_call_credentials_metadata_context { + grpc_composite_call_credentials_metadata_context( + grpc_composite_call_credentials* composite_creds, + grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata) + : composite_creds(composite_creds), + pollent(pollent), + auth_md_context(auth_md_context), + md_array(md_array), + on_request_metadata(on_request_metadata) { + GRPC_CLOSURE_INIT(&internal_on_request_metadata, composite_call_metadata_cb, + this, grpc_schedule_on_exec_ctx); + } + grpc_composite_call_credentials* composite_creds; - size_t creds_index; + size_t creds_index = 0; grpc_polling_entity* pollent; grpc_auth_metadata_context auth_md_context; grpc_credentials_mdelem_array* md_array; grpc_closure* on_request_metadata; grpc_closure internal_on_request_metadata; -} grpc_composite_call_credentials_metadata_context; - -static void composite_call_destruct(grpc_call_credentials* creds) { - grpc_composite_call_credentials* c = - reinterpret_cast(creds); - for (size_t i = 0; i < c->inner.num_creds; i++) { - grpc_call_credentials_unref(c->inner.creds_array[i]); - } - gpr_free(c->inner.creds_array); -} +}; +} // namespace static void composite_call_metadata_cb(void* arg, grpc_error* error) { grpc_composite_call_credentials_metadata_context* ctx = static_cast(arg); if (error == GRPC_ERROR_NONE) { + const grpc_composite_call_credentials::CallCredentialsList& inner = + ctx->composite_creds->inner(); /* See if we need to get some more metadata. */ - if (ctx->creds_index < ctx->composite_creds->inner.num_creds) { - grpc_call_credentials* inner_creds = - ctx->composite_creds->inner.creds_array[ctx->creds_index++]; - if (grpc_call_credentials_get_request_metadata( - inner_creds, ctx->pollent, ctx->auth_md_context, ctx->md_array, + if (ctx->creds_index < inner.size()) { + if (inner[ctx->creds_index++]->get_request_metadata( + ctx->pollent, ctx->auth_md_context, ctx->md_array, &ctx->internal_on_request_metadata, &error)) { // Synchronous response, so call ourselves recursively. composite_call_metadata_cb(arg, error); @@ -73,29 +84,18 @@ static void composite_call_metadata_cb(void* arg, grpc_error* error) { gpr_free(ctx); } -static bool composite_call_get_request_metadata( - grpc_call_credentials* creds, grpc_polling_entity* pollent, - grpc_auth_metadata_context auth_md_context, +bool grpc_composite_call_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, grpc_error** error) { - grpc_composite_call_credentials* c = - reinterpret_cast(creds); grpc_composite_call_credentials_metadata_context* ctx; - ctx = static_cast( - gpr_zalloc(sizeof(grpc_composite_call_credentials_metadata_context))); - ctx->composite_creds = c; - ctx->pollent = pollent; - ctx->auth_md_context = auth_md_context; - ctx->md_array = md_array; - ctx->on_request_metadata = on_request_metadata; - GRPC_CLOSURE_INIT(&ctx->internal_on_request_metadata, - composite_call_metadata_cb, ctx, grpc_schedule_on_exec_ctx); + ctx = grpc_core::New( + this, pollent, auth_md_context, md_array, on_request_metadata); bool synchronous = true; - while (ctx->creds_index < ctx->composite_creds->inner.num_creds) { - grpc_call_credentials* inner_creds = - ctx->composite_creds->inner.creds_array[ctx->creds_index++]; - if (grpc_call_credentials_get_request_metadata( - inner_creds, ctx->pollent, ctx->auth_md_context, ctx->md_array, + const CallCredentialsList& inner = ctx->composite_creds->inner(); + while (ctx->creds_index < inner.size()) { + if (inner[ctx->creds_index++]->get_request_metadata( + ctx->pollent, ctx->auth_md_context, ctx->md_array, &ctx->internal_on_request_metadata, error)) { if (*error != GRPC_ERROR_NONE) break; } else { @@ -103,46 +103,66 @@ static bool composite_call_get_request_metadata( break; } } - if (synchronous) gpr_free(ctx); + if (synchronous) grpc_core::Delete(ctx); return synchronous; } -static void composite_call_cancel_get_request_metadata( - grpc_call_credentials* creds, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { - grpc_composite_call_credentials* c = - reinterpret_cast(creds); - for (size_t i = 0; i < c->inner.num_creds; ++i) { - grpc_call_credentials_cancel_get_request_metadata( - c->inner.creds_array[i], md_array, GRPC_ERROR_REF(error)); +void grpc_composite_call_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { + for (size_t i = 0; i < inner_.size(); ++i) { + inner_[i]->cancel_get_request_metadata(md_array, GRPC_ERROR_REF(error)); } GRPC_ERROR_UNREF(error); } -static grpc_call_credentials_vtable composite_call_credentials_vtable = { - composite_call_destruct, composite_call_get_request_metadata, - composite_call_cancel_get_request_metadata}; +static size_t get_creds_array_size(const grpc_call_credentials* creds, + bool is_composite) { + return is_composite + ? static_cast(creds) + ->inner() + .size() + : 1; +} -static grpc_call_credentials_array get_creds_array( - grpc_call_credentials** creds_addr) { - grpc_call_credentials_array result; - grpc_call_credentials* creds = *creds_addr; - result.creds_array = creds_addr; - result.num_creds = 1; - if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { - result = *grpc_composite_call_credentials_get_credentials(creds); +void grpc_composite_call_credentials::push_to_inner( + grpc_core::RefCountedPtr creds, bool is_composite) { + if (!is_composite) { + inner_.push_back(std::move(creds)); + return; + } + auto composite_creds = + static_cast(creds.get()); + for (size_t i = 0; i < composite_creds->inner().size(); ++i) { + inner_.push_back(std::move(composite_creds->inner_[i])); } - return result; +} + +grpc_composite_call_credentials::grpc_composite_call_credentials( + grpc_core::RefCountedPtr creds1, + grpc_core::RefCountedPtr creds2) + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) { + const bool creds1_is_composite = + strcmp(creds1->type(), GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0; + const bool creds2_is_composite = + strcmp(creds2->type(), GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0; + const size_t size = get_creds_array_size(creds1.get(), creds1_is_composite) + + get_creds_array_size(creds2.get(), creds2_is_composite); + inner_.reserve(size); + push_to_inner(std::move(creds1), creds1_is_composite); + push_to_inner(std::move(creds2), creds2_is_composite); +} + +static grpc_core::RefCountedPtr +composite_call_credentials_create( + grpc_core::RefCountedPtr creds1, + grpc_core::RefCountedPtr creds2) { + return grpc_core::MakeRefCounted( + std::move(creds1), std::move(creds2)); } grpc_call_credentials* grpc_composite_call_credentials_create( grpc_call_credentials* creds1, grpc_call_credentials* creds2, void* reserved) { - size_t i; - size_t creds_array_byte_size; - grpc_call_credentials_array creds1_array; - grpc_call_credentials_array creds2_array; - grpc_composite_call_credentials* c; GRPC_API_TRACE( "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, " "reserved=%p)", @@ -150,120 +170,40 @@ grpc_call_credentials* grpc_composite_call_credentials_create( GPR_ASSERT(reserved == nullptr); GPR_ASSERT(creds1 != nullptr); GPR_ASSERT(creds2 != nullptr); - c = static_cast( - gpr_zalloc(sizeof(grpc_composite_call_credentials))); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE; - c->base.vtable = &composite_call_credentials_vtable; - gpr_ref_init(&c->base.refcount, 1); - creds1_array = get_creds_array(&creds1); - creds2_array = get_creds_array(&creds2); - c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds; - creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials*); - c->inner.creds_array = - static_cast(gpr_zalloc(creds_array_byte_size)); - for (i = 0; i < creds1_array.num_creds; i++) { - grpc_call_credentials* cur_creds = creds1_array.creds_array[i]; - c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds); - } - for (i = 0; i < creds2_array.num_creds; i++) { - grpc_call_credentials* cur_creds = creds2_array.creds_array[i]; - c->inner.creds_array[i + creds1_array.num_creds] = - grpc_call_credentials_ref(cur_creds); - } - return &c->base; -} - -const grpc_call_credentials_array* -grpc_composite_call_credentials_get_credentials(grpc_call_credentials* creds) { - const grpc_composite_call_credentials* c = - reinterpret_cast(creds); - GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); - return &c->inner; -} -grpc_call_credentials* grpc_credentials_contains_type( - grpc_call_credentials* creds, const char* type, - grpc_call_credentials** composite_creds) { - size_t i; - if (strcmp(creds->type, type) == 0) { - if (composite_creds != nullptr) *composite_creds = nullptr; - return creds; - } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { - const grpc_call_credentials_array* inner_creds_array = - grpc_composite_call_credentials_get_credentials(creds); - for (i = 0; i < inner_creds_array->num_creds; i++) { - if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) { - if (composite_creds != nullptr) *composite_creds = creds; - return inner_creds_array->creds_array[i]; - } - } - } - return nullptr; + return composite_call_credentials_create(creds1->Ref(), creds2->Ref()) + .release(); } /* -- Composite channel credentials. -- */ -static void composite_channel_destruct(grpc_channel_credentials* creds) { - grpc_composite_channel_credentials* c = - reinterpret_cast(creds); - grpc_channel_credentials_unref(c->inner_creds); - grpc_call_credentials_unref(c->call_creds); -} - -static grpc_security_status composite_channel_create_security_connector( - grpc_channel_credentials* creds, grpc_call_credentials* call_creds, +grpc_core::RefCountedPtr +grpc_composite_channel_credentials::create_security_connector( + grpc_core::RefCountedPtr call_creds, const char* target, const grpc_channel_args* args, - grpc_channel_security_connector** sc, grpc_channel_args** new_args) { - grpc_composite_channel_credentials* c = - reinterpret_cast(creds); - grpc_security_status status = GRPC_SECURITY_ERROR; - - GPR_ASSERT(c->inner_creds != nullptr && c->call_creds != nullptr && - c->inner_creds->vtable != nullptr && - c->inner_creds->vtable->create_security_connector != nullptr); + grpc_channel_args** new_args) { + GPR_ASSERT(inner_creds_ != nullptr && call_creds_ != nullptr); /* If we are passed a call_creds, create a call composite to pass it downstream. */ if (call_creds != nullptr) { - grpc_call_credentials* composite_call_creds = - grpc_composite_call_credentials_create(c->call_creds, call_creds, - nullptr); - status = c->inner_creds->vtable->create_security_connector( - c->inner_creds, composite_call_creds, target, args, sc, new_args); - grpc_call_credentials_unref(composite_call_creds); + return inner_creds_->create_security_connector( + composite_call_credentials_create(call_creds_, std::move(call_creds)), + target, args, new_args); } else { - status = c->inner_creds->vtable->create_security_connector( - c->inner_creds, c->call_creds, target, args, sc, new_args); + return inner_creds_->create_security_connector(call_creds_, target, args, + new_args); } - return status; } -static grpc_channel_credentials* -composite_channel_duplicate_without_call_credentials( - grpc_channel_credentials* creds) { - grpc_composite_channel_credentials* c = - reinterpret_cast(creds); - return grpc_channel_credentials_ref(c->inner_creds); -} - -static grpc_channel_credentials_vtable composite_channel_credentials_vtable = { - composite_channel_destruct, composite_channel_create_security_connector, - composite_channel_duplicate_without_call_credentials}; - grpc_channel_credentials* grpc_composite_channel_credentials_create( grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds, void* reserved) { - grpc_composite_channel_credentials* c = - static_cast(gpr_zalloc(sizeof(*c))); GPR_ASSERT(channel_creds != nullptr && call_creds != nullptr && reserved == nullptr); GRPC_API_TRACE( "grpc_composite_channel_credentials_create(channel_creds=%p, " "call_creds=%p, reserved=%p)", 3, (channel_creds, call_creds, reserved)); - c->base.type = channel_creds->type; - c->base.vtable = &composite_channel_credentials_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->inner_creds = grpc_channel_credentials_ref(channel_creds); - c->call_creds = grpc_call_credentials_ref(call_creds); - return &c->base; + return grpc_core::New( + channel_creds->Ref(), call_creds->Ref()); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.h index a952ad57f..0e6e5f9e1 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/composite/composite_credentials.h @@ -21,39 +21,79 @@ #include +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/credentials/credentials.h" -typedef struct { - grpc_call_credentials** creds_array; - size_t num_creds; -} grpc_call_credentials_array; +/* -- Composite channel credentials. -- */ -const grpc_call_credentials_array* -grpc_composite_call_credentials_get_credentials( - grpc_call_credentials* composite_creds); +class grpc_composite_channel_credentials : public grpc_channel_credentials { + public: + grpc_composite_channel_credentials( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr call_creds) + : grpc_channel_credentials(channel_creds->type()), + inner_creds_(std::move(channel_creds)), + call_creds_(std::move(call_creds)) {} -/* Returns creds if creds is of the specified type or the inner creds of the - specified type (if found), if the creds is of type COMPOSITE. - If composite_creds is not NULL, *composite_creds will point to creds if of - type COMPOSITE in case of success. */ -grpc_call_credentials* grpc_credentials_contains_type( - grpc_call_credentials* creds, const char* type, - grpc_call_credentials** composite_creds); + ~grpc_composite_channel_credentials() override = default; -/* -- Composite channel credentials. -- */ + grpc_core::RefCountedPtr + duplicate_without_call_credentials() override { + return inner_creds_; + } + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target, const grpc_channel_args* args, + grpc_channel_args** new_args) override; -typedef struct { - grpc_channel_credentials base; - grpc_channel_credentials* inner_creds; - grpc_call_credentials* call_creds; -} grpc_composite_channel_credentials; + grpc_channel_args* update_arguments(grpc_channel_args* args) override { + return inner_creds_->update_arguments(args); + } + + const grpc_channel_credentials* inner_creds() const { + return inner_creds_.get(); + } + const grpc_call_credentials* call_creds() const { return call_creds_.get(); } + grpc_call_credentials* mutable_call_creds() { return call_creds_.get(); } + + private: + grpc_core::RefCountedPtr inner_creds_; + grpc_core::RefCountedPtr call_creds_; +}; /* -- Composite call credentials. -- */ -typedef struct { - grpc_call_credentials base; - grpc_call_credentials_array inner; -} grpc_composite_call_credentials; +class grpc_composite_call_credentials : public grpc_call_credentials { + public: + using CallCredentialsList = + grpc_core::InlinedVector, + 2>; + + grpc_composite_call_credentials( + grpc_core::RefCountedPtr creds1, + grpc_core::RefCountedPtr creds2); + ~grpc_composite_call_credentials() override = default; + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + const CallCredentialsList& inner() const { return inner_; } + + private: + void push_to_inner(grpc_core::RefCountedPtr creds, + bool is_composite); + + CallCredentialsList inner_; +}; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H \ */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/credentials.cc index c43cb440e..90452d68d 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/credentials.cc @@ -39,120 +39,24 @@ /* -- Common. -- */ -grpc_credentials_metadata_request* grpc_credentials_metadata_request_create( - grpc_call_credentials* creds) { - grpc_credentials_metadata_request* r = - static_cast( - gpr_zalloc(sizeof(grpc_credentials_metadata_request))); - r->creds = grpc_call_credentials_ref(creds); - return r; -} - -void grpc_credentials_metadata_request_destroy( - grpc_credentials_metadata_request* r) { - grpc_call_credentials_unref(r->creds); - grpc_http_response_destroy(&r->response); - gpr_free(r); -} - -grpc_channel_credentials* grpc_channel_credentials_ref( - grpc_channel_credentials* creds) { - if (creds == nullptr) return nullptr; - gpr_ref(&creds->refcount); - return creds; -} - -void grpc_channel_credentials_unref(grpc_channel_credentials* creds) { - if (creds == nullptr) return; - if (gpr_unref(&creds->refcount)) { - if (creds->vtable->destruct != nullptr) { - creds->vtable->destruct(creds); - } - gpr_free(creds); - } -} - void grpc_channel_credentials_release(grpc_channel_credentials* creds) { GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds)); grpc_core::ExecCtx exec_ctx; - grpc_channel_credentials_unref(creds); -} - -grpc_call_credentials* grpc_call_credentials_ref(grpc_call_credentials* creds) { - if (creds == nullptr) return nullptr; - gpr_ref(&creds->refcount); - return creds; -} - -void grpc_call_credentials_unref(grpc_call_credentials* creds) { - if (creds == nullptr) return; - if (gpr_unref(&creds->refcount)) { - if (creds->vtable->destruct != nullptr) { - creds->vtable->destruct(creds); - } - gpr_free(creds); - } + if (creds) creds->Unref(); } void grpc_call_credentials_release(grpc_call_credentials* creds) { GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds)); grpc_core::ExecCtx exec_ctx; - grpc_call_credentials_unref(creds); -} - -bool grpc_call_credentials_get_request_metadata( - grpc_call_credentials* creds, grpc_polling_entity* pollent, - grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, grpc_error** error) { - if (creds == nullptr || creds->vtable->get_request_metadata == nullptr) { - return true; - } - return creds->vtable->get_request_metadata(creds, pollent, context, md_array, - on_request_metadata, error); -} - -void grpc_call_credentials_cancel_get_request_metadata( - grpc_call_credentials* creds, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { - if (creds == nullptr || - creds->vtable->cancel_get_request_metadata == nullptr) { - return; - } - creds->vtable->cancel_get_request_metadata(creds, md_array, error); -} - -grpc_security_status grpc_channel_credentials_create_security_connector( - grpc_channel_credentials* channel_creds, const char* target, - const grpc_channel_args* args, grpc_channel_security_connector** sc, - grpc_channel_args** new_args) { - *new_args = nullptr; - if (channel_creds == nullptr) { - return GRPC_SECURITY_ERROR; - } - GPR_ASSERT(channel_creds->vtable->create_security_connector != nullptr); - return channel_creds->vtable->create_security_connector( - channel_creds, nullptr, target, args, sc, new_args); -} - -grpc_channel_credentials* -grpc_channel_credentials_duplicate_without_call_credentials( - grpc_channel_credentials* channel_creds) { - if (channel_creds != nullptr && channel_creds->vtable != nullptr && - channel_creds->vtable->duplicate_without_call_credentials != nullptr) { - return channel_creds->vtable->duplicate_without_call_credentials( - channel_creds); - } else { - return grpc_channel_credentials_ref(channel_creds); - } + if (creds) creds->Unref(); } static void credentials_pointer_arg_destroy(void* p) { - grpc_channel_credentials_unref(static_cast(p)); + static_cast(p)->Unref(); } static void* credentials_pointer_arg_copy(void* p) { - return grpc_channel_credentials_ref( - static_cast(p)); + return static_cast(p)->Ref().release(); } static int credentials_pointer_cmp(void* a, void* b) { return GPR_ICMP(a, b); } @@ -191,63 +95,35 @@ grpc_channel_credentials* grpc_channel_credentials_find_in_args( return nullptr; } -grpc_server_credentials* grpc_server_credentials_ref( - grpc_server_credentials* creds) { - if (creds == nullptr) return nullptr; - gpr_ref(&creds->refcount); - return creds; -} - -void grpc_server_credentials_unref(grpc_server_credentials* creds) { - if (creds == nullptr) return; - if (gpr_unref(&creds->refcount)) { - if (creds->vtable->destruct != nullptr) { - creds->vtable->destruct(creds); - } - if (creds->processor.destroy != nullptr && - creds->processor.state != nullptr) { - creds->processor.destroy(creds->processor.state); - } - gpr_free(creds); - } -} - void grpc_server_credentials_release(grpc_server_credentials* creds) { GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds)); grpc_core::ExecCtx exec_ctx; - grpc_server_credentials_unref(creds); + if (creds) creds->Unref(); } -grpc_security_status grpc_server_credentials_create_security_connector( - grpc_server_credentials* creds, grpc_server_security_connector** sc) { - if (creds == nullptr || creds->vtable->create_security_connector == nullptr) { - gpr_log(GPR_ERROR, "Server credentials cannot create security context."); - return GRPC_SECURITY_ERROR; - } - return creds->vtable->create_security_connector(creds, sc); -} - -void grpc_server_credentials_set_auth_metadata_processor( - grpc_server_credentials* creds, grpc_auth_metadata_processor processor) { +void grpc_server_credentials::set_auth_metadata_processor( + const grpc_auth_metadata_processor& processor) { GRPC_API_TRACE( "grpc_server_credentials_set_auth_metadata_processor(" "creds=%p, " "processor=grpc_auth_metadata_processor { process: %p, state: %p })", - 3, (creds, (void*)(intptr_t)processor.process, processor.state)); - if (creds == nullptr) return; - if (creds->processor.destroy != nullptr && - creds->processor.state != nullptr) { - creds->processor.destroy(creds->processor.state); - } - creds->processor = processor; + 3, (this, (void*)(intptr_t)processor.process, processor.state)); + DestroyProcessor(); + processor_ = processor; +} + +void grpc_server_credentials_set_auth_metadata_processor( + grpc_server_credentials* creds, grpc_auth_metadata_processor processor) { + GPR_DEBUG_ASSERT(creds != nullptr); + creds->set_auth_metadata_processor(processor); } static void server_credentials_pointer_arg_destroy(void* p) { - grpc_server_credentials_unref(static_cast(p)); + static_cast(p)->Unref(); } static void* server_credentials_pointer_arg_copy(void* p) { - return grpc_server_credentials_ref(static_cast(p)); + return static_cast(p)->Ref().release(); } static int server_credentials_pointer_cmp(void* a, void* b) { diff --git a/Sources/CgRPC/src/core/lib/security/credentials/credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/credentials.h index b1421e83c..a9d581280 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/credentials.h @@ -26,6 +26,7 @@ #include #include "src/core/lib/transport/metadata_batch.h" +#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/http/httpcli.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -45,6 +46,7 @@ typedef enum { #define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl" #define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \ "FakeTransportSecurity" +#define GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT "GoogleDefault" #define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2" #define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt" @@ -58,7 +60,7 @@ typedef enum { #define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 -#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal" +#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal." #define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ "/computeMetadata/v1/instance/service-accounts/default/token" @@ -89,44 +91,54 @@ void grpc_override_well_known_credentials_path_getter( #define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.channel_credentials" -typedef struct { - void (*destruct)(grpc_channel_credentials* c); - - grpc_security_status (*create_security_connector)( - grpc_channel_credentials* c, grpc_call_credentials* call_creds, +// This type is forward declared as a C struct and we cannot define it as a +// class. Otherwise, compiler will complain about type mismatch due to +// -Wmismatched-tags. +struct grpc_channel_credentials + : grpc_core::RefCounted { + public: + explicit grpc_channel_credentials(const char* type) : type_(type) {} + virtual ~grpc_channel_credentials() = default; + + // Creates a security connector for the channel. May also create new channel + // args for the channel to be used in place of the passed in const args if + // returned non NULL. In that case the caller is responsible for destroying + // new_args after channel creation. + virtual grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, const char* target, const grpc_channel_args* args, - grpc_channel_security_connector** sc, grpc_channel_args** new_args); - - grpc_channel_credentials* (*duplicate_without_call_credentials)( - grpc_channel_credentials* c); -} grpc_channel_credentials_vtable; - -struct grpc_channel_credentials { - const grpc_channel_credentials_vtable* vtable; - const char* type; - gpr_refcount refcount; + grpc_channel_args** new_args) { + // Tell clang-tidy that call_creds cannot be passed as const-ref. + call_creds.reset(); + GRPC_ABSTRACT; + } + + // Creates a version of the channel credentials without any attached call + // credentials. This can be used in order to open a channel to a non-trusted + // gRPC load balancer. + virtual grpc_core::RefCountedPtr + duplicate_without_call_credentials() { + // By default we just increment the refcount. + return Ref(); + } + + // Allows credentials to optionally modify a parent channel's args. + // By default, leave channel args as is. The callee takes ownership + // of the passed-in channel args, and the caller takes ownership + // of the returned channel args. + virtual grpc_channel_args* update_arguments(grpc_channel_args* args) { + return args; + } + + const char* type() const { return type_; } + + GRPC_ABSTRACT_BASE_CLASS + + private: + const char* type_; }; -grpc_channel_credentials* grpc_channel_credentials_ref( - grpc_channel_credentials* creds); -void grpc_channel_credentials_unref(grpc_channel_credentials* creds); - -/* Creates a security connector for the channel. May also create new channel - args for the channel to be used in place of the passed in const args if - returned non NULL. In that case the caller is responsible for destroying - new_args after channel creation. */ -grpc_security_status grpc_channel_credentials_create_security_connector( - grpc_channel_credentials* creds, const char* target, - const grpc_channel_args* args, grpc_channel_security_connector** sc, - grpc_channel_args** new_args); - -/* Creates a version of the channel credentials without any attached call - credentials. This can be used in order to open a channel to a non-trusted - gRPC load balancer. */ -grpc_channel_credentials* -grpc_channel_credentials_duplicate_without_call_credentials( - grpc_channel_credentials* creds); - /* Util to encapsulate the channel credentials in a channel arg. */ grpc_arg grpc_channel_credentials_to_arg(grpc_channel_credentials* credentials); @@ -141,8 +153,8 @@ grpc_channel_credentials* grpc_channel_credentials_find_in_args( /* --- grpc_credentials_mdelem_array. --- */ typedef struct { - grpc_mdelem* md; - size_t size; + grpc_mdelem* md = nullptr; + size_t size = 0; } grpc_credentials_mdelem_array; /// Takes a new ref to \a md. @@ -157,44 +169,39 @@ void grpc_credentials_mdelem_array_destroy(grpc_credentials_mdelem_array* list); /* --- grpc_call_credentials. --- */ -typedef struct { - void (*destruct)(grpc_call_credentials* c); - bool (*get_request_metadata)(grpc_call_credentials* c, - grpc_polling_entity* pollent, - grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, - grpc_error** error); - void (*cancel_get_request_metadata)(grpc_call_credentials* c, - grpc_credentials_mdelem_array* md_array, - grpc_error* error); -} grpc_call_credentials_vtable; - -struct grpc_call_credentials { - const grpc_call_credentials_vtable* vtable; - const char* type; - gpr_refcount refcount; +// This type is forward declared as a C struct and we cannot define it as a +// class. Otherwise, compiler will complain about type mismatch due to +// -Wmismatched-tags. +struct grpc_call_credentials + : public grpc_core::RefCounted { + public: + explicit grpc_call_credentials(const char* type) : type_(type) {} + virtual ~grpc_call_credentials() = default; + + // Returns true if completed synchronously, in which case \a error will + // be set to indicate the result. Otherwise, \a on_request_metadata will + // be invoked asynchronously when complete. \a md_array will be populated + // with the resulting metadata once complete. + virtual bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) GRPC_ABSTRACT; + + // Cancels a pending asynchronous operation started by + // grpc_call_credentials_get_request_metadata() with the corresponding + // value of \a md_array. + virtual void cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) GRPC_ABSTRACT; + + const char* type() const { return type_; } + + GRPC_ABSTRACT_BASE_CLASS + + private: + const char* type_; }; -grpc_call_credentials* grpc_call_credentials_ref(grpc_call_credentials* creds); -void grpc_call_credentials_unref(grpc_call_credentials* creds); - -/// Returns true if completed synchronously, in which case \a error will -/// be set to indicate the result. Otherwise, \a on_request_metadata will -/// be invoked asynchronously when complete. \a md_array will be populated -/// with the resulting metadata once complete. -bool grpc_call_credentials_get_request_metadata( - grpc_call_credentials* creds, grpc_polling_entity* pollent, - grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, grpc_error** error); - -/// Cancels a pending asynchronous operation started by -/// grpc_call_credentials_get_request_metadata() with the corresponding -/// value of \a md_array. -void grpc_call_credentials_cancel_get_request_metadata( - grpc_call_credentials* c, grpc_credentials_mdelem_array* md_array, - grpc_error* error); - /* Metadata-only credentials with the specified key and value where asynchronicity can be simulated for testing. */ grpc_call_credentials* grpc_md_only_test_credentials_create( @@ -202,26 +209,40 @@ grpc_call_credentials* grpc_md_only_test_credentials_create( /* --- grpc_server_credentials. --- */ -typedef struct { - void (*destruct)(grpc_server_credentials* c); - grpc_security_status (*create_security_connector)( - grpc_server_credentials* c, grpc_server_security_connector** sc); -} grpc_server_credentials_vtable; - -struct grpc_server_credentials { - const grpc_server_credentials_vtable* vtable; - const char* type; - gpr_refcount refcount; - grpc_auth_metadata_processor processor; -}; +// This type is forward declared as a C struct and we cannot define it as a +// class. Otherwise, compiler will complain about type mismatch due to +// -Wmismatched-tags. +struct grpc_server_credentials + : public grpc_core::RefCounted { + public: + explicit grpc_server_credentials(const char* type) : type_(type) {} -grpc_security_status grpc_server_credentials_create_security_connector( - grpc_server_credentials* creds, grpc_server_security_connector** sc); + virtual ~grpc_server_credentials() { DestroyProcessor(); } -grpc_server_credentials* grpc_server_credentials_ref( - grpc_server_credentials* creds); + virtual grpc_core::RefCountedPtr + create_security_connector() GRPC_ABSTRACT; -void grpc_server_credentials_unref(grpc_server_credentials* creds); + const char* type() const { return type_; } + + const grpc_auth_metadata_processor& auth_metadata_processor() const { + return processor_; + } + void set_auth_metadata_processor( + const grpc_auth_metadata_processor& processor); + + GRPC_ABSTRACT_BASE_CLASS + + private: + void DestroyProcessor() { + if (processor_.destroy != nullptr && processor_.state != nullptr) { + processor_.destroy(processor_.state); + } + } + + const char* type_; + grpc_auth_metadata_processor processor_ = + grpc_auth_metadata_processor(); // Zero-initialize the C struct. +}; #define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials" @@ -232,15 +253,27 @@ grpc_server_credentials* grpc_find_server_credentials_in_args( /* -- Credentials Metadata Request. -- */ -typedef struct { - grpc_call_credentials* creds; +struct grpc_credentials_metadata_request { + explicit grpc_credentials_metadata_request( + grpc_core::RefCountedPtr creds) + : creds(std::move(creds)) {} + ~grpc_credentials_metadata_request() { + grpc_http_response_destroy(&response); + } + + grpc_core::RefCountedPtr creds; grpc_http_response response; -} grpc_credentials_metadata_request; +}; -grpc_credentials_metadata_request* grpc_credentials_metadata_request_create( - grpc_call_credentials* creds); +inline grpc_credentials_metadata_request* +grpc_credentials_metadata_request_create( + grpc_core::RefCountedPtr creds) { + return grpc_core::New(std::move(creds)); +} -void grpc_credentials_metadata_request_destroy( - grpc_credentials_metadata_request* r); +inline void grpc_credentials_metadata_request_destroy( + grpc_credentials_metadata_request* r) { + grpc_core::Delete(r); +} #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.cc index 858ab6b41..337dd7679 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.cc @@ -29,52 +29,49 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/security/security_connector/fake/fake_security_connector.h" /* -- Fake transport security credentials. -- */ -static grpc_security_status fake_transport_security_create_security_connector( - grpc_channel_credentials* c, grpc_call_credentials* call_creds, - const char* target, const grpc_channel_args* args, - grpc_channel_security_connector** sc, grpc_channel_args** new_args) { - *sc = - grpc_fake_channel_security_connector_create(c, call_creds, target, args); - return GRPC_SECURITY_OK; -} - -static grpc_security_status -fake_transport_security_server_create_security_connector( - grpc_server_credentials* c, grpc_server_security_connector** sc) { - *sc = grpc_fake_server_security_connector_create(c); - return GRPC_SECURITY_OK; -} +namespace { +class grpc_fake_channel_credentials final : public grpc_channel_credentials { + public: + grpc_fake_channel_credentials() + : grpc_channel_credentials( + GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY) {} + ~grpc_fake_channel_credentials() override = default; + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target, const grpc_channel_args* args, + grpc_channel_args** new_args) override { + return grpc_fake_channel_security_connector_create( + this->Ref(), std::move(call_creds), target, args); + } +}; + +class grpc_fake_server_credentials final : public grpc_server_credentials { + public: + grpc_fake_server_credentials() + : grpc_server_credentials( + GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY) {} + ~grpc_fake_server_credentials() override = default; + + grpc_core::RefCountedPtr + create_security_connector() override { + return grpc_fake_server_security_connector_create(this->Ref()); + } +}; +} // namespace -static grpc_channel_credentials_vtable - fake_transport_security_credentials_vtable = { - nullptr, fake_transport_security_create_security_connector, nullptr}; - -static grpc_server_credentials_vtable - fake_transport_security_server_credentials_vtable = { - nullptr, fake_transport_security_server_create_security_connector}; - -grpc_channel_credentials* grpc_fake_transport_security_credentials_create( - void) { - grpc_channel_credentials* c = static_cast( - gpr_zalloc(sizeof(grpc_channel_credentials))); - c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; - c->vtable = &fake_transport_security_credentials_vtable; - gpr_ref_init(&c->refcount, 1); - return c; +grpc_channel_credentials* grpc_fake_transport_security_credentials_create() { + return grpc_core::New(); } -grpc_server_credentials* grpc_fake_transport_security_server_credentials_create( - void) { - grpc_server_credentials* c = static_cast( - gpr_malloc(sizeof(grpc_server_credentials))); - memset(c, 0, sizeof(grpc_server_credentials)); - c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; - gpr_ref_init(&c->refcount, 1); - c->vtable = &fake_transport_security_server_credentials_vtable; - return c; +grpc_server_credentials* +grpc_fake_transport_security_server_credentials_create() { + return grpc_core::New(); } grpc_arg grpc_fake_transport_expected_targets_arg(char* expected_targets) { @@ -91,46 +88,25 @@ const char* grpc_fake_transport_get_expected_targets( /* -- Metadata-only test credentials. -- */ -static void md_only_test_destruct(grpc_call_credentials* creds) { - grpc_md_only_test_credentials* c = - reinterpret_cast(creds); - GRPC_MDELEM_UNREF(c->md); -} - -static bool md_only_test_get_request_metadata( - grpc_call_credentials* creds, grpc_polling_entity* pollent, - grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, grpc_error** error) { - grpc_md_only_test_credentials* c = - reinterpret_cast(creds); - grpc_credentials_mdelem_array_add(md_array, c->md); - if (c->is_async) { +bool grpc_md_only_test_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, + grpc_error** error) { + grpc_credentials_mdelem_array_add(md_array, md_); + if (is_async_) { GRPC_CLOSURE_SCHED(on_request_metadata, GRPC_ERROR_NONE); return false; } return true; } -static void md_only_test_cancel_get_request_metadata( - grpc_call_credentials* c, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { +void grpc_md_only_test_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static grpc_call_credentials_vtable md_only_test_vtable = { - md_only_test_destruct, md_only_test_get_request_metadata, - md_only_test_cancel_get_request_metadata}; - grpc_call_credentials* grpc_md_only_test_credentials_create( const char* md_key, const char* md_value, bool is_async) { - grpc_md_only_test_credentials* c = - static_cast( - gpr_zalloc(sizeof(grpc_md_only_test_credentials))); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; - c->base.vtable = &md_only_test_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->md = grpc_mdelem_from_slices(grpc_slice_from_copied_string(md_key), - grpc_slice_from_copied_string(md_value)); - c->is_async = is_async; - return &c->base; + return grpc_core::New(md_key, md_value, + is_async); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.h index e89e6e24c..b7f6a1909 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/fake/fake_credentials.h @@ -55,10 +55,28 @@ const char* grpc_fake_transport_get_expected_targets( /* -- Metadata-only Test credentials. -- */ -typedef struct { - grpc_call_credentials base; - grpc_mdelem md; - bool is_async; -} grpc_md_only_test_credentials; +class grpc_md_only_test_credentials : public grpc_call_credentials { + public: + grpc_md_only_test_credentials(const char* md_key, const char* md_value, + bool is_async) + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2), + md_(grpc_mdelem_from_slices(grpc_slice_from_copied_string(md_key), + grpc_slice_from_copied_string(md_value))), + is_async_(is_async) {} + ~grpc_md_only_test_credentials() override { GRPC_MDELEM_UNREF(md_); } + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + private: + grpc_mdelem md_; + bool is_async_; +}; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.cc index 70d4c3ea5..b6a79c103 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -26,12 +26,17 @@ #include #include +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/http/httpcli.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/security/credentials/alts/alts_credentials.h" +#include "src/core/lib/security/credentials/alts/check_gcp_environment.h" #include "src/core/lib/security/credentials/google_default/google_default_credentials.h" #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" @@ -41,15 +46,23 @@ /* -- Constants. -- */ -#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" +#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal." /* -- Default credentials. -- */ -static grpc_channel_credentials* default_credentials = nullptr; -static int compute_engine_detection_done = 0; +/* A sticky bit that will be set only if the result of metadata server detection + * is positive. We do not set the bit if the result is negative. Because it + * means the detection is done via network test that is unreliable and the + * unreliable result should not be referred by successive calls. */ +static int g_metadata_server_available = 0; +static int g_is_on_gce = 0; static gpr_mu g_state_mu; +/* Protect a metadata_server_detector instance that can be modified by more than + * one gRPC threads */ static gpr_mu* g_polling_mu; static gpr_once g_once = GPR_ONCE_INIT; +static grpc_core::internal::grpc_gce_tenancy_checker g_gce_tenancy_checker = + grpc_alts_is_running_on_gcp; static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); } @@ -58,12 +71,66 @@ typedef struct { int is_done; int success; grpc_http_response response; -} compute_engine_detector; +} metadata_server_detector; + +grpc_core::RefCountedPtr +grpc_google_default_channel_credentials::create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target, const grpc_channel_args* args, + grpc_channel_args** new_args) { + bool is_grpclb_load_balancer = grpc_channel_arg_get_bool( + grpc_channel_args_find(args, GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), + false); + bool is_backend_from_grpclb_load_balancer = grpc_channel_arg_get_bool( + grpc_channel_args_find( + args, GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER), + false); + bool use_alts = + is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer; + /* Return failure if ALTS is selected but not running on GCE. */ + if (use_alts && !g_is_on_gce) { + gpr_log(GPR_ERROR, "ALTS is selected, but not running on GCE."); + return nullptr; + } + + grpc_core::RefCountedPtr sc = + use_alts ? alts_creds_->create_security_connector(call_creds, target, + args, new_args) + : ssl_creds_->create_security_connector(call_creds, target, args, + new_args); + /* grpclb-specific channel args are removed from the channel args set + * to ensure backends and fallback adresses will have the same set of channel + * args. By doing that, it guarantees the connections to backends will not be + * torn down and re-connected when switching in and out of fallback mode. + */ + if (use_alts) { + static const char* args_to_remove[] = { + GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER, + GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER, + }; + *new_args = grpc_channel_args_copy_and_add_and_remove( + args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), nullptr, 0); + } + return sc; +} + +grpc_channel_args* grpc_google_default_channel_credentials::update_arguments( + grpc_channel_args* args) { + grpc_channel_args* updated = args; + if (grpc_channel_args_find(args, GRPC_ARG_DNS_ENABLE_SRV_QUERIES) == + nullptr) { + grpc_arg new_srv_arg = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_DNS_ENABLE_SRV_QUERIES), true); + updated = grpc_channel_args_copy_and_add(args, &new_srv_arg, 1); + grpc_channel_args_destroy(args); + } + return updated; +} -static void on_compute_engine_detection_http_response(void* user_data, - grpc_error* error) { - compute_engine_detector* detector = - static_cast(user_data); +static void on_metadata_server_detection_http_response(void* user_data, + grpc_error* error) { + metadata_server_detector* detector = + static_cast(user_data); if (error == GRPC_ERROR_NONE && detector->response.status == 200 && detector->response.hdr_count > 0) { /* Internet providers can return a generic response to all requests, so @@ -91,44 +158,37 @@ static void destroy_pollset(void* p, grpc_error* e) { grpc_pollset_destroy(static_cast(p)); } -static int is_stack_running_on_compute_engine() { - compute_engine_detector detector; +static int is_metadata_server_reachable() { + metadata_server_detector detector; grpc_httpcli_request request; grpc_httpcli_context context; grpc_closure destroy_closure; - /* The http call is local. If it takes more than one sec, it is for sure not on compute engine. */ grpc_millis max_detection_delay = GPR_MS_PER_SEC; - grpc_pollset* pollset = static_cast(gpr_zalloc(grpc_pollset_size())); grpc_pollset_init(pollset, &g_polling_mu); detector.pollent = grpc_polling_entity_create_from_pollset(pollset); detector.is_done = 0; detector.success = 0; - memset(&detector.response, 0, sizeof(detector.response)); memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = (char*)GRPC_COMPUTE_ENGINE_DETECTION_HOST; request.http.path = (char*)"/"; - grpc_httpcli_context_init(&context); - grpc_resource_quota* resource_quota = grpc_resource_quota_create("google_default_credentials"); grpc_httpcli_get( &context, &detector.pollent, resource_quota, &request, grpc_core::ExecCtx::Get()->Now() + max_detection_delay, - GRPC_CLOSURE_CREATE(on_compute_engine_detection_http_response, &detector, + GRPC_CLOSURE_CREATE(on_metadata_server_detection_http_response, &detector, grpc_schedule_on_exec_ctx), &detector.response); grpc_resource_quota_unref_internal(resource_quota); - grpc_core::ExecCtx::Get()->Flush(); - /* Block until we get the response. This is not ideal but this should only be - called once for the lifetime of the process by the default credentials. */ + called once for the lifetime of the process by the default credentials. */ gpr_mu_lock(g_polling_mu); while (!detector.is_done) { grpc_pollset_worker* worker = nullptr; @@ -141,7 +201,6 @@ static int is_stack_running_on_compute_engine() { } } gpr_mu_unlock(g_polling_mu); - grpc_httpcli_context_destroy(&context); GRPC_CLOSURE_INIT(&destroy_closure, destroy_pollset, grpc_polling_entity_pollset(&detector.pollent), @@ -150,20 +209,18 @@ static int is_stack_running_on_compute_engine() { &destroy_closure); g_polling_mu = nullptr; grpc_core::ExecCtx::Get()->Flush(); - gpr_free(grpc_polling_entity_pollset(&detector.pollent)); grpc_http_response_destroy(&detector.response); - return detector.success; } /* Takes ownership of creds_path if not NULL. */ static grpc_error* create_default_creds_from_path( - char* creds_path, grpc_call_credentials** creds) { + char* creds_path, grpc_core::RefCountedPtr* creds) { grpc_json* json = nullptr; grpc_auth_json_key key; grpc_auth_refresh_token token; - grpc_call_credentials* result = nullptr; + grpc_core::RefCountedPtr result; grpc_slice creds_data = grpc_empty_slice(); grpc_error* error = GRPC_ERROR_NONE; if (creds_path == nullptr) { @@ -215,14 +272,14 @@ static grpc_error* create_default_creds_from_path( GPR_ASSERT((result == nullptr) + (error == GRPC_ERROR_NONE) == 1); if (creds_path != nullptr) gpr_free(creds_path); grpc_slice_unref_internal(creds_data); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); *creds = result; return error; } -grpc_channel_credentials* grpc_google_default_credentials_create(void) { +grpc_channel_credentials* grpc_google_default_credentials_create() { grpc_channel_credentials* result = nullptr; - grpc_call_credentials* call_creds = nullptr; + grpc_core::RefCountedPtr call_creds; grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to create Google credentials"); grpc_error* err; @@ -232,13 +289,6 @@ grpc_channel_credentials* grpc_google_default_credentials_create(void) { gpr_once_init(&g_once, init_default_credentials); - gpr_mu_lock(&g_state_mu); - - if (default_credentials != nullptr) { - result = grpc_channel_credentials_ref(default_credentials); - goto end; - } - /* First, try the environment variable. */ err = create_default_creds_from_path( gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds); @@ -251,62 +301,77 @@ grpc_channel_credentials* grpc_google_default_credentials_create(void) { if (err == GRPC_ERROR_NONE) goto end; error = grpc_error_add_child(error, err); - /* At last try to see if we're on compute engine (do the detection only once - since it requires a network test). */ - if (!compute_engine_detection_done) { - int need_compute_engine_creds = is_stack_running_on_compute_engine(); - compute_engine_detection_done = 1; - if (need_compute_engine_creds) { - call_creds = grpc_google_compute_engine_credentials_create(nullptr); - if (call_creds == nullptr) { - error = grpc_error_add_child( - error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Failed to get credentials from network")); - } - } + gpr_mu_lock(&g_state_mu); + + /* Try a platform-provided hint for GCE. */ + if (!g_metadata_server_available) { + g_is_on_gce = g_gce_tenancy_checker(); + g_metadata_server_available = g_is_on_gce; } + /* TODO: Add a platform-provided hint for GAE. */ -end: - if (result == nullptr) { - if (call_creds != nullptr) { - /* Blend with default ssl credentials and add a global reference so that - it - can be cached and re-served. */ - grpc_channel_credentials* ssl_creds = - grpc_ssl_credentials_create(nullptr, nullptr, nullptr); - default_credentials = grpc_channel_credentials_ref( - grpc_composite_channel_credentials_create(ssl_creds, call_creds, - nullptr)); - GPR_ASSERT(default_credentials != nullptr); - grpc_channel_credentials_unref(ssl_creds); - grpc_call_credentials_unref(call_creds); - result = default_credentials; - } else { - gpr_log(GPR_ERROR, "Could not create google default credentials."); - } + /* Do a network test for metadata server. */ + if (!g_metadata_server_available) { + g_metadata_server_available = is_metadata_server_reachable(); } gpr_mu_unlock(&g_state_mu); - if (result == nullptr) { - GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error); - } else { - GRPC_ERROR_UNREF(error); + + if (g_metadata_server_available) { + call_creds = grpc_core::RefCountedPtr( + grpc_google_compute_engine_credentials_create(nullptr)); + if (call_creds == nullptr) { + error = grpc_error_add_child( + error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Failed to get credentials from network")); + } } +end: + if (call_creds != nullptr) { + /* Create google default credentials. */ + grpc_channel_credentials* ssl_creds = + grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); + GPR_ASSERT(ssl_creds != nullptr); + grpc_alts_credentials_options* options = + grpc_alts_credentials_client_options_create(); + grpc_channel_credentials* alts_creds = + grpc_alts_credentials_create(options); + grpc_alts_credentials_options_destroy(options); + auto creds = + grpc_core::MakeRefCounted( + alts_creds != nullptr ? alts_creds->Ref() : nullptr, + ssl_creds != nullptr ? ssl_creds->Ref() : nullptr); + if (ssl_creds) ssl_creds->Unref(); + if (alts_creds) alts_creds->Unref(); + result = grpc_composite_channel_credentials_create( + creds.get(), call_creds.get(), nullptr); + GPR_ASSERT(result != nullptr); + } else { + gpr_log(GPR_ERROR, "Could not create google default credentials: %s", + grpc_error_string(error)); + } + GRPC_ERROR_UNREF(error); return result; } +namespace grpc_core { +namespace internal { + +void set_gce_tenancy_checker_for_testing(grpc_gce_tenancy_checker checker) { + g_gce_tenancy_checker = checker; +} + void grpc_flush_cached_google_default_credentials(void) { grpc_core::ExecCtx exec_ctx; gpr_once_init(&g_once, init_default_credentials); gpr_mu_lock(&g_state_mu); - if (default_credentials != nullptr) { - grpc_channel_credentials_unref(default_credentials); - default_credentials = nullptr; - } - compute_engine_detection_done = 0; + g_metadata_server_available = 0; gpr_mu_unlock(&g_state_mu); } +} // namespace internal +} // namespace grpc_core + /* -- Well known credentials path. -- */ static grpc_well_known_credentials_path_getter creds_path_getter = nullptr; diff --git a/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.h index b163e4863..8a945da31 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/google_default/google_default_credentials.h @@ -21,6 +21,7 @@ #include +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/credentials/credentials.h" #define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud" @@ -39,7 +40,48 @@ "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE #endif +class grpc_google_default_channel_credentials + : public grpc_channel_credentials { + public: + grpc_google_default_channel_credentials( + grpc_core::RefCountedPtr alts_creds, + grpc_core::RefCountedPtr ssl_creds) + : grpc_channel_credentials(GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT), + alts_creds_(std::move(alts_creds)), + ssl_creds_(std::move(ssl_creds)) {} + + ~grpc_google_default_channel_credentials() override = default; + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target, const grpc_channel_args* args, + grpc_channel_args** new_args) override; + + grpc_channel_args* update_arguments(grpc_channel_args* args) override; + + const grpc_channel_credentials* alts_creds() const { + return alts_creds_.get(); + } + const grpc_channel_credentials* ssl_creds() const { return ssl_creds_.get(); } + + private: + grpc_core::RefCountedPtr alts_creds_; + grpc_core::RefCountedPtr ssl_creds_; +}; + +namespace grpc_core { +namespace internal { + +typedef bool (*grpc_gce_tenancy_checker)(void); + +void set_gce_tenancy_checker_for_testing(grpc_gce_tenancy_checker checker); + +// TEST-ONLY. Reset the internal global state. void grpc_flush_cached_google_default_credentials(void); +} // namespace internal +} // namespace grpc_core + #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H \ */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.cc index 5d92fa88c..5cd561f67 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.cc @@ -22,6 +22,7 @@ #include +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/surface/api_trace.h" #include @@ -29,32 +30,37 @@ #include #include -static void iam_destruct(grpc_call_credentials* creds) { - grpc_google_iam_credentials* c = - reinterpret_cast(creds); - grpc_credentials_mdelem_array_destroy(&c->md_array); +grpc_google_iam_credentials::~grpc_google_iam_credentials() { + grpc_credentials_mdelem_array_destroy(&md_array_); } -static bool iam_get_request_metadata(grpc_call_credentials* creds, - grpc_polling_entity* pollent, - grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, - grpc_error** error) { - grpc_google_iam_credentials* c = - reinterpret_cast(creds); - grpc_credentials_mdelem_array_append(md_array, &c->md_array); +bool grpc_google_iam_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, + grpc_error** error) { + grpc_credentials_mdelem_array_append(md_array, &md_array_); return true; } -static void iam_cancel_get_request_metadata( - grpc_call_credentials* c, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { +void grpc_google_iam_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static grpc_call_credentials_vtable iam_vtable = { - iam_destruct, iam_get_request_metadata, iam_cancel_get_request_metadata}; +grpc_google_iam_credentials::grpc_google_iam_credentials( + const char* token, const char* authority_selector) + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_IAM) { + grpc_mdelem md = grpc_mdelem_from_slices( + grpc_slice_from_static_string(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), + grpc_slice_from_copied_string(token)); + grpc_credentials_mdelem_array_add(&md_array_, md); + GRPC_MDELEM_UNREF(md); + md = grpc_mdelem_from_slices( + grpc_slice_from_static_string(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), + grpc_slice_from_copied_string(authority_selector)); + grpc_credentials_mdelem_array_add(&md_array_, md); + GRPC_MDELEM_UNREF(md); +} grpc_call_credentials* grpc_google_iam_credentials_create( const char* token, const char* authority_selector, void* reserved) { @@ -66,21 +72,7 @@ grpc_call_credentials* grpc_google_iam_credentials_create( GPR_ASSERT(reserved == nullptr); GPR_ASSERT(token != nullptr); GPR_ASSERT(authority_selector != nullptr); - grpc_google_iam_credentials* c = - static_cast(gpr_zalloc(sizeof(*c))); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM; - c->base.vtable = &iam_vtable; - gpr_ref_init(&c->base.refcount, 1); - grpc_mdelem md = grpc_mdelem_from_slices( - grpc_slice_from_static_string(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), - grpc_slice_from_copied_string(token)); - grpc_credentials_mdelem_array_add(&c->md_array, md); - GRPC_MDELEM_UNREF(md); - md = grpc_mdelem_from_slices( - grpc_slice_from_static_string(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), - grpc_slice_from_copied_string(authority_selector)); - grpc_credentials_mdelem_array_add(&c->md_array, md); - GRPC_MDELEM_UNREF(md); - - return &c->base; + return grpc_core::MakeRefCounted( + token, authority_selector) + .release(); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.h index a45710fe0..36f5ee893 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/iam/iam_credentials.h @@ -23,9 +23,23 @@ #include "src/core/lib/security/credentials/credentials.h" -typedef struct { - grpc_call_credentials base; - grpc_credentials_mdelem_array md_array; -} grpc_google_iam_credentials; +class grpc_google_iam_credentials : public grpc_call_credentials { + public: + grpc_google_iam_credentials(const char* token, + const char* authority_selector); + ~grpc_google_iam_credentials() override; + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + private: + grpc_credentials_mdelem_array md_array_; +}; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.cc b/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.cc index 1c4827df0..113e2b837 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.cc @@ -121,7 +121,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string( char* scratchpad = gpr_strdup(json_string); grpc_json* json = grpc_json_parse_string(scratchpad); grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); gpr_free(scratchpad); return result; } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.h b/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.h index d0fb4ebd0..3ed990140 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/jwt/json_token.h @@ -21,6 +21,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include #include diff --git a/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.cc index 05c08a68b..70fe45e56 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.cc @@ -23,6 +23,8 @@ #include #include +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/surface/api_trace.h" #include @@ -30,71 +32,66 @@ #include #include -static void jwt_reset_cache(grpc_service_account_jwt_access_credentials* c) { - GRPC_MDELEM_UNREF(c->cached.jwt_md); - c->cached.jwt_md = GRPC_MDNULL; - if (c->cached.service_url != nullptr) { - gpr_free(c->cached.service_url); - c->cached.service_url = nullptr; +void grpc_service_account_jwt_access_credentials::reset_cache() { + GRPC_MDELEM_UNREF(cached_.jwt_md); + cached_.jwt_md = GRPC_MDNULL; + if (cached_.service_url != nullptr) { + gpr_free(cached_.service_url); + cached_.service_url = nullptr; } - c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); + cached_.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); } -static void jwt_destruct(grpc_call_credentials* creds) { - grpc_service_account_jwt_access_credentials* c = - reinterpret_cast(creds); - grpc_auth_json_key_destruct(&c->key); - jwt_reset_cache(c); - gpr_mu_destroy(&c->cache_mu); +grpc_service_account_jwt_access_credentials:: + ~grpc_service_account_jwt_access_credentials() { + grpc_auth_json_key_destruct(&key_); + reset_cache(); + gpr_mu_destroy(&cache_mu_); } -static bool jwt_get_request_metadata(grpc_call_credentials* creds, - grpc_polling_entity* pollent, - grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, - grpc_error** error) { - grpc_service_account_jwt_access_credentials* c = - reinterpret_cast(creds); +bool grpc_service_account_jwt_access_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, + grpc_error** error) { gpr_timespec refresh_threshold = gpr_time_from_seconds( GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); /* See if we can return a cached jwt. */ grpc_mdelem jwt_md = GRPC_MDNULL; { - gpr_mu_lock(&c->cache_mu); - if (c->cached.service_url != nullptr && - strcmp(c->cached.service_url, context.service_url) == 0 && - !GRPC_MDISNULL(c->cached.jwt_md) && - (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, - gpr_now(GPR_CLOCK_REALTIME)), - refresh_threshold) > 0)) { - jwt_md = GRPC_MDELEM_REF(c->cached.jwt_md); + gpr_mu_lock(&cache_mu_); + if (cached_.service_url != nullptr && + strcmp(cached_.service_url, context.service_url) == 0 && + !GRPC_MDISNULL(cached_.jwt_md) && + (gpr_time_cmp( + gpr_time_sub(cached_.jwt_expiration, gpr_now(GPR_CLOCK_REALTIME)), + refresh_threshold) > 0)) { + jwt_md = GRPC_MDELEM_REF(cached_.jwt_md); } - gpr_mu_unlock(&c->cache_mu); + gpr_mu_unlock(&cache_mu_); } if (GRPC_MDISNULL(jwt_md)) { char* jwt = nullptr; /* Generate a new jwt. */ - gpr_mu_lock(&c->cache_mu); - jwt_reset_cache(c); - jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url, - c->jwt_lifetime, nullptr); + gpr_mu_lock(&cache_mu_); + reset_cache(); + jwt = grpc_jwt_encode_and_sign(&key_, context.service_url, jwt_lifetime_, + nullptr); if (jwt != nullptr) { char* md_value; gpr_asprintf(&md_value, "Bearer %s", jwt); gpr_free(jwt); - c->cached.jwt_expiration = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime); - c->cached.service_url = gpr_strdup(context.service_url); - c->cached.jwt_md = grpc_mdelem_from_slices( + cached_.jwt_expiration = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), jwt_lifetime_); + cached_.service_url = gpr_strdup(context.service_url); + cached_.jwt_md = grpc_mdelem_from_slices( grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY), grpc_slice_from_copied_string(md_value)); gpr_free(md_value); - jwt_md = GRPC_MDELEM_REF(c->cached.jwt_md); + jwt_md = GRPC_MDELEM_REF(cached_.jwt_md); } - gpr_mu_unlock(&c->cache_mu); + gpr_mu_unlock(&cache_mu_); } if (!GRPC_MDISNULL(jwt_md)) { @@ -106,29 +103,15 @@ static bool jwt_get_request_metadata(grpc_call_credentials* creds, return true; } -static void jwt_cancel_get_request_metadata( - grpc_call_credentials* c, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { +void grpc_service_account_jwt_access_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static grpc_call_credentials_vtable jwt_vtable = { - jwt_destruct, jwt_get_request_metadata, jwt_cancel_get_request_metadata}; - -grpc_call_credentials* -grpc_service_account_jwt_access_credentials_create_from_auth_json_key( - grpc_auth_json_key key, gpr_timespec token_lifetime) { - grpc_service_account_jwt_access_credentials* c; - if (!grpc_auth_json_key_is_valid(&key)) { - gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); - return nullptr; - } - c = static_cast( - gpr_zalloc(sizeof(grpc_service_account_jwt_access_credentials))); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT; - gpr_ref_init(&c->base.refcount, 1); - c->base.vtable = &jwt_vtable; - c->key = key; +grpc_service_account_jwt_access_credentials:: + grpc_service_account_jwt_access_credentials(grpc_auth_json_key key, + gpr_timespec token_lifetime) + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_JWT), key_(key) { gpr_timespec max_token_lifetime = grpc_max_auth_token_lifetime(); if (gpr_time_cmp(token_lifetime, max_token_lifetime) > 0) { gpr_log(GPR_INFO, @@ -136,10 +119,20 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( static_cast(max_token_lifetime.tv_sec)); token_lifetime = grpc_max_auth_token_lifetime(); } - c->jwt_lifetime = token_lifetime; - gpr_mu_init(&c->cache_mu); - jwt_reset_cache(c); - return &c->base; + jwt_lifetime_ = token_lifetime; + gpr_mu_init(&cache_mu_); + reset_cache(); +} + +grpc_core::RefCountedPtr +grpc_service_account_jwt_access_credentials_create_from_auth_json_key( + grpc_auth_json_key key, gpr_timespec token_lifetime) { + if (!grpc_auth_json_key_is_valid(&key)) { + gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); + return nullptr; + } + return grpc_core::MakeRefCounted( + key, token_lifetime); } static char* redact_private_key(const char* json_key) { @@ -181,10 +174,9 @@ grpc_call_credentials* grpc_service_account_jwt_access_credentials_create( gpr_free(clean_json); } GPR_ASSERT(reserved == nullptr); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - grpc_call_credentials* creds = - grpc_service_account_jwt_access_credentials_create_from_auth_json_key( - grpc_auth_json_key_create_from_string(json_key), token_lifetime); - - return creds; + return grpc_service_account_jwt_access_credentials_create_from_auth_json_key( + grpc_auth_json_key_create_from_string(json_key), token_lifetime) + .release(); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.h index 5c3d34aa5..5af909f44 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_credentials.h @@ -24,25 +24,44 @@ #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/jwt/json_token.h" -typedef struct { - grpc_call_credentials base; +class grpc_service_account_jwt_access_credentials + : public grpc_call_credentials { + public: + grpc_service_account_jwt_access_credentials(grpc_auth_json_key key, + gpr_timespec token_lifetime); + ~grpc_service_account_jwt_access_credentials() override; + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + const gpr_timespec& jwt_lifetime() const { return jwt_lifetime_; } + const grpc_auth_json_key& key() const { return key_; } + + private: + void reset_cache(); // Have a simple cache for now with just 1 entry. We could have a map based on // the service_url for a more sophisticated one. - gpr_mu cache_mu; + gpr_mu cache_mu_; struct { - grpc_mdelem jwt_md; - char* service_url; + grpc_mdelem jwt_md = GRPC_MDNULL; + char* service_url = nullptr; gpr_timespec jwt_expiration; - } cached; + } cached_; - grpc_auth_json_key key; - gpr_timespec jwt_lifetime; -} grpc_service_account_jwt_access_credentials; + grpc_auth_json_key key_; + gpr_timespec jwt_lifetime_; +}; // Private constructor for jwt credentials from an already parsed json key. // Takes ownership of the key. -grpc_call_credentials* +grpc_core::RefCountedPtr grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_auth_json_key key, gpr_timespec token_lifetime); diff --git a/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_verifier.cc index 5c47276e3..303f13300 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -18,6 +18,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include "src/core/lib/security/credentials/jwt/jwt_verifier.h" #include @@ -29,7 +31,9 @@ #include extern "C" { +#include #include +#include } #include "src/core/lib/gpr/string.h" @@ -349,6 +353,7 @@ static verifier_cb_ctx* verifier_cb_ctx_create( grpc_jwt_claims* claims, const char* audience, grpc_slice signature, const char* signed_jwt, size_t signed_jwt_len, void* user_data, grpc_jwt_verification_done_cb cb) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; verifier_cb_ctx* ctx = static_cast(gpr_zalloc(sizeof(verifier_cb_ctx))); @@ -662,7 +667,7 @@ static void on_keys_retrieved(void* user_data, grpc_error* error) { } end: - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); EVP_PKEY_free(verification_key); ctx->user_cb(ctx->user_data, status, claims); verifier_cb_ctx_destroy(ctx); @@ -715,7 +720,7 @@ static void on_openid_config_retrieved(void* user_data, grpc_error* error) { return; error: - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, nullptr); verifier_cb_ctx_destroy(ctx); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/local/local_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/local/local_credentials.cc new file mode 100644 index 000000000..6f6f95a34 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/credentials/local/local_credentials.cc @@ -0,0 +1,64 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/credentials/local/local_credentials.h" + +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/security_connector/local/local_security_connector.h" + +#define GRPC_CREDENTIALS_TYPE_LOCAL "Local" + +grpc_core::RefCountedPtr +grpc_local_credentials::create_security_connector( + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const grpc_channel_args* args, + grpc_channel_args** new_args) { + return grpc_local_channel_security_connector_create( + this->Ref(), std::move(request_metadata_creds), args, target_name); +} + +grpc_core::RefCountedPtr +grpc_local_server_credentials::create_security_connector() { + return grpc_local_server_security_connector_create(this->Ref()); +} + +grpc_local_credentials::grpc_local_credentials( + grpc_local_connect_type connect_type) + : grpc_channel_credentials(GRPC_CREDENTIALS_TYPE_LOCAL), + connect_type_(connect_type) {} + +grpc_channel_credentials* grpc_local_credentials_create( + grpc_local_connect_type connect_type) { + return grpc_core::New(connect_type); +} + +grpc_local_server_credentials::grpc_local_server_credentials( + grpc_local_connect_type connect_type) + : grpc_server_credentials(GRPC_CREDENTIALS_TYPE_LOCAL), + connect_type_(connect_type) {} + +grpc_server_credentials* grpc_local_server_credentials_create( + grpc_local_connect_type connect_type) { + return grpc_core::New(connect_type); +} diff --git a/Sources/CgRPC/src/core/lib/security/credentials/local/local_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/local/local_credentials.h new file mode 100644 index 000000000..60a8a4f64 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/credentials/local/local_credentials.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_LOCAL_LOCAL_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_LOCAL_LOCAL_CREDENTIALS_H + +#include + +#include + +#include "src/core/lib/security/credentials/credentials.h" + +/* Main class for grpc local channel credential. */ +class grpc_local_credentials final : public grpc_channel_credentials { + public: + explicit grpc_local_credentials(grpc_local_connect_type connect_type); + ~grpc_local_credentials() override = default; + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const grpc_channel_args* args, + grpc_channel_args** new_args) override; + + grpc_local_connect_type connect_type() const { return connect_type_; } + + private: + grpc_local_connect_type connect_type_; +}; + +/* Main class for grpc local server credential. */ +class grpc_local_server_credentials final : public grpc_server_credentials { + public: + explicit grpc_local_server_credentials(grpc_local_connect_type connect_type); + ~grpc_local_server_credentials() override = default; + + grpc_core::RefCountedPtr + create_security_connector() override; + + grpc_local_connect_type connect_type() const { return connect_type_; } + + private: + grpc_local_connect_type connect_type_; +}; + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_LOCAL_LOCAL_CREDENTIALS_H */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc index 212902973..b9af757d0 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc @@ -22,6 +22,7 @@ #include +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/util/json_util.h" #include "src/core/lib/surface/api_trace.h" @@ -79,7 +80,7 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( grpc_json* json = grpc_json_parse_string(scratchpad); grpc_auth_refresh_token result = grpc_auth_refresh_token_create_from_json(json); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); gpr_free(scratchpad); return result; } @@ -105,13 +106,12 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token* refresh_token) { // Oauth2 Token Fetcher credentials. // -static void oauth2_token_fetcher_destruct(grpc_call_credentials* creds) { - grpc_oauth2_token_fetcher_credentials* c = - reinterpret_cast(creds); - GRPC_MDELEM_UNREF(c->access_token_md); - gpr_mu_destroy(&c->mu); - grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&c->pollent)); - grpc_httpcli_context_destroy(&c->httpcli_context); +grpc_oauth2_token_fetcher_credentials:: + ~grpc_oauth2_token_fetcher_credentials() { + GRPC_MDELEM_UNREF(access_token_md_); + gpr_mu_destroy(&mu_); + grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&pollent_)); + grpc_httpcli_context_destroy(&httpcli_context_); } grpc_credentials_status @@ -199,7 +199,7 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response( } if (null_terminated_body != nullptr) gpr_free(null_terminated_body); if (new_access_token != nullptr) gpr_free(new_access_token); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); return status; } @@ -209,23 +209,29 @@ static void on_oauth2_token_fetcher_http_response(void* user_data, grpc_credentials_metadata_request* r = static_cast(user_data); grpc_oauth2_token_fetcher_credentials* c = - reinterpret_cast(r->creds); + reinterpret_cast(r->creds.get()); + c->on_http_response(r, error); +} + +void grpc_oauth2_token_fetcher_credentials::on_http_response( + grpc_credentials_metadata_request* r, grpc_error* error) { grpc_mdelem access_token_md = GRPC_MDNULL; grpc_millis token_lifetime; grpc_credentials_status status = grpc_oauth2_token_fetcher_credentials_parse_server_response( &r->response, &access_token_md, &token_lifetime); // Update cache and grab list of pending requests. - gpr_mu_lock(&c->mu); - c->token_fetch_pending = false; - c->access_token_md = GRPC_MDELEM_REF(access_token_md); - c->token_expiration = status == GRPC_CREDENTIALS_OK - ? grpc_core::ExecCtx::Get()->Now() + token_lifetime - : 0; - grpc_oauth2_pending_get_request_metadata* pending_request = - c->pending_requests; - c->pending_requests = nullptr; - gpr_mu_unlock(&c->mu); + gpr_mu_lock(&mu_); + token_fetch_pending_ = false; + access_token_md_ = GRPC_MDELEM_REF(access_token_md); + token_expiration_ = + status == GRPC_CREDENTIALS_OK + ? gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(token_lifetime, GPR_TIMESPAN)) + : gpr_inf_past(GPR_CLOCK_MONOTONIC); + grpc_oauth2_pending_get_request_metadata* pending_request = pending_requests_; + pending_requests_ = nullptr; + gpr_mu_unlock(&mu_); // Invoke callbacks for all pending requests. while (pending_request != nullptr) { if (status == GRPC_CREDENTIALS_OK) { @@ -233,44 +239,44 @@ static void on_oauth2_token_fetcher_http_response(void* user_data, access_token_md); } else { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occured when fetching oauth2 token.", &error, 1); + "Error occurred when fetching oauth2 token.", &error, 1); } GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, error); grpc_polling_entity_del_from_pollset_set( - pending_request->pollent, grpc_polling_entity_pollset_set(&c->pollent)); + pending_request->pollent, grpc_polling_entity_pollset_set(&pollent_)); grpc_oauth2_pending_get_request_metadata* prev = pending_request; pending_request = pending_request->next; gpr_free(prev); } GRPC_MDELEM_UNREF(access_token_md); - grpc_call_credentials_unref(r->creds); + Unref(); grpc_credentials_metadata_request_destroy(r); } -static bool oauth2_token_fetcher_get_request_metadata( - grpc_call_credentials* creds, grpc_polling_entity* pollent, - grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, grpc_error** error) { - grpc_oauth2_token_fetcher_credentials* c = - reinterpret_cast(creds); +bool grpc_oauth2_token_fetcher_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, + grpc_error** error) { // Check if we can use the cached token. grpc_millis refresh_threshold = GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS * GPR_MS_PER_SEC; grpc_mdelem cached_access_token_md = GRPC_MDNULL; - gpr_mu_lock(&c->mu); - if (!GRPC_MDISNULL(c->access_token_md) && - (c->token_expiration - grpc_core::ExecCtx::Get()->Now() > - refresh_threshold)) { - cached_access_token_md = GRPC_MDELEM_REF(c->access_token_md); + gpr_mu_lock(&mu_); + if (!GRPC_MDISNULL(access_token_md_) && + gpr_time_cmp( + gpr_time_sub(token_expiration_, gpr_now(GPR_CLOCK_MONOTONIC)), + gpr_time_from_seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, + GPR_TIMESPAN)) > 0) { + cached_access_token_md = GRPC_MDELEM_REF(access_token_md_); } if (!GRPC_MDISNULL(cached_access_token_md)) { - gpr_mu_unlock(&c->mu); + gpr_mu_unlock(&mu_); grpc_credentials_mdelem_array_add(md_array, cached_access_token_md); GRPC_MDELEM_UNREF(cached_access_token_md); return true; } // Couldn't get the token from the cache. - // Add request to c->pending_requests and start a new fetch if needed. + // Add request to pending_requests_ and start a new fetch if needed. grpc_oauth2_pending_get_request_metadata* pending_request = static_cast( gpr_malloc(sizeof(*pending_request))); @@ -278,41 +284,37 @@ static bool oauth2_token_fetcher_get_request_metadata( pending_request->on_request_metadata = on_request_metadata; pending_request->pollent = pollent; grpc_polling_entity_add_to_pollset_set( - pollent, grpc_polling_entity_pollset_set(&c->pollent)); - pending_request->next = c->pending_requests; - c->pending_requests = pending_request; + pollent, grpc_polling_entity_pollset_set(&pollent_)); + pending_request->next = pending_requests_; + pending_requests_ = pending_request; bool start_fetch = false; - if (!c->token_fetch_pending) { - c->token_fetch_pending = true; + if (!token_fetch_pending_) { + token_fetch_pending_ = true; start_fetch = true; } - gpr_mu_unlock(&c->mu); + gpr_mu_unlock(&mu_); if (start_fetch) { - grpc_call_credentials_ref(creds); - c->fetch_func(grpc_credentials_metadata_request_create(creds), - &c->httpcli_context, &c->pollent, - on_oauth2_token_fetcher_http_response, - grpc_core::ExecCtx::Get()->Now() + refresh_threshold); + Ref().release(); + fetch_oauth2(grpc_credentials_metadata_request_create(this->Ref()), + &httpcli_context_, &pollent_, + on_oauth2_token_fetcher_http_response, + grpc_core::ExecCtx::Get()->Now() + refresh_threshold); } return false; } -static void oauth2_token_fetcher_cancel_get_request_metadata( - grpc_call_credentials* creds, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { - grpc_oauth2_token_fetcher_credentials* c = - reinterpret_cast(creds); - gpr_mu_lock(&c->mu); +void grpc_oauth2_token_fetcher_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { + gpr_mu_lock(&mu_); grpc_oauth2_pending_get_request_metadata* prev = nullptr; - grpc_oauth2_pending_get_request_metadata* pending_request = - c->pending_requests; + grpc_oauth2_pending_get_request_metadata* pending_request = pending_requests_; while (pending_request != nullptr) { if (pending_request->md_array == md_array) { // Remove matching pending request from the list. if (prev != nullptr) { prev->next = pending_request->next; } else { - c->pending_requests = pending_request->next; + pending_requests_ = pending_request->next; } // Invoke the callback immediately with an error. GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, @@ -323,96 +325,89 @@ static void oauth2_token_fetcher_cancel_get_request_metadata( prev = pending_request; pending_request = pending_request->next; } - gpr_mu_unlock(&c->mu); + gpr_mu_unlock(&mu_); GRPC_ERROR_UNREF(error); } -static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials* c, - grpc_fetch_oauth2_func fetch_func) { - memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; - gpr_ref_init(&c->base.refcount, 1); - gpr_mu_init(&c->mu); - c->token_expiration = 0; - c->fetch_func = fetch_func; - c->pollent = - grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create()); - grpc_httpcli_context_init(&c->httpcli_context); +grpc_oauth2_token_fetcher_credentials::grpc_oauth2_token_fetcher_credentials() + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2), + token_expiration_(gpr_inf_past(GPR_CLOCK_MONOTONIC)), + pollent_(grpc_polling_entity_create_from_pollset_set( + grpc_pollset_set_create())) { + gpr_mu_init(&mu_); + grpc_httpcli_context_init(&httpcli_context_); } // // Google Compute Engine credentials. // -static grpc_call_credentials_vtable compute_engine_vtable = { - oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata, - oauth2_token_fetcher_cancel_get_request_metadata}; +namespace { + +class grpc_compute_engine_token_fetcher_credentials + : public grpc_oauth2_token_fetcher_credentials { + public: + grpc_compute_engine_token_fetcher_credentials() = default; + ~grpc_compute_engine_token_fetcher_credentials() override = default; + + protected: + void fetch_oauth2(grpc_credentials_metadata_request* metadata_req, + grpc_httpcli_context* http_context, + grpc_polling_entity* pollent, + grpc_iomgr_cb_func response_cb, + grpc_millis deadline) override { + grpc_http_header header = {(char*)"Metadata-Flavor", (char*)"Google"}; + grpc_httpcli_request request; + memset(&request, 0, sizeof(grpc_httpcli_request)); + request.host = (char*)GRPC_COMPUTE_ENGINE_METADATA_HOST; + request.http.path = (char*)GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH; + request.http.hdr_count = 1; + request.http.hdrs = &header; + /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host + channel. This would allow us to cancel an authentication query when under + extreme memory pressure. */ + grpc_resource_quota* resource_quota = + grpc_resource_quota_create("oauth2_credentials"); + grpc_httpcli_get(http_context, pollent, resource_quota, &request, deadline, + GRPC_CLOSURE_CREATE(response_cb, metadata_req, + grpc_schedule_on_exec_ctx), + &metadata_req->response); + grpc_resource_quota_unref_internal(resource_quota); + } +}; -static void compute_engine_fetch_oauth2( - grpc_credentials_metadata_request* metadata_req, - grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, - grpc_iomgr_cb_func response_cb, grpc_millis deadline) { - grpc_http_header header = {(char*)"Metadata-Flavor", (char*)"Google"}; - grpc_httpcli_request request; - memset(&request, 0, sizeof(grpc_httpcli_request)); - request.host = (char*)GRPC_COMPUTE_ENGINE_METADATA_HOST; - request.http.path = (char*)GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH; - request.http.hdr_count = 1; - request.http.hdrs = &header; - /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host - channel. This would allow us to cancel an authentication query when under - extreme memory pressure. */ - grpc_resource_quota* resource_quota = - grpc_resource_quota_create("oauth2_credentials"); - grpc_httpcli_get( - httpcli_context, pollent, resource_quota, &request, deadline, - GRPC_CLOSURE_CREATE(response_cb, metadata_req, grpc_schedule_on_exec_ctx), - &metadata_req->response); - grpc_resource_quota_unref_internal(resource_quota); -} +} // namespace grpc_call_credentials* grpc_google_compute_engine_credentials_create( void* reserved) { - grpc_oauth2_token_fetcher_credentials* c = - static_cast( - gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials))); GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1, (reserved)); GPR_ASSERT(reserved == nullptr); - init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2); - c->base.vtable = &compute_engine_vtable; - return &c->base; + return grpc_core::MakeRefCounted< + grpc_compute_engine_token_fetcher_credentials>() + .release(); } // // Google Refresh Token credentials. // -static void refresh_token_destruct(grpc_call_credentials* creds) { - grpc_google_refresh_token_credentials* c = - reinterpret_cast(creds); - grpc_auth_refresh_token_destruct(&c->refresh_token); - oauth2_token_fetcher_destruct(&c->base.base); +grpc_google_refresh_token_credentials:: + ~grpc_google_refresh_token_credentials() { + grpc_auth_refresh_token_destruct(&refresh_token_); } -static grpc_call_credentials_vtable refresh_token_vtable = { - refresh_token_destruct, oauth2_token_fetcher_get_request_metadata, - oauth2_token_fetcher_cancel_get_request_metadata}; - -static void refresh_token_fetch_oauth2( +void grpc_google_refresh_token_credentials::fetch_oauth2( grpc_credentials_metadata_request* metadata_req, grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, grpc_iomgr_cb_func response_cb, grpc_millis deadline) { - grpc_google_refresh_token_credentials* c = - reinterpret_cast( - metadata_req->creds); grpc_http_header header = {(char*)"Content-Type", (char*)"application/x-www-form-urlencoded"}; grpc_httpcli_request request; char* body = nullptr; gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, - c->refresh_token.client_id, c->refresh_token.client_secret, - c->refresh_token.refresh_token); + refresh_token_.client_id, refresh_token_.client_secret, + refresh_token_.refresh_token); memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = (char*)GRPC_GOOGLE_OAUTH2_SERVICE_HOST; request.http.path = (char*)GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH; @@ -433,20 +428,19 @@ static void refresh_token_fetch_oauth2( gpr_free(body); } -grpc_call_credentials* +grpc_google_refresh_token_credentials::grpc_google_refresh_token_credentials( + grpc_auth_refresh_token refresh_token) + : refresh_token_(refresh_token) {} + +grpc_core::RefCountedPtr grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token refresh_token) { - grpc_google_refresh_token_credentials* c; if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); return nullptr; } - c = static_cast( - gpr_zalloc(sizeof(grpc_google_refresh_token_credentials))); - init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2); - c->base.base.vtable = &refresh_token_vtable; - c->refresh_token = refresh_token; - return &c->base.base; + return grpc_core::MakeRefCounted( + refresh_token); } static char* create_loggable_refresh_token(grpc_auth_refresh_token* token) { @@ -474,59 +468,50 @@ grpc_call_credentials* grpc_google_refresh_token_credentials_create( gpr_free(loggable_token); } GPR_ASSERT(reserved == nullptr); - return grpc_refresh_token_credentials_create_from_auth_refresh_token(token); + return grpc_refresh_token_credentials_create_from_auth_refresh_token(token) + .release(); } // // Oauth2 Access Token credentials. // -static void access_token_destruct(grpc_call_credentials* creds) { - grpc_access_token_credentials* c = - reinterpret_cast(creds); - GRPC_MDELEM_UNREF(c->access_token_md); +grpc_access_token_credentials::~grpc_access_token_credentials() { + GRPC_MDELEM_UNREF(access_token_md_); } -static bool access_token_get_request_metadata( - grpc_call_credentials* creds, grpc_polling_entity* pollent, - grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, grpc_error** error) { - grpc_access_token_credentials* c = - reinterpret_cast(creds); - grpc_credentials_mdelem_array_add(md_array, c->access_token_md); +bool grpc_access_token_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, + grpc_error** error) { + grpc_credentials_mdelem_array_add(md_array, access_token_md_); return true; } -static void access_token_cancel_get_request_metadata( - grpc_call_credentials* c, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { +void grpc_access_token_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static grpc_call_credentials_vtable access_token_vtable = { - access_token_destruct, access_token_get_request_metadata, - access_token_cancel_get_request_metadata}; +grpc_access_token_credentials::grpc_access_token_credentials( + const char* access_token) + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) { + char* token_md_value; + gpr_asprintf(&token_md_value, "Bearer %s", access_token); + grpc_core::ExecCtx exec_ctx; + access_token_md_ = grpc_mdelem_from_slices( + grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY), + grpc_slice_from_copied_string(token_md_value)); + gpr_free(token_md_value); +} grpc_call_credentials* grpc_access_token_credentials_create( const char* access_token, void* reserved) { - grpc_access_token_credentials* c = - static_cast( - gpr_zalloc(sizeof(grpc_access_token_credentials))); GRPC_API_TRACE( "grpc_access_token_credentials_create(access_token=, " "reserved=%p)", 1, (reserved)); GPR_ASSERT(reserved == nullptr); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; - c->base.vtable = &access_token_vtable; - gpr_ref_init(&c->base.refcount, 1); - char* token_md_value; - gpr_asprintf(&token_md_value, "Bearer %s", access_token); - grpc_core::ExecCtx exec_ctx; - c->access_token_md = grpc_mdelem_from_slices( - grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY), - grpc_slice_from_copied_string(token_md_value)); - - gpr_free(token_md_value); - return &c->base; + return grpc_core::MakeRefCounted(access_token) + .release(); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.h index c0dd1546e..510a78b48 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/oauth2/oauth2_credentials.h @@ -54,46 +54,91 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token* refresh_token); // This object is a base for credentials that need to acquire an oauth2 token // from an http service. -typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request* req, - grpc_httpcli_context* http_context, - grpc_polling_entity* pollent, - grpc_iomgr_cb_func cb, - grpc_millis deadline); - -typedef struct grpc_oauth2_pending_get_request_metadata { +struct grpc_oauth2_pending_get_request_metadata { grpc_credentials_mdelem_array* md_array; grpc_closure* on_request_metadata; grpc_polling_entity* pollent; struct grpc_oauth2_pending_get_request_metadata* next; -} grpc_oauth2_pending_get_request_metadata; - -typedef struct { - grpc_call_credentials base; - gpr_mu mu; - grpc_mdelem access_token_md; - grpc_millis token_expiration; - bool token_fetch_pending; - grpc_oauth2_pending_get_request_metadata* pending_requests; - grpc_httpcli_context httpcli_context; - grpc_fetch_oauth2_func fetch_func; - grpc_polling_entity pollent; -} grpc_oauth2_token_fetcher_credentials; +}; + +class grpc_oauth2_token_fetcher_credentials : public grpc_call_credentials { + public: + grpc_oauth2_token_fetcher_credentials(); + ~grpc_oauth2_token_fetcher_credentials() override; + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + void on_http_response(grpc_credentials_metadata_request* r, + grpc_error* error); + + GRPC_ABSTRACT_BASE_CLASS + + protected: + virtual void fetch_oauth2(grpc_credentials_metadata_request* req, + grpc_httpcli_context* httpcli_context, + grpc_polling_entity* pollent, grpc_iomgr_cb_func cb, + grpc_millis deadline) GRPC_ABSTRACT; + + private: + gpr_mu mu_; + grpc_mdelem access_token_md_ = GRPC_MDNULL; + gpr_timespec token_expiration_; + bool token_fetch_pending_ = false; + grpc_oauth2_pending_get_request_metadata* pending_requests_ = nullptr; + grpc_httpcli_context httpcli_context_; + grpc_polling_entity pollent_; +}; // Google refresh token credentials. -typedef struct { - grpc_oauth2_token_fetcher_credentials base; - grpc_auth_refresh_token refresh_token; -} grpc_google_refresh_token_credentials; +class grpc_google_refresh_token_credentials final + : public grpc_oauth2_token_fetcher_credentials { + public: + grpc_google_refresh_token_credentials(grpc_auth_refresh_token refresh_token); + ~grpc_google_refresh_token_credentials() override; + + const grpc_auth_refresh_token& refresh_token() const { + return refresh_token_; + } + + protected: + void fetch_oauth2(grpc_credentials_metadata_request* req, + grpc_httpcli_context* httpcli_context, + grpc_polling_entity* pollent, grpc_iomgr_cb_func cb, + grpc_millis deadline) override; + + private: + grpc_auth_refresh_token refresh_token_; +}; // Access token credentials. -typedef struct { - grpc_call_credentials base; - grpc_mdelem access_token_md; -} grpc_access_token_credentials; +class grpc_access_token_credentials final : public grpc_call_credentials { + public: + grpc_access_token_credentials(const char* access_token); + ~grpc_access_token_credentials() override; + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + private: + grpc_mdelem access_token_md_; +}; // Private constructor for refresh token credentials from an already parsed // refresh token. Takes ownership of the refresh token. -grpc_call_credentials* +grpc_core::RefCountedPtr grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token token); diff --git a/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.cc index 73946ce03..59fecbca9 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.cc @@ -35,20 +35,17 @@ grpc_core::TraceFlag grpc_plugin_credentials_trace(false, "plugin_credentials"); -static void plugin_destruct(grpc_call_credentials* creds) { - grpc_plugin_credentials* c = - reinterpret_cast(creds); - gpr_mu_destroy(&c->mu); - if (c->plugin.state != nullptr && c->plugin.destroy != nullptr) { - c->plugin.destroy(c->plugin.state); +grpc_plugin_credentials::~grpc_plugin_credentials() { + gpr_mu_destroy(&mu_); + if (plugin_.state != nullptr && plugin_.destroy != nullptr) { + plugin_.destroy(plugin_.state); } } -static void pending_request_remove_locked( - grpc_plugin_credentials* c, - grpc_plugin_credentials_pending_request* pending_request) { +void grpc_plugin_credentials::pending_request_remove_locked( + pending_request* pending_request) { if (pending_request->prev == nullptr) { - c->pending_requests = pending_request->next; + pending_requests_ = pending_request->next; } else { pending_request->prev->next = pending_request->next; } @@ -62,17 +59,17 @@ static void pending_request_remove_locked( // cancelled out from under us. // When this returns, r->cancelled indicates whether the request was // cancelled before completion. -static void pending_request_complete( - grpc_plugin_credentials_pending_request* r) { - gpr_mu_lock(&r->creds->mu); - if (!r->cancelled) pending_request_remove_locked(r->creds, r); - gpr_mu_unlock(&r->creds->mu); +void grpc_plugin_credentials::pending_request_complete(pending_request* r) { + GPR_DEBUG_ASSERT(r->creds == this); + gpr_mu_lock(&mu_); + if (!r->cancelled) pending_request_remove_locked(r); + gpr_mu_unlock(&mu_); // Ref to credentials not needed anymore. - grpc_call_credentials_unref(&r->creds->base); + Unref(); } static grpc_error* process_plugin_result( - grpc_plugin_credentials_pending_request* r, const grpc_metadata* md, + grpc_plugin_credentials::pending_request* r, const grpc_metadata* md, size_t num_md, grpc_status_code status, const char* error_details) { grpc_error* error = GRPC_ERROR_NONE; if (status != GRPC_STATUS_OK) { @@ -102,8 +99,7 @@ static grpc_error* process_plugin_result( } else { for (size_t i = 0; i < num_md; ++i) { grpc_mdelem mdelem = - grpc_mdelem_from_slices(grpc_slice_ref_internal(md[i].key), - grpc_slice_ref_internal(md[i].value)); + grpc_mdelem_create(md[i].key, md[i].value, nullptr); grpc_credentials_mdelem_array_add(r->md_array, mdelem); GRPC_MDELEM_UNREF(mdelem); } @@ -118,10 +114,11 @@ static void plugin_md_request_metadata_ready(void* request, grpc_status_code status, const char* error_details) { /* called from application code */ + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP); - grpc_plugin_credentials_pending_request* r = - static_cast(request); + grpc_plugin_credentials::pending_request* r = + static_cast(request); if (grpc_plugin_credentials_trace.enabled()) { gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p: plugin returned " @@ -129,7 +126,7 @@ static void plugin_md_request_metadata_ready(void* request, r->creds, r); } // Remove request from pending list if not previously cancelled. - pending_request_complete(r); + r->creds->pending_request_complete(r); // If it has not been cancelled, process it. if (!r->cancelled) { grpc_error* error = @@ -144,65 +141,59 @@ static void plugin_md_request_metadata_ready(void* request, gpr_free(r); } -static bool plugin_get_request_metadata(grpc_call_credentials* creds, - grpc_polling_entity* pollent, - grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, - grpc_error** error) { - grpc_plugin_credentials* c = - reinterpret_cast(creds); +bool grpc_plugin_credentials::get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, + grpc_error** error) { bool retval = true; // Synchronous return. - if (c->plugin.get_metadata != nullptr) { + if (plugin_.get_metadata != nullptr) { // Create pending_request object. - grpc_plugin_credentials_pending_request* pending_request = - static_cast( - gpr_zalloc(sizeof(*pending_request))); - pending_request->creds = c; - pending_request->md_array = md_array; - pending_request->on_request_metadata = on_request_metadata; + pending_request* request = + static_cast(gpr_zalloc(sizeof(*request))); + request->creds = this; + request->md_array = md_array; + request->on_request_metadata = on_request_metadata; // Add it to the pending list. - gpr_mu_lock(&c->mu); - if (c->pending_requests != nullptr) { - c->pending_requests->prev = pending_request; + gpr_mu_lock(&mu_); + if (pending_requests_ != nullptr) { + pending_requests_->prev = request; } - pending_request->next = c->pending_requests; - c->pending_requests = pending_request; - gpr_mu_unlock(&c->mu); + request->next = pending_requests_; + pending_requests_ = request; + gpr_mu_unlock(&mu_); // Invoke the plugin. The callback holds a ref to us. if (grpc_plugin_credentials_trace.enabled()) { gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p: invoking plugin", - c, pending_request); + this, request); } - grpc_call_credentials_ref(creds); + Ref().release(); grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX]; size_t num_creds_md = 0; grpc_status_code status = GRPC_STATUS_OK; const char* error_details = nullptr; - if (!c->plugin.get_metadata(c->plugin.state, context, - plugin_md_request_metadata_ready, - pending_request, creds_md, &num_creds_md, - &status, &error_details)) { + if (!plugin_.get_metadata( + plugin_.state, context, plugin_md_request_metadata_ready, request, + creds_md, &num_creds_md, &status, &error_details)) { if (grpc_plugin_credentials_trace.enabled()) { gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p: plugin will return " "asynchronously", - c, pending_request); + this, request); } return false; // Asynchronous return. } // Returned synchronously. // Remove request from pending list if not previously cancelled. - pending_request_complete(pending_request); + request->creds->pending_request_complete(request); // If the request was cancelled, the error will have been returned // asynchronously by plugin_cancel_get_request_metadata(), so return // false. Otherwise, process the result. - if (pending_request->cancelled) { + if (request->cancelled) { if (grpc_plugin_credentials_trace.enabled()) { gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p was cancelled, error " "will be returned asynchronously", - c, pending_request); + this, request); } retval = false; } else { @@ -210,10 +201,10 @@ static bool plugin_get_request_metadata(grpc_call_credentials* creds, gpr_log(GPR_INFO, "plugin_credentials[%p]: request %p: plugin returned " "synchronously", - c, pending_request); + this, request); } - *error = process_plugin_result(pending_request, creds_md, num_creds_md, - status, error_details); + *error = process_plugin_result(request, creds_md, num_creds_md, status, + error_details); } // Clean up. for (size_t i = 0; i < num_creds_md; ++i) { @@ -221,51 +212,42 @@ static bool plugin_get_request_metadata(grpc_call_credentials* creds, grpc_slice_unref_internal(creds_md[i].value); } gpr_free((void*)error_details); - gpr_free(pending_request); + gpr_free(request); } return retval; } -static void plugin_cancel_get_request_metadata( - grpc_call_credentials* creds, grpc_credentials_mdelem_array* md_array, - grpc_error* error) { - grpc_plugin_credentials* c = - reinterpret_cast(creds); - gpr_mu_lock(&c->mu); - for (grpc_plugin_credentials_pending_request* pending_request = - c->pending_requests; +void grpc_plugin_credentials::cancel_get_request_metadata( + grpc_credentials_mdelem_array* md_array, grpc_error* error) { + gpr_mu_lock(&mu_); + for (pending_request* pending_request = pending_requests_; pending_request != nullptr; pending_request = pending_request->next) { if (pending_request->md_array == md_array) { if (grpc_plugin_credentials_trace.enabled()) { - gpr_log(GPR_INFO, "plugin_credentials[%p]: cancelling request %p", c, + gpr_log(GPR_INFO, "plugin_credentials[%p]: cancelling request %p", this, pending_request); } pending_request->cancelled = true; GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, GRPC_ERROR_REF(error)); - pending_request_remove_locked(c, pending_request); + pending_request_remove_locked(pending_request); break; } } - gpr_mu_unlock(&c->mu); + gpr_mu_unlock(&mu_); GRPC_ERROR_UNREF(error); } -static grpc_call_credentials_vtable plugin_vtable = { - plugin_destruct, plugin_get_request_metadata, - plugin_cancel_get_request_metadata}; +grpc_plugin_credentials::grpc_plugin_credentials( + grpc_metadata_credentials_plugin plugin) + : grpc_call_credentials(plugin.type), plugin_(plugin) { + gpr_mu_init(&mu_); +} grpc_call_credentials* grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void* reserved) { - grpc_plugin_credentials* c = - static_cast(gpr_zalloc(sizeof(*c))); GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1, (reserved)); GPR_ASSERT(reserved == nullptr); - c->base.type = plugin.type; - c->base.vtable = &plugin_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->plugin = plugin; - gpr_mu_init(&c->mu); - return &c->base; + return grpc_core::New(plugin); } diff --git a/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.h index caf990efa..77a957e51 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/plugin/plugin_credentials.h @@ -25,22 +25,45 @@ extern grpc_core::TraceFlag grpc_plugin_credentials_trace; -struct grpc_plugin_credentials; - -typedef struct grpc_plugin_credentials_pending_request { - bool cancelled; - struct grpc_plugin_credentials* creds; - grpc_credentials_mdelem_array* md_array; - grpc_closure* on_request_metadata; - struct grpc_plugin_credentials_pending_request* prev; - struct grpc_plugin_credentials_pending_request* next; -} grpc_plugin_credentials_pending_request; - -typedef struct grpc_plugin_credentials { - grpc_call_credentials base; - grpc_metadata_credentials_plugin plugin; - gpr_mu mu; - grpc_plugin_credentials_pending_request* pending_requests; -} grpc_plugin_credentials; +// This type is forward declared as a C struct and we cannot define it as a +// class. Otherwise, compiler will complain about type mismatch due to +// -Wmismatched-tags. +struct grpc_plugin_credentials final : public grpc_call_credentials { + public: + struct pending_request { + bool cancelled; + struct grpc_plugin_credentials* creds; + grpc_credentials_mdelem_array* md_array; + grpc_closure* on_request_metadata; + struct pending_request* prev; + struct pending_request* next; + }; + + explicit grpc_plugin_credentials(grpc_metadata_credentials_plugin plugin); + ~grpc_plugin_credentials() override; + + bool get_request_metadata(grpc_polling_entity* pollent, + grpc_auth_metadata_context context, + grpc_credentials_mdelem_array* md_array, + grpc_closure* on_request_metadata, + grpc_error** error) override; + + void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, + grpc_error* error) override; + + // Checks if the request has been cancelled. + // If not, removes it from the pending list, so that it cannot be + // cancelled out from under us. + // When this returns, r->cancelled indicates whether the request was + // cancelled before completion. + void pending_request_complete(pending_request* r); + + private: + void pending_request_remove_locked(pending_request* pending_request); + + grpc_metadata_credentials_plugin plugin_; + gpr_mu mu_; + pending_request* pending_requests_ = nullptr; +}; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H */ diff --git a/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.cc index 2b6377d3e..83db86f1e 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.cc +++ b/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.cc @@ -44,18 +44,27 @@ void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair* kp, gpr_free(kp); } -static void ssl_destruct(grpc_channel_credentials* creds) { - grpc_ssl_credentials* c = reinterpret_cast(creds); - gpr_free(c->config.pem_root_certs); - grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1); +grpc_ssl_credentials::grpc_ssl_credentials( + const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, + const verify_peer_options* verify_options) + : grpc_channel_credentials(GRPC_CHANNEL_CREDENTIALS_TYPE_SSL) { + build_config(pem_root_certs, pem_key_cert_pair, verify_options); +} + +grpc_ssl_credentials::~grpc_ssl_credentials() { + gpr_free(config_.pem_root_certs); + grpc_tsi_ssl_pem_key_cert_pairs_destroy(config_.pem_key_cert_pair, 1); + if (config_.verify_options.verify_peer_destruct != nullptr) { + config_.verify_options.verify_peer_destruct( + config_.verify_options.verify_peer_callback_userdata); + } } -static grpc_security_status ssl_create_security_connector( - grpc_channel_credentials* creds, grpc_call_credentials* call_creds, +grpc_core::RefCountedPtr +grpc_ssl_credentials::create_security_connector( + grpc_core::RefCountedPtr call_creds, const char* target, const grpc_channel_args* args, - grpc_channel_security_connector** sc, grpc_channel_args** new_args) { - grpc_ssl_credentials* c = reinterpret_cast(creds); - grpc_security_status status = GRPC_SECURITY_OK; + grpc_channel_args** new_args) { const char* overridden_target_name = nullptr; tsi_ssl_session_cache* ssl_session_cache = nullptr; for (size_t i = 0; args && i < args->num_args; i++) { @@ -70,55 +79,57 @@ static grpc_security_status ssl_create_security_connector( static_cast(arg->value.pointer.p); } } - status = grpc_ssl_channel_security_connector_create( - creds, call_creds, &c->config, target, overridden_target_name, - ssl_session_cache, sc); - if (status != GRPC_SECURITY_OK) { - return status; + grpc_core::RefCountedPtr sc = + grpc_ssl_channel_security_connector_create( + this->Ref(), std::move(call_creds), &config_, target, + overridden_target_name, ssl_session_cache); + if (sc == nullptr) { + return sc; } grpc_arg new_arg = grpc_channel_arg_string_create( (char*)GRPC_ARG_HTTP2_SCHEME, (char*)"https"); *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); - return status; + return sc; } -static grpc_channel_credentials_vtable ssl_vtable = { - ssl_destruct, ssl_create_security_connector, nullptr}; - -static void ssl_build_config(const char* pem_root_certs, - grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, - grpc_ssl_config* config) { - if (pem_root_certs != nullptr) { - config->pem_root_certs = gpr_strdup(pem_root_certs); - } +void grpc_ssl_credentials::build_config( + const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, + const verify_peer_options* verify_options) { + config_.pem_root_certs = gpr_strdup(pem_root_certs); if (pem_key_cert_pair != nullptr) { GPR_ASSERT(pem_key_cert_pair->private_key != nullptr); GPR_ASSERT(pem_key_cert_pair->cert_chain != nullptr); - config->pem_key_cert_pair = static_cast( + config_.pem_key_cert_pair = static_cast( gpr_zalloc(sizeof(tsi_ssl_pem_key_cert_pair))); - config->pem_key_cert_pair->cert_chain = + config_.pem_key_cert_pair->cert_chain = gpr_strdup(pem_key_cert_pair->cert_chain); - config->pem_key_cert_pair->private_key = + config_.pem_key_cert_pair->private_key = gpr_strdup(pem_key_cert_pair->private_key); + } else { + config_.pem_key_cert_pair = nullptr; + } + if (verify_options != nullptr) { + memcpy(&config_.verify_options, verify_options, + sizeof(verify_peer_options)); + } else { + // Otherwise set all options to default values + memset(&config_.verify_options, 0, sizeof(verify_peer_options)); } } grpc_channel_credentials* grpc_ssl_credentials_create( const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, - void* reserved) { - grpc_ssl_credentials* c = static_cast( - gpr_zalloc(sizeof(grpc_ssl_credentials))); + const verify_peer_options* verify_options, void* reserved) { GRPC_API_TRACE( "grpc_ssl_credentials_create(pem_root_certs=%s, " "pem_key_cert_pair=%p, " + "verify_options=%p, " "reserved=%p)", - 3, (pem_root_certs, pem_key_cert_pair, reserved)); + 4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved)); GPR_ASSERT(reserved == nullptr); - c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; - c->base.vtable = &ssl_vtable; - gpr_ref_init(&c->base.refcount, 1); - ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config); - return &c->base; + + return grpc_core::New(pem_root_certs, pem_key_cert_pair, + verify_options); } // @@ -131,21 +142,29 @@ struct grpc_ssl_server_credentials_options { grpc_ssl_server_certificate_config_fetcher* certificate_config_fetcher; }; -static void ssl_server_destruct(grpc_server_credentials* creds) { - grpc_ssl_server_credentials* c = - reinterpret_cast(creds); - grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pairs, - c->config.num_key_cert_pairs); - gpr_free(c->config.pem_root_certs); +grpc_ssl_server_credentials::grpc_ssl_server_credentials( + const grpc_ssl_server_credentials_options& options) + : grpc_server_credentials(GRPC_CHANNEL_CREDENTIALS_TYPE_SSL) { + if (options.certificate_config_fetcher != nullptr) { + config_.client_certificate_request = options.client_certificate_request; + certificate_config_fetcher_ = *options.certificate_config_fetcher; + } else { + build_config(options.certificate_config->pem_root_certs, + options.certificate_config->pem_key_cert_pairs, + options.certificate_config->num_key_cert_pairs, + options.client_certificate_request); + } } -static grpc_security_status ssl_server_create_security_connector( - grpc_server_credentials* creds, grpc_server_security_connector** sc) { - return grpc_ssl_server_security_connector_create(creds, sc); +grpc_ssl_server_credentials::~grpc_ssl_server_credentials() { + grpc_tsi_ssl_pem_key_cert_pairs_destroy(config_.pem_key_cert_pairs, + config_.num_key_cert_pairs); + gpr_free(config_.pem_root_certs); +} +grpc_core::RefCountedPtr +grpc_ssl_server_credentials::create_security_connector() { + return grpc_ssl_server_security_connector_create(this->Ref()); } - -static grpc_server_credentials_vtable ssl_server_vtable = { - ssl_server_destruct, ssl_server_create_security_connector}; tsi_ssl_pem_key_cert_pair* grpc_convert_grpc_to_tsi_cert_pairs( const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs, @@ -165,18 +184,15 @@ tsi_ssl_pem_key_cert_pair* grpc_convert_grpc_to_tsi_cert_pairs( return tsi_pairs; } -static void ssl_build_server_config( +void grpc_ssl_server_credentials::build_config( const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs, size_t num_key_cert_pairs, - grpc_ssl_client_certificate_request_type client_certificate_request, - grpc_ssl_server_config* config) { - config->client_certificate_request = client_certificate_request; - if (pem_root_certs != nullptr) { - config->pem_root_certs = gpr_strdup(pem_root_certs); - } - config->pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( + grpc_ssl_client_certificate_request_type client_certificate_request) { + config_.client_certificate_request = client_certificate_request; + config_.pem_root_certs = gpr_strdup(pem_root_certs); + config_.pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( pem_key_cert_pairs, num_key_cert_pairs); - config->num_key_cert_pairs = num_key_cert_pairs; + config_.num_key_cert_pairs = num_key_cert_pairs; } grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create( @@ -186,9 +202,7 @@ grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create( grpc_ssl_server_certificate_config* config = static_cast( gpr_zalloc(sizeof(grpc_ssl_server_certificate_config))); - if (pem_root_certs != nullptr) { - config->pem_root_certs = gpr_strdup(pem_root_certs); - } + config->pem_root_certs = gpr_strdup(pem_root_certs); if (num_key_cert_pairs > 0) { GPR_ASSERT(pem_key_cert_pairs != nullptr); config->pem_key_cert_pairs = static_cast( @@ -297,7 +311,6 @@ grpc_server_credentials* grpc_ssl_server_credentials_create_ex( grpc_server_credentials* grpc_ssl_server_credentials_create_with_options( grpc_ssl_server_credentials_options* options) { grpc_server_credentials* retval = nullptr; - grpc_ssl_server_credentials* c = nullptr; if (options == nullptr) { gpr_log(GPR_ERROR, @@ -317,23 +330,7 @@ grpc_server_credentials* grpc_ssl_server_credentials_create_with_options( goto done; } - c = static_cast( - gpr_zalloc(sizeof(grpc_ssl_server_credentials))); - c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; - gpr_ref_init(&c->base.refcount, 1); - c->base.vtable = &ssl_server_vtable; - - if (options->certificate_config_fetcher != nullptr) { - c->config.client_certificate_request = options->client_certificate_request; - c->certificate_config_fetcher = *options->certificate_config_fetcher; - } else { - ssl_build_server_config(options->certificate_config->pem_root_certs, - options->certificate_config->pem_key_cert_pairs, - options->certificate_config->num_key_cert_pairs, - options->client_certificate_request, &c->config); - } - - retval = &c->base; + retval = grpc_core::New(*options); done: grpc_ssl_server_credentials_options_destroy(options); diff --git a/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.h b/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.h index 712d34c73..e1174327b 100644 --- a/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.h +++ b/Sources/CgRPC/src/core/lib/security/credentials/ssl/ssl_credentials.h @@ -22,27 +22,72 @@ #include "src/core/lib/security/credentials/credentials.h" -typedef struct { - grpc_channel_credentials base; - grpc_ssl_config config; -} grpc_ssl_credentials; +#include "src/core/lib/security/security_connector/ssl/ssl_security_connector.h" + +class grpc_ssl_credentials : public grpc_channel_credentials { + public: + grpc_ssl_credentials(const char* pem_root_certs, + grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, + const verify_peer_options* verify_options); + + ~grpc_ssl_credentials() override; + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target, const grpc_channel_args* args, + grpc_channel_args** new_args) override; + + private: + void build_config(const char* pem_root_certs, + grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, + const verify_peer_options* verify_options); + + grpc_ssl_config config_; +}; struct grpc_ssl_server_certificate_config { - grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs; - size_t num_key_cert_pairs; - char* pem_root_certs; + grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr; + size_t num_key_cert_pairs = 0; + char* pem_root_certs = nullptr; }; -typedef struct { - grpc_ssl_server_certificate_config_callback cb; +struct grpc_ssl_server_certificate_config_fetcher { + grpc_ssl_server_certificate_config_callback cb = nullptr; void* user_data; -} grpc_ssl_server_certificate_config_fetcher; +}; -typedef struct { - grpc_server_credentials base; - grpc_ssl_server_config config; - grpc_ssl_server_certificate_config_fetcher certificate_config_fetcher; -} grpc_ssl_server_credentials; +class grpc_ssl_server_credentials final : public grpc_server_credentials { + public: + grpc_ssl_server_credentials( + const grpc_ssl_server_credentials_options& options); + ~grpc_ssl_server_credentials() override; + + grpc_core::RefCountedPtr + create_security_connector() override; + + bool has_cert_config_fetcher() const { + return certificate_config_fetcher_.cb != nullptr; + } + + grpc_ssl_certificate_config_reload_status FetchCertConfig( + grpc_ssl_server_certificate_config** config) { + GPR_DEBUG_ASSERT(has_cert_config_fetcher()); + return certificate_config_fetcher_.cb(certificate_config_fetcher_.user_data, + config); + } + + const grpc_ssl_server_config& config() const { return config_; } + + private: + void build_config( + const char* pem_root_certs, + grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs, size_t num_key_cert_pairs, + grpc_ssl_client_certificate_request_type client_certificate_request); + + grpc_ssl_server_config config_; + grpc_ssl_server_certificate_config_fetcher certificate_config_fetcher_; +}; tsi_ssl_pem_key_cert_pair* grpc_convert_grpc_to_tsi_cert_pairs( const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs, diff --git a/Sources/CgRPC/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc b/Sources/CgRPC/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc new file mode 100644 index 000000000..a6169a1b5 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc @@ -0,0 +1,192 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" + +#include +#include + +#include +#include +#include + +/** -- gRPC TLS key materials config API implementation. -- **/ +void grpc_tls_key_materials_config::set_key_materials( + grpc_core::UniquePtr pem_root_certs, + PemKeyCertPairList pem_key_cert_pair_list) { + pem_key_cert_pair_list_ = std::move(pem_key_cert_pair_list); + pem_root_certs_ = std::move(pem_root_certs); +} + +/** -- gRPC TLS credential reload config API implementation. -- **/ +grpc_tls_credential_reload_config::grpc_tls_credential_reload_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)) + : config_user_data_(const_cast(config_user_data)), + schedule_(schedule), + cancel_(cancel), + destruct_(destruct) {} + +grpc_tls_credential_reload_config::~grpc_tls_credential_reload_config() { + if (destruct_ != nullptr) { + destruct_((void*)config_user_data_); + } +} + +/** -- gRPC TLS server authorization check API implementation. -- **/ +grpc_tls_server_authorization_check_config:: + grpc_tls_server_authorization_check_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)) + : config_user_data_(const_cast(config_user_data)), + schedule_(schedule), + cancel_(cancel), + destruct_(destruct) {} + +grpc_tls_server_authorization_check_config:: + ~grpc_tls_server_authorization_check_config() { + if (destruct_ != nullptr) { + destruct_((void*)config_user_data_); + } +} + +/** -- Wrapper APIs declared in grpc_security.h -- **/ +grpc_tls_credentials_options* grpc_tls_credentials_options_create() { + return grpc_core::New(); +} + +int grpc_tls_credentials_options_set_cert_request_type( + grpc_tls_credentials_options* options, + grpc_ssl_client_certificate_request_type type) { + if (options == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_cert_request_type()"); + return 0; + } + options->set_cert_request_type(type); + return 1; +} + +int grpc_tls_credentials_options_set_key_materials_config( + grpc_tls_credentials_options* options, + grpc_tls_key_materials_config* config) { + if (options == nullptr || config == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_key_materials_config()"); + return 0; + } + options->set_key_materials_config(config->Ref()); + return 1; +} + +int grpc_tls_credentials_options_set_credential_reload_config( + grpc_tls_credentials_options* options, + grpc_tls_credential_reload_config* config) { + if (options == nullptr || config == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_credential_reload_config()"); + return 0; + } + options->set_credential_reload_config(config->Ref()); + return 1; +} + +int grpc_tls_credentials_options_set_server_authorization_check_config( + grpc_tls_credentials_options* options, + grpc_tls_server_authorization_check_config* config) { + if (options == nullptr || config == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_server_authorization_check_config()"); + return 0; + } + options->set_server_authorization_check_config(config->Ref()); + return 1; +} + +grpc_tls_key_materials_config* grpc_tls_key_materials_config_create() { + return grpc_core::New(); +} + +int grpc_tls_key_materials_config_set_key_materials( + grpc_tls_key_materials_config* config, const char* root_certs, + const grpc_ssl_pem_key_cert_pair** key_cert_pairs, size_t num) { + if (config == nullptr || key_cert_pairs == nullptr || num == 0) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_tls_key_materials_config_set_key_materials()"); + return 0; + } + grpc_core::UniquePtr pem_root(const_cast(root_certs)); + grpc_tls_key_materials_config::PemKeyCertPairList cert_pair_list; + for (size_t i = 0; i < num; i++) { + grpc_core::PemKeyCertPair key_cert_pair( + const_cast(key_cert_pairs[i])); + cert_pair_list.emplace_back(std::move(key_cert_pair)); + } + config->set_key_materials(std::move(pem_root), std::move(cert_pair_list)); + gpr_free(key_cert_pairs); + return 1; +} + +grpc_tls_credential_reload_config* grpc_tls_credential_reload_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)) { + if (schedule == nullptr) { + gpr_log( + GPR_ERROR, + "Schedule API is nullptr in creating TLS credential reload config."); + return nullptr; + } + return grpc_core::New( + config_user_data, schedule, cancel, destruct); +} + +grpc_tls_server_authorization_check_config* +grpc_tls_server_authorization_check_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)) { + if (schedule == nullptr) { + gpr_log(GPR_ERROR, + "Schedule API is nullptr in creating TLS server authorization " + "check config."); + return nullptr; + } + return grpc_core::New( + config_user_data, schedule, cancel, destruct); +} diff --git a/Sources/CgRPC/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/Sources/CgRPC/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h new file mode 100644 index 000000000..71410d20a --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h @@ -0,0 +1,213 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H + +#include + +#include + +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" + +/** TLS key materials config. **/ +struct grpc_tls_key_materials_config + : public grpc_core::RefCounted { + public: + typedef grpc_core::InlinedVector + PemKeyCertPairList; + + /** Getters for member fields. **/ + const char* pem_root_certs() const { return pem_root_certs_.get(); } + const PemKeyCertPairList& pem_key_cert_pair_list() const { + return pem_key_cert_pair_list_; + } + + /** Setters for member fields. **/ + void set_key_materials(grpc_core::UniquePtr pem_root_certs, + PemKeyCertPairList pem_key_cert_pair_list); + + private: + PemKeyCertPairList pem_key_cert_pair_list_; + grpc_core::UniquePtr pem_root_certs_; +}; + +/** TLS credential reload config. **/ +struct grpc_tls_credential_reload_config + : public grpc_core::RefCounted { + public: + grpc_tls_credential_reload_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)); + ~grpc_tls_credential_reload_config(); + + int Schedule(grpc_tls_credential_reload_arg* arg) const { + return schedule_(config_user_data_, arg); + } + void Cancel(grpc_tls_credential_reload_arg* arg) const { + if (cancel_ == nullptr) { + gpr_log(GPR_ERROR, "cancel API is nullptr."); + return; + } + cancel_(config_user_data_, arg); + } + + private: + /** config-specific, read-only user data that works for all channels created + with a credential using the config. */ + void* config_user_data_; + /** callback function for invoking credential reload API. The implementation + of this method has to be non-blocking, but can be performed synchronously + or asynchronously. + If processing occurs synchronously, it populates \a arg->key_materials, \a + arg->status, and \a arg->error_details and returns zero. + If processing occurs asynchronously, it returns a non-zero value. + Application then invokes \a arg->cb when processing is completed. Note that + \a arg->cb cannot be invoked before \a schedule returns. + */ + int (*schedule_)(void* config_user_data, grpc_tls_credential_reload_arg* arg); + /** callback function for cancelling a credential reload request scheduled via + an asynchronous \a schedule. \a arg is used to pinpoint an exact reloading + request to be cancelled, and the operation may not have any effect if the + request has already been processed. */ + void (*cancel_)(void* config_user_data, grpc_tls_credential_reload_arg* arg); + /** callback function for cleaning up any data associated with credential + reload config. */ + void (*destruct_)(void* config_user_data); +}; + +/** TLS server authorization check config. **/ +struct grpc_tls_server_authorization_check_config + : public grpc_core::RefCounted { + public: + grpc_tls_server_authorization_check_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)); + ~grpc_tls_server_authorization_check_config(); + + int Schedule(grpc_tls_server_authorization_check_arg* arg) const { + return schedule_(config_user_data_, arg); + } + void Cancel(grpc_tls_server_authorization_check_arg* arg) const { + if (cancel_ == nullptr) { + gpr_log(GPR_ERROR, "cancel API is nullptr."); + return; + } + cancel_(config_user_data_, arg); + } + + private: + /** config-specific, read-only user data that works for all channels created + with a Credential using the config. */ + void* config_user_data_; + + /** callback function for invoking server authorization check. The + implementation of this method has to be non-blocking, but can be performed + synchronously or asynchronously. + If processing occurs synchronously, it populates \a arg->result, \a + arg->status, and \a arg->error_details, and returns zero. + If processing occurs asynchronously, it returns a non-zero value. + Application then invokes \a arg->cb when processing is completed. Note that + \a arg->cb cannot be invoked before \a schedule() returns. + */ + int (*schedule_)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg); + + /** callback function for canceling a server authorization check request. */ + void (*cancel_)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg); + + /** callback function for cleaning up any data associated with server + authorization check config. */ + void (*destruct_)(void* config_user_data); +}; + +/* TLS credentials options. */ +struct grpc_tls_credentials_options + : public grpc_core::RefCounted { + public: + ~grpc_tls_credentials_options() { + if (key_materials_config_.get() != nullptr) { + key_materials_config_.get()->Unref(); + } + if (credential_reload_config_.get() != nullptr) { + credential_reload_config_.get()->Unref(); + } + if (server_authorization_check_config_.get() != nullptr) { + server_authorization_check_config_.get()->Unref(); + } + } + + /* Getters for member fields. */ + grpc_ssl_client_certificate_request_type cert_request_type() const { + return cert_request_type_; + } + const grpc_tls_key_materials_config* key_materials_config() const { + return key_materials_config_.get(); + } + const grpc_tls_credential_reload_config* credential_reload_config() const { + return credential_reload_config_.get(); + } + const grpc_tls_server_authorization_check_config* + server_authorization_check_config() const { + return server_authorization_check_config_.get(); + } + grpc_tls_key_materials_config* mutable_key_materials_config() { + return key_materials_config_.get(); + } + + /* Setters for member fields. */ + void set_cert_request_type( + const grpc_ssl_client_certificate_request_type type) { + cert_request_type_ = type; + } + void set_key_materials_config( + grpc_core::RefCountedPtr config) { + key_materials_config_ = std::move(config); + } + void set_credential_reload_config( + grpc_core::RefCountedPtr config) { + credential_reload_config_ = std::move(config); + } + void set_server_authorization_check_config( + grpc_core::RefCountedPtr + config) { + server_authorization_check_config_ = std::move(config); + } + + private: + grpc_ssl_client_certificate_request_type cert_request_type_; + grpc_core::RefCountedPtr key_materials_config_; + grpc_core::RefCountedPtr + credential_reload_config_; + grpc_core::RefCountedPtr + server_authorization_check_config_; +}; + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H \ + */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/alts/alts_security_connector.cc b/Sources/CgRPC/src/core/lib/security/security_connector/alts/alts_security_connector.cc new file mode 100644 index 000000000..38b1f856d --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/alts/alts_security_connector.cc @@ -0,0 +1,266 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/security_connector/alts/alts_security_connector.h" + +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/security/credentials/alts/alts_credentials.h" +#include "src/core/lib/security/transport/security_handshaker.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/transport.h" +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" +#include "src/core/tsi/transport_security.h" + +namespace { + +void alts_set_rpc_protocol_versions( + grpc_gcp_rpc_protocol_versions* rpc_versions) { + grpc_gcp_rpc_protocol_versions_set_max(rpc_versions, + GRPC_PROTOCOL_VERSION_MAX_MAJOR, + GRPC_PROTOCOL_VERSION_MAX_MINOR); + grpc_gcp_rpc_protocol_versions_set_min(rpc_versions, + GRPC_PROTOCOL_VERSION_MIN_MAJOR, + GRPC_PROTOCOL_VERSION_MIN_MINOR); +} + +void alts_check_peer(tsi_peer peer, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) { + *auth_context = + grpc_core::internal::grpc_alts_auth_context_from_tsi_peer(&peer); + tsi_peer_destruct(&peer); + grpc_error* error = + *auth_context != nullptr + ? GRPC_ERROR_NONE + : GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Could not get ALTS auth context from TSI peer"); + GRPC_CLOSURE_SCHED(on_peer_checked, error); +} + +class grpc_alts_channel_security_connector final + : public grpc_channel_security_connector { + public: + grpc_alts_channel_security_connector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name) + : grpc_channel_security_connector(/*url_scheme=*/nullptr, + std::move(channel_creds), + std::move(request_metadata_creds)), + target_name_(gpr_strdup(target_name)) { + grpc_alts_credentials* creds = + static_cast(mutable_channel_creds()); + alts_set_rpc_protocol_versions(&creds->mutable_options()->rpc_versions); + } + + ~grpc_alts_channel_security_connector() override { gpr_free(target_name_); } + + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { + tsi_handshaker* handshaker = nullptr; + const grpc_alts_credentials* creds = + static_cast(channel_creds()); + GPR_ASSERT(alts_tsi_handshaker_create(creds->options(), target_name_, + creds->handshaker_service_url(), true, + interested_parties, + &handshaker) == TSI_OK); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + alts_check_peer(peer, auth_context, on_peer_checked); + } + + int cmp(const grpc_security_connector* other_sc) const override { + auto* other = + reinterpret_cast(other_sc); + int c = channel_security_connector_cmp(other); + if (c != 0) return c; + return strcmp(target_name_, other->target_name_); + } + + bool check_call_host(const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) override { + if (host == nullptr || strcmp(host, target_name_) != 0) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "ALTS call host does not match target name"); + } + return true; + } + + void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) override { + GRPC_ERROR_UNREF(error); + } + + private: + char* target_name_; +}; + +class grpc_alts_server_security_connector final + : public grpc_server_security_connector { + public: + grpc_alts_server_security_connector( + grpc_core::RefCountedPtr server_creds) + : grpc_server_security_connector(/*url_scheme=*/nullptr, + std::move(server_creds)) { + grpc_alts_server_credentials* creds = + reinterpret_cast(mutable_server_creds()); + alts_set_rpc_protocol_versions(&creds->mutable_options()->rpc_versions); + } + ~grpc_alts_server_security_connector() override = default; + + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { + tsi_handshaker* handshaker = nullptr; + const grpc_alts_server_credentials* creds = + static_cast(server_creds()); + GPR_ASSERT(alts_tsi_handshaker_create( + creds->options(), nullptr, creds->handshaker_service_url(), + false, interested_parties, &handshaker) == TSI_OK); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + alts_check_peer(peer, auth_context, on_peer_checked); + } + + int cmp(const grpc_security_connector* other) const override { + return server_security_connector_cmp( + static_cast(other)); + } +}; +} // namespace + +namespace grpc_core { +namespace internal { +grpc_core::RefCountedPtr +grpc_alts_auth_context_from_tsi_peer(const tsi_peer* peer) { + if (peer == nullptr) { + gpr_log(GPR_ERROR, + "Invalid arguments to grpc_alts_auth_context_from_tsi_peer()"); + return nullptr; + } + /* Validate certificate type. */ + const tsi_peer_property* cert_type_prop = + tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY); + if (cert_type_prop == nullptr || + strncmp(cert_type_prop->value.data, TSI_ALTS_CERTIFICATE_TYPE, + cert_type_prop->value.length) != 0) { + gpr_log(GPR_ERROR, "Invalid or missing certificate type property."); + return nullptr; + } + /* Validate RPC protocol versions. */ + const tsi_peer_property* rpc_versions_prop = + tsi_peer_get_property_by_name(peer, TSI_ALTS_RPC_VERSIONS); + if (rpc_versions_prop == nullptr) { + gpr_log(GPR_ERROR, "Missing rpc protocol versions property."); + return nullptr; + } + grpc_gcp_rpc_protocol_versions local_versions, peer_versions; + alts_set_rpc_protocol_versions(&local_versions); + grpc_slice slice = grpc_slice_from_copied_buffer( + rpc_versions_prop->value.data, rpc_versions_prop->value.length); + bool decode_result = + grpc_gcp_rpc_protocol_versions_decode(slice, &peer_versions); + grpc_slice_unref_internal(slice); + if (!decode_result) { + gpr_log(GPR_ERROR, "Invalid peer rpc protocol versions."); + return nullptr; + } + /* TODO: Pass highest common rpc protocol version to grpc caller. */ + bool check_result = grpc_gcp_rpc_protocol_versions_check( + &local_versions, &peer_versions, nullptr); + if (!check_result) { + gpr_log(GPR_ERROR, "Mismatch of local and peer rpc protocol versions."); + return nullptr; + } + /* Create auth context. */ + auto ctx = grpc_core::MakeRefCounted(nullptr); + grpc_auth_context_add_cstring_property( + ctx.get(), GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_ALTS_TRANSPORT_SECURITY_TYPE); + size_t i = 0; + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property* tsi_prop = &peer->properties[i]; + /* Add service account to auth context. */ + if (strcmp(tsi_prop->name, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 0) { + grpc_auth_context_add_property( + ctx.get(), TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, + tsi_prop->value.data, tsi_prop->value.length); + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( + ctx.get(), TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 1); + } + } + if (!grpc_auth_context_peer_is_authenticated(ctx.get())) { + gpr_log(GPR_ERROR, "Invalid unauthenticated peer."); + ctx.reset(DEBUG_LOCATION, "test"); + return nullptr; + } + return ctx; +} + +} // namespace internal +} // namespace grpc_core + +grpc_core::RefCountedPtr +grpc_alts_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name) { + if (channel_creds == nullptr || target_name == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid arguments to grpc_alts_channel_security_connector_create()"); + return nullptr; + } + return grpc_core::MakeRefCounted( + std::move(channel_creds), std::move(request_metadata_creds), target_name); +} + +grpc_core::RefCountedPtr +grpc_alts_server_security_connector_create( + grpc_core::RefCountedPtr server_creds) { + if (server_creds == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid arguments to grpc_alts_server_security_connector_create()"); + return nullptr; + } + return grpc_core::MakeRefCounted( + std::move(server_creds)); +} diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/alts_security_connector.h b/Sources/CgRPC/src/core/lib/security/security_connector/alts/alts_security_connector.h similarity index 64% rename from Sources/CgRPC/src/core/lib/security/security_connector/alts_security_connector.h rename to Sources/CgRPC/src/core/lib/security/security_connector/alts/alts_security_connector.h index e7e4cffe2..b96dc36b3 100644 --- a/Sources/CgRPC/src/core/lib/security/security_connector/alts_security_connector.h +++ b/Sources/CgRPC/src/core/lib/security/security_connector/alts/alts_security_connector.h @@ -16,8 +16,8 @@ * */ -#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_SECURITY_CONNECTOR_H -#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_SECURITY_CONNECTOR_H +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_ALTS_SECURITY_CONNECTOR_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_ALTS_SECURITY_CONNECTOR_H #include @@ -36,12 +36,13 @@ * - sc: address of ALTS channel security connector instance to be returned from * the method. * - * It returns GRPC_SECURITY_OK on success, and an error stauts code on failure. + * It returns nullptr on failure. */ -grpc_security_status grpc_alts_channel_security_connector_create( - grpc_channel_credentials* channel_creds, - grpc_call_credentials* request_metadata_creds, const char* target_name, - grpc_channel_security_connector** sc); +grpc_core::RefCountedPtr +grpc_alts_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name); /** * This method creates an ALTS server security connector. @@ -50,20 +51,21 @@ grpc_security_status grpc_alts_channel_security_connector_create( * - sc: address of ALTS server security connector instance to be returned from * the method. * - * It returns GRPC_SECURITY_OK on success, and an error status code on failure. + * It returns nullptr on failure. */ -grpc_security_status grpc_alts_server_security_connector_create( - grpc_server_credentials* server_creds, grpc_server_security_connector** sc); +grpc_core::RefCountedPtr +grpc_alts_server_security_connector_create( + grpc_core::RefCountedPtr server_creds); namespace grpc_core { namespace internal { /* Exposed only for testing. */ -grpc_security_status grpc_alts_auth_context_from_tsi_peer( - const tsi_peer* peer, grpc_auth_context** ctx); +grpc_core::RefCountedPtr +grpc_alts_auth_context_from_tsi_peer(const tsi_peer* peer); } // namespace internal } // namespace grpc_core -#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_SECURITY_CONNECTOR_H \ +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_ALTS_SECURITY_CONNECTOR_H \ */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/alts_security_connector.cc b/Sources/CgRPC/src/core/lib/security/security_connector/alts_security_connector.cc deleted file mode 100644 index 5ff7d7938..000000000 --- a/Sources/CgRPC/src/core/lib/security/security_connector/alts_security_connector.cc +++ /dev/null @@ -1,287 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/security/security_connector/alts_security_connector.h" - -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/security/credentials/alts/alts_credentials.h" -#include "src/core/lib/security/transport/security_handshaker.h" -#include "src/core/lib/transport/transport.h" -#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" - -typedef struct { - grpc_channel_security_connector base; - char* target_name; -} grpc_alts_channel_security_connector; - -typedef struct { - grpc_server_security_connector base; -} grpc_alts_server_security_connector; - -static void alts_channel_destroy(grpc_security_connector* sc) { - if (sc == nullptr) { - return; - } - auto c = reinterpret_cast(sc); - grpc_call_credentials_unref(c->base.request_metadata_creds); - grpc_channel_credentials_unref(c->base.channel_creds); - gpr_free(c->target_name); - gpr_free(sc); -} - -static void alts_server_destroy(grpc_security_connector* sc) { - if (sc == nullptr) { - return; - } - auto c = reinterpret_cast(sc); - grpc_server_credentials_unref(c->base.server_creds); - gpr_free(sc); -} - -static void alts_channel_add_handshakers( - grpc_channel_security_connector* sc, - grpc_handshake_manager* handshake_manager) { - tsi_handshaker* handshaker = nullptr; - auto c = reinterpret_cast(sc); - grpc_alts_credentials* creds = - reinterpret_cast(c->base.channel_creds); - GPR_ASSERT(alts_tsi_handshaker_create(creds->options, c->target_name, - creds->handshaker_service_url, true, - &handshaker) == TSI_OK); - grpc_handshake_manager_add(handshake_manager, grpc_security_handshaker_create( - handshaker, &sc->base)); -} - -static void alts_server_add_handshakers( - grpc_server_security_connector* sc, - grpc_handshake_manager* handshake_manager) { - tsi_handshaker* handshaker = nullptr; - auto c = reinterpret_cast(sc); - grpc_alts_server_credentials* creds = - reinterpret_cast(c->base.server_creds); - GPR_ASSERT(alts_tsi_handshaker_create(creds->options, nullptr, - creds->handshaker_service_url, false, - &handshaker) == TSI_OK); - grpc_handshake_manager_add(handshake_manager, grpc_security_handshaker_create( - handshaker, &sc->base)); -} - -static void alts_set_rpc_protocol_versions( - grpc_gcp_rpc_protocol_versions* rpc_versions) { - grpc_gcp_rpc_protocol_versions_set_max(rpc_versions, - GRPC_PROTOCOL_VERSION_MAX_MAJOR, - GRPC_PROTOCOL_VERSION_MAX_MINOR); - grpc_gcp_rpc_protocol_versions_set_min(rpc_versions, - GRPC_PROTOCOL_VERSION_MIN_MAJOR, - GRPC_PROTOCOL_VERSION_MIN_MINOR); -} - -namespace grpc_core { -namespace internal { - -grpc_security_status grpc_alts_auth_context_from_tsi_peer( - const tsi_peer* peer, grpc_auth_context** ctx) { - if (peer == nullptr || ctx == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to grpc_alts_auth_context_from_tsi_peer()"); - return GRPC_SECURITY_ERROR; - } - *ctx = nullptr; - /* Validate certificate type. */ - const tsi_peer_property* cert_type_prop = - tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY); - if (cert_type_prop == nullptr || - strncmp(cert_type_prop->value.data, TSI_ALTS_CERTIFICATE_TYPE, - cert_type_prop->value.length) != 0) { - gpr_log(GPR_ERROR, "Invalid or missing certificate type property."); - return GRPC_SECURITY_ERROR; - } - /* Validate RPC protocol versions. */ - const tsi_peer_property* rpc_versions_prop = - tsi_peer_get_property_by_name(peer, TSI_ALTS_RPC_VERSIONS); - if (rpc_versions_prop == nullptr) { - gpr_log(GPR_ERROR, "Missing rpc protocol versions property."); - return GRPC_SECURITY_ERROR; - } - grpc_gcp_rpc_protocol_versions local_versions, peer_versions; - alts_set_rpc_protocol_versions(&local_versions); - grpc_slice slice = grpc_slice_from_copied_buffer( - rpc_versions_prop->value.data, rpc_versions_prop->value.length); - bool decode_result = - grpc_gcp_rpc_protocol_versions_decode(slice, &peer_versions); - grpc_slice_unref(slice); - if (!decode_result) { - gpr_log(GPR_ERROR, "Invalid peer rpc protocol versions."); - return GRPC_SECURITY_ERROR; - } - /* TODO: Pass highest common rpc protocol version to grpc caller. */ - bool check_result = grpc_gcp_rpc_protocol_versions_check( - &local_versions, &peer_versions, nullptr); - if (!check_result) { - gpr_log(GPR_ERROR, "Mismatch of local and peer rpc protocol versions."); - return GRPC_SECURITY_ERROR; - } - /* Create auth context. */ - *ctx = grpc_auth_context_create(nullptr); - grpc_auth_context_add_cstring_property( - *ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, - GRPC_ALTS_TRANSPORT_SECURITY_TYPE); - size_t i = 0; - for (i = 0; i < peer->property_count; i++) { - const tsi_peer_property* tsi_prop = &peer->properties[i]; - /* Add service account to auth context. */ - if (strcmp(tsi_prop->name, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 0) { - grpc_auth_context_add_property( - *ctx, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, tsi_prop->value.data, - tsi_prop->value.length); - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( - *ctx, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 1); - } - } - if (!grpc_auth_context_peer_is_authenticated(*ctx)) { - gpr_log(GPR_ERROR, "Invalid unauthenticated peer."); - GRPC_AUTH_CONTEXT_UNREF(*ctx, "test"); - *ctx = nullptr; - return GRPC_SECURITY_ERROR; - } - return GRPC_SECURITY_OK; -} - -} // namespace internal -} // namespace grpc_core - -static void alts_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - grpc_security_status status; - status = grpc_core::internal::grpc_alts_auth_context_from_tsi_peer( - &peer, auth_context); - tsi_peer_destruct(&peer); - grpc_error* error = - status == GRPC_SECURITY_OK - ? GRPC_ERROR_NONE - : GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Could not get ALTS auth context from TSI peer"); - GRPC_CLOSURE_SCHED(on_peer_checked, error); -} - -static int alts_channel_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - grpc_alts_channel_security_connector* c1 = - reinterpret_cast(sc1); - grpc_alts_channel_security_connector* c2 = - reinterpret_cast(sc2); - int c = grpc_channel_security_connector_cmp(&c1->base, &c2->base); - if (c != 0) return c; - return strcmp(c1->target_name, c2->target_name); -} - -static int alts_server_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - grpc_alts_server_security_connector* c1 = - reinterpret_cast(sc1); - grpc_alts_server_security_connector* c2 = - reinterpret_cast(sc2); - return grpc_server_security_connector_cmp(&c1->base, &c2->base); -} - -static grpc_security_connector_vtable alts_channel_vtable = { - alts_channel_destroy, alts_check_peer, alts_channel_cmp}; - -static grpc_security_connector_vtable alts_server_vtable = { - alts_server_destroy, alts_check_peer, alts_server_cmp}; - -static bool alts_check_call_host(grpc_channel_security_connector* sc, - const char* host, - grpc_auth_context* auth_context, - grpc_closure* on_call_host_checked, - grpc_error** error) { - grpc_alts_channel_security_connector* alts_sc = - reinterpret_cast(sc); - if (host == nullptr || alts_sc == nullptr || - strcmp(host, alts_sc->target_name) != 0) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "ALTS call host does not match target name"); - } - return true; -} - -static void alts_cancel_check_call_host(grpc_channel_security_connector* sc, - grpc_closure* on_call_host_checked, - grpc_error* error) { - GRPC_ERROR_UNREF(error); -} - -grpc_security_status grpc_alts_channel_security_connector_create( - grpc_channel_credentials* channel_creds, - grpc_call_credentials* request_metadata_creds, const char* target_name, - grpc_channel_security_connector** sc) { - if (channel_creds == nullptr || sc == nullptr || target_name == nullptr) { - gpr_log( - GPR_ERROR, - "Invalid arguments to grpc_alts_channel_security_connector_create()"); - return GRPC_SECURITY_ERROR; - } - auto c = static_cast( - gpr_zalloc(sizeof(grpc_alts_channel_security_connector))); - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.vtable = &alts_channel_vtable; - c->base.add_handshakers = alts_channel_add_handshakers; - c->base.channel_creds = grpc_channel_credentials_ref(channel_creds); - c->base.request_metadata_creds = - grpc_call_credentials_ref(request_metadata_creds); - c->base.check_call_host = alts_check_call_host; - c->base.cancel_check_call_host = alts_cancel_check_call_host; - grpc_alts_credentials* creds = - reinterpret_cast(c->base.channel_creds); - alts_set_rpc_protocol_versions(&creds->options->rpc_versions); - c->target_name = gpr_strdup(target_name); - *sc = &c->base; - return GRPC_SECURITY_OK; -} - -grpc_security_status grpc_alts_server_security_connector_create( - grpc_server_credentials* server_creds, - grpc_server_security_connector** sc) { - if (server_creds == nullptr || sc == nullptr) { - gpr_log( - GPR_ERROR, - "Invalid arguments to grpc_alts_server_security_connector_create()"); - return GRPC_SECURITY_ERROR; - } - auto c = static_cast( - gpr_zalloc(sizeof(grpc_alts_server_security_connector))); - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.vtable = &alts_server_vtable; - c->base.server_creds = grpc_server_credentials_ref(server_creds); - c->base.add_handshakers = alts_server_add_handshakers; - grpc_alts_server_credentials* creds = - reinterpret_cast(c->base.server_creds); - alts_set_rpc_protocol_versions(&creds->options->rpc_versions); - *sc = &c->base; - return GRPC_SECURITY_OK; -} diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/fake/fake_security_connector.cc b/Sources/CgRPC/src/core/lib/security/security_connector/fake/fake_security_connector.cc new file mode 100644 index 000000000..a0e2e6f03 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/fake/fake_security_connector.cc @@ -0,0 +1,301 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/security_connector/fake/fake_security_connector.h" + +#include + +#include +#include +#include + +#include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/security/transport/security_handshaker.h" +#include "src/core/lib/security/transport/target_authority_table.h" +#include "src/core/tsi/fake_transport_security.h" + +namespace { +class grpc_fake_channel_security_connector final + : public grpc_channel_security_connector { + public: + grpc_fake_channel_security_connector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target, const grpc_channel_args* args) + : grpc_channel_security_connector(GRPC_FAKE_SECURITY_URL_SCHEME, + std::move(channel_creds), + std::move(request_metadata_creds)), + target_(gpr_strdup(target)), + expected_targets_( + gpr_strdup(grpc_fake_transport_get_expected_targets(args))), + is_lb_channel_(grpc_core::FindTargetAuthorityTableInArgs(args) != + nullptr) { + const grpc_arg* target_name_override_arg = + grpc_channel_args_find(args, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); + if (target_name_override_arg != nullptr) { + target_name_override_ = + gpr_strdup(grpc_channel_arg_get_string(target_name_override_arg)); + } else { + target_name_override_ = nullptr; + } + } + + ~grpc_fake_channel_security_connector() override { + gpr_free(target_); + gpr_free(expected_targets_); + if (target_name_override_ != nullptr) gpr_free(target_name_override_); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override; + + int cmp(const grpc_security_connector* other_sc) const override { + auto* other = + reinterpret_cast(other_sc); + int c = channel_security_connector_cmp(other); + if (c != 0) return c; + c = strcmp(target_, other->target_); + if (c != 0) return c; + if (expected_targets_ == nullptr || other->expected_targets_ == nullptr) { + c = GPR_ICMP(expected_targets_, other->expected_targets_); + } else { + c = strcmp(expected_targets_, other->expected_targets_); + } + if (c != 0) return c; + return GPR_ICMP(is_lb_channel_, other->is_lb_channel_); + } + + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate( + tsi_create_fake_handshaker(/*is_client=*/true), this)); + } + + bool check_call_host(const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) override { + char* authority_hostname = nullptr; + char* authority_ignored_port = nullptr; + char* target_hostname = nullptr; + char* target_ignored_port = nullptr; + gpr_split_host_port(host, &authority_hostname, &authority_ignored_port); + gpr_split_host_port(target_, &target_hostname, &target_ignored_port); + if (target_name_override_ != nullptr) { + char* fake_security_target_name_override_hostname = nullptr; + char* fake_security_target_name_override_ignored_port = nullptr; + gpr_split_host_port(target_name_override_, + &fake_security_target_name_override_hostname, + &fake_security_target_name_override_ignored_port); + if (strcmp(authority_hostname, + fake_security_target_name_override_hostname) != 0) { + gpr_log(GPR_ERROR, + "Authority (host) '%s' != Fake Security Target override '%s'", + host, fake_security_target_name_override_hostname); + abort(); + } + gpr_free(fake_security_target_name_override_hostname); + gpr_free(fake_security_target_name_override_ignored_port); + } else if (strcmp(authority_hostname, target_hostname) != 0) { + gpr_log(GPR_ERROR, "Authority (host) '%s' != Target '%s'", + authority_hostname, target_hostname); + abort(); + } + gpr_free(authority_hostname); + gpr_free(authority_ignored_port); + gpr_free(target_hostname); + gpr_free(target_ignored_port); + return true; + } + + void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) override { + GRPC_ERROR_UNREF(error); + } + + char* target() const { return target_; } + char* expected_targets() const { return expected_targets_; } + bool is_lb_channel() const { return is_lb_channel_; } + char* target_name_override() const { return target_name_override_; } + + private: + bool fake_check_target(const char* target_type, const char* target, + const char* set_str) const { + GPR_ASSERT(target_type != nullptr); + GPR_ASSERT(target != nullptr); + char** set = nullptr; + size_t set_size = 0; + gpr_string_split(set_str, ",", &set, &set_size); + bool found = false; + for (size_t i = 0; i < set_size; ++i) { + if (set[i] != nullptr && strcmp(target, set[i]) == 0) found = true; + } + for (size_t i = 0; i < set_size; ++i) { + gpr_free(set[i]); + } + gpr_free(set); + return found; + } + + void fake_secure_name_check() const { + if (expected_targets_ == nullptr) return; + char** lbs_and_backends = nullptr; + size_t lbs_and_backends_size = 0; + bool success = false; + gpr_string_split(expected_targets_, ";", &lbs_and_backends, + &lbs_and_backends_size); + if (lbs_and_backends_size > 2 || lbs_and_backends_size == 0) { + gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'", + expected_targets_); + goto done; + } + if (is_lb_channel_) { + if (lbs_and_backends_size != 2) { + gpr_log(GPR_ERROR, + "Invalid expected targets arg value: '%s'. Expectations for LB " + "channels must be of the form 'be1,be2,be3,...;lb1,lb2,...", + expected_targets_); + goto done; + } + if (!fake_check_target("LB", target_, lbs_and_backends[1])) { + gpr_log(GPR_ERROR, "LB target '%s' not found in expected set '%s'", + target_, lbs_and_backends[1]); + goto done; + } + success = true; + } else { + if (!fake_check_target("Backend", target_, lbs_and_backends[0])) { + gpr_log(GPR_ERROR, "Backend target '%s' not found in expected set '%s'", + target_, lbs_and_backends[0]); + goto done; + } + success = true; + } + done: + for (size_t i = 0; i < lbs_and_backends_size; ++i) { + gpr_free(lbs_and_backends[i]); + } + gpr_free(lbs_and_backends); + if (!success) abort(); + } + + char* target_; + char* expected_targets_; + bool is_lb_channel_; + char* target_name_override_; +}; + +static void fake_check_peer( + grpc_security_connector* sc, tsi_peer peer, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) { + const char* prop_name; + grpc_error* error = GRPC_ERROR_NONE; + *auth_context = nullptr; + if (peer.property_count != 1) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Fake peers should only have 1 property."); + goto end; + } + prop_name = peer.properties[0].name; + if (prop_name == nullptr || + strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { + char* msg; + gpr_asprintf(&msg, "Unexpected property in fake peer: %s.", + prop_name == nullptr ? "" : prop_name); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + goto end; + } + if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, + peer.properties[0].value.length)) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid value for cert type property."); + goto end; + } + *auth_context = grpc_core::MakeRefCounted(nullptr); + grpc_auth_context_add_cstring_property( + auth_context->get(), GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_FAKE_TRANSPORT_SECURITY_TYPE); +end: + GRPC_CLOSURE_SCHED(on_peer_checked, error); + tsi_peer_destruct(&peer); +} + +void grpc_fake_channel_security_connector::check_peer( + tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) { + fake_check_peer(this, peer, auth_context, on_peer_checked); + fake_secure_name_check(); +} + +class grpc_fake_server_security_connector + : public grpc_server_security_connector { + public: + grpc_fake_server_security_connector( + grpc_core::RefCountedPtr server_creds) + : grpc_server_security_connector(GRPC_FAKE_SECURITY_URL_SCHEME, + std::move(server_creds)) {} + ~grpc_fake_server_security_connector() override = default; + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + fake_check_peer(this, peer, auth_context, on_peer_checked); + } + + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate( + tsi_create_fake_handshaker(/*=is_client*/ false), this)); + } + + int cmp(const grpc_security_connector* other) const override { + return server_security_connector_cmp( + static_cast(other)); + } +}; +} // namespace + +grpc_core::RefCountedPtr +grpc_fake_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target, const grpc_channel_args* args) { + return grpc_core::MakeRefCounted( + std::move(channel_creds), std::move(request_metadata_creds), target, + args); +} + +grpc_core::RefCountedPtr +grpc_fake_server_security_connector_create( + grpc_core::RefCountedPtr server_creds) { + return grpc_core::MakeRefCounted( + std::move(server_creds)); +} diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/fake/fake_security_connector.h b/Sources/CgRPC/src/core/lib/security/security_connector/fake/fake_security_connector.h new file mode 100644 index 000000000..344a2349a --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/fake/fake_security_connector.h @@ -0,0 +1,45 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_FAKE_FAKE_SECURITY_CONNECTOR_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_FAKE_FAKE_SECURITY_CONNECTOR_H + +#include + +#include + +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/security/security_connector/security_connector.h" + +#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security" + +/* Creates a fake connector that emulates real channel security. */ +grpc_core::RefCountedPtr +grpc_fake_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target, const grpc_channel_args* args); + +/* Creates a fake connector that emulates real server security. */ +grpc_core::RefCountedPtr +grpc_fake_server_security_connector_create( + grpc_core::RefCountedPtr server_creds); + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_FAKE_FAKE_SECURITY_CONNECTOR_H \ + */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots.h b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots.h new file mode 100644 index 000000000..5fdec1549 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots.h @@ -0,0 +1,29 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H + +namespace grpc_core { + +// Returns a slice containing roots from the OS trust store +grpc_slice LoadSystemRootCerts(); + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H */ diff --git a/Sources/CgRPC/src/core/lib/gpr/fork.h b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_fallback.cc similarity index 54% rename from Sources/CgRPC/src/core/lib/gpr/fork.h rename to Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_fallback.cc index 94c61bb83..73d1245f3 100644 --- a/Sources/CgRPC/src/core/lib/gpr/fork.h +++ b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_fallback.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2017 gRPC authors. + * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,20 +16,17 @@ * */ -#ifndef GRPC_CORE_LIB_GPR_FORK_H -#define GRPC_CORE_LIB_GPR_FORK_H +#include -/* - * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK - * AROUND VERY SPECIFIC USE CASES. - */ +#include +#include "src/core/lib/security/security_connector/load_system_roots.h" + +#ifndef GPR_LINUX -void grpc_fork_support_init(void); +namespace grpc_core { -int grpc_fork_support_enabled(void); +grpc_slice LoadSystemRootCerts() { return grpc_empty_slice(); } -// Test only: Must be called before grpc_init(), and overrides -// environment variables/compile flags -void grpc_enable_fork_support(int enable); +} // namespace grpc_core -#endif /* GRPC_CORE_LIB_GPR_FORK_H */ +#endif /* GPR_LINUX */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_linux.cc b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_linux.cc new file mode 100644 index 000000000..924fa8a3e --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_linux.cc @@ -0,0 +1,165 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include "src/core/lib/security/security_connector/load_system_roots_linux.h" + +#ifdef GPR_LINUX + +#include "src/core/lib/security/security_connector/load_system_roots.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/iomgr/load_file.h" + +namespace grpc_core { +namespace { + +const char* kLinuxCertFiles[] = { + "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/certs/ca-bundle.crt", + "/etc/ssl/ca-bundle.pem", "/etc/pki/tls/cacert.pem", + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"}; +const char* kLinuxCertDirectories[] = { + "/etc/ssl/certs", "/system/etc/security/cacerts", "/usr/local/share/certs", + "/etc/pki/tls/certs", "/etc/openssl/certs"}; + +grpc_slice GetSystemRootCerts() { + grpc_slice valid_bundle_slice = grpc_empty_slice(); + size_t num_cert_files_ = GPR_ARRAY_SIZE(kLinuxCertFiles); + for (size_t i = 0; i < num_cert_files_; i++) { + grpc_error* error = + grpc_load_file(kLinuxCertFiles[i], 1, &valid_bundle_slice); + if (error == GRPC_ERROR_NONE) { + return valid_bundle_slice; + } + } + return grpc_empty_slice(); +} + +} // namespace + +void GetAbsoluteFilePath(const char* valid_file_dir, + const char* file_entry_name, char* path_buffer) { + if (valid_file_dir != nullptr && file_entry_name != nullptr) { + int path_len = snprintf(path_buffer, MAXPATHLEN, "%s/%s", valid_file_dir, + file_entry_name); + if (path_len == 0) { + gpr_log(GPR_ERROR, "failed to get absolute path for file: %s", + file_entry_name); + } + } +} + +grpc_slice CreateRootCertsBundle(const char* certs_directory) { + grpc_slice bundle_slice = grpc_empty_slice(); + if (certs_directory == nullptr) { + return bundle_slice; + } + DIR* ca_directory = opendir(certs_directory); + if (ca_directory == nullptr) { + return bundle_slice; + } + struct FileData { + char path[MAXPATHLEN]; + off_t size; + }; + InlinedVector roots_filenames; + size_t total_bundle_size = 0; + struct dirent* directory_entry; + while ((directory_entry = readdir(ca_directory)) != nullptr) { + struct stat dir_entry_stat; + const char* file_entry_name = directory_entry->d_name; + FileData file_data; + GetAbsoluteFilePath(certs_directory, file_entry_name, file_data.path); + int stat_return = stat(file_data.path, &dir_entry_stat); + if (stat_return == -1 || !S_ISREG(dir_entry_stat.st_mode)) { + // no subdirectories. + if (stat_return == -1) { + gpr_log(GPR_ERROR, "failed to get status for file: %s", file_data.path); + } + continue; + } + file_data.size = dir_entry_stat.st_size; + total_bundle_size += file_data.size; + roots_filenames.push_back(file_data); + } + closedir(ca_directory); + char* bundle_string = static_cast(gpr_zalloc(total_bundle_size + 1)); + size_t bytes_read = 0; + for (size_t i = 0; i < roots_filenames.size(); i++) { + int file_descriptor = open(roots_filenames[i].path, O_RDONLY); + if (file_descriptor != -1) { + // Read file into bundle. + size_t cert_file_size = roots_filenames[i].size; + int read_ret = + read(file_descriptor, bundle_string + bytes_read, cert_file_size); + if (read_ret != -1) { + bytes_read += read_ret; + } else { + gpr_log(GPR_ERROR, "failed to read file: %s", roots_filenames[i].path); + } + } + } + bundle_slice = grpc_slice_new(bundle_string, bytes_read, gpr_free); + return bundle_slice; +} + +grpc_slice LoadSystemRootCerts() { + grpc_slice result = grpc_empty_slice(); + // Prioritize user-specified custom directory if flag is set. + char* custom_dir = gpr_getenv("GRPC_SYSTEM_SSL_ROOTS_DIR"); + if (custom_dir != nullptr) { + result = CreateRootCertsBundle(custom_dir); + gpr_free(custom_dir); + } + // If the custom directory is empty/invalid/not specified, fallback to + // distribution-specific directory. + if (GRPC_SLICE_IS_EMPTY(result)) { + result = GetSystemRootCerts(); + } + if (GRPC_SLICE_IS_EMPTY(result)) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(kLinuxCertDirectories); i++) { + result = CreateRootCertsBundle(kLinuxCertDirectories[i]); + if (!GRPC_SLICE_IS_EMPTY(result)) { + break; + } + } + } + return result; +} + +} // namespace grpc_core + +#endif /* GPR_LINUX */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_linux.h b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_linux.h new file mode 100644 index 000000000..12617df49 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/load_system_roots_linux.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H + +#include + +#ifdef GPR_LINUX + +namespace grpc_core { + +// Creates a bundle slice containing the contents of all certificate files in +// a directory. +// Returns such slice. +// Exposed for testing purposes only. +grpc_slice CreateRootCertsBundle(const char* certs_directory); + +// Gets the absolute file path needed to load a certificate file. +// Populates path_buffer, which must be of size MAXPATHLEN. +// Exposed for testing purposes only. +void GetAbsoluteFilePath(const char* valid_file_dir, + const char* file_entry_name, char* path_buffer); + +} // namespace grpc_core + +#endif /* GPR_LINUX */ +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H \ + */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/local/local_security_connector.cc b/Sources/CgRPC/src/core/lib/security/security_connector/local/local_security_connector.cc new file mode 100644 index 000000000..c1a101d4a --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/local/local_security_connector.cc @@ -0,0 +1,255 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/security_connector/local/local_security_connector.h" + +#include +#include + +#include +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/socket_utils.h" +#include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "src/core/lib/security/credentials/local/local_credentials.h" +#include "src/core/lib/security/transport/security_handshaker.h" +#include "src/core/tsi/local_transport_security.h" + +#define GRPC_UDS_URI_PATTERN "unix:" +#define GRPC_LOCAL_TRANSPORT_SECURITY_TYPE "local" + +namespace { + +grpc_core::RefCountedPtr local_auth_context_create() { + /* Create auth context. */ + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + grpc_auth_context_add_cstring_property( + ctx.get(), GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_LOCAL_TRANSPORT_SECURITY_TYPE); + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( + ctx.get(), GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME) == 1); + return ctx; +} + +void local_check_peer(grpc_security_connector* sc, tsi_peer peer, + grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked, + grpc_local_connect_type type) { + int fd = grpc_endpoint_get_fd(ep); + grpc_resolved_address resolved_addr; + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = GRPC_MAX_SOCKADDR_SIZE; + bool is_endpoint_local = false; + if (getsockname(fd, reinterpret_cast(resolved_addr.addr), + &resolved_addr.len) == 0) { + grpc_resolved_address addr_normalized; + grpc_resolved_address* addr = + grpc_sockaddr_is_v4mapped(&resolved_addr, &addr_normalized) + ? &addr_normalized + : &resolved_addr; + grpc_sockaddr* sock_addr = reinterpret_cast(&addr->addr); + // UDS + if (type == UDS && grpc_is_unix_socket(addr)) { + is_endpoint_local = true; + // IPV4 + } else if (type == LOCAL_TCP && sock_addr->sa_family == GRPC_AF_INET) { + const grpc_sockaddr_in* addr4 = + reinterpret_cast(sock_addr); + if (grpc_htonl(addr4->sin_addr.s_addr) == INADDR_LOOPBACK) { + is_endpoint_local = true; + } + // IPv6 + } else if (type == LOCAL_TCP && sock_addr->sa_family == GRPC_AF_INET6) { + const grpc_sockaddr_in6* addr6 = + reinterpret_cast(addr); + if (memcmp(&addr6->sin6_addr, &in6addr_loopback, + sizeof(in6addr_loopback)) == 0) { + is_endpoint_local = true; + } + } + } + grpc_error* error = GRPC_ERROR_NONE; + if (!is_endpoint_local) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Endpoint is neither UDS or TCP loopback address."); + GRPC_CLOSURE_SCHED(on_peer_checked, error); + return; + } + /* Create an auth context which is necessary to pass the santiy check in + * {client, server}_auth_filter that verifies if the peer's auth context is + * obtained during handshakes. The auth context is only checked for its + * existence and not actually used. + */ + *auth_context = local_auth_context_create(); + error = *auth_context != nullptr ? GRPC_ERROR_NONE + : GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Could not create local auth context"); + GRPC_CLOSURE_SCHED(on_peer_checked, error); +} + +class grpc_local_channel_security_connector final + : public grpc_channel_security_connector { + public: + grpc_local_channel_security_connector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name) + : grpc_channel_security_connector(nullptr, std::move(channel_creds), + std::move(request_metadata_creds)), + target_name_(gpr_strdup(target_name)) {} + + ~grpc_local_channel_security_connector() override { gpr_free(target_name_); } + + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { + tsi_handshaker* handshaker = nullptr; + GPR_ASSERT(local_tsi_handshaker_create(true /* is_client */, &handshaker) == + TSI_OK); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); + } + + int cmp(const grpc_security_connector* other_sc) const override { + auto* other = + reinterpret_cast( + other_sc); + int c = channel_security_connector_cmp(other); + if (c != 0) return c; + return strcmp(target_name_, other->target_name_); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + grpc_local_credentials* creds = + reinterpret_cast(mutable_channel_creds()); + local_check_peer(this, peer, ep, auth_context, on_peer_checked, + creds->connect_type()); + } + + bool check_call_host(const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) override { + if (host == nullptr || strcmp(host, target_name_) != 0) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "local call host does not match target name"); + } + return true; + } + + void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) override { + GRPC_ERROR_UNREF(error); + } + + const char* target_name() const { return target_name_; } + + private: + char* target_name_; +}; + +class grpc_local_server_security_connector final + : public grpc_server_security_connector { + public: + grpc_local_server_security_connector( + grpc_core::RefCountedPtr server_creds) + : grpc_server_security_connector(nullptr, std::move(server_creds)) {} + ~grpc_local_server_security_connector() override = default; + + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { + tsi_handshaker* handshaker = nullptr; + GPR_ASSERT(local_tsi_handshaker_create(false /* is_client */, + &handshaker) == TSI_OK); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + grpc_local_server_credentials* creds = + static_cast(mutable_server_creds()); + local_check_peer(this, peer, ep, auth_context, on_peer_checked, + creds->connect_type()); + } + + int cmp(const grpc_security_connector* other) const override { + return server_security_connector_cmp( + static_cast(other)); + } +}; +} // namespace + +grpc_core::RefCountedPtr +grpc_local_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const grpc_channel_args* args, const char* target_name) { + if (channel_creds == nullptr || target_name == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid arguments to grpc_local_channel_security_connector_create()"); + return nullptr; + } + // Perform sanity check on UDS address. For TCP local connection, the check + // will be done during check_peer procedure. + grpc_local_credentials* creds = + static_cast(channel_creds.get()); + const grpc_arg* server_uri_arg = + grpc_channel_args_find(args, GRPC_ARG_SERVER_URI); + const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg); + if (creds->connect_type() == UDS && + strncmp(GRPC_UDS_URI_PATTERN, server_uri_str, + strlen(GRPC_UDS_URI_PATTERN)) != 0) { + gpr_log(GPR_ERROR, + "Invalid UDS target name to " + "grpc_local_channel_security_connector_create()"); + return nullptr; + } + return grpc_core::MakeRefCounted( + channel_creds, request_metadata_creds, target_name); +} + +grpc_core::RefCountedPtr +grpc_local_server_security_connector_create( + grpc_core::RefCountedPtr server_creds) { + if (server_creds == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid arguments to grpc_local_server_security_connector_create()"); + return nullptr; + } + return grpc_core::MakeRefCounted( + std::move(server_creds)); +} diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/local/local_security_connector.h b/Sources/CgRPC/src/core/lib/security/security_connector/local/local_security_connector.h new file mode 100644 index 000000000..6eee0ca9a --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/local/local_security_connector.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOCAL_LOCAL_SECURITY_CONNECTOR_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOCAL_LOCAL_SECURITY_CONNECTOR_H + +#include + +#include "src/core/lib/security/context/security_context.h" + +/** + * This method creates a local channel security connector. + * + * - channel_creds: channel credential instance. + * - request_metadata_creds: credential object which will be sent with each + * request. This parameter can be nullptr. + * - target_name: the name of the endpoint that the channel is connecting to. + * - args: channel args passed from the caller. + * - sc: address of local channel security connector instance to be returned + * from the method. + * + * It returns nullptr on failure. + */ +grpc_core::RefCountedPtr +grpc_local_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const grpc_channel_args* args, const char* target_name); + +/** + * This method creates a local server security connector. + * + * - server_creds: server credential instance. + * - sc: address of local server security connector instance to be returned from + * the method. + * + * It returns nullptr on failure. + */ +grpc_core::RefCountedPtr +grpc_local_server_security_connector_create( + grpc_core::RefCountedPtr server_creds); + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOCAL_LOCAL_SECURITY_CONNECTOR_H \ + */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.cc b/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.cc index 6eae30a6e..96a196054 100644 --- a/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.cc +++ b/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.cc @@ -20,9 +20,6 @@ #include "src/core/lib/security/security_connector/security_connector.h" -#include -#include - #include #include #include @@ -37,212 +34,68 @@ #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" -#include "src/core/lib/security/transport/secure_endpoint.h" +#include "src/core/lib/security/security_connector/load_system_roots.h" +#include "src/core/lib/security/security_connector/security_connector.h" #include "src/core/lib/security/transport/security_handshaker.h" -#include "src/core/lib/security/transport/target_authority_table.h" -#include "src/core/tsi/fake_transport_security.h" -#include "src/core/tsi/ssl_transport_security.h" -#include "src/core/tsi/transport_security_adapter.h" grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount( false, "security_connector_refcount"); -/* -- Constants. -- */ - -#ifndef INSTALL_PREFIX -static const char* installed_roots_path = "/usr/share/grpc/roots.pem"; -#else -static const char* installed_roots_path = - INSTALL_PREFIX "/share/grpc/roots.pem"; -#endif - -/* -- Overridden default roots. -- */ - -static grpc_ssl_roots_override_callback ssl_roots_override_cb = nullptr; - -void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) { - ssl_roots_override_cb = cb; -} - -/* -- Cipher suites. -- */ - -/* Defines the cipher suites that we accept by default. All these cipher suites - are compliant with HTTP2. */ -#define GRPC_SSL_CIPHER_SUITES \ - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384" - -static gpr_once cipher_suites_once = GPR_ONCE_INIT; -static const char* cipher_suites = nullptr; - -static void init_cipher_suites(void) { - char* overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES"); - cipher_suites = overridden != nullptr ? overridden : GRPC_SSL_CIPHER_SUITES; -} - -static const char* ssl_cipher_suites(void) { - gpr_once_init(&cipher_suites_once, init_cipher_suites); - return cipher_suites; -} - -/* -- Common methods. -- */ - -/* Returns the first property with that name. */ -const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* peer, - const char* name) { - size_t i; - if (peer == nullptr) return nullptr; - for (i = 0; i < peer->property_count; i++) { - const tsi_peer_property* property = &peer->properties[i]; - if (name == nullptr && property->name == nullptr) { - return property; - } - if (name != nullptr && property->name != nullptr && - strcmp(property->name, name) == 0) { - return property; - } - } - return nullptr; -} - -void grpc_channel_security_connector_add_handshakers( - grpc_channel_security_connector* connector, - grpc_handshake_manager* handshake_mgr) { - if (connector != nullptr) { - connector->add_handshakers(connector, handshake_mgr); - } -} - -void grpc_server_security_connector_add_handshakers( - grpc_server_security_connector* connector, - grpc_handshake_manager* handshake_mgr) { - if (connector != nullptr) { - connector->add_handshakers(connector, handshake_mgr); - } -} - -void grpc_security_connector_check_peer(grpc_security_connector* sc, - tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - if (sc == nullptr) { - GRPC_CLOSURE_SCHED(on_peer_checked, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "cannot check peer -- no security connector")); - tsi_peer_destruct(&peer); - } else { - sc->vtable->check_peer(sc, peer, auth_context, on_peer_checked); - } -} - -int grpc_security_connector_cmp(grpc_security_connector* sc, - grpc_security_connector* other) { +grpc_server_security_connector::grpc_server_security_connector( + const char* url_scheme, + grpc_core::RefCountedPtr server_creds) + : grpc_security_connector(url_scheme), + server_creds_(std::move(server_creds)) {} + +grpc_channel_security_connector::grpc_channel_security_connector( + const char* url_scheme, + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds) + : grpc_security_connector(url_scheme), + channel_creds_(std::move(channel_creds)), + request_metadata_creds_(std::move(request_metadata_creds)) {} +grpc_channel_security_connector::~grpc_channel_security_connector() {} + +int grpc_security_connector_cmp(const grpc_security_connector* sc, + const grpc_security_connector* other) { if (sc == nullptr || other == nullptr) return GPR_ICMP(sc, other); - int c = GPR_ICMP(sc->vtable, other->vtable); - if (c != 0) return c; - return sc->vtable->cmp(sc, other); -} - -int grpc_channel_security_connector_cmp(grpc_channel_security_connector* sc1, - grpc_channel_security_connector* sc2) { - GPR_ASSERT(sc1->channel_creds != nullptr); - GPR_ASSERT(sc2->channel_creds != nullptr); - int c = GPR_ICMP(sc1->channel_creds, sc2->channel_creds); - if (c != 0) return c; - c = GPR_ICMP(sc1->request_metadata_creds, sc2->request_metadata_creds); - if (c != 0) return c; - c = GPR_ICMP((void*)sc1->check_call_host, (void*)sc2->check_call_host); - if (c != 0) return c; - c = GPR_ICMP((void*)sc1->cancel_check_call_host, - (void*)sc2->cancel_check_call_host); - if (c != 0) return c; - return GPR_ICMP((void*)sc1->add_handshakers, (void*)sc2->add_handshakers); + return sc->cmp(other); } -int grpc_server_security_connector_cmp(grpc_server_security_connector* sc1, - grpc_server_security_connector* sc2) { - GPR_ASSERT(sc1->server_creds != nullptr); - GPR_ASSERT(sc2->server_creds != nullptr); - int c = GPR_ICMP(sc1->server_creds, sc2->server_creds); +int grpc_channel_security_connector::channel_security_connector_cmp( + const grpc_channel_security_connector* other) const { + const grpc_channel_security_connector* other_sc = + static_cast(other); + GPR_ASSERT(channel_creds() != nullptr); + GPR_ASSERT(other_sc->channel_creds() != nullptr); + int c = GPR_ICMP(channel_creds(), other_sc->channel_creds()); if (c != 0) return c; - return GPR_ICMP((void*)sc1->add_handshakers, (void*)sc2->add_handshakers); -} - -bool grpc_channel_security_connector_check_call_host( - grpc_channel_security_connector* sc, const char* host, - grpc_auth_context* auth_context, grpc_closure* on_call_host_checked, - grpc_error** error) { - if (sc == nullptr || sc->check_call_host == nullptr) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "cannot check call host -- no security connector"); - return true; - } - return sc->check_call_host(sc, host, auth_context, on_call_host_checked, - error); -} - -void grpc_channel_security_connector_cancel_check_call_host( - grpc_channel_security_connector* sc, grpc_closure* on_call_host_checked, - grpc_error* error) { - if (sc == nullptr || sc->cancel_check_call_host == nullptr) { - GRPC_ERROR_UNREF(error); - return; - } - sc->cancel_check_call_host(sc, on_call_host_checked, error); + return GPR_ICMP(request_metadata_creds(), other_sc->request_metadata_creds()); } -#ifndef NDEBUG -grpc_security_connector* grpc_security_connector_ref( - grpc_security_connector* sc, const char* file, int line, - const char* reason) { - if (sc == nullptr) return nullptr; - if (grpc_trace_security_connector_refcount.enabled()) { - gpr_atm val = gpr_atm_no_barrier_load(&sc->refcount.count); - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SECURITY_CONNECTOR:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", sc, - val, val + 1, reason); - } -#else -grpc_security_connector* grpc_security_connector_ref( - grpc_security_connector* sc) { - if (sc == nullptr) return nullptr; -#endif - gpr_ref(&sc->refcount); - return sc; -} - -#ifndef NDEBUG -void grpc_security_connector_unref(grpc_security_connector* sc, - const char* file, int line, - const char* reason) { - if (sc == nullptr) return; - if (grpc_trace_security_connector_refcount.enabled()) { - gpr_atm val = gpr_atm_no_barrier_load(&sc->refcount.count); - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SECURITY_CONNECTOR:%p unref %" PRIdPTR " -> %" PRIdPTR " %s", sc, - val, val - 1, reason); - } -#else -void grpc_security_connector_unref(grpc_security_connector* sc) { - if (sc == nullptr) return; -#endif - if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc); +int grpc_server_security_connector::server_security_connector_cmp( + const grpc_server_security_connector* other) const { + const grpc_server_security_connector* other_sc = + static_cast(other); + GPR_ASSERT(server_creds() != nullptr); + GPR_ASSERT(other_sc->server_creds() != nullptr); + return GPR_ICMP(server_creds(), other_sc->server_creds()); } static void connector_arg_destroy(void* p) { - GRPC_SECURITY_CONNECTOR_UNREF((grpc_security_connector*)p, - "connector_arg_destroy"); + static_cast(p)->Unref(DEBUG_LOCATION, + "connector_arg_destroy"); } static void* connector_arg_copy(void* p) { - return GRPC_SECURITY_CONNECTOR_REF((grpc_security_connector*)p, - "connector_arg_copy"); + return static_cast(p) + ->Ref(DEBUG_LOCATION, "connector_arg_copy") + .release(); } static int connector_cmp(void* a, void* b) { - return grpc_security_connector_cmp(static_cast(a), - static_cast(b)); + return static_cast(a)->cmp( + static_cast(b)); } static const grpc_arg_pointer_vtable connector_arg_vtable = { @@ -274,930 +127,3 @@ grpc_security_connector* grpc_security_connector_find_in_args( } return nullptr; } - -static tsi_client_certificate_request_type -get_tsi_client_certificate_request_type( - grpc_ssl_client_certificate_request_type grpc_request_type) { - switch (grpc_request_type) { - case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: - return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; - - case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; - - case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: - return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; - - case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; - - case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: - return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; - - default: - return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; - } -} - -/* -- Fake implementation. -- */ - -typedef struct { - grpc_channel_security_connector base; - char* target; - char* expected_targets; - bool is_lb_channel; - char* target_name_override; -} grpc_fake_channel_security_connector; - -static void fake_channel_destroy(grpc_security_connector* sc) { - grpc_fake_channel_security_connector* c = - reinterpret_cast(sc); - grpc_call_credentials_unref(c->base.request_metadata_creds); - gpr_free(c->target); - gpr_free(c->expected_targets); - gpr_free(c->target_name_override); - gpr_free(c); -} - -static void fake_server_destroy(grpc_security_connector* sc) { gpr_free(sc); } - -static bool fake_check_target(const char* target_type, const char* target, - const char* set_str) { - GPR_ASSERT(target_type != nullptr); - GPR_ASSERT(target != nullptr); - char** set = nullptr; - size_t set_size = 0; - gpr_string_split(set_str, ",", &set, &set_size); - bool found = false; - for (size_t i = 0; i < set_size; ++i) { - if (set[i] != nullptr && strcmp(target, set[i]) == 0) found = true; - } - for (size_t i = 0; i < set_size; ++i) { - gpr_free(set[i]); - } - gpr_free(set); - return found; -} - -static void fake_secure_name_check(const char* target, - const char* expected_targets, - bool is_lb_channel) { - if (expected_targets == nullptr) return; - char** lbs_and_backends = nullptr; - size_t lbs_and_backends_size = 0; - bool success = false; - gpr_string_split(expected_targets, ";", &lbs_and_backends, - &lbs_and_backends_size); - if (lbs_and_backends_size > 2 || lbs_and_backends_size == 0) { - gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'", - expected_targets); - goto done; - } - if (is_lb_channel) { - if (lbs_and_backends_size != 2) { - gpr_log(GPR_ERROR, - "Invalid expected targets arg value: '%s'. Expectations for LB " - "channels must be of the form 'be1,be2,be3,...;lb1,lb2,...", - expected_targets); - goto done; - } - if (!fake_check_target("LB", target, lbs_and_backends[1])) { - gpr_log(GPR_ERROR, "LB target '%s' not found in expected set '%s'", - target, lbs_and_backends[1]); - goto done; - } - success = true; - } else { - if (!fake_check_target("Backend", target, lbs_and_backends[0])) { - gpr_log(GPR_ERROR, "Backend target '%s' not found in expected set '%s'", - target, lbs_and_backends[0]); - goto done; - } - success = true; - } -done: - for (size_t i = 0; i < lbs_and_backends_size; ++i) { - gpr_free(lbs_and_backends[i]); - } - gpr_free(lbs_and_backends); - if (!success) abort(); -} - -static void fake_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - const char* prop_name; - grpc_error* error = GRPC_ERROR_NONE; - *auth_context = nullptr; - if (peer.property_count != 1) { - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Fake peers should only have 1 property."); - goto end; - } - prop_name = peer.properties[0].name; - if (prop_name == nullptr || - strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { - char* msg; - gpr_asprintf(&msg, "Unexpected property in fake peer: %s.", - prop_name == nullptr ? "" : prop_name); - error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); - gpr_free(msg); - goto end; - } - if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, - peer.properties[0].value.length)) { - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Invalid value for cert type property."); - goto end; - } - *auth_context = grpc_auth_context_create(nullptr); - grpc_auth_context_add_cstring_property( - *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, - GRPC_FAKE_TRANSPORT_SECURITY_TYPE); -end: - GRPC_CLOSURE_SCHED(on_peer_checked, error); - tsi_peer_destruct(&peer); -} - -static void fake_channel_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - fake_check_peer(sc, peer, auth_context, on_peer_checked); - grpc_fake_channel_security_connector* c = - reinterpret_cast(sc); - fake_secure_name_check(c->target, c->expected_targets, c->is_lb_channel); -} - -static void fake_server_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - fake_check_peer(sc, peer, auth_context, on_peer_checked); -} - -static int fake_channel_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - grpc_fake_channel_security_connector* c1 = - reinterpret_cast(sc1); - grpc_fake_channel_security_connector* c2 = - reinterpret_cast(sc2); - int c = grpc_channel_security_connector_cmp(&c1->base, &c2->base); - if (c != 0) return c; - c = strcmp(c1->target, c2->target); - if (c != 0) return c; - if (c1->expected_targets == nullptr || c2->expected_targets == nullptr) { - c = GPR_ICMP(c1->expected_targets, c2->expected_targets); - } else { - c = strcmp(c1->expected_targets, c2->expected_targets); - } - if (c != 0) return c; - return GPR_ICMP(c1->is_lb_channel, c2->is_lb_channel); -} - -static int fake_server_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - return grpc_server_security_connector_cmp( - reinterpret_cast(sc1), - reinterpret_cast(sc2)); -} - -static bool fake_channel_check_call_host(grpc_channel_security_connector* sc, - const char* host, - grpc_auth_context* auth_context, - grpc_closure* on_call_host_checked, - grpc_error** error) { - grpc_fake_channel_security_connector* c = - reinterpret_cast(sc); - char* authority_hostname = nullptr; - char* authority_ignored_port = nullptr; - char* target_hostname = nullptr; - char* target_ignored_port = nullptr; - gpr_split_host_port(host, &authority_hostname, &authority_ignored_port); - gpr_split_host_port(c->target, &target_hostname, &target_ignored_port); - if (c->target_name_override != nullptr) { - char* fake_security_target_name_override_hostname = nullptr; - char* fake_security_target_name_override_ignored_port = nullptr; - gpr_split_host_port(c->target_name_override, - &fake_security_target_name_override_hostname, - &fake_security_target_name_override_ignored_port); - if (strcmp(authority_hostname, - fake_security_target_name_override_hostname) != 0) { - gpr_log(GPR_ERROR, - "Authority (host) '%s' != Fake Security Target override '%s'", - host, fake_security_target_name_override_hostname); - abort(); - } - gpr_free(fake_security_target_name_override_hostname); - gpr_free(fake_security_target_name_override_ignored_port); - } else if (strcmp(authority_hostname, target_hostname) != 0) { - gpr_log(GPR_ERROR, "Authority (host) '%s' != Target '%s'", - authority_hostname, target_hostname); - abort(); - } - gpr_free(authority_hostname); - gpr_free(authority_ignored_port); - gpr_free(target_hostname); - gpr_free(target_ignored_port); - return true; -} - -static void fake_channel_cancel_check_call_host( - grpc_channel_security_connector* sc, grpc_closure* on_call_host_checked, - grpc_error* error) { - GRPC_ERROR_UNREF(error); -} - -static void fake_channel_add_handshakers( - grpc_channel_security_connector* sc, - grpc_handshake_manager* handshake_mgr) { - grpc_handshake_manager_add( - handshake_mgr, - grpc_security_handshaker_create( - tsi_create_fake_handshaker(true /* is_client */), &sc->base)); -} - -static void fake_server_add_handshakers(grpc_server_security_connector* sc, - grpc_handshake_manager* handshake_mgr) { - grpc_handshake_manager_add( - handshake_mgr, - grpc_security_handshaker_create( - tsi_create_fake_handshaker(false /* is_client */), &sc->base)); -} - -static grpc_security_connector_vtable fake_channel_vtable = { - fake_channel_destroy, fake_channel_check_peer, fake_channel_cmp}; - -static grpc_security_connector_vtable fake_server_vtable = { - fake_server_destroy, fake_server_check_peer, fake_server_cmp}; - -grpc_channel_security_connector* grpc_fake_channel_security_connector_create( - grpc_channel_credentials* channel_creds, - grpc_call_credentials* request_metadata_creds, const char* target, - const grpc_channel_args* args) { - grpc_fake_channel_security_connector* c = - static_cast( - gpr_zalloc(sizeof(*c))); - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; - c->base.base.vtable = &fake_channel_vtable; - c->base.channel_creds = channel_creds; - c->base.request_metadata_creds = - grpc_call_credentials_ref(request_metadata_creds); - c->base.check_call_host = fake_channel_check_call_host; - c->base.cancel_check_call_host = fake_channel_cancel_check_call_host; - c->base.add_handshakers = fake_channel_add_handshakers; - c->target = gpr_strdup(target); - const char* expected_targets = grpc_fake_transport_get_expected_targets(args); - c->expected_targets = gpr_strdup(expected_targets); - c->is_lb_channel = grpc_core::FindTargetAuthorityTableInArgs(args) != nullptr; - const grpc_arg* target_name_override_arg = - grpc_channel_args_find(args, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); - if (target_name_override_arg != nullptr) { - c->target_name_override = - gpr_strdup(grpc_channel_arg_get_string(target_name_override_arg)); - } - return &c->base; -} - -grpc_server_security_connector* grpc_fake_server_security_connector_create( - grpc_server_credentials* server_creds) { - grpc_server_security_connector* c = - static_cast( - gpr_zalloc(sizeof(grpc_server_security_connector))); - gpr_ref_init(&c->base.refcount, 1); - c->base.vtable = &fake_server_vtable; - c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; - c->server_creds = server_creds; - c->add_handshakers = fake_server_add_handshakers; - return c; -} - -/* --- Ssl implementation. --- */ - -grpc_ssl_session_cache* grpc_ssl_session_cache_create_lru(size_t capacity) { - tsi_ssl_session_cache* cache = tsi_ssl_session_cache_create_lru(capacity); - return reinterpret_cast(cache); -} - -void grpc_ssl_session_cache_destroy(grpc_ssl_session_cache* cache) { - tsi_ssl_session_cache* tsi_cache = - reinterpret_cast(cache); - tsi_ssl_session_cache_unref(tsi_cache); -} - -static void* grpc_ssl_session_cache_arg_copy(void* p) { - tsi_ssl_session_cache* tsi_cache = - reinterpret_cast(p); - // destroy call below will unref the pointer. - tsi_ssl_session_cache_ref(tsi_cache); - return p; -} - -static void grpc_ssl_session_cache_arg_destroy(void* p) { - tsi_ssl_session_cache* tsi_cache = - reinterpret_cast(p); - tsi_ssl_session_cache_unref(tsi_cache); -} - -static int grpc_ssl_session_cache_arg_cmp(void* p, void* q) { - return GPR_ICMP(p, q); -} - -grpc_arg grpc_ssl_session_cache_create_channel_arg( - grpc_ssl_session_cache* cache) { - static const grpc_arg_pointer_vtable vtable = { - grpc_ssl_session_cache_arg_copy, - grpc_ssl_session_cache_arg_destroy, - grpc_ssl_session_cache_arg_cmp, - }; - return grpc_channel_arg_pointer_create( - const_cast(GRPC_SSL_SESSION_CACHE_ARG), cache, &vtable); -} - -typedef struct { - grpc_channel_security_connector base; - tsi_ssl_client_handshaker_factory* client_handshaker_factory; - char* target_name; - char* overridden_target_name; -} grpc_ssl_channel_security_connector; - -typedef struct { - grpc_server_security_connector base; - tsi_ssl_server_handshaker_factory* server_handshaker_factory; -} grpc_ssl_server_security_connector; - -static bool server_connector_has_cert_config_fetcher( - grpc_ssl_server_security_connector* c) { - GPR_ASSERT(c != nullptr); - grpc_ssl_server_credentials* server_creds = - reinterpret_cast(c->base.server_creds); - GPR_ASSERT(server_creds != nullptr); - return server_creds->certificate_config_fetcher.cb != nullptr; -} - -static void ssl_channel_destroy(grpc_security_connector* sc) { - grpc_ssl_channel_security_connector* c = - reinterpret_cast(sc); - grpc_channel_credentials_unref(c->base.channel_creds); - grpc_call_credentials_unref(c->base.request_metadata_creds); - tsi_ssl_client_handshaker_factory_unref(c->client_handshaker_factory); - c->client_handshaker_factory = nullptr; - if (c->target_name != nullptr) gpr_free(c->target_name); - if (c->overridden_target_name != nullptr) gpr_free(c->overridden_target_name); - gpr_free(sc); -} - -static void ssl_server_destroy(grpc_security_connector* sc) { - grpc_ssl_server_security_connector* c = - reinterpret_cast(sc); - grpc_server_credentials_unref(c->base.server_creds); - tsi_ssl_server_handshaker_factory_unref(c->server_handshaker_factory); - c->server_handshaker_factory = nullptr; - gpr_free(sc); -} - -static void ssl_channel_add_handshakers(grpc_channel_security_connector* sc, - grpc_handshake_manager* handshake_mgr) { - grpc_ssl_channel_security_connector* c = - reinterpret_cast(sc); - // Instantiate TSI handshaker. - tsi_handshaker* tsi_hs = nullptr; - tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( - c->client_handshaker_factory, - c->overridden_target_name != nullptr ? c->overridden_target_name - : c->target_name, - &tsi_hs); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); - return; - } - // Create handshakers. - grpc_handshake_manager_add( - handshake_mgr, grpc_security_handshaker_create( - tsi_create_adapter_handshaker(tsi_hs), &sc->base)); -} - -static const char** fill_alpn_protocol_strings(size_t* num_alpn_protocols) { - GPR_ASSERT(num_alpn_protocols != nullptr); - *num_alpn_protocols = grpc_chttp2_num_alpn_versions(); - const char** alpn_protocol_strings = static_cast( - gpr_malloc(sizeof(const char*) * (*num_alpn_protocols))); - for (size_t i = 0; i < *num_alpn_protocols; i++) { - alpn_protocol_strings[i] = grpc_chttp2_get_alpn_version_index(i); - } - return alpn_protocol_strings; -} - -/* Attempts to replace the server_handshaker_factory with a new factory using - * the provided grpc_ssl_server_certificate_config. Should new factory creation - * fail, the existing factory will not be replaced. Returns true on success (new - * factory created). */ -static bool try_replace_server_handshaker_factory( - grpc_ssl_server_security_connector* sc, - const grpc_ssl_server_certificate_config* config) { - if (config == nullptr) { - gpr_log(GPR_ERROR, - "Server certificate config callback returned invalid (NULL) " - "config."); - return false; - } - gpr_log(GPR_DEBUG, "Using new server certificate config (%p).", config); - - size_t num_alpn_protocols = 0; - const char** alpn_protocol_strings = - fill_alpn_protocol_strings(&num_alpn_protocols); - tsi_ssl_pem_key_cert_pair* cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( - config->pem_key_cert_pairs, config->num_key_cert_pairs); - tsi_ssl_server_handshaker_factory* new_handshaker_factory = nullptr; - grpc_ssl_server_credentials* server_creds = - reinterpret_cast(sc->base.server_creds); - tsi_result result = tsi_create_ssl_server_handshaker_factory_ex( - cert_pairs, config->num_key_cert_pairs, config->pem_root_certs, - get_tsi_client_certificate_request_type( - server_creds->config.client_certificate_request), - ssl_cipher_suites(), alpn_protocol_strings, - static_cast(num_alpn_protocols), &new_handshaker_factory); - gpr_free(cert_pairs); - gpr_free((void*)alpn_protocol_strings); - - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - return false; - } - tsi_ssl_server_handshaker_factory_unref(sc->server_handshaker_factory); - sc->server_handshaker_factory = new_handshaker_factory; - return true; -} - -/* Attempts to fetch the server certificate config if a callback is available. - * Current certificate config will continue to be used if the callback returns - * an error. Returns true if new credentials were sucessfully loaded. */ -static bool try_fetch_ssl_server_credentials( - grpc_ssl_server_security_connector* sc) { - grpc_ssl_server_certificate_config* certificate_config = nullptr; - bool status; - - GPR_ASSERT(sc != nullptr); - if (!server_connector_has_cert_config_fetcher(sc)) return false; - - grpc_ssl_server_credentials* server_creds = - reinterpret_cast(sc->base.server_creds); - grpc_ssl_certificate_config_reload_status cb_result = - server_creds->certificate_config_fetcher.cb( - server_creds->certificate_config_fetcher.user_data, - &certificate_config); - if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) { - gpr_log(GPR_DEBUG, "No change in SSL server credentials."); - status = false; - } else if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) { - status = try_replace_server_handshaker_factory(sc, certificate_config); - } else { - // Log error, continue using previously-loaded credentials. - gpr_log(GPR_ERROR, - "Failed fetching new server credentials, continuing to " - "use previously-loaded credentials."); - status = false; - } - - if (certificate_config != nullptr) { - grpc_ssl_server_certificate_config_destroy(certificate_config); - } - return status; -} - -static void ssl_server_add_handshakers(grpc_server_security_connector* sc, - grpc_handshake_manager* handshake_mgr) { - grpc_ssl_server_security_connector* c = - reinterpret_cast(sc); - // Instantiate TSI handshaker. - try_fetch_ssl_server_credentials(c); - tsi_handshaker* tsi_hs = nullptr; - tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( - c->server_handshaker_factory, &tsi_hs); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); - return; - } - // Create handshakers. - grpc_handshake_manager_add( - handshake_mgr, grpc_security_handshaker_create( - tsi_create_adapter_handshaker(tsi_hs), &sc->base)); -} - -int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) { - char* allocated_name = nullptr; - int r; - - char* ignored_port; - gpr_split_host_port(peer_name, &allocated_name, &ignored_port); - gpr_free(ignored_port); - peer_name = allocated_name; - if (!peer_name) return 0; - - // IPv6 zone-id should not be included in comparisons. - char* const zone_id = strchr(allocated_name, '%'); - if (zone_id != nullptr) *zone_id = '\0'; - - r = tsi_ssl_peer_matches_name(peer, peer_name); - gpr_free(allocated_name); - return r; -} - -grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer) { - size_t i; - grpc_auth_context* ctx = nullptr; - const char* peer_identity_property_name = nullptr; - - /* The caller has checked the certificate type property. */ - GPR_ASSERT(peer->property_count >= 1); - ctx = grpc_auth_context_create(nullptr); - grpc_auth_context_add_cstring_property( - ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, - GRPC_SSL_TRANSPORT_SECURITY_TYPE); - for (i = 0; i < peer->property_count; i++) { - const tsi_peer_property* prop = &peer->properties[i]; - if (prop->name == nullptr) continue; - if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) { - /* If there is no subject alt name, have the CN as the identity. */ - if (peer_identity_property_name == nullptr) { - peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME; - } - grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME, - prop->value.data, prop->value.length); - } else if (strcmp(prop->name, - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { - peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME; - grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME, - prop->value.data, prop->value.length); - } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) { - grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME, - prop->value.data, prop->value.length); - } else if (strcmp(prop->name, TSI_SSL_SESSION_REUSED_PEER_PROPERTY) == 0) { - grpc_auth_context_add_property(ctx, GRPC_SSL_SESSION_REUSED_PROPERTY, - prop->value.data, prop->value.length); - } - } - if (peer_identity_property_name != nullptr) { - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( - ctx, peer_identity_property_name) == 1); - } - return ctx; -} - -static grpc_error* ssl_check_peer(grpc_security_connector* sc, - const char* peer_name, const tsi_peer* peer, - grpc_auth_context** auth_context) { - /* Check the ALPN. */ - const tsi_peer_property* p = - tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); - if (p == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: missing selected ALPN property."); - } - if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: invalid ALPN value."); - } - - /* Check the peer name if specified. */ - if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { - char* msg; - gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); - gpr_free(msg); - return error; - } - *auth_context = grpc_ssl_peer_to_auth_context(peer); - return GRPC_ERROR_NONE; -} - -static void ssl_channel_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - grpc_ssl_channel_security_connector* c = - reinterpret_cast(sc); - grpc_error* error = ssl_check_peer(sc, - c->overridden_target_name != nullptr - ? c->overridden_target_name - : c->target_name, - &peer, auth_context); - GRPC_CLOSURE_SCHED(on_peer_checked, error); - tsi_peer_destruct(&peer); -} - -static void ssl_server_check_peer(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked) { - grpc_error* error = ssl_check_peer(sc, nullptr, &peer, auth_context); - tsi_peer_destruct(&peer); - GRPC_CLOSURE_SCHED(on_peer_checked, error); -} - -static int ssl_channel_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - grpc_ssl_channel_security_connector* c1 = - reinterpret_cast(sc1); - grpc_ssl_channel_security_connector* c2 = - reinterpret_cast(sc2); - int c = grpc_channel_security_connector_cmp(&c1->base, &c2->base); - if (c != 0) return c; - c = strcmp(c1->target_name, c2->target_name); - if (c != 0) return c; - return (c1->overridden_target_name == nullptr || - c2->overridden_target_name == nullptr) - ? GPR_ICMP(c1->overridden_target_name, c2->overridden_target_name) - : strcmp(c1->overridden_target_name, c2->overridden_target_name); -} - -static int ssl_server_cmp(grpc_security_connector* sc1, - grpc_security_connector* sc2) { - return grpc_server_security_connector_cmp( - reinterpret_cast(sc1), - reinterpret_cast(sc2)); -} - -static void add_shallow_auth_property_to_peer(tsi_peer* peer, - const grpc_auth_property* prop, - const char* tsi_prop_name) { - tsi_peer_property* tsi_prop = &peer->properties[peer->property_count++]; - tsi_prop->name = const_cast(tsi_prop_name); - tsi_prop->value.data = prop->value; - tsi_prop->value.length = prop->value_length; -} - -tsi_peer grpc_shallow_peer_from_ssl_auth_context( - const grpc_auth_context* auth_context) { - size_t max_num_props = 0; - grpc_auth_property_iterator it; - const grpc_auth_property* prop; - tsi_peer peer; - memset(&peer, 0, sizeof(peer)); - - it = grpc_auth_context_property_iterator(auth_context); - while (grpc_auth_property_iterator_next(&it) != nullptr) max_num_props++; - - if (max_num_props > 0) { - peer.properties = static_cast( - gpr_malloc(max_num_props * sizeof(tsi_peer_property))); - it = grpc_auth_context_property_iterator(auth_context); - while ((prop = grpc_auth_property_iterator_next(&it)) != nullptr) { - if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) { - add_shallow_auth_property_to_peer( - &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY); - } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) { - add_shallow_auth_property_to_peer( - &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); - } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) { - add_shallow_auth_property_to_peer(&peer, prop, - TSI_X509_PEM_CERT_PROPERTY); - } - } - } - return peer; -} - -void grpc_shallow_peer_destruct(tsi_peer* peer) { - if (peer->properties != nullptr) gpr_free(peer->properties); -} - -static bool ssl_channel_check_call_host(grpc_channel_security_connector* sc, - const char* host, - grpc_auth_context* auth_context, - grpc_closure* on_call_host_checked, - grpc_error** error) { - grpc_ssl_channel_security_connector* c = - reinterpret_cast(sc); - grpc_security_status status = GRPC_SECURITY_ERROR; - tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context); - if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; - /* If the target name was overridden, then the original target_name was - 'checked' transitively during the previous peer check at the end of the - handshake. */ - if (c->overridden_target_name != nullptr && - strcmp(host, c->target_name) == 0) { - status = GRPC_SECURITY_OK; - } - if (status != GRPC_SECURITY_OK) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "call host does not match SSL server name"); - } - grpc_shallow_peer_destruct(&peer); - return true; -} - -static void ssl_channel_cancel_check_call_host( - grpc_channel_security_connector* sc, grpc_closure* on_call_host_checked, - grpc_error* error) { - GRPC_ERROR_UNREF(error); -} - -static grpc_security_connector_vtable ssl_channel_vtable = { - ssl_channel_destroy, ssl_channel_check_peer, ssl_channel_cmp}; - -static grpc_security_connector_vtable ssl_server_vtable = { - ssl_server_destroy, ssl_server_check_peer, ssl_server_cmp}; - -grpc_security_status grpc_ssl_channel_security_connector_create( - grpc_channel_credentials* channel_creds, - grpc_call_credentials* request_metadata_creds, - const grpc_ssl_config* config, const char* target_name, - const char* overridden_target_name, - tsi_ssl_session_cache* ssl_session_cache, - grpc_channel_security_connector** sc) { - tsi_result result = TSI_OK; - grpc_ssl_channel_security_connector* c; - char* port; - bool has_key_cert_pair; - tsi_ssl_client_handshaker_options options; - memset(&options, 0, sizeof(options)); - options.alpn_protocols = - fill_alpn_protocol_strings(&options.num_alpn_protocols); - - if (config == nullptr || target_name == nullptr) { - gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); - goto error; - } - if (config->pem_root_certs == nullptr) { - // Use default root certificates. - options.pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); - options.root_store = grpc_core::DefaultSslRootStore::GetRootStore(); - if (options.pem_root_certs == nullptr) { - gpr_log(GPR_ERROR, "Could not get default pem root certs."); - goto error; - } - } else { - options.pem_root_certs = config->pem_root_certs; - } - c = static_cast( - gpr_zalloc(sizeof(grpc_ssl_channel_security_connector))); - - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.vtable = &ssl_channel_vtable; - c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; - c->base.channel_creds = grpc_channel_credentials_ref(channel_creds); - c->base.request_metadata_creds = - grpc_call_credentials_ref(request_metadata_creds); - c->base.check_call_host = ssl_channel_check_call_host; - c->base.cancel_check_call_host = ssl_channel_cancel_check_call_host; - c->base.add_handshakers = ssl_channel_add_handshakers; - gpr_split_host_port(target_name, &c->target_name, &port); - gpr_free(port); - if (overridden_target_name != nullptr) { - c->overridden_target_name = gpr_strdup(overridden_target_name); - } - - has_key_cert_pair = config->pem_key_cert_pair != nullptr && - config->pem_key_cert_pair->private_key != nullptr && - config->pem_key_cert_pair->cert_chain != nullptr; - if (has_key_cert_pair) { - options.pem_key_cert_pair = config->pem_key_cert_pair; - } - options.cipher_suites = ssl_cipher_suites(); - options.session_cache = ssl_session_cache; - result = tsi_create_ssl_client_handshaker_factory_with_options( - &options, &c->client_handshaker_factory); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - ssl_channel_destroy(&c->base.base); - *sc = nullptr; - goto error; - } - *sc = &c->base; - gpr_free((void*)options.alpn_protocols); - return GRPC_SECURITY_OK; - -error: - gpr_free((void*)options.alpn_protocols); - return GRPC_SECURITY_ERROR; -} - -static grpc_ssl_server_security_connector* -grpc_ssl_server_security_connector_initialize( - grpc_server_credentials* server_creds) { - grpc_ssl_server_security_connector* c = - static_cast( - gpr_zalloc(sizeof(grpc_ssl_server_security_connector))); - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; - c->base.base.vtable = &ssl_server_vtable; - c->base.add_handshakers = ssl_server_add_handshakers; - c->base.server_creds = grpc_server_credentials_ref(server_creds); - return c; -} - -grpc_security_status grpc_ssl_server_security_connector_create( - grpc_server_credentials* gsc, grpc_server_security_connector** sc) { - tsi_result result = TSI_OK; - grpc_ssl_server_credentials* server_credentials = - reinterpret_cast(gsc); - grpc_security_status retval = GRPC_SECURITY_OK; - - GPR_ASSERT(server_credentials != nullptr); - GPR_ASSERT(sc != nullptr); - - grpc_ssl_server_security_connector* c = - grpc_ssl_server_security_connector_initialize(gsc); - if (server_connector_has_cert_config_fetcher(c)) { - // Load initial credentials from certificate_config_fetcher: - if (!try_fetch_ssl_server_credentials(c)) { - gpr_log(GPR_ERROR, "Failed loading SSL server credentials from fetcher."); - retval = GRPC_SECURITY_ERROR; - } - } else { - size_t num_alpn_protocols = 0; - const char** alpn_protocol_strings = - fill_alpn_protocol_strings(&num_alpn_protocols); - result = tsi_create_ssl_server_handshaker_factory_ex( - server_credentials->config.pem_key_cert_pairs, - server_credentials->config.num_key_cert_pairs, - server_credentials->config.pem_root_certs, - get_tsi_client_certificate_request_type( - server_credentials->config.client_certificate_request), - ssl_cipher_suites(), alpn_protocol_strings, - static_cast(num_alpn_protocols), - &c->server_handshaker_factory); - gpr_free((void*)alpn_protocol_strings); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - retval = GRPC_SECURITY_ERROR; - } - } - - if (retval == GRPC_SECURITY_OK) { - *sc = &c->base; - } else { - if (c != nullptr) ssl_server_destroy(&c->base.base); - if (sc != nullptr) *sc = nullptr; - } - return retval; -} - -namespace grpc_core { - -tsi_ssl_root_certs_store* DefaultSslRootStore::default_root_store_; -grpc_slice DefaultSslRootStore::default_pem_root_certs_; - -const tsi_ssl_root_certs_store* DefaultSslRootStore::GetRootStore() { - InitRootStore(); - return default_root_store_; -} - -const char* DefaultSslRootStore::GetPemRootCerts() { - InitRootStore(); - return GRPC_SLICE_IS_EMPTY(default_pem_root_certs_) - ? nullptr - : reinterpret_cast - GRPC_SLICE_START_PTR(default_pem_root_certs_); -} - -grpc_slice DefaultSslRootStore::ComputePemRootCerts() { - grpc_slice result = grpc_empty_slice(); - // First try to load the roots from the environment. - char* default_root_certs_path = - gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); - if (default_root_certs_path != nullptr) { - GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(default_root_certs_path, 1, &result)); - gpr_free(default_root_certs_path); - } - // Try overridden roots if needed. - grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; - if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != nullptr) { - char* pem_root_certs = nullptr; - ovrd_res = ssl_roots_override_cb(&pem_root_certs); - if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { - GPR_ASSERT(pem_root_certs != nullptr); - result = grpc_slice_from_copied_buffer( - pem_root_certs, - strlen(pem_root_certs) + 1); // nullptr terminator. - } - gpr_free(pem_root_certs); - } - // Fall back to installed certs if needed. - if (GRPC_SLICE_IS_EMPTY(result) && - ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { - GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(installed_roots_path, 1, &result)); - } - return result; -} - -void DefaultSslRootStore::InitRootStore() { - static gpr_once once = GPR_ONCE_INIT; - gpr_once_init(&once, DefaultSslRootStore::InitRootStoreOnce); -} - -void DefaultSslRootStore::InitRootStoreOnce() { - default_pem_root_certs_ = ComputePemRootCerts(); - if (!GRPC_SLICE_IS_EMPTY(default_pem_root_certs_)) { - default_root_store_ = - tsi_ssl_root_certs_store_create(reinterpret_cast( - GRPC_SLICE_START_PTR(default_pem_root_certs_))); - } -} - -} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.h b/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.h index f9723166d..4c74c5cfe 100644 --- a/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.h +++ b/Sources/CgRPC/src/core/lib/security/security_connector/security_connector.h @@ -26,75 +26,50 @@ #include #include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/transport_security_interface.h" extern grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount; -/* --- status enum. --- */ - typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; -/* --- URL schemes. --- */ - -#define GRPC_SSL_URL_SCHEME "https" -#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security" - /* --- security_connector object. --- A security connector object represents away to configure the underlying transport security mechanism and check the resulting trusted peer. */ -typedef struct grpc_security_connector grpc_security_connector; - #define GRPC_ARG_SECURITY_CONNECTOR "grpc.security_connector" -typedef struct { - void (*destroy)(grpc_security_connector* sc); - void (*check_peer)(grpc_security_connector* sc, tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked); - int (*cmp)(grpc_security_connector* sc, grpc_security_connector* other); -} grpc_security_connector_vtable; - -struct grpc_security_connector { - const grpc_security_connector_vtable* vtable; - gpr_refcount refcount; - const char* url_scheme; -}; +class grpc_security_connector + : public grpc_core::RefCounted { + public: + explicit grpc_security_connector(const char* url_scheme) + : grpc_core::RefCounted( + &grpc_trace_security_connector_refcount), + url_scheme_(url_scheme) {} + virtual ~grpc_security_connector() = default; + + /* Check the peer. Callee takes ownership of the peer object. + When done, sets *auth_context and invokes on_peer_checked. */ + virtual void check_peer( + tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) GRPC_ABSTRACT; + + /* Compares two security connectors. */ + virtual int cmp(const grpc_security_connector* other) const GRPC_ABSTRACT; -/* Refcounting. */ -#ifndef NDEBUG -#define GRPC_SECURITY_CONNECTOR_REF(p, r) \ - grpc_security_connector_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) \ - grpc_security_connector_unref((p), __FILE__, __LINE__, (r)) -grpc_security_connector* grpc_security_connector_ref( - grpc_security_connector* policy, const char* file, int line, - const char* reason); -void grpc_security_connector_unref(grpc_security_connector* policy, - const char* file, int line, - const char* reason); -#else -#define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p)) -#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) grpc_security_connector_unref((p)) -grpc_security_connector* grpc_security_connector_ref( - grpc_security_connector* policy); -void grpc_security_connector_unref(grpc_security_connector* policy); -#endif - -/* Check the peer. Callee takes ownership of the peer object. - When done, sets *auth_context and invokes on_peer_checked. */ -void grpc_security_connector_check_peer(grpc_security_connector* sc, - tsi_peer peer, - grpc_auth_context** auth_context, - grpc_closure* on_peer_checked); - -/* Compares two security connectors. */ -int grpc_security_connector_cmp(grpc_security_connector* sc, - grpc_security_connector* other); + const char* url_scheme() const { return url_scheme_; } + + GRPC_ABSTRACT_BASE_CLASS + + private: + const char* url_scheme_; +}; /* Util to encapsulate the connector in a channel arg. */ grpc_arg grpc_security_connector_to_arg(grpc_security_connector* sc); @@ -111,174 +86,89 @@ grpc_security_connector* grpc_security_connector_find_in_args( A channel security connector object represents a way to configure the underlying transport security mechanism on the client side. */ -typedef struct grpc_channel_security_connector grpc_channel_security_connector; - -struct grpc_channel_security_connector { - grpc_security_connector base; - grpc_channel_credentials* channel_creds; - grpc_call_credentials* request_metadata_creds; - bool (*check_call_host)(grpc_channel_security_connector* sc, const char* host, - grpc_auth_context* auth_context, - grpc_closure* on_call_host_checked, - grpc_error** error); - void (*cancel_check_call_host)(grpc_channel_security_connector* sc, - grpc_closure* on_call_host_checked, - grpc_error* error); - void (*add_handshakers)(grpc_channel_security_connector* sc, - grpc_handshake_manager* handshake_mgr); -}; +class grpc_channel_security_connector : public grpc_security_connector { + public: + grpc_channel_security_connector( + const char* url_scheme, + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds); + ~grpc_channel_security_connector() override; + + /// Checks that the host that will be set for a call is acceptable. + /// Returns true if completed synchronously, in which case \a error will + /// be set to indicate the result. Otherwise, \a on_call_host_checked + /// will be invoked when complete. + virtual bool check_call_host(const char* host, + grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) GRPC_ABSTRACT; + /// Cancels a pending asychronous call to + /// grpc_channel_security_connector_check_call_host() with + /// \a on_call_host_checked as its callback. + virtual void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) GRPC_ABSTRACT; + /// Registers handshakers with \a handshake_mgr. + virtual void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) + GRPC_ABSTRACT; + + const grpc_channel_credentials* channel_creds() const { + return channel_creds_.get(); + } + grpc_channel_credentials* mutable_channel_creds() { + return channel_creds_.get(); + } + const grpc_call_credentials* request_metadata_creds() const { + return request_metadata_creds_.get(); + } + grpc_call_credentials* mutable_request_metadata_creds() { + return request_metadata_creds_.get(); + } + + GRPC_ABSTRACT_BASE_CLASS -/// A helper function for use in grpc_security_connector_cmp() implementations. -int grpc_channel_security_connector_cmp(grpc_channel_security_connector* sc1, - grpc_channel_security_connector* sc2); - -/// Checks that the host that will be set for a call is acceptable. -/// Returns true if completed synchronously, in which case \a error will -/// be set to indicate the result. Otherwise, \a on_call_host_checked -/// will be invoked when complete. -bool grpc_channel_security_connector_check_call_host( - grpc_channel_security_connector* sc, const char* host, - grpc_auth_context* auth_context, grpc_closure* on_call_host_checked, - grpc_error** error); - -/// Cancels a pending asychronous call to -/// grpc_channel_security_connector_check_call_host() with -/// \a on_call_host_checked as its callback. -void grpc_channel_security_connector_cancel_check_call_host( - grpc_channel_security_connector* sc, grpc_closure* on_call_host_checked, - grpc_error* error); - -/* Registers handshakers with \a handshake_mgr. */ -void grpc_channel_security_connector_add_handshakers( - grpc_channel_security_connector* connector, - grpc_handshake_manager* handshake_mgr); + protected: + // Helper methods to be used in subclasses. + int channel_security_connector_cmp( + const grpc_channel_security_connector* other) const; + + private: + grpc_core::RefCountedPtr channel_creds_; + grpc_core::RefCountedPtr request_metadata_creds_; +}; /* --- server_security_connector object. --- A server security connector object represents a way to configure the underlying transport security mechanism on the server side. */ -typedef struct grpc_server_security_connector grpc_server_security_connector; - -struct grpc_server_security_connector { - grpc_security_connector base; - grpc_server_credentials* server_creds; - void (*add_handshakers)(grpc_server_security_connector* sc, - grpc_handshake_manager* handshake_mgr); -}; - -/// A helper function for use in grpc_security_connector_cmp() implementations. -int grpc_server_security_connector_cmp(grpc_server_security_connector* sc1, - grpc_server_security_connector* sc2); +class grpc_server_security_connector : public grpc_security_connector { + public: + grpc_server_security_connector( + const char* url_scheme, + grpc_core::RefCountedPtr server_creds); + ~grpc_server_security_connector() override = default; -void grpc_server_security_connector_add_handshakers( - grpc_server_security_connector* sc, grpc_handshake_manager* handshake_mgr); + virtual void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) + GRPC_ABSTRACT; -/* --- Creation security connectors. --- */ + const grpc_server_credentials* server_creds() const { + return server_creds_.get(); + } + grpc_server_credentials* mutable_server_creds() { + return server_creds_.get(); + } -/* For TESTING ONLY! - Creates a fake connector that emulates real channel security. */ -grpc_channel_security_connector* grpc_fake_channel_security_connector_create( - grpc_channel_credentials* channel_creds, - grpc_call_credentials* request_metadata_creds, const char* target, - const grpc_channel_args* args); - -/* For TESTING ONLY! - Creates a fake connector that emulates real server security. */ -grpc_server_security_connector* grpc_fake_server_security_connector_create( - grpc_server_credentials* server_creds); - -/* Config for ssl clients. */ - -typedef struct { - tsi_ssl_pem_key_cert_pair* pem_key_cert_pair; - char* pem_root_certs; -} grpc_ssl_config; - -/* Creates an SSL channel_security_connector. - - request_metadata_creds is the credentials object which metadata - will be sent with each request. This parameter can be NULL. - - config is the SSL config to be used for the SSL channel establishment. - - is_client should be 0 for a server or a non-0 value for a client. - - secure_peer_name is the secure peer name that should be checked in - grpc_channel_security_connector_check_peer. This parameter may be NULL in - which case the peer name will not be checked. Note that if this parameter - is not NULL, then, pem_root_certs should not be NULL either. - - sc is a pointer on the connector to be created. - This function returns GRPC_SECURITY_OK in case of success or a - specific error code otherwise. -*/ -grpc_security_status grpc_ssl_channel_security_connector_create( - grpc_channel_credentials* channel_creds, - grpc_call_credentials* request_metadata_creds, - const grpc_ssl_config* config, const char* target_name, - const char* overridden_target_name, - tsi_ssl_session_cache* ssl_session_cache, - grpc_channel_security_connector** sc); - -/* Config for ssl servers. */ -typedef struct { - tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs; - size_t num_key_cert_pairs; - char* pem_root_certs; - grpc_ssl_client_certificate_request_type client_certificate_request; -} grpc_ssl_server_config; - -/* Creates an SSL server_security_connector. - - config is the SSL config to be used for the SSL channel establishment. - - sc is a pointer on the connector to be created. - This function returns GRPC_SECURITY_OK in case of success or a - specific error code otherwise. -*/ -grpc_security_status grpc_ssl_server_security_connector_create( - grpc_server_credentials* server_credentials, - grpc_server_security_connector** sc); - -/* Util. */ -const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* peer, - const char* name); - -/* Exposed for testing only. */ -grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer); -tsi_peer grpc_shallow_peer_from_ssl_auth_context( - const grpc_auth_context* auth_context); -void grpc_shallow_peer_destruct(tsi_peer* peer); -int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name); - -/* --- Default SSL Root Store. --- */ -namespace grpc_core { - -// The class implements default SSL root store. -class DefaultSslRootStore { - public: - // Gets the default SSL root store. Returns nullptr if not found. - static const tsi_ssl_root_certs_store* GetRootStore(); - - // Gets the default PEM root certificate. - static const char* GetPemRootCerts(); + GRPC_ABSTRACT_BASE_CLASS protected: - // Returns default PEM root certificates in nullptr terminated grpc_slice. - // This function is protected instead of private, so that it can be tested. - static grpc_slice ComputePemRootCerts(); + // Helper methods to be used in subclasses. + int server_security_connector_cmp( + const grpc_server_security_connector* other) const; private: - // Construct me not! - DefaultSslRootStore(); - - // Initialization of default SSL root store. - static void InitRootStore(); - - // One-time initialization of default SSL root store. - static void InitRootStoreOnce(); - - // SSL root store in tsi_ssl_root_certs_store object. - static tsi_ssl_root_certs_store* default_root_store_; - - // Default PEM root certificates. - static grpc_slice default_pem_root_certs_; + grpc_core::RefCountedPtr server_creds_; }; -} // namespace grpc_core - #endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SECURITY_CONNECTOR_H */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/Sources/CgRPC/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc new file mode 100644 index 000000000..37cb41b96 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc @@ -0,0 +1,450 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/security_connector/ssl/ssl_security_connector.h" + +#include + +#include +#include +#include + +#include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" +#include "src/core/lib/security/security_connector/load_system_roots.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" +#include "src/core/lib/security/transport/security_handshaker.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" + +namespace { +grpc_error* ssl_check_peer( + const char* peer_name, const tsi_peer* peer, + grpc_core::RefCountedPtr* auth_context) { +#if TSI_OPENSSL_ALPN_SUPPORT + /* Check the ALPN if ALPN is supported. */ + const tsi_peer_property* p = + tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); + if (p == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: missing selected ALPN property."); + } + if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: invalid ALPN value."); + } +#endif /* TSI_OPENSSL_ALPN_SUPPORT */ + /* Check the peer name if specified. */ + if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { + char* msg; + gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); + grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + return error; + } + *auth_context = grpc_ssl_peer_to_auth_context(peer); + return GRPC_ERROR_NONE; +} + +class grpc_ssl_channel_security_connector final + : public grpc_channel_security_connector { + public: + grpc_ssl_channel_security_connector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const grpc_ssl_config* config, const char* target_name, + const char* overridden_target_name) + : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME, + std::move(channel_creds), + std::move(request_metadata_creds)), + overridden_target_name_(overridden_target_name == nullptr + ? nullptr + : gpr_strdup(overridden_target_name)), + verify_options_(&config->verify_options) { + char* port; + gpr_split_host_port(target_name, &target_name_, &port); + gpr_free(port); + } + + ~grpc_ssl_channel_security_connector() override { + tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_); + if (target_name_ != nullptr) gpr_free(target_name_); + if (overridden_target_name_ != nullptr) gpr_free(overridden_target_name_); + } + + grpc_security_status InitializeHandshakerFactory( + const grpc_ssl_config* config, const char* pem_root_certs, + const tsi_ssl_root_certs_store* root_store, + tsi_ssl_session_cache* ssl_session_cache) { + bool has_key_cert_pair = + config->pem_key_cert_pair != nullptr && + config->pem_key_cert_pair->private_key != nullptr && + config->pem_key_cert_pair->cert_chain != nullptr; + tsi_ssl_client_handshaker_options options; + memset(&options, 0, sizeof(options)); + GPR_DEBUG_ASSERT(pem_root_certs != nullptr); + options.pem_root_certs = pem_root_certs; + options.root_store = root_store; + options.alpn_protocols = + grpc_fill_alpn_protocol_strings(&options.num_alpn_protocols); + if (has_key_cert_pair) { + options.pem_key_cert_pair = config->pem_key_cert_pair; + } + options.cipher_suites = grpc_get_ssl_cipher_suites(); + options.session_cache = ssl_session_cache; + const tsi_result result = + tsi_create_ssl_client_handshaker_factory_with_options( + &options, &client_handshaker_factory_); + gpr_free((void*)options.alpn_protocols); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + return GRPC_SECURITY_ERROR; + } + return GRPC_SECURITY_OK; + } + + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override { + // Instantiate TSI handshaker. + tsi_handshaker* tsi_hs = nullptr; + tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( + client_handshaker_factory_, + overridden_target_name_ != nullptr ? overridden_target_name_ + : target_name_, + &tsi_hs); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return; + } + // Create handshakers. + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this)); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + const char* target_name = overridden_target_name_ != nullptr + ? overridden_target_name_ + : target_name_; + grpc_error* error = ssl_check_peer(target_name, &peer, auth_context); + if (error == GRPC_ERROR_NONE && + verify_options_->verify_peer_callback != nullptr) { + const tsi_peer_property* p = + tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY); + if (p == nullptr) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: missing pem cert property."); + } else { + char* peer_pem = static_cast(gpr_malloc(p->value.length + 1)); + memcpy(peer_pem, p->value.data, p->value.length); + peer_pem[p->value.length] = '\0'; + int callback_status = verify_options_->verify_peer_callback( + target_name, peer_pem, + verify_options_->verify_peer_callback_userdata); + gpr_free(peer_pem); + if (callback_status) { + char* msg; + gpr_asprintf(&msg, "Verify peer callback returned a failure (%d)", + callback_status); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + } + } + } + GRPC_CLOSURE_SCHED(on_peer_checked, error); + tsi_peer_destruct(&peer); + } + + int cmp(const grpc_security_connector* other_sc) const override { + auto* other = + reinterpret_cast(other_sc); + int c = channel_security_connector_cmp(other); + if (c != 0) return c; + c = strcmp(target_name_, other->target_name_); + if (c != 0) return c; + return (overridden_target_name_ == nullptr || + other->overridden_target_name_ == nullptr) + ? GPR_ICMP(overridden_target_name_, + other->overridden_target_name_) + : strcmp(overridden_target_name_, + other->overridden_target_name_); + } + + bool check_call_host(const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) override { + grpc_security_status status = GRPC_SECURITY_ERROR; + tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context); + if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; + /* If the target name was overridden, then the original target_name was + 'checked' transitively during the previous peer check at the end of the + handshake. */ + if (overridden_target_name_ != nullptr && strcmp(host, target_name_) == 0) { + status = GRPC_SECURITY_OK; + } + if (status != GRPC_SECURITY_OK) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "call host does not match SSL server name"); + } + grpc_shallow_peer_destruct(&peer); + return true; + } + + void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) override { + GRPC_ERROR_UNREF(error); + } + + private: + tsi_ssl_client_handshaker_factory* client_handshaker_factory_; + char* target_name_; + char* overridden_target_name_; + const verify_peer_options* verify_options_; +}; + +class grpc_ssl_server_security_connector + : public grpc_server_security_connector { + public: + grpc_ssl_server_security_connector( + grpc_core::RefCountedPtr server_creds) + : grpc_server_security_connector(GRPC_SSL_URL_SCHEME, + std::move(server_creds)) {} + + ~grpc_ssl_server_security_connector() override { + tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_); + } + + bool has_cert_config_fetcher() const { + return static_cast(server_creds()) + ->has_cert_config_fetcher(); + } + + const tsi_ssl_server_handshaker_factory* server_handshaker_factory() const { + return server_handshaker_factory_; + } + + grpc_security_status InitializeHandshakerFactory() { + if (has_cert_config_fetcher()) { + // Load initial credentials from certificate_config_fetcher: + if (!try_fetch_ssl_server_credentials()) { + gpr_log(GPR_ERROR, + "Failed loading SSL server credentials from fetcher."); + return GRPC_SECURITY_ERROR; + } + } else { + auto* server_credentials = + static_cast(server_creds()); + size_t num_alpn_protocols = 0; + const char** alpn_protocol_strings = + grpc_fill_alpn_protocol_strings(&num_alpn_protocols); + const tsi_result result = tsi_create_ssl_server_handshaker_factory_ex( + server_credentials->config().pem_key_cert_pairs, + server_credentials->config().num_key_cert_pairs, + server_credentials->config().pem_root_certs, + grpc_get_tsi_client_certificate_request_type( + server_credentials->config().client_certificate_request), + grpc_get_ssl_cipher_suites(), alpn_protocol_strings, + static_cast(num_alpn_protocols), + &server_handshaker_factory_); + gpr_free((void*)alpn_protocol_strings); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + return GRPC_SECURITY_ERROR; + } + } + return GRPC_SECURITY_OK; + } + + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override { + // Instantiate TSI handshaker. + try_fetch_ssl_server_credentials(); + tsi_handshaker* tsi_hs = nullptr; + tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( + server_handshaker_factory_, &tsi_hs); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return; + } + // Create handshakers. + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this)); + } + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override { + grpc_error* error = ssl_check_peer(nullptr, &peer, auth_context); + tsi_peer_destruct(&peer); + GRPC_CLOSURE_SCHED(on_peer_checked, error); + } + + int cmp(const grpc_security_connector* other) const override { + return server_security_connector_cmp( + static_cast(other)); + } + + private: + /* Attempts to fetch the server certificate config if a callback is available. + * Current certificate config will continue to be used if the callback returns + * an error. Returns true if new credentials were sucessfully loaded. */ + bool try_fetch_ssl_server_credentials() { + grpc_ssl_server_certificate_config* certificate_config = nullptr; + bool status; + + if (!has_cert_config_fetcher()) return false; + + grpc_ssl_server_credentials* server_creds = + static_cast(this->mutable_server_creds()); + grpc_ssl_certificate_config_reload_status cb_result = + server_creds->FetchCertConfig(&certificate_config); + if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) { + gpr_log(GPR_DEBUG, "No change in SSL server credentials."); + status = false; + } else if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) { + status = try_replace_server_handshaker_factory(certificate_config); + } else { + // Log error, continue using previously-loaded credentials. + gpr_log(GPR_ERROR, + "Failed fetching new server credentials, continuing to " + "use previously-loaded credentials."); + status = false; + } + + if (certificate_config != nullptr) { + grpc_ssl_server_certificate_config_destroy(certificate_config); + } + return status; + } + + /* Attempts to replace the server_handshaker_factory with a new factory using + * the provided grpc_ssl_server_certificate_config. Should new factory + * creation fail, the existing factory will not be replaced. Returns true on + * success (new factory created). */ + bool try_replace_server_handshaker_factory( + const grpc_ssl_server_certificate_config* config) { + if (config == nullptr) { + gpr_log(GPR_ERROR, + "Server certificate config callback returned invalid (NULL) " + "config."); + return false; + } + gpr_log(GPR_DEBUG, "Using new server certificate config (%p).", config); + + size_t num_alpn_protocols = 0; + const char** alpn_protocol_strings = + grpc_fill_alpn_protocol_strings(&num_alpn_protocols); + tsi_ssl_pem_key_cert_pair* cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( + config->pem_key_cert_pairs, config->num_key_cert_pairs); + tsi_ssl_server_handshaker_factory* new_handshaker_factory = nullptr; + const grpc_ssl_server_credentials* server_creds = + static_cast(this->server_creds()); + GPR_DEBUG_ASSERT(config->pem_root_certs != nullptr); + tsi_result result = tsi_create_ssl_server_handshaker_factory_ex( + cert_pairs, config->num_key_cert_pairs, config->pem_root_certs, + grpc_get_tsi_client_certificate_request_type( + server_creds->config().client_certificate_request), + grpc_get_ssl_cipher_suites(), alpn_protocol_strings, + static_cast(num_alpn_protocols), &new_handshaker_factory); + gpr_free(cert_pairs); + gpr_free((void*)alpn_protocol_strings); + + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + return false; + } + set_server_handshaker_factory(new_handshaker_factory); + return true; + } + + void set_server_handshaker_factory( + tsi_ssl_server_handshaker_factory* new_factory) { + if (server_handshaker_factory_) { + tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_); + } + server_handshaker_factory_ = new_factory; + } + + tsi_ssl_server_handshaker_factory* server_handshaker_factory_ = nullptr; +}; +} // namespace + +grpc_core::RefCountedPtr +grpc_ssl_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const grpc_ssl_config* config, const char* target_name, + const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache) { + if (config == nullptr || target_name == nullptr) { + gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); + return nullptr; + } + + const char* pem_root_certs; + const tsi_ssl_root_certs_store* root_store; + if (config->pem_root_certs == nullptr) { + // Use default root certificates. + pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); + if (pem_root_certs == nullptr) { + gpr_log(GPR_ERROR, "Could not get default pem root certs."); + return nullptr; + } + root_store = grpc_core::DefaultSslRootStore::GetRootStore(); + } else { + pem_root_certs = config->pem_root_certs; + root_store = nullptr; + } + + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + std::move(channel_creds), std::move(request_metadata_creds), config, + target_name, overridden_target_name); + const grpc_security_status result = c->InitializeHandshakerFactory( + config, pem_root_certs, root_store, ssl_session_cache); + if (result != GRPC_SECURITY_OK) { + return nullptr; + } + return c; +} + +grpc_core::RefCountedPtr +grpc_ssl_server_security_connector_create( + grpc_core::RefCountedPtr server_credentials) { + GPR_ASSERT(server_credentials != nullptr); + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + std::move(server_credentials)); + const grpc_security_status retval = c->InitializeHandshakerFactory(); + if (retval != GRPC_SECURITY_OK) { + return nullptr; + } + return c; +} diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/ssl/ssl_security_connector.h b/Sources/CgRPC/src/core/lib/security/security_connector/ssl/ssl_security_connector.h new file mode 100644 index 000000000..70e26e338 --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/ssl/ssl_security_connector.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_SSL_SECURITY_CONNECTOR_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_SSL_SECURITY_CONNECTOR_H + +#include + +#include + +#include "src/core/lib/security/security_connector/security_connector.h" + +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security_interface.h" + +typedef struct { + tsi_ssl_pem_key_cert_pair* pem_key_cert_pair; + char* pem_root_certs; + verify_peer_options verify_options; +} grpc_ssl_config; + +/* Creates an SSL channel_security_connector. + - request_metadata_creds is the credentials object which metadata + will be sent with each request. This parameter can be NULL. + - config is the SSL config to be used for the SSL channel establishment. + - is_client should be 0 for a server or a non-0 value for a client. + - secure_peer_name is the secure peer name that should be checked in + grpc_channel_security_connector_check_peer. This parameter may be NULL in + which case the peer name will not be checked. Note that if this parameter + is not NULL, then, pem_root_certs should not be NULL either. + - sc is a pointer on the connector to be created. + This function returns GRPC_SECURITY_OK in case of success or a + specific error code otherwise. +*/ +grpc_core::RefCountedPtr +grpc_ssl_channel_security_connector_create( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const grpc_ssl_config* config, const char* target_name, + const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache); + +/* Config for ssl servers. */ +typedef struct { + tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr; + size_t num_key_cert_pairs = 0; + char* pem_root_certs = nullptr; + grpc_ssl_client_certificate_request_type client_certificate_request = + GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; +} grpc_ssl_server_config; + +/* Creates an SSL server_security_connector. + - config is the SSL config to be used for the SSL channel establishment. + - sc is a pointer on the connector to be created. + This function returns GRPC_SECURITY_OK in case of success or a + specific error code otherwise. +*/ +grpc_core::RefCountedPtr +grpc_ssl_server_security_connector_create( + grpc_core::RefCountedPtr server_credentials); + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_SSL_SECURITY_CONNECTOR_H \ + */ diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/ssl_utils.cc b/Sources/CgRPC/src/core/lib/security/security_connector/ssl_utils.cc new file mode 100644 index 000000000..29030f07a --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/ssl_utils.cc @@ -0,0 +1,349 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/security_connector/ssl_utils.h" + +#include +#include +#include +#include + +#include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/security_connector/load_system_roots.h" +#include "src/core/tsi/ssl_transport_security.h" + +/* -- Constants. -- */ + +#ifndef INSTALL_PREFIX +static const char* installed_roots_path = "/usr/share/grpc/roots.pem"; +#else +static const char* installed_roots_path = + INSTALL_PREFIX "/share/grpc/roots.pem"; +#endif + +/** Environment variable used as a flag to enable/disable loading system root + certificates from the OS trust store. */ +#ifndef GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR +#define GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_NOT_USE_SYSTEM_SSL_ROOTS" +#endif + +#ifndef TSI_OPENSSL_ALPN_SUPPORT +#define TSI_OPENSSL_ALPN_SUPPORT 1 +#endif + +/* -- Overridden default roots. -- */ + +static grpc_ssl_roots_override_callback ssl_roots_override_cb = nullptr; + +void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) { + ssl_roots_override_cb = cb; +} + +/* -- Cipher suites. -- */ + +/* Defines the cipher suites that we accept by default. All these cipher suites + are compliant with HTTP2. */ +#define GRPC_SSL_CIPHER_SUITES \ + "ECDHE-ECDSA-AES128-GCM-SHA256:" \ + "ECDHE-ECDSA-AES256-GCM-SHA384:" \ + "ECDHE-RSA-AES128-GCM-SHA256:" \ + "ECDHE-RSA-AES256-GCM-SHA384" + +static gpr_once cipher_suites_once = GPR_ONCE_INIT; +static const char* cipher_suites = nullptr; + +static void init_cipher_suites(void) { + char* overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES"); + cipher_suites = overridden != nullptr ? overridden : GRPC_SSL_CIPHER_SUITES; +} + +/* --- Util --- */ + +const char* grpc_get_ssl_cipher_suites(void) { + gpr_once_init(&cipher_suites_once, init_cipher_suites); + return cipher_suites; +} + +tsi_client_certificate_request_type +grpc_get_tsi_client_certificate_request_type( + grpc_ssl_client_certificate_request_type grpc_request_type) { + switch (grpc_request_type) { + case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: + return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; + + case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; + + case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: + return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; + + case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; + + case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: + return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; + + default: + return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; + } +} + +const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols) { + GPR_ASSERT(num_alpn_protocols != nullptr); + *num_alpn_protocols = grpc_chttp2_num_alpn_versions(); + const char** alpn_protocol_strings = static_cast( + gpr_malloc(sizeof(const char*) * (*num_alpn_protocols))); + for (size_t i = 0; i < *num_alpn_protocols; i++) { + alpn_protocol_strings[i] = grpc_chttp2_get_alpn_version_index(i); + } + return alpn_protocol_strings; +} + +int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) { + char* allocated_name = nullptr; + int r; + + char* ignored_port; + gpr_split_host_port(peer_name, &allocated_name, &ignored_port); + gpr_free(ignored_port); + peer_name = allocated_name; + if (!peer_name) return 0; + + // IPv6 zone-id should not be included in comparisons. + char* const zone_id = strchr(allocated_name, '%'); + if (zone_id != nullptr) *zone_id = '\0'; + + r = tsi_ssl_peer_matches_name(peer, peer_name); + gpr_free(allocated_name); + return r; +} + +grpc_core::RefCountedPtr grpc_ssl_peer_to_auth_context( + const tsi_peer* peer) { + size_t i; + const char* peer_identity_property_name = nullptr; + + /* The caller has checked the certificate type property. */ + GPR_ASSERT(peer->property_count >= 1); + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + grpc_auth_context_add_cstring_property( + ctx.get(), GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property* prop = &peer->properties[i]; + if (prop->name == nullptr) continue; + if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) { + /* If there is no subject alt name, have the CN as the identity. */ + if (peer_identity_property_name == nullptr) { + peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME; + } + grpc_auth_context_add_property(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, + prop->value.data, prop->value.length); + } else if (strcmp(prop->name, + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { + peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME; + grpc_auth_context_add_property(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, + prop->value.data, prop->value.length); + } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) { + grpc_auth_context_add_property(ctx.get(), + GRPC_X509_PEM_CERT_PROPERTY_NAME, + prop->value.data, prop->value.length); + } else if (strcmp(prop->name, TSI_SSL_SESSION_REUSED_PEER_PROPERTY) == 0) { + grpc_auth_context_add_property(ctx.get(), + GRPC_SSL_SESSION_REUSED_PROPERTY, + prop->value.data, prop->value.length); + } + } + if (peer_identity_property_name != nullptr) { + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( + ctx.get(), peer_identity_property_name) == 1); + } + return ctx; +} + +static void add_shallow_auth_property_to_peer(tsi_peer* peer, + const grpc_auth_property* prop, + const char* tsi_prop_name) { + tsi_peer_property* tsi_prop = &peer->properties[peer->property_count++]; + tsi_prop->name = const_cast(tsi_prop_name); + tsi_prop->value.data = prop->value; + tsi_prop->value.length = prop->value_length; +} + +tsi_peer grpc_shallow_peer_from_ssl_auth_context( + const grpc_auth_context* auth_context) { + size_t max_num_props = 0; + grpc_auth_property_iterator it; + const grpc_auth_property* prop; + tsi_peer peer; + memset(&peer, 0, sizeof(peer)); + + it = grpc_auth_context_property_iterator(auth_context); + while (grpc_auth_property_iterator_next(&it) != nullptr) max_num_props++; + + if (max_num_props > 0) { + peer.properties = static_cast( + gpr_malloc(max_num_props * sizeof(tsi_peer_property))); + it = grpc_auth_context_property_iterator(auth_context); + while ((prop = grpc_auth_property_iterator_next(&it)) != nullptr) { + if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer( + &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY); + } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer( + &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); + } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer(&peer, prop, + TSI_X509_PEM_CERT_PROPERTY); + } + } + } + return peer; +} + +void grpc_shallow_peer_destruct(tsi_peer* peer) { + if (peer->properties != nullptr) gpr_free(peer->properties); +} + +/* --- Ssl cache implementation. --- */ + +grpc_ssl_session_cache* grpc_ssl_session_cache_create_lru(size_t capacity) { + tsi_ssl_session_cache* cache = tsi_ssl_session_cache_create_lru(capacity); + return reinterpret_cast(cache); +} + +void grpc_ssl_session_cache_destroy(grpc_ssl_session_cache* cache) { + tsi_ssl_session_cache* tsi_cache = + reinterpret_cast(cache); + tsi_ssl_session_cache_unref(tsi_cache); +} + +static void* grpc_ssl_session_cache_arg_copy(void* p) { + tsi_ssl_session_cache* tsi_cache = + reinterpret_cast(p); + // destroy call below will unref the pointer. + tsi_ssl_session_cache_ref(tsi_cache); + return p; +} + +static void grpc_ssl_session_cache_arg_destroy(void* p) { + tsi_ssl_session_cache* tsi_cache = + reinterpret_cast(p); + tsi_ssl_session_cache_unref(tsi_cache); +} + +static int grpc_ssl_session_cache_arg_cmp(void* p, void* q) { + return GPR_ICMP(p, q); +} + +grpc_arg grpc_ssl_session_cache_create_channel_arg( + grpc_ssl_session_cache* cache) { + static const grpc_arg_pointer_vtable vtable = { + grpc_ssl_session_cache_arg_copy, + grpc_ssl_session_cache_arg_destroy, + grpc_ssl_session_cache_arg_cmp, + }; + return grpc_channel_arg_pointer_create( + const_cast(GRPC_SSL_SESSION_CACHE_ARG), cache, &vtable); +} + +/* --- Default SSL root store implementation. --- */ + +namespace grpc_core { + +tsi_ssl_root_certs_store* DefaultSslRootStore::default_root_store_; +grpc_slice DefaultSslRootStore::default_pem_root_certs_; + +const tsi_ssl_root_certs_store* DefaultSslRootStore::GetRootStore() { + InitRootStore(); + return default_root_store_; +} + +const char* DefaultSslRootStore::GetPemRootCerts() { + InitRootStore(); + return GRPC_SLICE_IS_EMPTY(default_pem_root_certs_) + ? nullptr + : reinterpret_cast + GRPC_SLICE_START_PTR(default_pem_root_certs_); +} + +grpc_slice DefaultSslRootStore::ComputePemRootCerts() { + grpc_slice result = grpc_empty_slice(); + char* not_use_system_roots_env_value = + gpr_getenv(GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR); + const bool not_use_system_roots = gpr_is_true(not_use_system_roots_env_value); + gpr_free(not_use_system_roots_env_value); + // First try to load the roots from the environment. + char* default_root_certs_path = + gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); + if (default_root_certs_path != nullptr) { + GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(default_root_certs_path, 1, &result)); + gpr_free(default_root_certs_path); + } + // Try overridden roots if needed. + grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; + if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != nullptr) { + char* pem_root_certs = nullptr; + ovrd_res = ssl_roots_override_cb(&pem_root_certs); + if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { + GPR_ASSERT(pem_root_certs != nullptr); + result = grpc_slice_from_copied_buffer( + pem_root_certs, + strlen(pem_root_certs) + 1); // nullptr terminator. + } + gpr_free(pem_root_certs); + } + // Try loading roots from OS trust store if flag is enabled. + if (GRPC_SLICE_IS_EMPTY(result) && !not_use_system_roots) { + result = LoadSystemRootCerts(); + } + // Fallback to roots manually shipped with gRPC. + if (GRPC_SLICE_IS_EMPTY(result) && + ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { + GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(installed_roots_path, 1, &result)); + } + return result; +} + +void DefaultSslRootStore::InitRootStore() { + static gpr_once once = GPR_ONCE_INIT; + gpr_once_init(&once, DefaultSslRootStore::InitRootStoreOnce); +} + +void DefaultSslRootStore::InitRootStoreOnce() { + default_pem_root_certs_ = ComputePemRootCerts(); + if (!GRPC_SLICE_IS_EMPTY(default_pem_root_certs_)) { + default_root_store_ = + tsi_ssl_root_certs_store_create(reinterpret_cast( + GRPC_SLICE_START_PTR(default_pem_root_certs_))); + } +} + +} // namespace grpc_core diff --git a/Sources/CgRPC/src/core/lib/security/security_connector/ssl_utils.h b/Sources/CgRPC/src/core/lib/security/security_connector/ssl_utils.h new file mode 100644 index 000000000..972ca439d --- /dev/null +++ b/Sources/CgRPC/src/core/lib/security/security_connector/ssl_utils.h @@ -0,0 +1,128 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_H + +#include + +#include + +#include +#include + +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security_interface.h" + +/* --- Util. --- */ + +/* --- URL schemes. --- */ +#define GRPC_SSL_URL_SCHEME "https" + +/* Return HTTP2-compliant cipher suites that gRPC accepts by default. */ +const char* grpc_get_ssl_cipher_suites(void); + +/* Map from grpc_ssl_client_certificate_request_type to + * tsi_client_certificate_request_type. */ +tsi_client_certificate_request_type +grpc_get_tsi_client_certificate_request_type( + grpc_ssl_client_certificate_request_type grpc_request_type); + +/* Return an array of strings containing alpn protocols. */ +const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols); + +/* Exposed for testing only. */ +grpc_core::RefCountedPtr grpc_ssl_peer_to_auth_context( + const tsi_peer* peer); +tsi_peer grpc_shallow_peer_from_ssl_auth_context( + const grpc_auth_context* auth_context); +void grpc_shallow_peer_destruct(tsi_peer* peer); +int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name); + +/* --- Default SSL Root Store. --- */ +namespace grpc_core { + +// The class implements default SSL root store. +class DefaultSslRootStore { + public: + // Gets the default SSL root store. Returns nullptr if not found. + static const tsi_ssl_root_certs_store* GetRootStore(); + + // Gets the default PEM root certificate. + static const char* GetPemRootCerts(); + + protected: + // Returns default PEM root certificates in nullptr terminated grpc_slice. + // This function is protected instead of private, so that it can be tested. + static grpc_slice ComputePemRootCerts(); + + private: + // Construct me not! + DefaultSslRootStore(); + + // Initialization of default SSL root store. + static void InitRootStore(); + + // One-time initialization of default SSL root store. + static void InitRootStoreOnce(); + + // SSL root store in tsi_ssl_root_certs_store object. + static tsi_ssl_root_certs_store* default_root_store_; + + // Default PEM root certificates. + static grpc_slice default_pem_root_certs_; +}; + +class PemKeyCertPair { + public: + // Construct from the C struct. We steal its members and then immediately + // free it. + explicit PemKeyCertPair(grpc_ssl_pem_key_cert_pair* pair) + : private_key_(const_cast(pair->private_key)), + cert_chain_(const_cast(pair->cert_chain)) { + gpr_free(pair); + } + + // Movable. + PemKeyCertPair(PemKeyCertPair&& other) { + private_key_ = std::move(other.private_key_); + cert_chain_ = std::move(other.cert_chain_); + } + PemKeyCertPair& operator=(PemKeyCertPair&& other) { + private_key_ = std::move(other.private_key_); + cert_chain_ = std::move(other.cert_chain_); + return *this; + } + + // Not copyable. + PemKeyCertPair(const PemKeyCertPair&) = delete; + PemKeyCertPair& operator=(const PemKeyCertPair&) = delete; + + char* private_key() const { return private_key_.get(); } + char* cert_chain() const { return cert_chain_.get(); } + + private: + grpc_core::UniquePtr private_key_; + grpc_core::UniquePtr cert_chain_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_H \ + */ diff --git a/Sources/CgRPC/src/core/lib/security/transport/client_auth_filter.cc b/Sources/CgRPC/src/core/lib/security/transport/client_auth_filter.cc index 048e390a7..66f86b8bc 100644 --- a/Sources/CgRPC/src/core/lib/security/transport/client_auth_filter.cc +++ b/Sources/CgRPC/src/core/lib/security/transport/client_auth_filter.cc @@ -32,6 +32,7 @@ #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/security_connector/security_connector.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/call.h" @@ -42,19 +43,39 @@ namespace { /* We can have a per-call credentials. */ struct call_data { + call_data(grpc_call_element* elem, const grpc_call_element_args& args) + : arena(args.arena), + owning_call(args.call_stack), + call_combiner(args.call_combiner) {} + + // This method is technically the dtor of this class. However, since + // `get_request_metadata_cancel_closure` can run in parallel to + // `destroy_call_elem`, we cannot call the dtor in them. Otherwise, + // fields will be accessed after calling dtor, and msan correctly complains + // that the memory is not initialized. + void destroy() { + grpc_credentials_mdelem_array_destroy(&md_array); + creds.reset(); + grpc_slice_unref_internal(host); + grpc_slice_unref_internal(method); + grpc_auth_metadata_context_reset(&auth_md_context); + } + + gpr_arena* arena; grpc_call_stack* owning_call; grpc_call_combiner* call_combiner; - grpc_call_credentials* creds; - grpc_slice host; - grpc_slice method; + grpc_core::RefCountedPtr creds; + grpc_slice host = grpc_empty_slice(); + grpc_slice method = grpc_empty_slice(); /* pollset{_set} bound to this call; if we need to make external network requests, they should be done under a pollset added to this pollset_set so that work can progress when this call wants work to progress */ - grpc_polling_entity* pollent; + grpc_polling_entity* pollent = nullptr; grpc_credentials_mdelem_array md_array; - grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT]; - grpc_auth_metadata_context auth_md_context; + grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT] = {}; + grpc_auth_metadata_context auth_md_context = + grpc_auth_metadata_context(); // Zero-initialize the C struct. grpc_closure async_result_closure; grpc_closure check_call_host_cancel_closure; grpc_closure get_request_metadata_cancel_closure; @@ -62,8 +83,18 @@ struct call_data { /* We can have a per-channel credentials. */ struct channel_data { - grpc_channel_security_connector* security_connector; - grpc_auth_context* auth_context; + channel_data(grpc_channel_security_connector* security_connector, + grpc_auth_context* auth_context) + : security_connector( + security_connector->Ref(DEBUG_LOCATION, "client_auth_filter")), + auth_context(auth_context->Ref(DEBUG_LOCATION, "client_auth_filter")) {} + ~channel_data() { + security_connector.reset(DEBUG_LOCATION, "client_auth_filter"); + auth_context.reset(DEBUG_LOCATION, "client_auth_filter"); + } + + grpc_core::RefCountedPtr security_connector; + grpc_core::RefCountedPtr auth_context; }; } // namespace @@ -77,10 +108,11 @@ void grpc_auth_metadata_context_reset( gpr_free(const_cast(auth_md_context->method_name)); auth_md_context->method_name = nullptr; } - GRPC_AUTH_CONTEXT_UNREF( - (grpc_auth_context*)auth_md_context->channel_auth_context, - "grpc_auth_metadata_context"); - auth_md_context->channel_auth_context = nullptr; + if (auth_md_context->channel_auth_context != nullptr) { + const_cast(auth_md_context->channel_auth_context) + ->Unref(DEBUG_LOCATION, "grpc_auth_metadata_context"); + auth_md_context->channel_auth_context = nullptr; + } } static void add_error(grpc_error** combined, grpc_error* error) { @@ -154,7 +186,10 @@ void grpc_auth_metadata_context_build( auth_md_context->service_url = service_url; auth_md_context->method_name = method_name; auth_md_context->channel_auth_context = - GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context"); + auth_context == nullptr + ? nullptr + : auth_context->Ref(DEBUG_LOCATION, "grpc_auth_metadata_context") + .release(); gpr_free(service); gpr_free(host_and_port); } @@ -163,10 +198,9 @@ static void cancel_get_request_metadata(void* arg, grpc_error* error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { - grpc_call_credentials_cancel_get_request_metadata( - calld->creds, &calld->md_array, GRPC_ERROR_REF(error)); + calld->creds->cancel_get_request_metadata(&calld->md_array, + GRPC_ERROR_REF(error)); } - GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_get_request_metadata"); } static void send_security_metadata(grpc_call_element* elem, @@ -177,7 +211,7 @@ static void send_security_metadata(grpc_call_element* elem, static_cast( batch->payload->context[GRPC_CONTEXT_SECURITY].value); grpc_call_credentials* channel_call_creds = - chand->security_connector->request_metadata_creds; + chand->security_connector->mutable_request_metadata_creds(); int call_creds_has_md = (ctx != nullptr) && (ctx->creds != nullptr); if (channel_call_creds == nullptr && !call_creds_has_md) { @@ -187,8 +221,9 @@ static void send_security_metadata(grpc_call_element* elem, } if (channel_call_creds != nullptr && call_creds_has_md) { - calld->creds = grpc_composite_call_credentials_create(channel_call_creds, - ctx->creds, nullptr); + calld->creds = grpc_core::RefCountedPtr( + grpc_composite_call_credentials_create(channel_call_creds, + ctx->creds.get(), nullptr)); if (calld->creds == nullptr) { grpc_transport_stream_op_batch_finish_with_failure( batch, @@ -200,28 +235,27 @@ static void send_security_metadata(grpc_call_element* elem, return; } } else { - calld->creds = grpc_call_credentials_ref( - call_creds_has_md ? ctx->creds : channel_call_creds); + calld->creds = + call_creds_has_md ? ctx->creds->Ref() : channel_call_creds->Ref(); } grpc_auth_metadata_context_build( - chand->security_connector->base.url_scheme, calld->host, calld->method, - chand->auth_context, &calld->auth_md_context); + chand->security_connector->url_scheme(), calld->host, calld->method, + chand->auth_context.get(), &calld->auth_md_context); GPR_ASSERT(calld->pollent != nullptr); GRPC_CALL_STACK_REF(calld->owning_call, "get_request_metadata"); GRPC_CLOSURE_INIT(&calld->async_result_closure, on_credentials_metadata, batch, grpc_schedule_on_exec_ctx); grpc_error* error = GRPC_ERROR_NONE; - if (grpc_call_credentials_get_request_metadata( - calld->creds, calld->pollent, calld->auth_md_context, - &calld->md_array, &calld->async_result_closure, &error)) { + if (calld->creds->get_request_metadata( + calld->pollent, calld->auth_md_context, &calld->md_array, + &calld->async_result_closure, &error)) { // Synchronous return; invoke on_credentials_metadata() directly. on_credentials_metadata(batch, error); GRPC_ERROR_UNREF(error); } else { // Async return; register cancellation closure with call combiner. - GRPC_CALL_STACK_REF(calld->owning_call, "cancel_get_request_metadata"); grpc_call_combiner_set_notify_on_cancel( calld->call_combiner, GRPC_CLOSURE_INIT(&calld->get_request_metadata_cancel_closure, @@ -260,11 +294,9 @@ static void cancel_check_call_host(void* arg, grpc_error* error) { call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); if (error != GRPC_ERROR_NONE) { - grpc_channel_security_connector_cancel_check_call_host( - chand->security_connector, &calld->async_result_closure, - GRPC_ERROR_REF(error)); + chand->security_connector->cancel_check_call_host( + &calld->async_result_closure, GRPC_ERROR_REF(error)); } - GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_check_call_host"); } static void auth_start_transport_stream_op_batch( @@ -276,19 +308,21 @@ static void auth_start_transport_stream_op_batch( channel_data* chand = static_cast(elem->channel_data); if (!batch->cancel_stream) { + // TODO(hcaseyal): move this to init_call_elem once issue #15927 is + // resolved. GPR_ASSERT(batch->payload->context != nullptr); if (batch->payload->context[GRPC_CONTEXT_SECURITY].value == nullptr) { batch->payload->context[GRPC_CONTEXT_SECURITY].value = - grpc_client_security_context_create(); + grpc_client_security_context_create(calld->arena, /*creds=*/nullptr); batch->payload->context[GRPC_CONTEXT_SECURITY].destroy = grpc_client_security_context_destroy; } grpc_client_security_context* sec_ctx = static_cast( batch->payload->context[GRPC_CONTEXT_SECURITY].value); - GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); + sec_ctx->auth_context.reset(DEBUG_LOCATION, "client_auth_filter"); sec_ctx->auth_context = - GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter"); + chand->auth_context->Ref(DEBUG_LOCATION, "client_auth_filter"); } if (batch->send_initial_metadata) { @@ -307,15 +341,14 @@ static void auth_start_transport_stream_op_batch( grpc_schedule_on_exec_ctx); char* call_host = grpc_slice_to_c_string(calld->host); grpc_error* error = GRPC_ERROR_NONE; - if (grpc_channel_security_connector_check_call_host( - chand->security_connector, call_host, chand->auth_context, + if (chand->security_connector->check_call_host( + call_host, chand->auth_context.get(), &calld->async_result_closure, &error)) { // Synchronous return; invoke on_host_checked() directly. on_host_checked(batch, error); GRPC_ERROR_UNREF(error); } else { // Async return; register cancellation closure with call combiner. - GRPC_CALL_STACK_REF(calld->owning_call, "cancel_check_call_host"); grpc_call_combiner_set_notify_on_cancel( calld->call_combiner, GRPC_CLOSURE_INIT(&calld->check_call_host_cancel_closure, @@ -334,11 +367,7 @@ static void auth_start_transport_stream_op_batch( /* Constructor for call_data */ static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); - calld->owning_call = args->call_stack; - calld->call_combiner = args->call_combiner; - calld->host = grpc_empty_slice(); - calld->method = grpc_empty_slice(); + new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } @@ -353,16 +382,16 @@ static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { call_data* calld = static_cast(elem->call_data); - grpc_credentials_mdelem_array_destroy(&calld->md_array); - grpc_call_credentials_unref(calld->creds); - grpc_slice_unref_internal(calld->host); - grpc_slice_unref_internal(calld->method); - grpc_auth_metadata_context_reset(&calld->auth_md_context); + calld->destroy(); } /* Constructor for channel_data */ static grpc_error* init_channel_elem(grpc_channel_element* elem, grpc_channel_element_args* args) { + /* The first and the last filters tend to be implemented differently to + handle the case that there's no 'next' filter to call on the up or down + path */ + GPR_ASSERT(!args->is_last); grpc_security_connector* sc = grpc_security_connector_find_in_args(args->channel_args); if (sc == nullptr) { @@ -375,33 +404,15 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Auth context missing from client auth filter args"); } - - /* grab pointers to our data from the channel element */ - channel_data* chand = static_cast(elem->channel_data); - - /* The first and the last filters tend to be implemented differently to - handle the case that there's no 'next' filter to call on the up or down - path */ - GPR_ASSERT(!args->is_last); - - /* initialize members */ - chand->security_connector = - reinterpret_cast( - GRPC_SECURITY_CONNECTOR_REF(sc, "client_auth_filter")); - chand->auth_context = - GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter"); + new (elem->channel_data) channel_data( + static_cast(sc), auth_context); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_channel_element* elem) { - /* grab pointers to our data from the channel element */ channel_data* chand = static_cast(elem->channel_data); - grpc_channel_security_connector* sc = chand->security_connector; - if (sc != nullptr) { - GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter"); - } - GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter"); + chand->~channel_data(); } const grpc_channel_filter grpc_client_auth_filter = { diff --git a/Sources/CgRPC/src/core/lib/security/transport/secure_endpoint.cc b/Sources/CgRPC/src/core/lib/security/transport/secure_endpoint.cc index 840b2e73b..14fb55884 100644 --- a/Sources/CgRPC/src/core/lib/security/transport/secure_endpoint.cc +++ b/Sources/CgRPC/src/core/lib/security/transport/secure_endpoint.cc @@ -22,6 +22,8 @@ headers. Therefore, sockaddr.h must always be included first */ #include +#include + #include "src/core/lib/iomgr/sockaddr.h" #include @@ -31,6 +33,7 @@ #include #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/tsi_error.h" @@ -40,44 +43,68 @@ #define STAGING_BUFFER_SIZE 8192 -typedef struct { +static void on_read(void* user_data, grpc_error* error); + +namespace { +struct secure_endpoint { + secure_endpoint(const grpc_endpoint_vtable* vtable, + tsi_frame_protector* protector, + tsi_zero_copy_grpc_protector* zero_copy_protector, + grpc_endpoint* transport, grpc_slice* leftover_slices, + size_t leftover_nslices) + : wrapped_ep(transport), + protector(protector), + zero_copy_protector(zero_copy_protector) { + base.vtable = vtable; + gpr_mu_init(&protector_mu); + GRPC_CLOSURE_INIT(&on_read, ::on_read, this, grpc_schedule_on_exec_ctx); + grpc_slice_buffer_init(&source_buffer); + grpc_slice_buffer_init(&leftover_bytes); + for (size_t i = 0; i < leftover_nslices; i++) { + grpc_slice_buffer_add(&leftover_bytes, + grpc_slice_ref_internal(leftover_slices[i])); + } + grpc_slice_buffer_init(&output_buffer); + gpr_ref_init(&ref, 1); + } + + ~secure_endpoint() { + grpc_endpoint_destroy(wrapped_ep); + tsi_frame_protector_destroy(protector); + tsi_zero_copy_grpc_protector_destroy(zero_copy_protector); + grpc_slice_buffer_destroy_internal(&source_buffer); + grpc_slice_buffer_destroy_internal(&leftover_bytes); + grpc_slice_unref_internal(read_staging_buffer); + grpc_slice_unref_internal(write_staging_buffer); + grpc_slice_buffer_destroy_internal(&output_buffer); + gpr_mu_destroy(&protector_mu); + } + grpc_endpoint base; grpc_endpoint* wrapped_ep; struct tsi_frame_protector* protector; struct tsi_zero_copy_grpc_protector* zero_copy_protector; gpr_mu protector_mu; /* saved upper level callbacks and user_data. */ - grpc_closure* read_cb; - grpc_closure* write_cb; + grpc_closure* read_cb = nullptr; + grpc_closure* write_cb = nullptr; grpc_closure on_read; - grpc_slice_buffer* read_buffer; + grpc_slice_buffer* read_buffer = nullptr; grpc_slice_buffer source_buffer; /* saved handshaker leftover data to unprotect. */ grpc_slice_buffer leftover_bytes; /* buffers for read and write */ - grpc_slice read_staging_buffer; - - grpc_slice write_staging_buffer; + grpc_slice read_staging_buffer = GRPC_SLICE_MALLOC(STAGING_BUFFER_SIZE); + grpc_slice write_staging_buffer = GRPC_SLICE_MALLOC(STAGING_BUFFER_SIZE); grpc_slice_buffer output_buffer; gpr_refcount ref; -} secure_endpoint; +}; +} // namespace grpc_core::TraceFlag grpc_trace_secure_endpoint(false, "secure_endpoint"); -static void destroy(secure_endpoint* secure_ep) { - secure_endpoint* ep = secure_ep; - grpc_endpoint_destroy(ep->wrapped_ep); - tsi_frame_protector_destroy(ep->protector); - tsi_zero_copy_grpc_protector_destroy(ep->zero_copy_protector); - grpc_slice_buffer_destroy_internal(&ep->leftover_bytes); - grpc_slice_unref_internal(ep->read_staging_buffer); - grpc_slice_unref_internal(ep->write_staging_buffer); - grpc_slice_buffer_destroy_internal(&ep->output_buffer); - grpc_slice_buffer_destroy_internal(&ep->source_buffer); - gpr_mu_destroy(&ep->protector_mu); - gpr_free(ep); -} +static void destroy(secure_endpoint* ep) { grpc_core::Delete(ep); } #ifndef NDEBUG #define SECURE_ENDPOINT_UNREF(ep, reason) \ @@ -254,7 +281,7 @@ static void flush_write_staging_buffer(secure_endpoint* ep, uint8_t** cur, } static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { GPR_TIMER_SCOPE("secure_endpoint.endpoint_write", 0); unsigned i; @@ -342,7 +369,7 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, return; } - grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb); + grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb, arg); } static void endpoint_shutdown(grpc_endpoint* secure_ep, grpc_error* why) { @@ -389,6 +416,11 @@ static grpc_resource_user* endpoint_get_resource_user( return grpc_endpoint_get_resource_user(ep->wrapped_ep); } +static bool endpoint_can_track_err(grpc_endpoint* secure_ep) { + secure_endpoint* ep = reinterpret_cast(secure_ep); + return grpc_endpoint_can_track_err(ep->wrapped_ep); +} + static const grpc_endpoint_vtable vtable = {endpoint_read, endpoint_write, endpoint_add_to_pollset, @@ -398,32 +430,16 @@ static const grpc_endpoint_vtable vtable = {endpoint_read, endpoint_destroy, endpoint_get_resource_user, endpoint_get_peer, - endpoint_get_fd}; + endpoint_get_fd, + endpoint_can_track_err}; grpc_endpoint* grpc_secure_endpoint_create( struct tsi_frame_protector* protector, struct tsi_zero_copy_grpc_protector* zero_copy_protector, grpc_endpoint* transport, grpc_slice* leftover_slices, size_t leftover_nslices) { - size_t i; - secure_endpoint* ep = - static_cast(gpr_malloc(sizeof(secure_endpoint))); - ep->base.vtable = &vtable; - ep->wrapped_ep = transport; - ep->protector = protector; - ep->zero_copy_protector = zero_copy_protector; - grpc_slice_buffer_init(&ep->leftover_bytes); - for (i = 0; i < leftover_nslices; i++) { - grpc_slice_buffer_add(&ep->leftover_bytes, - grpc_slice_ref_internal(leftover_slices[i])); - } - ep->write_staging_buffer = GRPC_SLICE_MALLOC(STAGING_BUFFER_SIZE); - ep->read_staging_buffer = GRPC_SLICE_MALLOC(STAGING_BUFFER_SIZE); - grpc_slice_buffer_init(&ep->output_buffer); - grpc_slice_buffer_init(&ep->source_buffer); - ep->read_buffer = nullptr; - GRPC_CLOSURE_INIT(&ep->on_read, on_read, ep, grpc_schedule_on_exec_ctx); - gpr_mu_init(&ep->protector_mu); - gpr_ref_init(&ep->ref, 1); + secure_endpoint* ep = grpc_core::New( + &vtable, protector, zero_copy_protector, transport, leftover_slices, + leftover_nslices); return &ep->base; } diff --git a/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.cc b/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.cc index d9ba3483e..5369574b8 100644 --- a/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.cc +++ b/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.cc @@ -30,6 +30,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/tsi_error.h" @@ -38,46 +39,113 @@ #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 -typedef struct { - grpc_handshaker base; +namespace grpc_core { + +namespace { + +class SecurityHandshaker : public Handshaker { + public: + SecurityHandshaker(tsi_handshaker* handshaker, + grpc_security_connector* connector); + ~SecurityHandshaker() override; + void Shutdown(grpc_error* why) override; + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override; + const char* name() const override { return "security"; } + + private: + grpc_error* DoHandshakerNextLocked(const unsigned char* bytes_received, + size_t bytes_received_size); + + grpc_error* OnHandshakeNextDoneLocked( + tsi_result result, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result); + void HandshakeFailedLocked(grpc_error* error); + void CleanupArgsForFailureLocked(); + + static void OnHandshakeDataReceivedFromPeerFn(void* arg, grpc_error* error); + static void OnHandshakeDataSentToPeerFn(void* arg, grpc_error* error); + static void OnHandshakeNextDoneGrpcWrapper( + tsi_result result, void* user_data, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result); + static void OnPeerCheckedFn(void* arg, grpc_error* error); + void OnPeerCheckedInner(grpc_error* error); + size_t MoveReadBufferIntoHandshakeBuffer(); + grpc_error* CheckPeerLocked(); // State set at creation time. - tsi_handshaker* handshaker; - grpc_security_connector* connector; + tsi_handshaker* handshaker_; + RefCountedPtr connector_; - gpr_mu mu; - gpr_refcount refs; + gpr_mu mu_; - bool shutdown; + bool is_shutdown_ = false; // Endpoint and read buffer to destroy after a shutdown. - grpc_endpoint* endpoint_to_destroy; - grpc_slice_buffer* read_buffer_to_destroy; + grpc_endpoint* endpoint_to_destroy_ = nullptr; + grpc_slice_buffer* read_buffer_to_destroy_ = nullptr; // State saved while performing the handshake. - grpc_handshaker_args* args; - grpc_closure* on_handshake_done; - - unsigned char* handshake_buffer; - size_t handshake_buffer_size; - grpc_slice_buffer outgoing; - grpc_closure on_handshake_data_sent_to_peer; - grpc_closure on_handshake_data_received_from_peer; - grpc_closure on_peer_checked; - grpc_auth_context* auth_context; - tsi_handshaker_result* handshaker_result; -} security_handshaker; - -static size_t move_read_buffer_into_handshake_buffer(security_handshaker* h) { - size_t bytes_in_read_buffer = h->args->read_buffer->length; - if (h->handshake_buffer_size < bytes_in_read_buffer) { - h->handshake_buffer = static_cast( - gpr_realloc(h->handshake_buffer, bytes_in_read_buffer)); - h->handshake_buffer_size = bytes_in_read_buffer; + HandshakerArgs* args_ = nullptr; + grpc_closure* on_handshake_done_ = nullptr; + + size_t handshake_buffer_size_; + unsigned char* handshake_buffer_; + grpc_slice_buffer outgoing_; + grpc_closure on_handshake_data_sent_to_peer_; + grpc_closure on_handshake_data_received_from_peer_; + grpc_closure on_peer_checked_; + RefCountedPtr auth_context_; + tsi_handshaker_result* handshaker_result_ = nullptr; +}; + +SecurityHandshaker::SecurityHandshaker(tsi_handshaker* handshaker, + grpc_security_connector* connector) + : handshaker_(handshaker), + connector_(connector->Ref(DEBUG_LOCATION, "handshake")), + handshake_buffer_size_(GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE), + handshake_buffer_( + static_cast(gpr_malloc(handshake_buffer_size_))) { + gpr_mu_init(&mu_); + grpc_slice_buffer_init(&outgoing_); + GRPC_CLOSURE_INIT(&on_handshake_data_sent_to_peer_, + &SecurityHandshaker::OnHandshakeDataSentToPeerFn, this, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_handshake_data_received_from_peer_, + &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn, + this, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_peer_checked_, &SecurityHandshaker::OnPeerCheckedFn, + this, grpc_schedule_on_exec_ctx); +} + +SecurityHandshaker::~SecurityHandshaker() { + gpr_mu_destroy(&mu_); + tsi_handshaker_destroy(handshaker_); + tsi_handshaker_result_destroy(handshaker_result_); + if (endpoint_to_destroy_ != nullptr) { + grpc_endpoint_destroy(endpoint_to_destroy_); + } + if (read_buffer_to_destroy_ != nullptr) { + grpc_slice_buffer_destroy_internal(read_buffer_to_destroy_); + gpr_free(read_buffer_to_destroy_); + } + gpr_free(handshake_buffer_); + grpc_slice_buffer_destroy_internal(&outgoing_); + auth_context_.reset(DEBUG_LOCATION, "handshake"); + connector_.reset(DEBUG_LOCATION, "handshake"); +} + +size_t SecurityHandshaker::MoveReadBufferIntoHandshakeBuffer() { + size_t bytes_in_read_buffer = args_->read_buffer->length; + if (handshake_buffer_size_ < bytes_in_read_buffer) { + handshake_buffer_ = static_cast( + gpr_realloc(handshake_buffer_, bytes_in_read_buffer)); + handshake_buffer_size_ = bytes_in_read_buffer; } size_t offset = 0; - while (h->args->read_buffer->count > 0) { - grpc_slice next_slice = grpc_slice_buffer_take_first(h->args->read_buffer); - memcpy(h->handshake_buffer + offset, GRPC_SLICE_START_PTR(next_slice), + while (args_->read_buffer->count > 0) { + grpc_slice next_slice = grpc_slice_buffer_take_first(args_->read_buffer); + memcpy(handshake_buffer_ + offset, GRPC_SLICE_START_PTR(next_slice), GRPC_SLICE_LENGTH(next_slice)); offset += GRPC_SLICE_LENGTH(next_slice); grpc_slice_unref_internal(next_slice); @@ -85,41 +153,20 @@ static size_t move_read_buffer_into_handshake_buffer(security_handshaker* h) { return bytes_in_read_buffer; } -static void security_handshaker_unref(security_handshaker* h) { - if (gpr_unref(&h->refs)) { - gpr_mu_destroy(&h->mu); - tsi_handshaker_destroy(h->handshaker); - tsi_handshaker_result_destroy(h->handshaker_result); - if (h->endpoint_to_destroy != nullptr) { - grpc_endpoint_destroy(h->endpoint_to_destroy); - } - if (h->read_buffer_to_destroy != nullptr) { - grpc_slice_buffer_destroy_internal(h->read_buffer_to_destroy); - gpr_free(h->read_buffer_to_destroy); - } - gpr_free(h->handshake_buffer); - grpc_slice_buffer_destroy_internal(&h->outgoing); - GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); - GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); - gpr_free(h); - } -} - -// Set args fields to NULL, saving the endpoint and read buffer for +// Set args_ fields to NULL, saving the endpoint and read buffer for // later destruction. -static void cleanup_args_for_failure_locked(security_handshaker* h) { - h->endpoint_to_destroy = h->args->endpoint; - h->args->endpoint = nullptr; - h->read_buffer_to_destroy = h->args->read_buffer; - h->args->read_buffer = nullptr; - grpc_channel_args_destroy(h->args->args); - h->args->args = nullptr; +void SecurityHandshaker::CleanupArgsForFailureLocked() { + endpoint_to_destroy_ = args_->endpoint; + args_->endpoint = nullptr; + read_buffer_to_destroy_ = args_->read_buffer; + args_->read_buffer = nullptr; + grpc_channel_args_destroy(args_->args); + args_->args = nullptr; } // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. -static void security_handshake_failed_locked(security_handshaker* h, - grpc_error* error) { +void SecurityHandshaker::HandshakeFailedLocked(grpc_error* error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after the handshake succeeded but before an // endpoint callback was invoked, we need to generate our own error. @@ -128,50 +175,51 @@ static void security_handshake_failed_locked(security_handshaker* h, const char* msg = grpc_error_string(error); gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); - if (!h->shutdown) { + if (!is_shutdown_) { // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. - grpc_endpoint_shutdown(h->args->endpoint, GRPC_ERROR_REF(error)); + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(error)); // Not shutting down, so the write failed. Clean up before // invoking the callback. - cleanup_args_for_failure_locked(h); + CleanupArgsForFailureLocked(); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. - h->shutdown = true; + is_shutdown_ = true; } // Invoke callback. - GRPC_CLOSURE_SCHED(h->on_handshake_done, error); + GRPC_CLOSURE_SCHED(on_handshake_done_, error); } -static void on_peer_checked_inner(security_handshaker* h, grpc_error* error) { - if (error != GRPC_ERROR_NONE || h->shutdown) { - security_handshake_failed_locked(h, GRPC_ERROR_REF(error)); +void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { + MutexLock lock(&mu_); + if (error != GRPC_ERROR_NONE || is_shutdown_) { + HandshakeFailedLocked(GRPC_ERROR_REF(error)); return; } // Create zero-copy frame protector, if implemented. tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr; tsi_result result = tsi_handshaker_result_create_zero_copy_grpc_protector( - h->handshaker_result, nullptr, &zero_copy_protector); + handshaker_result_, nullptr, &zero_copy_protector); if (result != TSI_OK && result != TSI_UNIMPLEMENTED) { error = grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Zero-copy frame protector creation failed"), result); - security_handshake_failed_locked(h, error); + HandshakeFailedLocked(error); return; } // Create frame protector if zero-copy frame protector is NULL. tsi_frame_protector* protector = nullptr; if (zero_copy_protector == nullptr) { - result = tsi_handshaker_result_create_frame_protector(h->handshaker_result, + result = tsi_handshaker_result_create_frame_protector(handshaker_result_, nullptr, &protector); if (result != TSI_OK) { error = grpc_set_tsi_error_result(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Frame protector creation failed"), result); - security_handshake_failed_locked(h, error); + HandshakeFailedLocked(error); return; } } @@ -179,68 +227,63 @@ static void on_peer_checked_inner(security_handshaker* h, grpc_error* error) { const unsigned char* unused_bytes = nullptr; size_t unused_bytes_size = 0; result = tsi_handshaker_result_get_unused_bytes( - h->handshaker_result, &unused_bytes, &unused_bytes_size); + handshaker_result_, &unused_bytes, &unused_bytes_size); // Create secure endpoint. if (unused_bytes_size > 0) { grpc_slice slice = grpc_slice_from_copied_buffer((char*)unused_bytes, unused_bytes_size); - h->args->endpoint = grpc_secure_endpoint_create( - protector, zero_copy_protector, h->args->endpoint, &slice, 1); + args_->endpoint = grpc_secure_endpoint_create( + protector, zero_copy_protector, args_->endpoint, &slice, 1); grpc_slice_unref_internal(slice); } else { - h->args->endpoint = grpc_secure_endpoint_create( - protector, zero_copy_protector, h->args->endpoint, nullptr, 0); + args_->endpoint = grpc_secure_endpoint_create( + protector, zero_copy_protector, args_->endpoint, nullptr, 0); } - tsi_handshaker_result_destroy(h->handshaker_result); - h->handshaker_result = nullptr; + tsi_handshaker_result_destroy(handshaker_result_); + handshaker_result_ = nullptr; // Add auth context to channel args. - grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); - grpc_channel_args* tmp_args = h->args->args; - h->args->args = - grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); + grpc_arg auth_context_arg = grpc_auth_context_to_arg(auth_context_.get()); + grpc_channel_args* tmp_args = args_->args; + args_->args = grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); grpc_channel_args_destroy(tmp_args); // Invoke callback. - GRPC_CLOSURE_SCHED(h->on_handshake_done, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(on_handshake_done_, GRPC_ERROR_NONE); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. - h->shutdown = true; + is_shutdown_ = true; } -static void on_peer_checked(void* arg, grpc_error* error) { - security_handshaker* h = static_cast(arg); - gpr_mu_lock(&h->mu); - on_peer_checked_inner(h, error); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); +void SecurityHandshaker::OnPeerCheckedFn(void* arg, grpc_error* error) { + RefCountedPtr(static_cast(arg)) + ->OnPeerCheckedInner(error); } -static grpc_error* check_peer_locked(security_handshaker* h) { +grpc_error* SecurityHandshaker::CheckPeerLocked() { tsi_peer peer; tsi_result result = - tsi_handshaker_result_extract_peer(h->handshaker_result, &peer); + tsi_handshaker_result_extract_peer(handshaker_result_, &peer); if (result != TSI_OK) { return grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result); } - grpc_security_connector_check_peer(h->connector, peer, &h->auth_context, - &h->on_peer_checked); + connector_->check_peer(peer, args_->endpoint, &auth_context_, + &on_peer_checked_); return GRPC_ERROR_NONE; } -static grpc_error* on_handshake_next_done_locked( - security_handshaker* h, tsi_result result, - const unsigned char* bytes_to_send, size_t bytes_to_send_size, - tsi_handshaker_result* handshaker_result) { +grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked( + tsi_result result, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) { grpc_error* error = GRPC_ERROR_NONE; // Handshaker was shutdown. - if (h->shutdown) { + if (is_shutdown_) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } // Read more if we need to. if (result == TSI_INCOMPLETE_DATA) { GPR_ASSERT(bytes_to_send_size == 0); - grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, - &h->on_handshake_data_received_from_peer); + grpc_endpoint_read(args_->endpoint, args_->read_buffer, + &on_handshake_data_received_from_peer_); return error; } if (result != TSI_OK) { @@ -249,58 +292,52 @@ static grpc_error* on_handshake_next_done_locked( } // Update handshaker result. if (handshaker_result != nullptr) { - GPR_ASSERT(h->handshaker_result == nullptr); - h->handshaker_result = handshaker_result; + GPR_ASSERT(handshaker_result_ == nullptr); + handshaker_result_ = handshaker_result; } if (bytes_to_send_size > 0) { // Send data to peer, if needed. grpc_slice to_send = grpc_slice_from_copied_buffer( reinterpret_cast(bytes_to_send), bytes_to_send_size); - grpc_slice_buffer_reset_and_unref_internal(&h->outgoing); - grpc_slice_buffer_add(&h->outgoing, to_send); - grpc_endpoint_write(h->args->endpoint, &h->outgoing, - &h->on_handshake_data_sent_to_peer); + grpc_slice_buffer_reset_and_unref_internal(&outgoing_); + grpc_slice_buffer_add(&outgoing_, to_send); + grpc_endpoint_write(args_->endpoint, &outgoing_, + &on_handshake_data_sent_to_peer_, nullptr); } else if (handshaker_result == nullptr) { // There is nothing to send, but need to read from peer. - grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, - &h->on_handshake_data_received_from_peer); + grpc_endpoint_read(args_->endpoint, args_->read_buffer, + &on_handshake_data_received_from_peer_); } else { // Handshake has finished, check peer and so on. - error = check_peer_locked(h); + error = CheckPeerLocked(); } return error; } -static void on_handshake_next_done_grpc_wrapper( +void SecurityHandshaker::OnHandshakeNextDoneGrpcWrapper( tsi_result result, void* user_data, const unsigned char* bytes_to_send, size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) { - security_handshaker* h = static_cast(user_data); - // This callback will be invoked by TSI in a non-grpc thread, so it's - // safe to create our own exec_ctx here. - grpc_core::ExecCtx exec_ctx; - gpr_mu_lock(&h->mu); - grpc_error* error = on_handshake_next_done_locked( - h, result, bytes_to_send, bytes_to_send_size, handshaker_result); + RefCountedPtr h( + static_cast(user_data)); + MutexLock lock(&h->mu_); + grpc_error* error = h->OnHandshakeNextDoneLocked( + result, bytes_to_send, bytes_to_send_size, handshaker_result); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); + h->HandshakeFailedLocked(error); } else { - gpr_mu_unlock(&h->mu); + h.release(); // Avoid unref } } -static grpc_error* do_handshaker_next_locked( - security_handshaker* h, const unsigned char* bytes_received, - size_t bytes_received_size) { +grpc_error* SecurityHandshaker::DoHandshakerNextLocked( + const unsigned char* bytes_received, size_t bytes_received_size) { // Invoke TSI handshaker. const unsigned char* bytes_to_send = nullptr; size_t bytes_to_send_size = 0; - tsi_handshaker_result* handshaker_result = nullptr; + tsi_handshaker_result* hs_result = nullptr; tsi_result result = tsi_handshaker_next( - h->handshaker, bytes_received, bytes_received_size, &bytes_to_send, - &bytes_to_send_size, &handshaker_result, - &on_handshake_next_done_grpc_wrapper, h); + handshaker_, bytes_received, bytes_received_size, &bytes_to_send, + &bytes_to_send_size, &hs_result, &OnHandshakeNextDoneGrpcWrapper, this); if (result == TSI_ASYNC) { // Handshaker operating asynchronously. Nothing else to do here; // callback will be invoked in a TSI thread. @@ -308,223 +345,169 @@ static grpc_error* do_handshaker_next_locked( } // Handshaker returned synchronously. Invoke callback directly in // this thread with our existing exec_ctx. - return on_handshake_next_done_locked(h, result, bytes_to_send, - bytes_to_send_size, handshaker_result); + return OnHandshakeNextDoneLocked(result, bytes_to_send, bytes_to_send_size, + hs_result); } -static void on_handshake_data_received_from_peer(void* arg, grpc_error* error) { - security_handshaker* h = static_cast(arg); - gpr_mu_lock(&h->mu); - if (error != GRPC_ERROR_NONE || h->shutdown) { - security_handshake_failed_locked( - h, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Handshake read failed", &error, 1)); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); +void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg, + grpc_error* error) { + RefCountedPtr h(static_cast(arg)); + MutexLock lock(&h->mu_); + if (error != GRPC_ERROR_NONE || h->is_shutdown_) { + h->HandshakeFailedLocked(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Handshake read failed", &error, 1)); return; } // Copy all slices received. - size_t bytes_received_size = move_read_buffer_into_handshake_buffer(h); + size_t bytes_received_size = h->MoveReadBufferIntoHandshakeBuffer(); // Call TSI handshaker. - error = - do_handshaker_next_locked(h, h->handshake_buffer, bytes_received_size); + error = h->DoHandshakerNextLocked(h->handshake_buffer_, bytes_received_size); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); + h->HandshakeFailedLocked(error); } else { - gpr_mu_unlock(&h->mu); + h.release(); // Avoid unref } } -static void on_handshake_data_sent_to_peer(void* arg, grpc_error* error) { - security_handshaker* h = static_cast(arg); - gpr_mu_lock(&h->mu); - if (error != GRPC_ERROR_NONE || h->shutdown) { - security_handshake_failed_locked( - h, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Handshake write failed", &error, 1)); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); +void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg, + grpc_error* error) { + RefCountedPtr h(static_cast(arg)); + MutexLock lock(&h->mu_); + if (error != GRPC_ERROR_NONE || h->is_shutdown_) { + h->HandshakeFailedLocked(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Handshake write failed", &error, 1)); return; } // We may be done. - if (h->handshaker_result == nullptr) { - grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, - &h->on_handshake_data_received_from_peer); + if (h->handshaker_result_ == nullptr) { + grpc_endpoint_read(h->args_->endpoint, h->args_->read_buffer, + &h->on_handshake_data_received_from_peer_); } else { - error = check_peer_locked(h); + error = h->CheckPeerLocked(); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); + h->HandshakeFailedLocked(error); return; } } - gpr_mu_unlock(&h->mu); + h.release(); // Avoid unref } // // public handshaker API // -static void security_handshaker_destroy(grpc_handshaker* handshaker) { - security_handshaker* h = reinterpret_cast(handshaker); - security_handshaker_unref(h); -} - -static void security_handshaker_shutdown(grpc_handshaker* handshaker, - grpc_error* why) { - security_handshaker* h = reinterpret_cast(handshaker); - gpr_mu_lock(&h->mu); - if (!h->shutdown) { - h->shutdown = true; - grpc_endpoint_shutdown(h->args->endpoint, GRPC_ERROR_REF(why)); - cleanup_args_for_failure_locked(h); +void SecurityHandshaker::Shutdown(grpc_error* why) { + MutexLock lock(&mu_); + if (!is_shutdown_) { + is_shutdown_ = true; + tsi_handshaker_shutdown(handshaker_); + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why)); + CleanupArgsForFailureLocked(); } - gpr_mu_unlock(&h->mu); GRPC_ERROR_UNREF(why); } -static void security_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args) { - security_handshaker* h = reinterpret_cast(handshaker); - gpr_mu_lock(&h->mu); - h->args = args; - h->on_handshake_done = on_handshake_done; - gpr_ref(&h->refs); - size_t bytes_received_size = move_read_buffer_into_handshake_buffer(h); +void SecurityHandshaker::DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) { + auto ref = Ref(); + MutexLock lock(&mu_); + args_ = args; + on_handshake_done_ = on_handshake_done; + size_t bytes_received_size = MoveReadBufferIntoHandshakeBuffer(); grpc_error* error = - do_handshaker_next_locked(h, h->handshake_buffer, bytes_received_size); + DoHandshakerNextLocked(handshake_buffer_, bytes_received_size); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - security_handshaker_unref(h); - return; + HandshakeFailedLocked(error); + } else { + ref.release(); // Avoid unref } - gpr_mu_unlock(&h->mu); -} - -static const grpc_handshaker_vtable security_handshaker_vtable = { - security_handshaker_destroy, security_handshaker_shutdown, - security_handshaker_do_handshake, "security"}; - -static grpc_handshaker* security_handshaker_create( - tsi_handshaker* handshaker, grpc_security_connector* connector) { - security_handshaker* h = static_cast( - gpr_zalloc(sizeof(security_handshaker))); - grpc_handshaker_init(&security_handshaker_vtable, &h->base); - h->handshaker = handshaker; - h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); - gpr_mu_init(&h->mu); - gpr_ref_init(&h->refs, 1); - h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; - h->handshake_buffer = - static_cast(gpr_malloc(h->handshake_buffer_size)); - GRPC_CLOSURE_INIT(&h->on_handshake_data_sent_to_peer, - on_handshake_data_sent_to_peer, h, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&h->on_handshake_data_received_from_peer, - on_handshake_data_received_from_peer, h, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&h->on_peer_checked, on_peer_checked, h, - grpc_schedule_on_exec_ctx); - grpc_slice_buffer_init(&h->outgoing); - return &h->base; } // -// fail_handshaker +// FailHandshaker // -static void fail_handshaker_destroy(grpc_handshaker* handshaker) { - gpr_free(handshaker); -} - -static void fail_handshaker_shutdown(grpc_handshaker* handshaker, - grpc_error* why) { - GRPC_ERROR_UNREF(why); -} - -static void fail_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args) { - GRPC_CLOSURE_SCHED(on_handshake_done, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Failed to create security handshaker")); -} +class FailHandshaker : public Handshaker { + public: + const char* name() const override { return "security_fail"; } + void Shutdown(grpc_error* why) override { GRPC_ERROR_UNREF(why); } + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override { + GRPC_CLOSURE_SCHED(on_handshake_done, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Failed to create security handshaker")); + } -static const grpc_handshaker_vtable fail_handshaker_vtable = { - fail_handshaker_destroy, fail_handshaker_shutdown, - fail_handshaker_do_handshake, "security_fail"}; - -static grpc_handshaker* fail_handshaker_create() { - grpc_handshaker* h = static_cast(gpr_malloc(sizeof(*h))); - grpc_handshaker_init(&fail_handshaker_vtable, h); - return h; -} + private: + virtual ~FailHandshaker() = default; +}; // // handshaker factories // -static void client_handshaker_factory_add_handshakers( - grpc_handshaker_factory* handshaker_factory, const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr) { - grpc_channel_security_connector* security_connector = - reinterpret_cast( - grpc_security_connector_find_in_args(args)); - grpc_channel_security_connector_add_handshakers(security_connector, - handshake_mgr); -} - -static void server_handshaker_factory_add_handshakers( - grpc_handshaker_factory* hf, const grpc_channel_args* args, - grpc_handshake_manager* handshake_mgr) { - grpc_server_security_connector* security_connector = - reinterpret_cast( - grpc_security_connector_find_in_args(args)); - grpc_server_security_connector_add_handshakers(security_connector, - handshake_mgr); -} - -static void handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory) {} - -static const grpc_handshaker_factory_vtable client_handshaker_factory_vtable = { - client_handshaker_factory_add_handshakers, handshaker_factory_destroy}; - -static grpc_handshaker_factory client_handshaker_factory = { - &client_handshaker_factory_vtable}; - -static const grpc_handshaker_factory_vtable server_handshaker_factory_vtable = { - server_handshaker_factory_add_handshakers, handshaker_factory_destroy}; +class ClientSecurityHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + auto* security_connector = + reinterpret_cast( + grpc_security_connector_find_in_args(args)); + if (security_connector) { + security_connector->add_handshakers(interested_parties, handshake_mgr); + } + } + ~ClientSecurityHandshakerFactory() override = default; +}; + +class ServerSecurityHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + auto* security_connector = + reinterpret_cast( + grpc_security_connector_find_in_args(args)); + if (security_connector) { + security_connector->add_handshakers(interested_parties, handshake_mgr); + } + } + ~ServerSecurityHandshakerFactory() override = default; +}; -static grpc_handshaker_factory server_handshaker_factory = { - &server_handshaker_factory_vtable}; +} // namespace // // exported functions // -grpc_handshaker* grpc_security_handshaker_create( +RefCountedPtr SecurityHandshakerCreate( tsi_handshaker* handshaker, grpc_security_connector* connector) { // If no TSI handshaker was created, return a handshaker that always fails. // Otherwise, return a real security handshaker. if (handshaker == nullptr) { - return fail_handshaker_create(); + return MakeRefCounted(); } else { - return security_handshaker_create(handshaker, connector); + return MakeRefCounted(handshaker, connector); } } -void grpc_security_register_handshaker_factories() { - grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_CLIENT, - &client_handshaker_factory); - grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_SERVER, - &server_handshaker_factory); +void SecurityRegisterHandshakerFactories() { + HandshakerRegistry::RegisterHandshakerFactory( + false /* at_start */, HANDSHAKER_CLIENT, + UniquePtr(New())); + HandshakerRegistry::RegisterHandshakerFactory( + false /* at_start */, HANDSHAKER_SERVER, + UniquePtr(New())); +} + +} // namespace grpc_core + +grpc_handshaker* grpc_security_handshaker_create( + tsi_handshaker* handshaker, grpc_security_connector* connector) { + return SecurityHandshakerCreate(handshaker, connector).release(); } diff --git a/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.h b/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.h index 88483b02e..263fe5559 100644 --- a/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.h +++ b/Sources/CgRPC/src/core/lib/security/transport/security_handshaker.h @@ -24,11 +24,20 @@ #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/security/security_connector/security_connector.h" +namespace grpc_core { + /// Creates a security handshaker using \a handshaker. -grpc_handshaker* grpc_security_handshaker_create( +RefCountedPtr SecurityHandshakerCreate( tsi_handshaker* handshaker, grpc_security_connector* connector); /// Registers security handshaker factories. -void grpc_security_register_handshaker_factories(); +void SecurityRegisterHandshakerFactories(); + +} // namespace grpc_core + +// TODO(arjunroy): This is transitional to account for the new handshaker API +// and will eventually be removed entirely. +grpc_handshaker* grpc_security_handshaker_create( + tsi_handshaker* handshaker, grpc_security_connector* connector); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */ diff --git a/Sources/CgRPC/src/core/lib/security/transport/server_auth_filter.cc b/Sources/CgRPC/src/core/lib/security/transport/server_auth_filter.cc index a560a4a02..81b9c2ce0 100644 --- a/Sources/CgRPC/src/core/lib/security/transport/server_auth_filter.cc +++ b/Sources/CgRPC/src/core/lib/security/transport/server_auth_filter.cc @@ -28,6 +28,9 @@ #include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/slice/slice_internal.h" +static void recv_initial_metadata_ready(void* arg, grpc_error* error); +static void recv_trailing_metadata_ready(void* user_data, grpc_error* error); + namespace { enum async_state { STATE_INIT = 0, @@ -35,24 +38,59 @@ enum async_state { STATE_CANCELLED, }; +struct channel_data { + channel_data(grpc_auth_context* auth_context, grpc_server_credentials* creds) + : auth_context(auth_context->Ref()), creds(creds->Ref()) {} + ~channel_data() { auth_context.reset(DEBUG_LOCATION, "server_auth_filter"); } + + grpc_core::RefCountedPtr auth_context; + grpc_core::RefCountedPtr creds; +}; + struct call_data { + call_data(grpc_call_element* elem, const grpc_call_element_args& args) + : call_combiner(args.call_combiner), owning_call(args.call_stack) { + GRPC_CLOSURE_INIT(&recv_initial_metadata_ready, + ::recv_initial_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready, + ::recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + // Create server security context. Set its auth context from channel + // data and save it in the call context. + grpc_server_security_context* server_ctx = + grpc_server_security_context_create(args.arena); + channel_data* chand = static_cast(elem->channel_data); + server_ctx->auth_context = + chand->auth_context->Ref(DEBUG_LOCATION, "server_auth_filter"); + if (args.context[GRPC_CONTEXT_SECURITY].value != nullptr) { + args.context[GRPC_CONTEXT_SECURITY].destroy( + args.context[GRPC_CONTEXT_SECURITY].value); + } + args.context[GRPC_CONTEXT_SECURITY].value = server_ctx; + args.context[GRPC_CONTEXT_SECURITY].destroy = + grpc_server_security_context_destroy; + } + + ~call_data() { GRPC_ERROR_UNREF(recv_initial_metadata_error); } + grpc_call_combiner* call_combiner; grpc_call_stack* owning_call; grpc_transport_stream_op_batch* recv_initial_metadata_batch; grpc_closure* original_recv_initial_metadata_ready; grpc_closure recv_initial_metadata_ready; + grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; + grpc_closure recv_trailing_metadata_ready; + grpc_closure* original_recv_trailing_metadata_ready; + grpc_error* recv_trailing_metadata_error; + bool seen_recv_trailing_metadata_ready = false; grpc_metadata_array md; const grpc_metadata* consumed_md; size_t num_consumed_md; - grpc_auth_context* auth_context; grpc_closure cancel_closure; - gpr_atm state; // async_state + gpr_atm state = STATE_INIT; // async_state }; -struct channel_data { - grpc_auth_context* auth_context; - grpc_server_credentials* creds; -}; } // namespace static grpc_metadata_array metadata_batch_to_md_array( @@ -112,7 +150,16 @@ static void on_md_processing_done_inner(grpc_call_element* elem, batch->payload->recv_initial_metadata.recv_initial_metadata, remove_consumed_md, elem, "Response metadata filtering error"); } - GRPC_CLOSURE_SCHED(calld->original_recv_initial_metadata_ready, error); + calld->recv_initial_metadata_error = GRPC_ERROR_REF(error); + grpc_closure* closure = calld->original_recv_initial_metadata_ready; + calld->original_recv_initial_metadata_ready = nullptr; + if (calld->seen_recv_trailing_metadata_ready) { + GRPC_CALL_COMBINER_START(calld->call_combiner, + &calld->recv_trailing_metadata_ready, + calld->recv_trailing_metadata_error, + "continue recv_trailing_metadata_ready"); + } + GRPC_CLOSURE_SCHED(closure, error); } // Called from application code. @@ -122,6 +169,7 @@ static void on_md_processing_done( grpc_status_code status, const char* error_details) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; // If the call was not cancelled while we were in flight, process the result. if (gpr_atm_full_cas(&calld->state, static_cast(STATE_INIT), @@ -157,7 +205,6 @@ static void cancel_call(void* arg, grpc_error* error) { on_md_processing_done_inner(elem, nullptr, 0, nullptr, 0, GRPC_ERROR_REF(error)); } - GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_call"); } static void recv_initial_metadata_ready(void* arg, grpc_error* error) { @@ -166,10 +213,10 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { call_data* calld = static_cast(elem->call_data); grpc_transport_stream_op_batch* batch = calld->recv_initial_metadata_batch; if (error == GRPC_ERROR_NONE) { - if (chand->creds != nullptr && chand->creds->processor.process != nullptr) { + if (chand->creds != nullptr && + chand->creds->auth_metadata_processor().process != nullptr) { // We're calling out to the application, so we need to make sure // to drop the call combiner early if we get cancelled. - GRPC_CALL_STACK_REF(calld->owning_call, "cancel_call"); GRPC_CLOSURE_INIT(&calld->cancel_closure, cancel_call, elem, grpc_schedule_on_exec_ctx); grpc_call_combiner_set_notify_on_cancel(calld->call_combiner, @@ -177,14 +224,38 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { GRPC_CALL_STACK_REF(calld->owning_call, "server_auth_metadata"); calld->md = metadata_batch_to_md_array( batch->payload->recv_initial_metadata.recv_initial_metadata); - chand->creds->processor.process( - chand->creds->processor.state, calld->auth_context, - calld->md.metadata, calld->md.count, on_md_processing_done, elem); + chand->creds->auth_metadata_processor().process( + chand->creds->auth_metadata_processor().state, + chand->auth_context.get(), calld->md.metadata, calld->md.count, + on_md_processing_done, elem); return; } } - GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, - GRPC_ERROR_REF(error)); + grpc_closure* closure = calld->original_recv_initial_metadata_ready; + calld->original_recv_initial_metadata_ready = nullptr; + if (calld->seen_recv_trailing_metadata_ready) { + GRPC_CALL_COMBINER_START(calld->call_combiner, + &calld->recv_trailing_metadata_ready, + calld->recv_trailing_metadata_error, + "continue recv_trailing_metadata_ready"); + } + GRPC_CLOSURE_RUN(closure, GRPC_ERROR_REF(error)); +} + +static void recv_trailing_metadata_ready(void* user_data, grpc_error* err) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + if (calld->original_recv_initial_metadata_ready != nullptr) { + calld->recv_trailing_metadata_error = GRPC_ERROR_REF(err); + calld->seen_recv_trailing_metadata_ready = true; + GRPC_CALL_COMBINER_STOP(calld->call_combiner, + "deferring recv_trailing_metadata_ready until " + "after recv_initial_metadata_ready"); + return; + } + err = grpc_error_add_child( + GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->recv_initial_metadata_error)); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); } static void auth_start_transport_stream_op_batch( @@ -198,61 +269,47 @@ static void auth_start_transport_stream_op_batch( batch->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; } + if (batch->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; + } grpc_call_next_op(elem, batch); } /* Constructor for call_data */ static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); - channel_data* chand = static_cast(elem->channel_data); - calld->call_combiner = args->call_combiner; - calld->owning_call = args->call_stack; - GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready, - recv_initial_metadata_ready, elem, - grpc_schedule_on_exec_ctx); - // Create server security context. Set its auth context from channel - // data and save it in the call context. - grpc_server_security_context* server_ctx = - grpc_server_security_context_create(); - server_ctx->auth_context = grpc_auth_context_create(chand->auth_context); - calld->auth_context = server_ctx->auth_context; - if (args->context[GRPC_CONTEXT_SECURITY].value != nullptr) { - args->context[GRPC_CONTEXT_SECURITY].destroy( - args->context[GRPC_CONTEXT_SECURITY].value); - } - args->context[GRPC_CONTEXT_SECURITY].value = server_ctx; - args->context[GRPC_CONTEXT_SECURITY].destroy = - grpc_server_security_context_destroy; + new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, - grpc_closure* ignored) {} + grpc_closure* ignored) { + call_data* calld = static_cast(elem->call_data); + calld->~call_data(); +} /* Constructor for channel_data */ static grpc_error* init_channel_elem(grpc_channel_element* elem, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); - channel_data* chand = static_cast(elem->channel_data); grpc_auth_context* auth_context = grpc_find_auth_context_in_args(args->channel_args); GPR_ASSERT(auth_context != nullptr); - chand->auth_context = - GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter"); grpc_server_credentials* creds = grpc_find_server_credentials_in_args(args->channel_args); - chand->creds = grpc_server_credentials_ref(creds); + new (elem->channel_data) channel_data(auth_context, creds); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_channel_element* elem) { channel_data* chand = static_cast(elem->channel_data); - GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter"); - grpc_server_credentials_unref(chand->creds); + chand->~channel_data(); } const grpc_channel_filter grpc_server_auth_filter = { diff --git a/Sources/CgRPC/src/core/lib/security/util/json_util.cc b/Sources/CgRPC/src/core/lib/security/util/json_util.cc index 75512a19c..fe9f5fe3d 100644 --- a/Sources/CgRPC/src/core/lib/security/util/json_util.cc +++ b/Sources/CgRPC/src/core/lib/security/util/json_util.cc @@ -29,6 +29,10 @@ const char* grpc_json_get_string_property(const grpc_json* json, const char* prop_name) { grpc_json* child; for (child = json->child; child != nullptr; child = child->next) { + if (child->key == nullptr) { + gpr_log(GPR_ERROR, "Invalid (null) JSON key encountered"); + return nullptr; + } if (strcmp(child->key, prop_name) == 0) break; } if (child == nullptr || child->type != GRPC_JSON_STRING) { diff --git a/Sources/CgRPC/src/core/lib/slice/slice.cc b/Sources/CgRPC/src/core/lib/slice/slice.cc index 419474129..e842d84f1 100644 --- a/Sources/CgRPC/src/core/lib/slice/slice.cc +++ b/Sources/CgRPC/src/core/lib/slice/slice.cc @@ -88,6 +88,14 @@ static const grpc_slice_refcount_vtable noop_refcount_vtable = { static grpc_slice_refcount noop_refcount = {&noop_refcount_vtable, &noop_refcount}; +size_t grpc_slice_memory_usage(grpc_slice s) { + if (s.refcount == nullptr || s.refcount == &noop_refcount) { + return 0; + } else { + return s.data.refcounted.length; + } +} + grpc_slice grpc_slice_from_static_buffer(const void* s, size_t len) { grpc_slice slice; slice.refcount = &noop_refcount; diff --git a/Sources/CgRPC/src/core/lib/slice/slice_buffer.cc b/Sources/CgRPC/src/core/lib/slice/slice_buffer.cc index fd5699738..1f1c08b15 100644 --- a/Sources/CgRPC/src/core/lib/slice/slice_buffer.cc +++ b/Sources/CgRPC/src/core/lib/slice/slice_buffer.cc @@ -333,14 +333,26 @@ void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n, size_t slice_len = GRPC_SLICE_LENGTH(slice); if (slice_len > n) { sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n); - grpc_slice_buffer_add_indexed(garbage, slice); + if (garbage) { + grpc_slice_buffer_add_indexed(garbage, slice); + } else { + grpc_slice_unref_internal(slice); + } return; } else if (slice_len == n) { - grpc_slice_buffer_add_indexed(garbage, slice); + if (garbage) { + grpc_slice_buffer_add_indexed(garbage, slice); + } else { + grpc_slice_unref_internal(slice); + } sb->count = idx; return; } else { - grpc_slice_buffer_add_indexed(garbage, slice); + if (garbage) { + grpc_slice_buffer_add_indexed(garbage, slice); + } else { + grpc_slice_unref_internal(slice); + } n -= slice_len; sb->count = idx; } diff --git a/Sources/CgRPC/src/core/lib/slice/slice_internal.h b/Sources/CgRPC/src/core/lib/slice/slice_internal.h index 5d3d26b67..5b0595152 100644 --- a/Sources/CgRPC/src/core/lib/slice/slice_internal.h +++ b/Sources/CgRPC/src/core/lib/slice/slice_internal.h @@ -46,4 +46,9 @@ grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice, uint32_t grpc_static_slice_hash(grpc_slice s); int grpc_static_slice_eq(grpc_slice a, grpc_slice b); +// Returns the memory used by this slice, not counting the slice structure +// itself. This means that inlined and slices from static strings will return +// 0. All other slices will return the size of the allocated chars. +size_t grpc_slice_memory_usage(grpc_slice s); + #endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */ diff --git a/Sources/CgRPC/src/core/lib/surface/call.cc b/Sources/CgRPC/src/core/lib/surface/call.cc index da488034c..d53eb7044 100644 --- a/Sources/CgRPC/src/core/lib/surface/call.cc +++ b/Sources/CgRPC/src/core/lib/surface/call.cc @@ -34,6 +34,7 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/compression/algorithm_metadata.h" #include "src/core/lib/debug/stats.h" +#include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" @@ -47,6 +48,7 @@ #include "src/core/lib/surface/call_test_only.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" #include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/metadata.h" @@ -67,48 +69,14 @@ #define MAX_SEND_EXTRA_METADATA_COUNT 3 -/* Status data for a request can come from several sources; this - enumerates them all, and acts as a priority sorting for which - status to return to the application - earlier entries override - later ones */ -typedef enum { - /* Status came from the application layer overriding whatever - the wire says */ - STATUS_FROM_API_OVERRIDE = 0, - /* Status came from 'the wire' - or somewhere below the surface - layer */ - STATUS_FROM_WIRE, - /* Status was created by some internal channel stack operation: must come via - add_batch_error */ - STATUS_FROM_CORE, - /* Status was created by some surface error */ - STATUS_FROM_SURFACE, - /* Status came from the server sending status */ - STATUS_FROM_SERVER_STATUS, - STATUS_SOURCE_COUNT -} status_source; +// Used to create arena for the first call. +#define ESTIMATED_MDELEM_COUNT 16 -typedef struct { - bool is_set; - grpc_error* error; -} received_status; - -static gpr_atm pack_received_status(received_status r) { - return r.is_set ? (1 | (gpr_atm)r.error) : 0; -} - -static received_status unpack_received_status(gpr_atm atm) { - if ((atm & 1) == 0) { - return {false, GRPC_ERROR_NONE}; - } else { - return {true, (grpc_error*)(atm & ~static_cast(1))}; - } -} - -#define MAX_ERRORS_PER_BATCH 4 +struct batch_control { + batch_control() { gpr_ref_init(&steps_to_complete, 0); } -typedef struct batch_control { - grpc_call* call; + grpc_call* call = nullptr; + grpc_transport_stream_op_batch op; /* Share memory for cq_completion and notify_tag as they are never needed simultaneously. Each byte used in this data structure count as six bytes per call, so any savings we can make are worthwhile, @@ -131,90 +99,110 @@ typedef struct batch_control { grpc_closure start_batch; grpc_closure finish_batch; gpr_refcount steps_to_complete; + gpr_atm batch_error = reinterpret_cast(GRPC_ERROR_NONE); +}; - grpc_error* errors[MAX_ERRORS_PER_BATCH]; - gpr_atm num_errors; - - grpc_transport_stream_op_batch op; -} batch_control; +struct parent_call { + parent_call() { gpr_mu_init(&child_list_mu); } + ~parent_call() { gpr_mu_destroy(&child_list_mu); } -typedef struct { gpr_mu child_list_mu; - grpc_call* first_child; -} parent_call; + grpc_call* first_child = nullptr; +}; -typedef struct { +struct child_call { + child_call(grpc_call* parent) : parent(parent) {} grpc_call* parent; /** siblings: children of the same parent form a list, and this list is protected under parent->mu */ - grpc_call* sibling_next; - grpc_call* sibling_prev; -} child_call; + grpc_call* sibling_next = nullptr; + grpc_call* sibling_prev = nullptr; +}; #define RECV_NONE ((gpr_atm)0) #define RECV_INITIAL_METADATA_FIRST ((gpr_atm)1) struct grpc_call { + grpc_call(gpr_arena* arena, const grpc_call_create_args& args) + : arena(arena), + cq(args.cq), + channel(args.channel), + is_client(args.server_transport_data == nullptr), + stream_op_payload(context) { + gpr_ref_init(&ext_ref, 1); + grpc_call_combiner_init(&call_combiner); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + metadata_batch[i][j].deadline = GRPC_MILLIS_INF_FUTURE; + } + } + } + + ~grpc_call() { + gpr_free(static_cast(const_cast(final_info.error_string))); + grpc_call_combiner_destroy(&call_combiner); + } + gpr_refcount ext_ref; gpr_arena* arena; grpc_call_combiner call_combiner; grpc_completion_queue* cq; grpc_polling_entity pollent; grpc_channel* channel; - gpr_timespec start_time; - /* parent_call* */ gpr_atm parent_call_atm; - child_call* child; + gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC); + /* parent_call* */ gpr_atm parent_call_atm = 0; + child_call* child = nullptr; /* client or server call */ bool is_client; /** has grpc_call_unref been called */ - bool destroy_called; + bool destroy_called = false; /** flag indicating that cancellation is inherited */ - bool cancellation_is_inherited; + bool cancellation_is_inherited = false; /** which ops are in-flight */ - bool sent_initial_metadata; - bool sending_message; - bool sent_final_op; - bool received_initial_metadata; - bool receiving_message; - bool requested_final_op; - gpr_atm any_ops_sent_atm; - gpr_atm received_final_op_atm; - - batch_control* active_batches[MAX_CONCURRENT_BATCHES]; + bool sent_initial_metadata = false; + bool sending_message = false; + bool sent_final_op = false; + bool received_initial_metadata = false; + bool receiving_message = false; + bool requested_final_op = false; + gpr_atm any_ops_sent_atm = 0; + gpr_atm received_final_op_atm = 0; + + batch_control* active_batches[MAX_CONCURRENT_BATCHES] = {}; grpc_transport_stream_op_batch_payload stream_op_payload; /* first idx: is_receiving, second idx: is_trailing */ - grpc_metadata_batch metadata_batch[2][2]; + grpc_metadata_batch metadata_batch[2][2] = {}; /* Buffered read metadata waiting to be returned to the application. Element 0 is initial metadata, element 1 is trailing metadata. */ - grpc_metadata_array* buffered_metadata[2]; + grpc_metadata_array* buffered_metadata[2] = {}; grpc_metadata compression_md; // A char* indicating the peer name. - gpr_atm peer_string; - - /* Packed received call statuses from various sources */ - gpr_atm status[STATUS_SOURCE_COUNT]; + gpr_atm peer_string = 0; /* Call data useful used for reporting. Only valid after the call has * completed */ grpc_call_final_info final_info; /* Compression algorithm for *incoming* data */ - grpc_message_compression_algorithm incoming_message_compression_algorithm; + grpc_message_compression_algorithm incoming_message_compression_algorithm = + GRPC_MESSAGE_COMPRESS_NONE; /* Stream compression algorithm for *incoming* data */ - grpc_stream_compression_algorithm incoming_stream_compression_algorithm; - /* Supported encodings (compression algorithms), a bitset */ - uint32_t encodings_accepted_by_peer; + grpc_stream_compression_algorithm incoming_stream_compression_algorithm = + GRPC_STREAM_COMPRESS_NONE; + /* Supported encodings (compression algorithms), a bitset. + * Always support no compression. */ + uint32_t encodings_accepted_by_peer = 1 << GRPC_MESSAGE_COMPRESS_NONE; /* Supported stream encodings (stream compression algorithms), a bitset */ - uint32_t stream_encodings_accepted_by_peer; + uint32_t stream_encodings_accepted_by_peer = 0; /* Contexts for various subsystems (security, tracing, ...). */ - grpc_call_context_element context[GRPC_CONTEXT_COUNT]; + grpc_call_context_element context[GRPC_CONTEXT_COUNT] = {}; /* for the client, extra metadata is initial metadata; for the server, it's trailing metadata */ @@ -225,12 +213,14 @@ struct grpc_call { grpc_core::ManualConstructor sending_stream; grpc_core::OrphanablePtr receiving_stream; - grpc_byte_buffer** receiving_buffer; - grpc_slice receiving_slice; + grpc_byte_buffer** receiving_buffer = nullptr; + grpc_slice receiving_slice = grpc_empty_slice(); grpc_closure receiving_slice_ready; grpc_closure receiving_stream_ready; grpc_closure receiving_initial_metadata_ready; - uint32_t test_only_last_message_flags; + grpc_closure receiving_trailing_metadata_ready; + uint32_t test_only_last_message_flags = 0; + gpr_atm cancelled = 0; grpc_closure release_call; @@ -242,8 +232,11 @@ struct grpc_call { } client; struct { int* cancelled; + // backpointer to owning server if this is a server side call. + grpc_server* server; } server; } final_op; + gpr_atm status_error = 0; /* recv_state can contain one of the following values: RECV_NONE : : no initial metadata and messages received @@ -261,14 +254,19 @@ struct grpc_call { For 1, 4: See receiving_initial_metadata_ready() function For 2, 3: See receiving_stream_ready() function */ - gpr_atm recv_state; + gpr_atm recv_state = 0; }; grpc_core::TraceFlag grpc_call_error_trace(false, "call_error"); grpc_core::TraceFlag grpc_compression_trace(false, "compression"); -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack*)((call) + 1)) -#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call*)(call_stack)) - 1) +#define CALL_STACK_FROM_CALL(call) \ + (grpc_call_stack*)((char*)(call) + \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call))) +#define CALL_FROM_CALL_STACK(call_stack) \ + (grpc_call*)(((char*)(call_stack)) - \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call))) + #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) #define CALL_FROM_TOP_ELEM(top_elem) \ @@ -276,23 +274,15 @@ grpc_core::TraceFlag grpc_compression_trace(false, "compression"); static void execute_batch(grpc_call* call, grpc_transport_stream_op_batch* op, grpc_closure* start_batch_closure); -static void cancel_with_status(grpc_call* c, status_source source, - grpc_status_code status, + +static void cancel_with_status(grpc_call* c, grpc_status_code status, const char* description); -static void cancel_with_error(grpc_call* c, status_source source, - grpc_error* error); +static void cancel_with_error(grpc_call* c, grpc_error* error); static void destroy_call(void* call_stack, grpc_error* error); static void receiving_slice_ready(void* bctlp, grpc_error* error); -static void get_final_status( - grpc_call* call, void (*set_value)(grpc_status_code code, void* user_data), - void* set_value_user_data, grpc_slice* details, const char** error_string); -static void set_status_value_directly(grpc_status_code status, void* dest); -static void set_status_from_error(grpc_call* call, status_source source, - grpc_error* error); +static void set_final_status(grpc_call* call, grpc_error* error); static void process_data_after_md(batch_control* bctl); static void post_batch_completion(batch_control* bctl); -static void add_batch_error(batch_control* bctl, grpc_error* error, - bool has_cancelled); static void add_init_error(grpc_error** composite, grpc_error* new_err) { if (new_err == GRPC_ERROR_NONE) return; @@ -308,11 +298,10 @@ void* grpc_call_arena_alloc(grpc_call* call, size_t size) { static parent_call* get_or_create_parent_call(grpc_call* call) { parent_call* p = (parent_call*)gpr_atm_acq_load(&call->parent_call_atm); if (p == nullptr) { - p = static_cast(gpr_arena_alloc(call->arena, sizeof(*p))); - gpr_mu_init(&p->child_list_mu); + p = new (gpr_arena_alloc(call->arena, sizeof(*p))) parent_call(); if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm) nullptr, (gpr_atm)p)) { - gpr_mu_destroy(&p->child_list_mu); + p->~parent_call(); p = (parent_call*)gpr_atm_acq_load(&call->parent_call_atm); } } @@ -323,10 +312,17 @@ static parent_call* get_parent_call(grpc_call* call) { return (parent_call*)gpr_atm_acq_load(&call->parent_call_atm); } +size_t grpc_call_get_initial_size_estimate() { + return sizeof(grpc_call) + sizeof(batch_control) * MAX_CONCURRENT_BATCHES + + sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT; +} + grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_call** out_call) { GPR_TIMER_SCOPE("grpc_call_create", 0); - size_t i, j; + + GRPC_CHANNEL_INTERNAL_REF(args->channel, "call"); + grpc_error* error = GRPC_ERROR_NONE; grpc_channel_stack* channel_stack = grpc_channel_get_channel_stack(args->channel); @@ -334,29 +330,19 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, size_t initial_size = grpc_channel_get_call_size_estimate(args->channel); GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size); gpr_arena* arena = gpr_arena_create(initial_size); - call = static_cast(gpr_arena_alloc( - arena, sizeof(grpc_call) + channel_stack->call_stack_size)); - gpr_ref_init(&call->ext_ref, 1); - call->arena = arena; - grpc_call_combiner_init(&call->call_combiner); + call = new (gpr_arena_alloc( + arena, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) + + channel_stack->call_stack_size)) grpc_call(arena, *args); *out_call = call; - call->channel = args->channel; - call->cq = args->cq; - call->start_time = gpr_now(GPR_CLOCK_MONOTONIC); - /* Always support no compression */ - GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_MESSAGE_COMPRESS_NONE); - call->is_client = args->server_transport_data == nullptr; - if (call->is_client) { - GRPC_STATS_INC_CLIENT_CALLS_CREATED(); - } else { - GRPC_STATS_INC_SERVER_CALLS_CREATED(); - } - call->stream_op_payload.context = call->context; grpc_slice path = grpc_empty_slice(); if (call->is_client) { + call->final_op.client.status_details = nullptr; + call->final_op.client.status = nullptr; + call->final_op.client.error_string = nullptr; + GRPC_STATS_INC_CLIENT_CALLS_CREATED(); GPR_ASSERT(args->add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); - for (i = 0; i < args->add_initial_metadata_count; i++) { + for (size_t i = 0; i < args->add_initial_metadata_count; i++) { call->send_extra_metadata[i].md = args->add_initial_metadata[i]; if (grpc_slice_eq(GRPC_MDKEY(args->add_initial_metadata[i]), GRPC_MDSTR_PATH)) { @@ -367,22 +353,19 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->send_extra_metadata_count = static_cast(args->add_initial_metadata_count); } else { + GRPC_STATS_INC_SERVER_CALLS_CREATED(); + call->final_op.server.cancelled = nullptr; + call->final_op.server.server = args->server; GPR_ASSERT(args->add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - call->metadata_batch[i][j].deadline = GRPC_MILLIS_INF_FUTURE; - } - } - grpc_millis send_deadline = args->send_deadline; + grpc_millis send_deadline = args->send_deadline; bool immediately_cancel = false; if (args->parent != nullptr) { - call->child = - static_cast(gpr_arena_alloc(arena, sizeof(child_call))); - call->child->parent = args->parent; + call->child = new (gpr_arena_alloc(arena, sizeof(child_call))) + child_call(args->parent); GRPC_CALL_INTERNAL_REF(args->parent, "child"); GPR_ASSERT(call->is_client); @@ -416,10 +399,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, } } } - call->send_deadline = send_deadline; - - GRPC_CHANNEL_INTERNAL_REF(args->channel, "call"); /* initial refcount dropped by grpc_call_unref */ grpc_call_element_args call_args = {CALL_STACK_FROM_CALL(call), args->server_transport_data, @@ -447,11 +427,12 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, } gpr_mu_unlock(&pc->child_list_mu); } + if (error != GRPC_ERROR_NONE) { - cancel_with_error(call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); + cancel_with_error(call, GRPC_ERROR_REF(error)); } if (immediately_cancel) { - cancel_with_error(call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); + cancel_with_error(call, GRPC_ERROR_CANCELLED); } if (args->cq != nullptr) { GPR_ASSERT(args->pollset_set_alternative == nullptr && @@ -470,6 +451,20 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, &call->pollent); } + if (call->is_client) { + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + channelz_channel->RecordCallStarted(); + } + } else { + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(call->final_op.server.server); + if (channelz_server != nullptr) { + channelz_server->RecordCallStarted(); + } + } + grpc_slice_unref_internal(path); return error; @@ -507,13 +502,12 @@ void grpc_call_internal_unref(grpc_call* c REF_ARG) { static void release_call(void* call, grpc_error* error) { grpc_call* c = static_cast(call); grpc_channel* channel = c->channel; - grpc_call_combiner_destroy(&c->call_combiner); - gpr_free((char*)c->peer_string); - grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena)); + gpr_arena* arena = c->arena; + c->~grpc_call(); + grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(arena)); GRPC_CHANNEL_INTERNAL_UNREF(channel, "call"); } -static void set_status_value_directly(grpc_status_code status, void* dest); static void destroy_call(void* call, grpc_error* error) { GPR_TIMER_SCOPE("destroy_call", 0); size_t i; @@ -526,7 +520,7 @@ static void destroy_call(void* call, grpc_error* error) { c->receiving_stream.reset(); parent_call* pc = get_parent_call(c); if (pc != nullptr) { - gpr_mu_destroy(&pc->child_list_mu); + pc->~parent_call(); } for (ii = 0; ii < c->send_extra_metadata_count; ii++) { GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md); @@ -540,16 +534,15 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - get_final_status(c, set_status_value_directly, &c->final_info.final_status, - nullptr, c->final_info.error_string); + grpc_error* status_error = + reinterpret_cast(gpr_atm_acq_load(&c->status_error)); + grpc_error_get_status(status_error, c->send_deadline, + &c->final_info.final_status, nullptr, nullptr, + &(c->final_info.error_string)); + GRPC_ERROR_UNREF(status_error); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - GRPC_ERROR_UNREF( - unpack_received_status(gpr_atm_acq_load(&c->status[i])).error); - } - grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c), &c->final_info, GRPC_CLOSURE_INIT(&c->release_call, release_call, c, grpc_schedule_on_exec_ctx)); @@ -563,6 +556,7 @@ void grpc_call_unref(grpc_call* c) { GPR_TIMER_SCOPE("grpc_call_unref", 0); child_call* cc = c->child; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c)); @@ -587,13 +581,16 @@ void grpc_call_unref(grpc_call* c) { bool cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) != 0 && gpr_atm_acq_load(&c->received_final_op_atm) == 0; if (cancel) { - cancel_with_error(c, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); + cancel_with_error(c, GRPC_ERROR_CANCELLED); } else { // Unset the call combiner cancellation closure. This has the // effect of scheduling the previously set cancellation closure, if // any, so that it can release any internal references it may be - // holding to the call stack. + // holding to the call stack. Also flush the closures on exec_ctx so that + // filters that schedule cancel notification closures on exec_ctx do not + // need to take a ref of the call stack to guarantee closure liveness. grpc_call_combiner_set_notify_on_cancel(&c->call_combiner, nullptr); + grpc_core::ExecCtx::Get()->Flush(); } GRPC_CALL_INTERNAL_UNREF(c, "destroy"); } @@ -601,9 +598,9 @@ void grpc_call_unref(grpc_call* c) { grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved) { GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved)); GPR_ASSERT(!reserved); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - cancel_with_error(call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); - + cancel_with_error(call, GRPC_ERROR_CANCELLED); return GRPC_CALL_OK; } @@ -651,14 +648,14 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call* c, grpc_status_code status, const char* description, void* reserved) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE( "grpc_call_cancel_with_status(" "c=%p, status=%d, description=%s, reserved=%p)", 4, (c, (int)status, description, reserved)); GPR_ASSERT(reserved == nullptr); - cancel_with_status(c, STATUS_FROM_API_OVERRIDE, status, description); - + cancel_with_status(c, status, description); return GRPC_CALL_OK; } @@ -678,15 +675,17 @@ static void done_termination(void* arg, grpc_error* error) { gpr_free(state); } -static void cancel_with_error(grpc_call* c, status_source source, - grpc_error* error) { +static void cancel_with_error(grpc_call* c, grpc_error* error) { + if (!gpr_atm_rel_cas(&c->cancelled, 0, 1)) { + GRPC_ERROR_UNREF(error); + return; + } GRPC_CALL_INTERNAL_REF(c, "termination"); // Inform the call combiner of the cancellation, so that it can cancel // any in-flight asynchronous actions that may be holding the call // combiner. This ensures that the cancel_stream batch can be sent // down the filter stack in a timely manner. grpc_call_combiner_cancel(&c->call_combiner, GRPC_ERROR_REF(error)); - set_status_from_error(c, source, GRPC_ERROR_REF(error)); cancel_state* state = static_cast(gpr_malloc(sizeof(*state))); state->call = c; GRPC_CLOSURE_INIT(&state->finish_batch, done_termination, state, @@ -698,6 +697,10 @@ static void cancel_with_error(grpc_call* c, status_source source, execute_batch(c, op, &state->start_batch); } +void grpc_call_cancel_internal(grpc_call* call) { + cancel_with_error(call, GRPC_ERROR_CANCELLED); +} + static grpc_error* error_from_status(grpc_status_code status, const char* description) { // copying 'description' is needed to ensure the grpc_call_cancel_with_status @@ -709,90 +712,47 @@ static grpc_error* error_from_status(grpc_status_code status, GRPC_ERROR_INT_GRPC_STATUS, status); } -static void cancel_with_status(grpc_call* c, status_source source, - grpc_status_code status, +static void cancel_with_status(grpc_call* c, grpc_status_code status, const char* description) { - cancel_with_error(c, source, error_from_status(status, description)); + cancel_with_error(c, error_from_status(status, description)); } -/******************************************************************************* - * FINAL STATUS CODE MANIPULATION - */ - -static bool get_final_status_from( - grpc_call* call, grpc_error* error, bool allow_ok_status, - void (*set_value)(grpc_status_code code, void* user_data), - void* set_value_user_data, grpc_slice* details, const char** error_string) { - grpc_status_code code; - grpc_slice slice = grpc_empty_slice(); - grpc_error_get_status(error, call->send_deadline, &code, &slice, nullptr, - error_string); - if (code == GRPC_STATUS_OK && !allow_ok_status) { - return false; - } - - set_value(code, set_value_user_data); - if (details != nullptr) { - *details = grpc_slice_ref_internal(slice); - } - return true; -} - -static void get_final_status( - grpc_call* call, void (*set_value)(grpc_status_code code, void* user_data), - void* set_value_user_data, grpc_slice* details, const char** error_string) { - int i; - received_status status[STATUS_SOURCE_COUNT]; - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i])); - } +static void set_final_status(grpc_call* call, grpc_error* error) { if (grpc_call_error_trace.enabled()) { - gpr_log(GPR_INFO, "get_final_status %s", call->is_client ? "CLI" : "SVR"); - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (status[i].is_set) { - gpr_log(GPR_INFO, " %d: %s", i, grpc_error_string(status[i].error)); - } - } + gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); + gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } - /* first search through ignoring "OK" statuses: if something went wrong, - * ensure we report it */ - for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) { - /* search for the best status we can present: ideally the error we use has a - clearly defined grpc-status, and we'll prefer that. */ - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (status[i].is_set && - grpc_error_has_clear_grpc_status(status[i].error)) { - if (get_final_status_from(call, status[i].error, allow_ok_status != 0, - set_value, set_value_user_data, details, - error_string)) { - return; - } + if (call->is_client) { + grpc_error_get_status(error, call->send_deadline, + call->final_op.client.status, + call->final_op.client.status_details, nullptr, + call->final_op.client.error_string); + // explicitly take a ref + grpc_slice_ref_internal(*call->final_op.client.status_details); + gpr_atm_rel_store(&call->status_error, reinterpret_cast(error)); + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); } } - /* If no clearly defined status exists, search for 'anything' */ - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (status[i].is_set) { - if (get_final_status_from(call, status[i].error, allow_ok_status != 0, - set_value, set_value_user_data, details, - error_string)) { - return; - } + } else { + *call->final_op.server.cancelled = + error != GRPC_ERROR_NONE || + reinterpret_cast(gpr_atm_acq_load(&call->status_error)) != + GRPC_ERROR_NONE; + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(call->final_op.server.server); + if (channelz_server != nullptr) { + if (*call->final_op.server.cancelled) { + channelz_server->RecordCallFailed(); + } else { + channelz_server->RecordCallSucceeded(); } } - } - /* If nothing exists, set some default */ - if (call->is_client) { - set_value(GRPC_STATUS_UNKNOWN, set_value_user_data); - } else { - set_value(GRPC_STATUS_OK, set_value_user_data); - } -} - -static void set_status_from_error(grpc_call* call, status_source source, - grpc_error* error) { - if (!gpr_atm_rel_cas(&call->status[source], - pack_received_status({false, GRPC_ERROR_NONE}), - pack_received_status({true, error}))) { GRPC_ERROR_UNREF(error); } } @@ -1011,6 +971,7 @@ static grpc_stream_compression_algorithm decode_stream_compression( static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b, int is_trailing) { if (b->list.count == 0) return; + if (!call->is_client && is_trailing) return; if (is_trailing && call->buffered_metadata[1] == nullptr) return; GPR_TIMER_SCOPE("publish_app_metadata", 0); grpc_metadata_array* dest; @@ -1064,18 +1025,20 @@ static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) { publish_app_metadata(call, b, false); } -static void recv_trailing_filter(void* args, grpc_metadata_batch* b) { +static void recv_trailing_filter(void* args, grpc_metadata_batch* b, + grpc_error* batch_error) { grpc_call* call = static_cast(args); - if (b->idx.named.grpc_status != nullptr) { + if (batch_error != GRPC_ERROR_NONE) { + set_final_status(call, batch_error); + } else if (b->idx.named.grpc_status != nullptr) { grpc_status_code status_code = grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md); - grpc_error* error = - status_code == GRPC_STATUS_OK - ? GRPC_ERROR_NONE - : grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Error received from peer"), - GRPC_ERROR_INT_GRPC_STATUS, - static_cast(status_code)); + grpc_error* error = GRPC_ERROR_NONE; + if (status_code != GRPC_STATUS_OK) { + error = grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error received from peer"), + GRPC_ERROR_INT_GRPC_STATUS, static_cast(status_code)); + } if (b->idx.named.grpc_message != nullptr) { error = grpc_error_set_str( error, GRPC_ERROR_STR_GRPC_MESSAGE, @@ -1085,12 +1048,24 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b) { error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_empty_slice()); } - set_status_from_error(call, STATUS_FROM_WIRE, error); + set_final_status(call, GRPC_ERROR_REF(error)); grpc_metadata_batch_remove(b, b->idx.named.grpc_status); + GRPC_ERROR_UNREF(error); + } else if (!call->is_client) { + set_final_status(call, GRPC_ERROR_NONE); + } else { + gpr_log(GPR_DEBUG, + "Received trailing metadata with no error and no status"); + set_final_status( + call, grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No status received"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNKNOWN)); } publish_app_metadata(call, b, true); } +gpr_arena* grpc_call_get_arena(grpc_call* call) { return call->arena; } + grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) { return CALL_STACK_FROM_CALL(call); } @@ -1099,14 +1074,6 @@ grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) { * BATCH API IMPLEMENTATION */ -static void set_status_value_directly(grpc_status_code status, void* dest) { - *static_cast(dest) = status; -} - -static void set_cancelled_value(grpc_status_code status, void* dest) { - *static_cast(dest) = (status != GRPC_STATUS_OK); -} - static bool are_write_flags_valid(uint32_t flags) { /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */ const uint32_t allowed_write_positions = @@ -1124,7 +1091,7 @@ static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) { return !(flags & invalid_positions); } -static int batch_slot_for_op(grpc_op_type type) { +static size_t batch_slot_for_op(grpc_op_type type) { switch (type) { case GRPC_OP_SEND_INITIAL_METADATA: return 0; @@ -1144,20 +1111,24 @@ static int batch_slot_for_op(grpc_op_type type) { GPR_UNREACHABLE_CODE(return 123456789); } -static batch_control* allocate_batch_control(grpc_call* call, - const grpc_op* ops, - size_t num_ops) { - int slot = batch_slot_for_op(ops[0].op); - batch_control** pslot = &call->active_batches[slot]; - if (*pslot == nullptr) { - *pslot = static_cast( - gpr_arena_alloc(call->arena, sizeof(batch_control))); - } - batch_control* bctl = *pslot; - if (bctl->call != nullptr) { - return nullptr; +static batch_control* reuse_or_allocate_batch_control(grpc_call* call, + const grpc_op* ops, + size_t num_ops) { + size_t slot_idx = batch_slot_for_op(ops[0].op); + batch_control** pslot = &call->active_batches[slot_idx]; + batch_control* bctl; + if (*pslot != nullptr) { + bctl = *pslot; + if (bctl->call != nullptr) { + return nullptr; + } + bctl->~batch_control(); + bctl->op = {}; + } else { + bctl = new (gpr_arena_alloc(call->arena, sizeof(batch_control))) + batch_control(); + *pslot = bctl; } - memset(bctl, 0, sizeof(*bctl)); bctl->call = call; bctl->op.payload = &call->stream_op_payload; return bctl; @@ -1171,35 +1142,21 @@ static void finish_batch_completion(void* user_data, GRPC_CALL_INTERNAL_UNREF(call, "completion"); } -static grpc_error* consolidate_batch_errors(batch_control* bctl) { - size_t n = static_cast(gpr_atm_acq_load(&bctl->num_errors)); - if (n == 0) { - return GRPC_ERROR_NONE; - } else if (n == 1) { - /* Skip creating a composite error in the case that only one error was - logged */ - grpc_error* e = bctl->errors[0]; - bctl->errors[0] = nullptr; - return e; - } else { - grpc_error* error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Call batch failed", bctl->errors, n); - for (size_t i = 0; i < n; i++) { - GRPC_ERROR_UNREF(bctl->errors[i]); - bctl->errors[i] = nullptr; - } - return error; - } +static void reset_batch_errors(batch_control* bctl) { + GRPC_ERROR_UNREF( + reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_NONE)); } static void post_batch_completion(batch_control* bctl) { grpc_call* next_child_call; grpc_call* call = bctl->call; - grpc_error* error = consolidate_batch_errors(bctl); + grpc_error* error = GRPC_ERROR_REF( + reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); if (bctl->op.send_initial_metadata) { grpc_metadata_batch_destroy( - &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]); } if (bctl->op.send_message) { @@ -1207,14 +1164,9 @@ static void post_batch_completion(batch_control* bctl) { } if (bctl->op.send_trailing_metadata) { grpc_metadata_batch_destroy( - &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]); } if (bctl->op.recv_trailing_metadata) { - grpc_metadata_batch* md = - &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - recv_trailing_filter(call, md); - /* propagate cancellation to any interested children */ gpr_atm_rel_store(&call->received_final_op_atm, 1); parent_call* pc = get_parent_call(call); @@ -1227,8 +1179,7 @@ static void post_batch_completion(batch_control* bctl) { next_child_call = child->child->sibling_next; if (child->cancellation_is_inherited) { GRPC_CALL_INTERNAL_REF(child, "propagate_cancel"); - cancel_with_error(child, STATUS_FROM_API_OVERRIDE, - GRPC_ERROR_CANCELLED); + cancel_with_error(child, GRPC_ERROR_CANCELLED); GRPC_CALL_INTERNAL_UNREF(child, "propagate_cancel"); } child = next_child_call; @@ -1236,17 +1187,6 @@ static void post_batch_completion(batch_control* bctl) { } gpr_mu_unlock(&pc->child_list_mu); } - - if (call->is_client) { - get_final_status(call, set_status_value_directly, - call->final_op.client.status, - call->final_op.client.status_details, - call->final_op.client.error_string); - } else { - get_final_status(call, set_cancelled_value, - call->final_op.server.cancelled, nullptr, nullptr); - } - GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } @@ -1255,15 +1195,20 @@ static void post_batch_completion(batch_control* bctl) { grpc_byte_buffer_destroy(*call->receiving_buffer); *call->receiving_buffer = nullptr; } + reset_batch_errors(bctl); if (bctl->completion_data.notify_tag.is_closure) { - /* unrefs bctl->error */ + /* unrefs error */ bctl->call = nullptr; - GRPC_CLOSURE_RUN((grpc_closure*)bctl->completion_data.notify_tag.tag, - error); + /* This closure may be meant to be run within some combiner. Since we aren't + * running in any combiner here, we need to use GRPC_CLOSURE_SCHED instead + * of GRPC_CLOSURE_RUN. + */ + GRPC_CLOSURE_SCHED((grpc_closure*)bctl->completion_data.notify_tag.tag, + error); GRPC_CALL_INTERNAL_UNREF(call, "completion"); } else { - /* unrefs bctl->error */ + /* unrefs error */ grpc_cq_end_op(bctl->call->cq, bctl->completion_data.notify_tag.tag, error, finish_batch_completion, bctl, &bctl->completion_data.cq_completion); @@ -1372,8 +1317,12 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { grpc_call* call = bctl->call; if (error != GRPC_ERROR_NONE) { call->receiving_stream.reset(); - add_batch_error(bctl, GRPC_ERROR_REF(error), true); - cancel_with_error(call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); + } + cancel_with_error(call, GRPC_ERROR_REF(error)); } /* If recv_state is RECV_NONE, we will save the batch_control * object with rel_cas, and will not use it after the cas. Its corresponding @@ -1409,8 +1358,7 @@ static void validate_filtered_metadata(batch_control* bctl) { call->incoming_stream_compression_algorithm, call->incoming_message_compression_algorithm); gpr_log(GPR_ERROR, "%s", error_msg); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_INTERNAL, - error_msg); + cancel_with_status(call, GRPC_STATUS_INTERNAL, error_msg); gpr_free(error_msg); } else if ( grpc_compression_algorithm_from_message_stream_compression_algorithm( @@ -1422,8 +1370,7 @@ static void validate_filtered_metadata(batch_control* bctl) { "compression (%d).", call->incoming_stream_compression_algorithm, call->incoming_message_compression_algorithm); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_INTERNAL, - error_msg); + cancel_with_status(call, GRPC_STATUS_INTERNAL, error_msg); gpr_free(error_msg); } else { char* error_msg = nullptr; @@ -1433,8 +1380,7 @@ static void validate_filtered_metadata(batch_control* bctl) { gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.", compression_algorithm); gpr_log(GPR_ERROR, "%s", error_msg); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED, - error_msg); + cancel_with_status(call, GRPC_STATUS_UNIMPLEMENTED, error_msg); } else if (grpc_compression_options_is_algorithm_enabled( &compression_options, compression_algorithm) == 0) { /* check if algorithm is supported by current channel config */ @@ -1443,8 +1389,7 @@ static void validate_filtered_metadata(batch_control* bctl) { gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.", algo_name); gpr_log(GPR_ERROR, "%s", error_msg); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED, - error_msg); + cancel_with_status(call, GRPC_STATUS_UNIMPLEMENTED, error_msg); } gpr_free(error_msg); @@ -1462,23 +1407,12 @@ static void validate_filtered_metadata(batch_control* bctl) { } } -static void add_batch_error(batch_control* bctl, grpc_error* error, - bool has_cancelled) { - if (error == GRPC_ERROR_NONE) return; - int idx = static_cast(gpr_atm_full_fetch_add(&bctl->num_errors, 1)); - if (idx == 0 && !has_cancelled) { - cancel_with_error(bctl->call, STATUS_FROM_CORE, GRPC_ERROR_REF(error)); - } - bctl->errors[idx] = error; -} - static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready"); - add_batch_error(bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; @@ -1491,6 +1425,13 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { if (md->deadline != GRPC_MILLIS_INF_FUTURE && !call->is_client) { call->send_deadline = md->deadline; } + } else { + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); + } + cancel_with_error(call, GRPC_ERROR_REF(error)); } grpc_closure* saved_rsr_closure = nullptr; @@ -1524,11 +1465,28 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { finish_batch_step(bctl); } +static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { + batch_control* bctl = static_cast(bctlp); + grpc_call* call = bctl->call; + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); + grpc_metadata_batch* md = + &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; + recv_trailing_filter(call, md, GRPC_ERROR_REF(error)); + finish_batch_step(bctl); +} + static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - add_batch_error(bctl, GRPC_ERROR_REF(error), false); + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); + } + if (error != GRPC_ERROR_NONE) { + cancel_with_error(call, GRPC_ERROR_REF(error)); + } finish_batch_step(bctl); } @@ -1544,7 +1502,8 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, size_t i; const grpc_op* op; batch_control* bctl; - int num_completion_callbacks_needed = 1; + bool has_send_ops = false; + int num_recv_ops = 0; grpc_call_error error = GRPC_CALL_OK; grpc_transport_stream_op_batch* stream_op; grpc_transport_stream_op_batch_payload* stream_op_payload; @@ -1565,7 +1524,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, goto done; } - bctl = allocate_batch_control(call, ops, nops); + bctl = reuse_or_allocate_batch_control(call, ops, nops); if (bctl == nullptr) { return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; } @@ -1650,6 +1609,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, stream_op_payload->send_initial_metadata.peer_string = &call->peer_string; } + has_send_ops = true; break; } case GRPC_OP_SEND_MESSAGE: { @@ -1679,6 +1639,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, &op->data.send_message.send_message->data.raw.slice_buffer, flags); stream_op_payload->send_message.send_message.reset( call->sending_stream.get()); + has_send_ops = true; break; } case GRPC_OP_SEND_CLOSE_FROM_CLIENT: { @@ -1699,6 +1660,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->sent_final_op = true; stream_op_payload->send_trailing_metadata.send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; + has_send_ops = true; break; } case GRPC_OP_SEND_STATUS_FROM_SERVER: { @@ -1726,28 +1688,33 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->send_extra_metadata_count = 1; call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem( call->channel, op->data.send_status_from_server.status); - { - grpc_error* override_error = GRPC_ERROR_NONE; - if (op->data.send_status_from_server.status != GRPC_STATUS_OK) { - override_error = - error_from_status(op->data.send_status_from_server.status, - "Returned non-ok status"); - } - if (op->data.send_status_from_server.status_details != nullptr) { - call->send_extra_metadata[1].md = grpc_mdelem_from_slices( - GRPC_MDSTR_GRPC_MESSAGE, - grpc_slice_ref_internal( - *op->data.send_status_from_server.status_details)); - call->send_extra_metadata_count++; + grpc_error* status_error = + op->data.send_status_from_server.status == GRPC_STATUS_OK + ? GRPC_ERROR_NONE + : grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Server returned error"), + GRPC_ERROR_INT_GRPC_STATUS, + static_cast( + op->data.send_status_from_server.status)); + if (op->data.send_status_from_server.status_details != nullptr) { + call->send_extra_metadata[1].md = grpc_mdelem_from_slices( + GRPC_MDSTR_GRPC_MESSAGE, + grpc_slice_ref_internal( + *op->data.send_status_from_server.status_details)); + call->send_extra_metadata_count++; + if (status_error != GRPC_ERROR_NONE) { char* msg = grpc_slice_to_c_string( GRPC_MDVALUE(call->send_extra_metadata[1].md)); - override_error = - grpc_error_set_str(override_error, GRPC_ERROR_STR_GRPC_MESSAGE, + status_error = + grpc_error_set_str(status_error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(msg)); gpr_free(msg); } - set_status_from_error(call, STATUS_FROM_API_OVERRIDE, override_error); } + + gpr_atm_rel_store(&call->status_error, + reinterpret_cast(status_error)); if (!prepare_application_metadata( call, static_cast( @@ -1763,6 +1730,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, } stream_op_payload->send_trailing_metadata.send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; + has_send_ops = true; break; } case GRPC_OP_RECV_INITIAL_METADATA: { @@ -1790,7 +1758,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, stream_op_payload->recv_initial_metadata.peer_string = &call->peer_string; } - num_completion_callbacks_needed++; + ++num_recv_ops; break; } case GRPC_OP_RECV_MESSAGE: { @@ -1812,7 +1780,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, grpc_schedule_on_exec_ctx); stream_op_payload->recv_message.recv_message_ready = &call->receiving_stream_ready; - num_completion_callbacks_needed++; + ++num_recv_ops; break; } case GRPC_OP_RECV_STATUS_ON_CLIENT: { @@ -1838,11 +1806,16 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->final_op.client.error_string = op->data.recv_status_on_client.error_string; stream_op->recv_trailing_metadata = true; - stream_op->collect_stats = true; stream_op_payload->recv_trailing_metadata.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op_payload->collect_stats.collect_stats = + stream_op_payload->recv_trailing_metadata.collect_stats = &call->final_info.stats.transport_stream_stats; + GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready, + receiving_trailing_metadata_ready, bctl, + grpc_schedule_on_exec_ctx); + stream_op_payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &call->receiving_trailing_metadata_ready; + ++num_recv_ops; break; } case GRPC_OP_RECV_CLOSE_ON_SERVER: { @@ -1863,11 +1836,16 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->final_op.server.cancelled = op->data.recv_close_on_server.cancelled; stream_op->recv_trailing_metadata = true; - stream_op->collect_stats = true; stream_op_payload->recv_trailing_metadata.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op_payload->collect_stats.collect_stats = + stream_op_payload->recv_trailing_metadata.collect_stats = &call->final_info.stats.transport_stream_stats; + GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready, + receiving_trailing_metadata_ready, bctl, + grpc_schedule_on_exec_ctx); + stream_op_payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &call->receiving_trailing_metadata_ready; + ++num_recv_ops; break; } } @@ -1877,20 +1855,22 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, if (!is_notify_tag_closure) { GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag)); } - gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed); + gpr_ref_init(&bctl->steps_to_complete, (has_send_ops ? 1 : 0) + num_recv_ops); - GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl, - grpc_schedule_on_exec_ctx); - stream_op->on_complete = &bctl->finish_batch; - gpr_atm_rel_store(&call->any_ops_sent_atm, 1); + if (has_send_ops) { + GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl, + grpc_schedule_on_exec_ctx); + stream_op->on_complete = &bctl->finish_batch; + } + gpr_atm_rel_store(&call->any_ops_sent_atm, 1); execute_batch(call, stream_op, &bctl->start_batch); done: return error; done_with_error: - /* reverse any mutations that occured */ + /* reverse any mutations that occurred */ if (stream_op->send_initial_metadata) { call->sent_initial_metadata = false; grpc_metadata_batch_clear(&call->metadata_batch[0][0]); @@ -1917,7 +1897,6 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops, size_t nops, void* tag, void* reserved) { - grpc_core::ExecCtx exec_ctx; grpc_call_error err; GRPC_API_TRACE( @@ -1928,6 +1907,8 @@ grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops, if (reserved != nullptr) { err = GRPC_CALL_ERROR; } else { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; err = call_start_batch(call, ops, nops, tag, 0); } diff --git a/Sources/CgRPC/src/core/lib/surface/call.h b/Sources/CgRPC/src/core/lib/surface/call.h index 793cce4ef..bd7295fe1 100644 --- a/Sources/CgRPC/src/core/lib/surface/call.h +++ b/Sources/CgRPC/src/core/lib/surface/call.h @@ -33,6 +33,7 @@ typedef void (*grpc_ioreq_completion_func)(grpc_call* call, int success, typedef struct grpc_call_create_args { grpc_channel* channel; + grpc_server* server; grpc_call* parent; uint32_t propagation_mask; @@ -71,6 +72,8 @@ void grpc_call_internal_unref(grpc_call* call); #define GRPC_CALL_INTERNAL_UNREF(call, reason) grpc_call_internal_unref(call) #endif +gpr_arena* grpc_call_get_arena(grpc_call* call); + grpc_call_stack* grpc_call_get_call_stack(grpc_call* call); grpc_call_error grpc_call_start_batch_and_execute(grpc_call* call, @@ -78,6 +81,10 @@ grpc_call_error grpc_call_start_batch_and_execute(grpc_call* call, size_t nops, grpc_closure* closure); +/* gRPC core internal version of grpc_call_cancel that does not create + * exec_ctx. */ +void grpc_call_cancel_internal(grpc_call* call); + /* Given the top call_element, get the call object. */ grpc_call* grpc_call_from_top_element(grpc_call_element* surface_element); @@ -98,6 +105,11 @@ void* grpc_call_context_get(grpc_call* call, grpc_context_index elem); uint8_t grpc_call_is_client(grpc_call* call); +/* Get the estimated memory size for a call BESIDES the call stack. Combined + * with the size of the call stack, it helps estimate the arena size for the + * initial call. */ +size_t grpc_call_get_initial_size_estimate(); + /* Return an appropriate compression algorithm for the requested compression \a * level in the context of \a call. */ grpc_compression_algorithm grpc_call_compression_for_level( diff --git a/Sources/CgRPC/src/core/lib/surface/channel.cc b/Sources/CgRPC/src/core/lib/surface/channel.cc index d740ebd41..e47cb4360 100644 --- a/Sources/CgRPC/src/core/lib/surface/channel.cc +++ b/Sources/CgRPC/src/core/lib/surface/channel.cc @@ -32,12 +32,14 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" @@ -62,20 +64,17 @@ struct grpc_channel { grpc_compression_options compression_options; gpr_atm call_size_estimate; + grpc_resource_user* resource_user; gpr_mu registered_call_mu; registered_call* registered_calls; - grpc_core::RefCountedPtr tracer; + grpc_core::RefCountedPtr channelz_channel; char* target; }; #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack*)((c) + 1)) -#define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \ - (((grpc_channel*)(channel_stack)) - 1) -#define CHANNEL_FROM_TOP_ELEM(top_elem) \ - CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem)) static void destroy_channel(void* arg, grpc_error* error); @@ -85,6 +84,8 @@ grpc_channel* grpc_channel_create_with_builder( char* target = gpr_strdup(grpc_channel_stack_builder_get_target(builder)); grpc_channel_args* args = grpc_channel_args_copy( grpc_channel_stack_builder_get_channel_arguments(builder)); + grpc_resource_user* resource_user = + grpc_channel_stack_builder_get_resource_user(builder); grpc_channel* channel; if (channel_stack_type == GRPC_SERVER_CHANNEL) { GRPC_STATS_INC_SERVER_CHANNELS_CREATED(); @@ -103,16 +104,24 @@ grpc_channel* grpc_channel_create_with_builder( return channel; } - memset(channel, 0, sizeof(*channel)); channel->target = target; + channel->resource_user = resource_user; channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); - size_t channel_tracer_max_nodes = 0; // default to off + bool channelz_enabled = GRPC_ENABLE_CHANNELZ_DEFAULT; + size_t channel_tracer_max_memory = + GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT; + bool internal_channel = false; + // this creates the default ChannelNode. Different types of channels may + // override this to ensure a correct ChannelNode is created. + grpc_core::channelz::ChannelNodeCreationFunc channel_node_create_func = + grpc_core::channelz::ChannelNode::MakeChannelNode; gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = nullptr; gpr_atm_no_barrier_store( &channel->call_size_estimate, - (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size); + (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size + + grpc_call_get_initial_size_estimate()); grpc_compression_options_init(&channel->compression_options); for (size_t i = 0; i < args->num_args; i++) { @@ -138,21 +147,39 @@ grpc_channel* grpc_channel_create_with_builder( static_cast(args->args[i].value.integer) | 0x1; /* always support no compression */ } else if (0 == strcmp(args->args[i].key, - GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE)) { - GPR_ASSERT(channel_tracer_max_nodes == 0); - // max_nodes defaults to 0 (which is off), clamped between 0 and INT_MAX - const grpc_integer_options options = {0, 0, INT_MAX}; - channel_tracer_max_nodes = + GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE)) { + const grpc_integer_options options = { + GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX}; + channel_tracer_max_memory = (size_t)grpc_channel_arg_get_integer(&args->args[i], options); + } else if (0 == strcmp(args->args[i].key, GRPC_ARG_ENABLE_CHANNELZ)) { + // channelz will not be enabled by default until all concerns in + // https://github.com/grpc/grpc/issues/15986 are addressed. + channelz_enabled = grpc_channel_arg_get_bool( + &args->args[i], GRPC_ENABLE_CHANNELZ_DEFAULT); + } else if (0 == strcmp(args->args[i].key, + GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC)) { + GPR_ASSERT(args->args[i].type == GRPC_ARG_POINTER); + GPR_ASSERT(args->args[i].value.pointer.p != nullptr); + channel_node_create_func = + reinterpret_cast( + args->args[i].value.pointer.p); + } else if (0 == strcmp(args->args[i].key, + GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL)) { + internal_channel = grpc_channel_arg_get_bool(&args->args[i], false); } } grpc_channel_args_destroy(args); - channel->tracer = grpc_core::MakeRefCounted( - channel_tracer_max_nodes); - channel->tracer->AddTraceEvent( - grpc_core::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("Channel created")); + // we only need to do the channelz bookkeeping for clients here. The channelz + // bookkeeping for server channels occurs in src/core/lib/surface/server.cc + if (channelz_enabled && channel->is_client) { + channel->channelz_channel = channel_node_create_func( + channel, channel_tracer_max_memory, !internal_channel); + channel->channelz_channel->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Channel created")); + } return channel; } @@ -187,18 +214,16 @@ static grpc_channel_args* build_channel_args( return grpc_channel_args_copy_and_add(input_args, new_args, num_new_args); } -char* grpc_channel_get_trace(grpc_channel* channel) { - return channel->tracer->RenderTrace(); -} - -intptr_t grpc_channel_get_uuid(grpc_channel* channel) { - return channel->tracer->GetUuid(); +grpc_core::channelz::ChannelNode* grpc_channel_get_channelz_node( + grpc_channel* channel) { + return channel->channelz_channel.get(); } grpc_channel* grpc_channel_create(const char* target, const grpc_channel_args* input_args, grpc_channel_stack_type channel_stack_type, - grpc_transport* optional_transport) { + grpc_transport* optional_transport, + grpc_resource_user* resource_user) { grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); const grpc_core::UniquePtr default_authority = get_default_authority(input_args); @@ -208,11 +233,17 @@ grpc_channel* grpc_channel_create(const char* target, grpc_channel_args_destroy(args); grpc_channel_stack_builder_set_target(builder, target); grpc_channel_stack_builder_set_transport(builder, optional_transport); + grpc_channel_stack_builder_set_resource_user(builder, resource_user); if (!grpc_channel_init_create_stack(builder, channel_stack_type)) { grpc_channel_stack_builder_destroy(builder); + if (resource_user != nullptr) { + grpc_resource_user_free(resource_user, GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); + } return nullptr; } - return grpc_channel_create_with_builder(builder, channel_stack_type); + grpc_channel* channel = + grpc_channel_create_with_builder(builder, channel_stack_type); + return channel; } size_t grpc_channel_get_call_size_estimate(grpc_channel* channel) { @@ -263,6 +294,17 @@ void grpc_channel_get_info(grpc_channel* channel, elem->filter->get_channel_info(elem, channel_info); } +void grpc_channel_reset_connect_backoff(grpc_channel* channel) { + grpc_core::ExecCtx exec_ctx; + GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1, + (channel)); + grpc_transport_op* op = grpc_make_transport_op(nullptr); + op->reset_connect_backoff = true; + grpc_channel_element* elem = + grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); + elem->filter->start_transport_op(elem, op); +} + static grpc_call* grpc_channel_create_call_internal( grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative, @@ -280,8 +322,8 @@ static grpc_call* grpc_channel_create_call_internal( } grpc_call_create_args args; - memset(&args, 0, sizeof(args)); args.channel = channel; + args.server = nullptr; args.parent = parent_call; args.propagation_mask = propagation_mask; args.cq = cq; @@ -306,9 +348,8 @@ grpc_call* grpc_channel_create_call(grpc_channel* channel, grpc_core::ExecCtx exec_ctx; grpc_call* call = grpc_channel_create_call_internal( channel, parent_call, propagation_mask, cq, nullptr, - grpc_mdelem_from_slices(GRPC_MDSTR_PATH, grpc_slice_ref_internal(method)), - host != nullptr ? grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY, - grpc_slice_ref_internal(*host)) + grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr), + host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr) : GRPC_MDNULL, grpc_timespec_to_millis_round_up(deadline)); @@ -317,14 +358,13 @@ grpc_call* grpc_channel_create_call(grpc_channel* channel, grpc_call* grpc_channel_create_pollset_set_call( grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, - grpc_pollset_set* pollset_set, grpc_slice method, const grpc_slice* host, - grpc_millis deadline, void* reserved) { + grpc_pollset_set* pollset_set, const grpc_slice& method, + const grpc_slice* host, grpc_millis deadline, void* reserved) { GPR_ASSERT(!reserved); return grpc_channel_create_call_internal( channel, parent_call, propagation_mask, nullptr, pollset_set, - grpc_mdelem_from_slices(GRPC_MDSTR_PATH, grpc_slice_ref_internal(method)), - host != nullptr ? grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY, - grpc_slice_ref_internal(*host)) + grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr), + host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr) : GRPC_MDNULL, deadline); } @@ -398,6 +438,13 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); + if (channel->channelz_channel != nullptr) { + channel->channelz_channel->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Channel destroyed")); + channel->channelz_channel->MarkChannelDestroyed(); + channel->channelz_channel.reset(); + } grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel)); while (channel->registered_calls) { registered_call* rc = channel->registered_calls; @@ -406,7 +453,10 @@ static void destroy_channel(void* arg, grpc_error* error) { GRPC_MDELEM_UNREF(rc->authority); gpr_free(rc); } - channel->tracer.reset(); + if (channel->resource_user != nullptr) { + grpc_resource_user_free(channel->resource_user, + GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); + } gpr_mu_destroy(&channel->registered_call_mu); gpr_free(channel->target); gpr_free(channel); diff --git a/Sources/CgRPC/src/core/lib/surface/channel.h b/Sources/CgRPC/src/core/lib/surface/channel.h index 288313951..ab00b8e94 100644 --- a/Sources/CgRPC/src/core/lib/surface/channel.h +++ b/Sources/CgRPC/src/core/lib/surface/channel.h @@ -23,12 +23,14 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/surface/channel_stack_type.h" grpc_channel* grpc_channel_create(const char* target, const grpc_channel_args* args, grpc_channel_stack_type channel_stack_type, - grpc_transport* optional_transport); + grpc_transport* optional_transport, + grpc_resource_user* resource_user = nullptr); grpc_channel* grpc_channel_create_with_builder( grpc_channel_stack_builder* builder, @@ -44,12 +46,15 @@ grpc_channel* grpc_channel_create_with_builder( value of \a propagation_mask (see propagation_bits.h for possible values) */ grpc_call* grpc_channel_create_pollset_set_call( grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, - grpc_pollset_set* pollset_set, grpc_slice method, const grpc_slice* host, - grpc_millis deadline, void* reserved); + grpc_pollset_set* pollset_set, const grpc_slice& method, + const grpc_slice* host, grpc_millis deadline, void* reserved); /** Get a (borrowed) pointer to this channels underlying channel stack */ grpc_channel_stack* grpc_channel_get_channel_stack(grpc_channel* channel); +grpc_core::channelz::ChannelNode* grpc_channel_get_channelz_node( + grpc_channel* channel); + /** Get a grpc_mdelem of grpc-status: X where X is the numeric value of status_code. diff --git a/Sources/CgRPC/src/core/lib/surface/channel_init.h b/Sources/CgRPC/src/core/lib/surface/channel_init.h index f01852473..d17a72160 100644 --- a/Sources/CgRPC/src/core/lib/surface/channel_init.h +++ b/Sources/CgRPC/src/core/lib/surface/channel_init.h @@ -45,6 +45,11 @@ void grpc_channel_init_init(void); /// registration order (in the case of a tie). /// Stages are registered against one of the pre-determined channel stack /// types. +/// If the channel stack type is GRPC_CLIENT_SUBCHANNEL, the caller should +/// ensure that subchannels with different filter lists will always have +/// different channel args. This requires setting a channel arg in case the +/// registration function relies on some condition other than channel args to +/// decide whether to add a filter or not. void grpc_channel_init_register_stage(grpc_channel_stack_type type, int priority, grpc_channel_init_stage stage_fn, diff --git a/Sources/CgRPC/src/core/lib/surface/completion_queue.cc b/Sources/CgRPC/src/core/lib/surface/completion_queue.cc index d0363917b..f473b2378 100644 --- a/Sources/CgRPC/src/core/lib/surface/completion_queue.cc +++ b/Sources/CgRPC/src/core/lib/surface/completion_queue.cc @@ -79,6 +79,7 @@ typedef struct non_polling_worker { typedef struct { gpr_mu mu; + bool kicked_without_poller; non_polling_worker* root; grpc_closure* shutdown; } non_polling_poller; @@ -103,6 +104,10 @@ static grpc_error* non_polling_poller_work(grpc_pollset* pollset, grpc_millis deadline) { non_polling_poller* npp = reinterpret_cast(pollset); if (npp->shutdown) return GRPC_ERROR_NONE; + if (npp->kicked_without_poller) { + npp->kicked_without_poller = false; + return GRPC_ERROR_NONE; + } non_polling_worker w; gpr_cv_init(&w.cv); if (worker != nullptr) *worker = reinterpret_cast(&w); @@ -148,6 +153,8 @@ static grpc_error* non_polling_poller_kick( w->kicked = true; gpr_cv_signal(&w->cv); } + } else { + p->kicked_without_poller = true; } return GRPC_ERROR_NONE; } @@ -184,7 +191,8 @@ static const cq_poller_vtable g_poller_vtable_by_poller_type[] = { typedef struct cq_vtable { grpc_cq_completion_type cq_completion_type; size_t data_size; - void (*init)(void* data); + void (*init)(void* data, + grpc_experimental_completion_queue_functor* shutdown_callback); void (*shutdown)(grpc_completion_queue* cq); void (*destroy)(void* data); bool (*begin_op)(grpc_completion_queue* cq, void* tag); @@ -253,6 +261,23 @@ typedef struct cq_pluck_data { plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS]; } cq_pluck_data; +typedef struct cq_callback_data { + /** No actual completed events queue, unlike other types */ + + /** Number of pending events (+1 if we're not shutdown) */ + gpr_atm pending_events; + + /** Counter of how many things have ever been queued on this completion queue + useful for avoiding locks to check the queue */ + gpr_atm things_queued_ever; + + /** 0 initially. 1 once we initiated shutdown */ + bool shutdown_called; + + /** A callback that gets invoked when the CQ completes shutdown */ + grpc_experimental_completion_queue_functor* shutdown_callback; +} cq_callback_data; + /* Completion queue structure */ struct grpc_completion_queue { /** Once owning_refs drops to zero, we will destroy the cq */ @@ -276,12 +301,21 @@ struct grpc_completion_queue { /* Forward declarations */ static void cq_finish_shutdown_next(grpc_completion_queue* cq); static void cq_finish_shutdown_pluck(grpc_completion_queue* cq); +static void cq_finish_shutdown_callback(grpc_completion_queue* cq); static void cq_shutdown_next(grpc_completion_queue* cq); static void cq_shutdown_pluck(grpc_completion_queue* cq); +static void cq_shutdown_callback(grpc_completion_queue* cq); static bool cq_begin_op_for_next(grpc_completion_queue* cq, void* tag); static bool cq_begin_op_for_pluck(grpc_completion_queue* cq, void* tag); - +static bool cq_begin_op_for_callback(grpc_completion_queue* cq, void* tag); + +// A cq_end_op function is called when an operation on a given CQ with +// a given tag has completed. The storage argument is a reference to the +// space reserved for this completion as it is placed into the corresponding +// queue. The done argument is a callback that will be invoked when it is +// safe to free up that storage. The storage MUST NOT be freed until the +// done callback is invoked. static void cq_end_op_for_next(grpc_completion_queue* cq, void* tag, grpc_error* error, void (*done)(void* done_arg, @@ -294,16 +328,28 @@ static void cq_end_op_for_pluck(grpc_completion_queue* cq, void* tag, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage); +static void cq_end_op_for_callback(grpc_completion_queue* cq, void* tag, + grpc_error* error, + void (*done)(void* done_arg, + grpc_cq_completion* storage), + void* done_arg, grpc_cq_completion* storage); + static grpc_event cq_next(grpc_completion_queue* cq, gpr_timespec deadline, void* reserved); static grpc_event cq_pluck(grpc_completion_queue* cq, void* tag, gpr_timespec deadline, void* reserved); -static void cq_init_next(void* data); -static void cq_init_pluck(void* data); +// Note that cq_init_next and cq_init_pluck do not use the shutdown_callback +static void cq_init_next( + void* data, grpc_experimental_completion_queue_functor* shutdown_callback); +static void cq_init_pluck( + void* data, grpc_experimental_completion_queue_functor* shutdown_callback); +static void cq_init_callback( + void* data, grpc_experimental_completion_queue_functor* shutdown_callback); static void cq_destroy_next(void* data); static void cq_destroy_pluck(void* data); +static void cq_destroy_callback(void* data); /* Completion queue vtables based on the completion-type */ static const cq_vtable g_cq_vtable[] = { @@ -315,14 +361,17 @@ static const cq_vtable g_cq_vtable[] = { {GRPC_CQ_PLUCK, sizeof(cq_pluck_data), cq_init_pluck, cq_shutdown_pluck, cq_destroy_pluck, cq_begin_op_for_pluck, cq_end_op_for_pluck, nullptr, cq_pluck}, + /* GRPC_CQ_CALLBACK */ + {GRPC_CQ_CALLBACK, sizeof(cq_callback_data), cq_init_callback, + cq_shutdown_callback, cq_destroy_callback, cq_begin_op_for_callback, + cq_end_op_for_callback, nullptr, nullptr}, }; #define DATA_FROM_CQ(cq) ((void*)(cq + 1)) #define POLLSET_FROM_CQ(cq) \ ((grpc_pollset*)(cq->vtable->data_size + (char*)DATA_FROM_CQ(cq))) -grpc_core::TraceFlag grpc_cq_pluck_trace(true, "queue_pluck"); -grpc_core::TraceFlag grpc_cq_event_timeout_trace(true, "queue_timeout"); +grpc_core::TraceFlag grpc_cq_pluck_trace(false, "queue_pluck"); #define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \ if (grpc_api_trace.enabled() && (grpc_cq_pluck_trace.enabled() || \ @@ -390,7 +439,6 @@ static bool cq_event_queue_push(grpc_cq_event_queue* q, grpc_cq_completion* c) { static grpc_cq_completion* cq_event_queue_pop(grpc_cq_event_queue* q) { grpc_cq_completion* c = nullptr; - grpc_core::ExecCtx exec_ctx; if (gpr_spinlock_trylock(&q->queue_lock)) { GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES(); @@ -421,8 +469,8 @@ static long cq_event_queue_num_items(grpc_cq_event_queue* q) { } grpc_completion_queue* grpc_completion_queue_create_internal( - grpc_cq_completion_type completion_type, - grpc_cq_polling_type polling_type) { + grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type, + grpc_experimental_completion_queue_functor* shutdown_callback) { GPR_TIMER_SCOPE("grpc_completion_queue_create_internal", 0); grpc_completion_queue* cq; @@ -450,15 +498,16 @@ grpc_completion_queue* grpc_completion_queue_create_internal( gpr_ref_init(&cq->owning_refs, 2); poller_vtable->init(POLLSET_FROM_CQ(cq), &cq->mu); - vtable->init(DATA_FROM_CQ(cq)); + vtable->init(DATA_FROM_CQ(cq), shutdown_callback); GRPC_CLOSURE_INIT(&cq->pollset_shutdown_done, on_pollset_shutdown_done, cq, grpc_schedule_on_exec_ctx); return cq; } -static void cq_init_next(void* ptr) { - cq_next_data* cqd = static_cast(ptr); +static void cq_init_next( + void* data, grpc_experimental_completion_queue_functor* shutdown_callback) { + cq_next_data* cqd = static_cast(data); /* Initial count is dropped by grpc_completion_queue_shutdown */ gpr_atm_no_barrier_store(&cqd->pending_events, 1); cqd->shutdown_called = false; @@ -466,14 +515,15 @@ static void cq_init_next(void* ptr) { cq_event_queue_init(&cqd->queue); } -static void cq_destroy_next(void* ptr) { - cq_next_data* cqd = static_cast(ptr); +static void cq_destroy_next(void* data) { + cq_next_data* cqd = static_cast(data); GPR_ASSERT(cq_event_queue_num_items(&cqd->queue) == 0); cq_event_queue_destroy(&cqd->queue); } -static void cq_init_pluck(void* ptr) { - cq_pluck_data* cqd = static_cast(ptr); +static void cq_init_pluck( + void* data, grpc_experimental_completion_queue_functor* shutdown_callback) { + cq_pluck_data* cqd = static_cast(data); /* Initial count is dropped by grpc_completion_queue_shutdown */ gpr_atm_no_barrier_store(&cqd->pending_events, 1); cqd->completed_tail = &cqd->completed_head; @@ -484,11 +534,23 @@ static void cq_init_pluck(void* ptr) { gpr_atm_no_barrier_store(&cqd->things_queued_ever, 0); } -static void cq_destroy_pluck(void* ptr) { - cq_pluck_data* cqd = static_cast(ptr); +static void cq_destroy_pluck(void* data) { + cq_pluck_data* cqd = static_cast(data); GPR_ASSERT(cqd->completed_head.next == (uintptr_t)&cqd->completed_head); } +static void cq_init_callback( + void* data, grpc_experimental_completion_queue_functor* shutdown_callback) { + cq_callback_data* cqd = static_cast(data); + /* Initial count is dropped by grpc_completion_queue_shutdown */ + gpr_atm_no_barrier_store(&cqd->pending_events, 1); + cqd->shutdown_called = false; + gpr_atm_no_barrier_store(&cqd->things_queued_ever, 0); + cqd->shutdown_callback = shutdown_callback; +} + +static void cq_destroy_callback(void* data) {} + grpc_cq_completion_type grpc_get_cq_completion_type(grpc_completion_queue* cq) { return cq->vtable->cq_completion_type; } @@ -598,6 +660,11 @@ static bool cq_begin_op_for_pluck(grpc_completion_queue* cq, void* tag) { return atm_inc_if_nonzero(&cqd->pending_events); } +static bool cq_begin_op_for_callback(grpc_completion_queue* cq, void* tag) { + cq_callback_data* cqd = static_cast DATA_FROM_CQ(cq); + return atm_inc_if_nonzero(&cqd->pending_events); +} + bool grpc_cq_begin_op(grpc_completion_queue* cq, void* tag) { #ifndef NDEBUG gpr_mu_lock(cq->mu); @@ -761,6 +828,45 @@ static void cq_end_op_for_pluck(grpc_completion_queue* cq, void* tag, GRPC_ERROR_UNREF(error); } +/* Complete an event on a completion queue of type GRPC_CQ_CALLBACK */ +static void cq_end_op_for_callback( + grpc_completion_queue* cq, void* tag, grpc_error* error, + void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, + grpc_cq_completion* storage) { + GPR_TIMER_SCOPE("cq_end_op_for_callback", 0); + + cq_callback_data* cqd = static_cast DATA_FROM_CQ(cq); + bool is_success = (error == GRPC_ERROR_NONE); + + if (grpc_api_trace.enabled() || + (grpc_trace_operation_failures.enabled() && error != GRPC_ERROR_NONE)) { + const char* errmsg = grpc_error_string(error); + GRPC_API_TRACE( + "cq_end_op_for_callback(cq=%p, tag=%p, error=%s, " + "done=%p, done_arg=%p, storage=%p)", + 6, (cq, tag, errmsg, done, done_arg, storage)); + if (grpc_trace_operation_failures.enabled() && error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg); + } + } + + // The callback-based CQ isn't really a queue at all and thus has no need + // for reserved storage. Invoke the done callback right away to release it. + done(done_arg, storage); + + cq_check_tag(cq, tag, true); /* Used in debug builds only */ + + gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1); + if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + cq_finish_shutdown_callback(cq); + } + + GRPC_ERROR_UNREF(error); + + auto* functor = static_cast(tag); + grpc_core::ApplicationCallbackExecCtx::Enqueue(functor, is_success); +} + void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, grpc_error* error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage) { @@ -1235,10 +1341,47 @@ static void cq_shutdown_pluck(grpc_completion_queue* cq) { GRPC_CQ_INTERNAL_UNREF(cq, "shutting_down (pluck cq)"); } +static void cq_finish_shutdown_callback(grpc_completion_queue* cq) { + cq_callback_data* cqd = static_cast DATA_FROM_CQ(cq); + auto* callback = cqd->shutdown_callback; + + GPR_ASSERT(cqd->shutdown_called); + + cq->poller_vtable->shutdown(POLLSET_FROM_CQ(cq), &cq->pollset_shutdown_done); + grpc_core::ApplicationCallbackExecCtx::Enqueue(callback, true); +} + +static void cq_shutdown_callback(grpc_completion_queue* cq) { + cq_callback_data* cqd = static_cast DATA_FROM_CQ(cq); + + /* Need an extra ref for cq here because: + * We call cq_finish_shutdown_callback() below, which calls pollset shutdown. + * Pollset shutdown decrements the cq ref count which can potentially destroy + * the cq (if that happens to be the last ref). + * Creating an extra ref here prevents the cq from getting destroyed while + * this function is still active */ + GRPC_CQ_INTERNAL_REF(cq, "shutting_down (callback cq)"); + gpr_mu_lock(cq->mu); + if (cqd->shutdown_called) { + gpr_mu_unlock(cq->mu); + GRPC_CQ_INTERNAL_UNREF(cq, "shutting_down (callback cq)"); + return; + } + cqd->shutdown_called = true; + if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + gpr_mu_unlock(cq->mu); + cq_finish_shutdown_callback(cq); + } else { + gpr_mu_unlock(cq->mu); + } + GRPC_CQ_INTERNAL_UNREF(cq, "shutting_down (callback cq)"); +} + /* Shutdown simply drops a ref that we reserved at creation time; if we drop to zero here, then enter shutdown mode and wake up any waiters */ void grpc_completion_queue_shutdown(grpc_completion_queue* cq) { GPR_TIMER_SCOPE("grpc_completion_queue_shutdown", 0); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_completion_queue_shutdown(cq=%p)", 1, (cq)); cq->vtable->shutdown(cq); diff --git a/Sources/CgRPC/src/core/lib/surface/completion_queue.h b/Sources/CgRPC/src/core/lib/surface/completion_queue.h index c9dc2d93c..d60fe6d6e 100644 --- a/Sources/CgRPC/src/core/lib/surface/completion_queue.h +++ b/Sources/CgRPC/src/core/lib/surface/completion_queue.h @@ -25,12 +25,12 @@ #include #include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/iomgr/pollset.h" /* These trace flags default to 1. The corresponding lines are only traced if grpc_api_trace is also truthy */ extern grpc_core::TraceFlag grpc_cq_pluck_trace; -extern grpc_core::TraceFlag grpc_cq_event_timeout_trace; extern grpc_core::TraceFlag grpc_trace_operation_failures; extern grpc_core::DebugOnlyTraceFlag grpc_trace_pending_tags; extern grpc_core::DebugOnlyTraceFlag grpc_trace_cq_refcount; @@ -88,6 +88,7 @@ grpc_cq_completion_type grpc_get_cq_completion_type(grpc_completion_queue* cc); int grpc_get_cq_poll_num(grpc_completion_queue* cc); grpc_completion_queue* grpc_completion_queue_create_internal( - grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type); + grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type, + grpc_experimental_completion_queue_functor* shutdown_callback); #endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */ diff --git a/Sources/CgRPC/src/core/lib/surface/completion_queue_factory.cc b/Sources/CgRPC/src/core/lib/surface/completion_queue_factory.cc index 51c1183c5..2616c156e 100644 --- a/Sources/CgRPC/src/core/lib/surface/completion_queue_factory.cc +++ b/Sources/CgRPC/src/core/lib/surface/completion_queue_factory.cc @@ -30,8 +30,8 @@ static grpc_completion_queue* default_create( const grpc_completion_queue_factory* factory, const grpc_completion_queue_attributes* attr) { - return grpc_completion_queue_create_internal(attr->cq_completion_type, - attr->cq_polling_type); + return grpc_completion_queue_create_internal( + attr->cq_completion_type, attr->cq_polling_type, attr->cq_shutdown_cb); } static grpc_completion_queue_factory_vtable default_vtable = {default_create}; @@ -60,14 +60,23 @@ const grpc_completion_queue_factory* grpc_completion_queue_factory_lookup( grpc_completion_queue* grpc_completion_queue_create_for_next(void* reserved) { GPR_ASSERT(!reserved); grpc_completion_queue_attributes attr = {1, GRPC_CQ_NEXT, - GRPC_CQ_DEFAULT_POLLING}; + GRPC_CQ_DEFAULT_POLLING, nullptr}; return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr); } grpc_completion_queue* grpc_completion_queue_create_for_pluck(void* reserved) { GPR_ASSERT(!reserved); grpc_completion_queue_attributes attr = {1, GRPC_CQ_PLUCK, - GRPC_CQ_DEFAULT_POLLING}; + GRPC_CQ_DEFAULT_POLLING, nullptr}; + return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr); +} + +grpc_completion_queue* grpc_completion_queue_create_for_callback( + grpc_experimental_completion_queue_functor* shutdown_callback, + void* reserved) { + GPR_ASSERT(!reserved); + grpc_completion_queue_attributes attr = { + 2, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}; return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr); } diff --git a/Sources/CgRPC/src/core/lib/surface/init.cc b/Sources/CgRPC/src/core/lib/surface/init.cc index bd436d685..e507de87c 100644 --- a/Sources/CgRPC/src/core/lib/surface/init.cc +++ b/Sources/CgRPC/src/core/lib/surface/init.cc @@ -27,13 +27,12 @@ #include #include #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/channel/channel_trace_registry.h" +#include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gpr/fork.h" -#include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/gprpp/fork.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/combiner.h" @@ -65,12 +64,10 @@ static int g_initializations; static void do_basic_init(void) { gpr_log_verbosity_init(); - grpc_fork_support_init(); gpr_mu_init(&g_init_mu); grpc_register_built_in_plugins(); grpc_cq_global_init(); g_initializations = 0; - grpc_fork_handlers_auto_register(); } static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { @@ -123,18 +120,21 @@ void grpc_init(void) { gpr_mu_lock(&g_init_mu); if (++g_initializations == 1) { + grpc_core::Fork::GlobalInit(); + grpc_fork_handlers_auto_register(); gpr_time_init(); - grpc_core::Thread::Init(); + gpr_arena_init(); grpc_stats_init(); grpc_slice_intern_init(); grpc_mdctx_global_init(); grpc_channel_init_init(); - grpc_channel_trace_registry_init(); + grpc_core::channelz::ChannelzRegistry::Init(); grpc_security_pre_init(); + grpc_core::ApplicationCallbackExecCtx::GlobalInit(); grpc_core::ExecCtx::GlobalInit(); grpc_iomgr_init(); gpr_timers_global_init(); - grpc_handshaker_factory_registry_init(); + grpc_core::HandshakerRegistry::Init(); grpc_security_init(); for (i = 0; i < g_number_of_plugins; i++) { if (g_all_of_the_plugins[i].init != nullptr) { @@ -162,10 +162,11 @@ void grpc_shutdown(void) { if (--g_initializations == 0) { { grpc_core::ExecCtx exec_ctx(0); + grpc_iomgr_shutdown_background_closure(); { grpc_timer_manager_set_threading( false); // shutdown timer_manager thread - grpc_executor_shutdown(); + grpc_core::Executor::ShutdownAll(); for (i = g_number_of_plugins; i >= 0; i--) { if (g_all_of_the_plugins[i].destroy != nullptr) { g_all_of_the_plugins[i].destroy(); @@ -176,12 +177,14 @@ void grpc_shutdown(void) { gpr_timers_global_destroy(); grpc_tracer_shutdown(); grpc_mdctx_global_shutdown(); - grpc_handshaker_factory_registry_shutdown(); + grpc_core::HandshakerRegistry::Shutdown(); grpc_slice_intern_shutdown(); - grpc_channel_trace_registry_shutdown(); + grpc_core::channelz::ChannelzRegistry::Shutdown(); grpc_stats_shutdown(); + grpc_core::Fork::GlobalShutdown(); } grpc_core::ExecCtx::GlobalShutdown(); + grpc_core::ApplicationCallbackExecCtx::GlobalShutdown(); } gpr_mu_unlock(&g_init_mu); } diff --git a/Sources/CgRPC/src/core/lib/surface/init.h b/Sources/CgRPC/src/core/lib/surface/init.h index 935320833..193f51447 100644 --- a/Sources/CgRPC/src/core/lib/surface/init.h +++ b/Sources/CgRPC/src/core/lib/surface/init.h @@ -22,6 +22,5 @@ void grpc_register_security_filters(void); void grpc_security_pre_init(void); void grpc_security_init(void); -int grpc_is_initialized(void); #endif /* GRPC_CORE_LIB_SURFACE_INIT_H */ diff --git a/Sources/CgRPC/src/core/lib/surface/init_secure.cc b/Sources/CgRPC/src/core/lib/surface/init_secure.cc index 28c6f7b12..0e83a11a5 100644 --- a/Sources/CgRPC/src/core/lib/surface/init_secure.cc +++ b/Sources/CgRPC/src/core/lib/surface/init_secure.cc @@ -74,8 +74,8 @@ void grpc_register_security_filters(void) { maybe_prepend_client_auth_filter, nullptr); grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX - 1, maybe_prepend_client_auth_filter, nullptr); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX - 1, maybe_prepend_server_auth_filter, nullptr); } -void grpc_security_init() { grpc_security_register_handshaker_factories(); } +void grpc_security_init() { grpc_core::SecurityRegisterHandshakerFactories(); } diff --git a/Sources/CgRPC/src/core/lib/surface/server.cc b/Sources/CgRPC/src/core/lib/surface/server.cc index cb34def74..1e0ac0e92 100644 --- a/Sources/CgRPC/src/core/lib/surface/server.cc +++ b/Sources/CgRPC/src/core/lib/surface/server.cc @@ -28,6 +28,8 @@ #include #include +#include + #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/debug/stats.h" @@ -47,6 +49,10 @@ grpc_core::TraceFlag grpc_server_channel_trace(false, "server_channel"); +static void server_on_recv_initial_metadata(void* ptr, grpc_error* error); +static void server_recv_trailing_metadata_ready(void* user_data, + grpc_error* error); + namespace { struct listener { void* arg; @@ -54,6 +60,7 @@ struct listener { size_t pollset_count); void (*destroy)(grpc_server* server, void* arg, grpc_closure* closure); struct listener* next; + intptr_t socket_uuid; grpc_closure destroy_done; }; @@ -104,6 +111,7 @@ struct channel_data { uint32_t registered_method_max_probes; grpc_closure finish_destroy_channel_closure; grpc_closure channel_connectivity_changed; + grpc_core::RefCountedPtr socket_node; }; typedef struct shutdown_tag { @@ -126,33 +134,63 @@ typedef enum { typedef struct request_matcher request_matcher; struct call_data { + call_data(grpc_call_element* elem, const grpc_call_element_args& args) + : call(grpc_call_from_top_element(elem)), + call_combiner(args.call_combiner) { + GRPC_CLOSURE_INIT(&server_on_recv_initial_metadata, + ::server_on_recv_initial_metadata, elem, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready, + server_recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + } + ~call_data() { + GPR_ASSERT(state != PENDING); + GRPC_ERROR_UNREF(recv_initial_metadata_error); + if (host_set) { + grpc_slice_unref_internal(host); + } + if (path_set) { + grpc_slice_unref_internal(path); + } + grpc_metadata_array_destroy(&initial_metadata); + grpc_byte_buffer_destroy(payload); + } + grpc_call* call; - gpr_atm state; + gpr_atm state = NOT_STARTED; - bool path_set; - bool host_set; + bool path_set = false; + bool host_set = false; grpc_slice path; grpc_slice host; - grpc_millis deadline; + grpc_millis deadline = GRPC_MILLIS_INF_FUTURE; - grpc_completion_queue* cq_new; + grpc_completion_queue* cq_new = nullptr; - grpc_metadata_batch* recv_initial_metadata; - uint32_t recv_initial_metadata_flags; - grpc_metadata_array initial_metadata; + grpc_metadata_batch* recv_initial_metadata = nullptr; + uint32_t recv_initial_metadata_flags = 0; + grpc_metadata_array initial_metadata = + grpc_metadata_array(); // Zero-initialize the C struct. - request_matcher* matcher; - grpc_byte_buffer* payload; + request_matcher* matcher = nullptr; + grpc_byte_buffer* payload = nullptr; grpc_closure got_initial_metadata; grpc_closure server_on_recv_initial_metadata; grpc_closure kill_zombie_closure; grpc_closure* on_done_recv_initial_metadata; + grpc_closure recv_trailing_metadata_ready; + grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; + grpc_closure* original_recv_trailing_metadata_ready; + grpc_error* recv_trailing_metadata_error = GRPC_ERROR_NONE; + bool seen_recv_trailing_metadata_ready = false; grpc_closure publish; - call_data* pending_next; + call_data* pending_next = nullptr; + grpc_call_combiner* call_combiner; }; struct request_matcher { @@ -181,6 +219,8 @@ typedef struct { struct grpc_server { grpc_channel_args* channel_args; + grpc_resource_user* default_resource_user; + grpc_completion_queue** cqs; grpc_pollset** pollsets; size_t cq_count; @@ -219,6 +259,8 @@ struct grpc_server { /** when did we print the last shutdown progress message */ gpr_timespec last_shutdown_message_time; + + grpc_core::RefCountedPtr channelz_server; }; #define SERVER_FROM_CALL_ELEM(elem) \ @@ -364,6 +406,7 @@ static void server_ref(grpc_server* server) { static void server_delete(grpc_server* server) { registered_method* rm; size_t i; + server->channelz_server.reset(); grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu_global); gpr_mu_destroy(&server->mu_call); @@ -721,13 +764,43 @@ static void server_on_recv_initial_metadata(void* ptr, grpc_error* error) { if (calld->host_set && calld->path_set) { /* do nothing */ } else { + /* Pass the error reference to calld->recv_initial_metadata_error */ grpc_error* src_error = error; error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Missing :authority or :path", &error, 1); + "Missing :authority or :path", &src_error, 1); GRPC_ERROR_UNREF(src_error); + calld->recv_initial_metadata_error = GRPC_ERROR_REF(error); } + grpc_closure* closure = calld->on_done_recv_initial_metadata; + calld->on_done_recv_initial_metadata = nullptr; + if (calld->seen_recv_trailing_metadata_ready) { + GRPC_CALL_COMBINER_START(calld->call_combiner, + &calld->recv_trailing_metadata_ready, + calld->recv_trailing_metadata_error, + "continue server_recv_trailing_metadata_ready"); + } + GRPC_CLOSURE_RUN(closure, error); +} - GRPC_CLOSURE_RUN(calld->on_done_recv_initial_metadata, error); +static void server_recv_trailing_metadata_ready(void* user_data, + grpc_error* error) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + if (calld->on_done_recv_initial_metadata != nullptr) { + calld->recv_trailing_metadata_error = GRPC_ERROR_REF(error); + calld->seen_recv_trailing_metadata_ready = true; + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready, + server_recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); + GRPC_CALL_COMBINER_STOP(calld->call_combiner, + "deferring server_recv_trailing_metadata_ready " + "until after server_on_recv_initial_metadata"); + return; + } + error = + grpc_error_add_child(GRPC_ERROR_REF(error), + GRPC_ERROR_REF(calld->recv_initial_metadata_error)); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error); } static void server_mutate_op(grpc_call_element* elem, @@ -745,6 +818,12 @@ static void server_mutate_op(grpc_call_element* elem, op->payload->recv_initial_metadata.recv_flags = &calld->recv_initial_metadata_flags; } + if (op->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; + } } static void server_start_transport_stream_op_batch( @@ -775,9 +854,15 @@ static void accept_stream(void* cd, grpc_transport* transport, channel_data* chand = static_cast(cd); /* create a call */ grpc_call_create_args args; - memset(&args, 0, sizeof(args)); args.channel = chand->channel; + args.server = chand->server; + args.parent = nullptr; + args.propagation_mask = 0; + args.cq = nullptr; + args.pollset_set_alternative = nullptr; args.server_transport_data = transport_server_data; + args.add_initial_metadata = nullptr; + args.add_initial_metadata_count = 0; args.send_deadline = GRPC_MILLIS_INF_FUTURE; grpc_call* call; grpc_error* error = grpc_call_create(&args, &call); @@ -790,8 +875,9 @@ static void accept_stream(void* cd, grpc_transport* transport, } call_data* calld = static_cast(elem->call_data); grpc_op op; - memset(&op, 0, sizeof(op)); op.op = GRPC_OP_RECV_INITIAL_METADATA; + op.flags = 0; + op.reserved = nullptr; op.data.recv_initial_metadata.recv_initial_metadata = &calld->initial_metadata; GRPC_CLOSURE_INIT(&calld->got_initial_metadata, got_initial_metadata, elem, @@ -819,37 +905,18 @@ static void channel_connectivity_changed(void* cd, grpc_error* error) { static grpc_error* init_call_elem(grpc_call_element* elem, const grpc_call_element_args* args) { - call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); - memset(calld, 0, sizeof(call_data)); - calld->deadline = GRPC_MILLIS_INF_FUTURE; - calld->call = grpc_call_from_top_element(elem); - - GRPC_CLOSURE_INIT(&calld->server_on_recv_initial_metadata, - server_on_recv_initial_metadata, elem, - grpc_schedule_on_exec_ctx); - server_ref(chand->server); + new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { - channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); - - GPR_ASSERT(calld->state != PENDING); - - if (calld->host_set) { - grpc_slice_unref_internal(calld->host); - } - if (calld->path_set) { - grpc_slice_unref_internal(calld->path); - } - grpc_metadata_array_destroy(&calld->initial_metadata); - grpc_byte_buffer_destroy(calld->payload); - + calld->~call_data(); + channel_data* chand = static_cast(elem->channel_data); server_unref(chand->server); } @@ -872,6 +939,7 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, static void destroy_channel_elem(grpc_channel_element* elem) { size_t i; channel_data* chand = static_cast(elem->channel_data); + chand->socket_node.reset(); if (chand->registered_methods) { for (i = 0; i < chand->registered_method_slots; i++) { grpc_slice_unref_internal(chand->registered_methods[i].method); @@ -929,10 +997,12 @@ void grpc_server_register_completion_queue(grpc_server* server, "grpc_server_register_completion_queue(server=%p, cq=%p, reserved=%p)", 3, (server, cq, reserved)); - if (grpc_get_cq_completion_type(cq) != GRPC_CQ_NEXT) { + auto cq_type = grpc_get_cq_completion_type(cq); + if (cq_type != GRPC_CQ_NEXT && cq_type != GRPC_CQ_CALLBACK) { gpr_log(GPR_INFO, - "Completion queue which is not of type GRPC_CQ_NEXT is being " - "registered as a server-completion-queue"); + "Completion queue of type %d is being registered as a " + "server-completion-queue", + static_cast(cq_type)); /* Ideally we should log an error and abort but ruby-wrapped-language API calls grpc_completion_queue_pluck() on server completion queues */ } @@ -941,6 +1011,7 @@ void grpc_server_register_completion_queue(grpc_server* server, } grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { + grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved)); grpc_server* server = @@ -957,6 +1028,30 @@ grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { server->channel_args = grpc_channel_args_copy(args); + const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ); + if (grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT)) { + arg = grpc_channel_args_find( + args, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); + size_t channel_tracer_max_memory = grpc_channel_arg_get_integer( + arg, + {GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX}); + server->channelz_server = + grpc_core::MakeRefCounted( + server, channel_tracer_max_memory); + server->channelz_server->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Server created")); + } + + if (args != nullptr) { + grpc_resource_quota* resource_quota = + grpc_resource_quota_from_channel_args(args, false /* create */); + if (resource_quota != nullptr) { + server->default_resource_user = + grpc_resource_user_create(resource_quota, "default"); + } + } + return server; } @@ -1041,8 +1136,9 @@ void grpc_server_start(grpc_server* server) { server_ref(server); server->starting = true; GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(start_listeners, server, - grpc_executor_scheduler(GRPC_EXECUTOR_SHORT)), + GRPC_CLOSURE_CREATE( + start_listeners, server, + grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT)), GRPC_ERROR_NONE); } @@ -1052,9 +1148,11 @@ void grpc_server_get_pollsets(grpc_server* server, grpc_pollset*** pollsets, *pollsets = server->pollsets; } -void grpc_server_setup_transport(grpc_server* s, grpc_transport* transport, - grpc_pollset* accepting_pollset, - const grpc_channel_args* args) { +void grpc_server_setup_transport( + grpc_server* s, grpc_transport* transport, grpc_pollset* accepting_pollset, + const grpc_channel_args* args, + grpc_core::RefCountedPtr socket_node, + grpc_resource_user* resource_user) { size_t num_registered_methods; size_t alloc; registered_method* rm; @@ -1067,13 +1165,15 @@ void grpc_server_setup_transport(grpc_server* s, grpc_transport* transport, uint32_t max_probes = 0; grpc_transport_op* op = nullptr; - channel = grpc_channel_create(nullptr, args, GRPC_SERVER_CHANNEL, transport); + channel = grpc_channel_create(nullptr, args, GRPC_SERVER_CHANNEL, transport, + resource_user); chand = static_cast( grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0) ->channel_data); chand->server = s; server_ref(s); chand->channel = channel; + chand->socket_node = std::move(socket_node); size_t cq_idx; for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) { @@ -1148,6 +1248,28 @@ void grpc_server_setup_transport(grpc_server* s, grpc_transport* transport, grpc_transport_perform_op(transport, op); } +void grpc_server_populate_server_sockets( + grpc_server* s, grpc_core::channelz::ChildSocketsList* server_sockets, + intptr_t start_idx) { + gpr_mu_lock(&s->mu_global); + channel_data* c = nullptr; + for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) { + if (c->socket_node != nullptr && c->socket_node->uuid() >= start_idx) { + server_sockets->push_back(c->socket_node.get()); + } + } + gpr_mu_unlock(&s->mu_global); +} + +void grpc_server_populate_listen_sockets( + grpc_server* server, grpc_core::channelz::ChildRefsList* listen_sockets) { + gpr_mu_lock(&server->mu_global); + for (listener* l = server->listeners; l != nullptr; l = l->next) { + listen_sockets->push_back(l->socket_uuid); + } + gpr_mu_unlock(&server->mu_global); +} + void done_published_shutdown(void* done_arg, grpc_cq_completion* storage) { (void)done_arg; gpr_free(storage); @@ -1182,6 +1304,7 @@ void grpc_server_shutdown_and_notify(grpc_server* server, listener* l; shutdown_tag* sdt; channel_broadcaster broadcaster; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3, @@ -1238,10 +1361,18 @@ void grpc_server_shutdown_and_notify(grpc_server* server, channel_broadcaster_shutdown(&broadcaster, true /* send_goaway */, GRPC_ERROR_NONE); + + if (server->default_resource_user != nullptr) { + grpc_resource_quota_unref( + grpc_resource_user_quota(server->default_resource_user)); + grpc_resource_user_shutdown(server->default_resource_user); + grpc_resource_user_unref(server->default_resource_user); + } } void grpc_server_cancel_all_calls(grpc_server* server) { channel_broadcaster broadcaster; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_cancel_all_calls(server=%p)", 1, (server)); @@ -1257,6 +1388,7 @@ void grpc_server_cancel_all_calls(grpc_server* server) { void grpc_server_destroy(grpc_server* server) { listener* l; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_destroy(server=%p)", 1, (server)); @@ -1281,11 +1413,13 @@ void grpc_server_add_listener(grpc_server* server, void* arg, grpc_pollset** pollsets, size_t pollset_count), void (*destroy)(grpc_server* server, void* arg, - grpc_closure* on_done)) { + grpc_closure* on_done), + intptr_t socket_uuid) { listener* l = static_cast(gpr_malloc(sizeof(listener))); l->arg = arg; l->start = start; l->destroy = destroy; + l->socket_uuid = socket_uuid; l->next = server->listeners; server->listeners = l; } @@ -1340,6 +1474,7 @@ grpc_call_error grpc_server_request_call( grpc_completion_queue* cq_bound_to_call, grpc_completion_queue* cq_for_notification, void* tag) { grpc_call_error error; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; requested_call* rc = static_cast(gpr_malloc(sizeof(*rc))); GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); @@ -1386,11 +1521,11 @@ grpc_call_error grpc_server_request_registered_call( grpc_metadata_array* initial_metadata, grpc_byte_buffer** optional_payload, grpc_completion_queue* cq_bound_to_call, grpc_completion_queue* cq_for_notification, void* tag) { - grpc_call_error error; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; + GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); requested_call* rc = static_cast(gpr_malloc(sizeof(*rc))); registered_method* rm = static_cast(rmp); - GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); GRPC_API_TRACE( "grpc_server_request_registered_call(" "server=%p, rmp=%p, call=%p, deadline=%p, initial_metadata=%p, " @@ -1408,19 +1543,17 @@ grpc_call_error grpc_server_request_registered_call( } if (cq_idx == server->cq_count) { gpr_free(rc); - error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; - goto done; + return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; } if ((optional_payload == nullptr) != (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) { gpr_free(rc); - error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; - goto done; + return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; } + if (grpc_cq_begin_op(cq_for_notification, tag) == false) { gpr_free(rc); - error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; - goto done; + return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; } rc->cq_idx = cq_idx; rc->type = REGISTERED_CALL; @@ -1432,10 +1565,7 @@ grpc_call_error grpc_server_request_registered_call( rc->data.registered.deadline = deadline; rc->initial_metadata = initial_metadata; rc->data.registered.optional_payload = optional_payload; - error = queue_call_request(server, cq_idx, rc); -done: - - return error; + return queue_call_request(server, cq_idx, rc); } static void fail_call(grpc_server* server, size_t cq_idx, requested_call* rc, @@ -1452,6 +1582,10 @@ const grpc_channel_args* grpc_server_get_channel_args(grpc_server* server) { return server->channel_args; } +grpc_resource_user* grpc_server_get_default_resource_user(grpc_server* server) { + return server->default_resource_user; +} + int grpc_server_has_open_connections(grpc_server* server) { int r; gpr_mu_lock(&server->mu_global); @@ -1459,3 +1593,11 @@ int grpc_server_has_open_connections(grpc_server* server) { gpr_mu_unlock(&server->mu_global); return r; } + +grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( + grpc_server* server) { + if (server == nullptr) { + return nullptr; + } + return server->channelz_server.get(); +} diff --git a/Sources/CgRPC/src/core/lib/surface/server.h b/Sources/CgRPC/src/core/lib/surface/server.h index c617cc223..393bb2421 100644 --- a/Sources/CgRPC/src/core/lib/surface/server.h +++ b/Sources/CgRPC/src/core/lib/surface/server.h @@ -23,6 +23,7 @@ #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/transport.h" @@ -38,16 +39,33 @@ void grpc_server_add_listener(grpc_server* server, void* listener, grpc_pollset** pollsets, size_t npollsets), void (*destroy)(grpc_server* server, void* arg, - grpc_closure* on_done)); + grpc_closure* on_done), + intptr_t socket_uuid); /* Setup a transport - creates a channel stack, binds the transport to the server */ -void grpc_server_setup_transport(grpc_server* server, grpc_transport* transport, - grpc_pollset* accepting_pollset, - const grpc_channel_args* args); +void grpc_server_setup_transport( + grpc_server* server, grpc_transport* transport, + grpc_pollset* accepting_pollset, const grpc_channel_args* args, + grpc_core::RefCountedPtr socket_node, + grpc_resource_user* resource_user = nullptr); + +/* fills in the uuids of all sockets used for connections on this server */ +void grpc_server_populate_server_sockets( + grpc_server* server, grpc_core::channelz::ChildSocketsList* server_sockets, + intptr_t start_idx); + +/* fills in the uuids of all listen sockets on this server */ +void grpc_server_populate_listen_sockets( + grpc_server* server, grpc_core::channelz::ChildRefsList* listen_sockets); + +grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( + grpc_server* server); const grpc_channel_args* grpc_server_get_channel_args(grpc_server* server); +grpc_resource_user* grpc_server_get_default_resource_user(grpc_server* server); + int grpc_server_has_open_connections(grpc_server* server); /* Do not call this before grpc_server_start. Returns the pollsets and the diff --git a/Sources/CgRPC/src/core/lib/surface/version.cc b/Sources/CgRPC/src/core/lib/surface/version.cc index b8d6a2c46..3ad52aee5 100644 --- a/Sources/CgRPC/src/core/lib/surface/version.cc +++ b/Sources/CgRPC/src/core/lib/surface/version.cc @@ -23,6 +23,6 @@ #include -const char* grpc_version_string(void) { return "6.0.0"; } +const char* grpc_version_string(void) { return "7.0.0"; } -const char* grpc_g_stands_for(void) { return "glorious"; } +const char* grpc_g_stands_for(void) { return "gold"; } diff --git a/Sources/CgRPC/src/core/lib/transport/byte_stream.cc b/Sources/CgRPC/src/core/lib/transport/byte_stream.cc index cb15a71a9..16b85ca0d 100644 --- a/Sources/CgRPC/src/core/lib/transport/byte_stream.cc +++ b/Sources/CgRPC/src/core/lib/transport/byte_stream.cc @@ -45,7 +45,7 @@ SliceBufferByteStream::SliceBufferByteStream(grpc_slice_buffer* slice_buffer, SliceBufferByteStream::~SliceBufferByteStream() {} void SliceBufferByteStream::Orphan() { - grpc_slice_buffer_destroy(&backing_buffer_); + grpc_slice_buffer_destroy_internal(&backing_buffer_); GRPC_ERROR_UNREF(shutdown_error_); // Note: We do not actually delete the object here, since // SliceBufferByteStream is usually allocated as part of a larger diff --git a/Sources/CgRPC/src/core/lib/transport/error_utils.cc b/Sources/CgRPC/src/core/lib/transport/error_utils.cc index 2eff8b291..558f1d494 100644 --- a/Sources/CgRPC/src/core/lib/transport/error_utils.cc +++ b/Sources/CgRPC/src/core/lib/transport/error_utils.cc @@ -26,8 +26,9 @@ static grpc_error* recursively_find_error_with_field(grpc_error* error, grpc_error_ints which) { + intptr_t unused; // If the error itself has a status code, return it. - if (grpc_error_get_int(error, which, nullptr)) { + if (grpc_error_get_int(error, which, &unused)) { return error; } if (grpc_error_is_special(error)) return nullptr; @@ -102,7 +103,8 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline, } bool grpc_error_has_clear_grpc_status(grpc_error* error) { - if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, nullptr)) { + intptr_t unused; + if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) { return true; } uint8_t slot = error->first_err; diff --git a/Sources/CgRPC/src/core/lib/transport/metadata.cc b/Sources/CgRPC/src/core/lib/transport/metadata.cc index d10194a2f..30482a1b3 100644 --- a/Sources/CgRPC/src/core/lib/transport/metadata.cc +++ b/Sources/CgRPC/src/core/lib/transport/metadata.cc @@ -187,6 +187,7 @@ static void gc_mdtab(mdtab_shard* shard) { ((destroy_user_data_func)gpr_atm_no_barrier_load( &md->destroy_user_data))(user_data); } + gpr_mu_destroy(&md->mu_user_data); gpr_free(md); *prev_next = next; num_freed++; @@ -237,7 +238,7 @@ static void rehash_mdtab(mdtab_shard* shard) { } grpc_mdelem grpc_mdelem_create( - grpc_slice key, grpc_slice value, + const grpc_slice& key, const grpc_slice& value, grpc_mdelem_data* compatible_external_backing_store) { if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) { if (compatible_external_backing_store != nullptr) { @@ -324,7 +325,8 @@ grpc_mdelem grpc_mdelem_create( return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); } -grpc_mdelem grpc_mdelem_from_slices(grpc_slice key, grpc_slice value) { +grpc_mdelem grpc_mdelem_from_slices(const grpc_slice& key, + const grpc_slice& value) { grpc_mdelem out = grpc_mdelem_create(key, value, nullptr); grpc_slice_unref_internal(key); grpc_slice_unref_internal(value); @@ -342,24 +344,6 @@ grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata) { changed ? nullptr : reinterpret_cast(metadata)); } -static size_t get_base64_encoded_size(size_t raw_length) { - static const uint8_t tail_xtra[3] = {0, 2, 3}; - return raw_length / 3 * 4 + tail_xtra[raw_length % 3]; -} - -size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem, - bool use_true_binary_metadata) { - size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); - size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem)); - if (grpc_is_binary_header(GRPC_MDKEY(elem))) { - return overhead_and_key + (use_true_binary_metadata - ? value_len + 1 - : get_base64_encoded_size(value_len)); - } else { - return overhead_and_key + value_len; - } -} - grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) { switch (GRPC_MDELEM_STORAGE(gmd)) { case GRPC_MDELEM_STORAGE_EXTERNAL: diff --git a/Sources/CgRPC/src/core/lib/transport/metadata.h b/Sources/CgRPC/src/core/lib/transport/metadata.h index 78df4bc3a..989c7544c 100644 --- a/Sources/CgRPC/src/core/lib/transport/metadata.h +++ b/Sources/CgRPC/src/core/lib/transport/metadata.h @@ -109,7 +109,8 @@ struct grpc_mdelem { (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT)) /* Unrefs the slices. */ -grpc_mdelem grpc_mdelem_from_slices(grpc_slice key, grpc_slice value); +grpc_mdelem grpc_mdelem_from_slices(const grpc_slice& key, + const grpc_slice& value); /* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata object as backing storage (so lifetimes should align) */ @@ -120,14 +121,11 @@ grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata); compatible_external_backing_store if it is non-NULL (in which case it's the users responsibility to ensure that it outlives usage) */ grpc_mdelem grpc_mdelem_create( - grpc_slice key, grpc_slice value, + const grpc_slice& key, const grpc_slice& value, grpc_mdelem_data* compatible_external_backing_store); bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b); -size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem, - bool use_true_binary_metadata); - /* Mutator and accessor for grpc_mdelem user data. The destructor function is used as a type tag and is checked during user_data fetch. */ void* grpc_mdelem_get_user_data(grpc_mdelem md, void (*if_destroy_func)(void*)); diff --git a/Sources/CgRPC/src/core/lib/transport/metadata_batch.cc b/Sources/CgRPC/src/core/lib/transport/metadata_batch.cc index 49740fcd1..928ed73cd 100644 --- a/Sources/CgRPC/src/core/lib/transport/metadata_batch.cc +++ b/Sources/CgRPC/src/core/lib/transport/metadata_batch.cc @@ -105,7 +105,7 @@ static grpc_error* maybe_link_callout(grpc_metadata_batch* batch, return GRPC_ERROR_NONE; } if (batch->idx.array[idx] == nullptr) { - if (grpc_static_callout_is_default[idx]) ++batch->list.default_count; + ++batch->list.default_count; batch->idx.array[idx] = storage; return GRPC_ERROR_NONE; } @@ -121,7 +121,7 @@ static void maybe_unlink_callout(grpc_metadata_batch* batch, if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return; } - if (grpc_static_callout_is_default[idx]) --batch->list.default_count; + --batch->list.default_count; GPR_ASSERT(batch->idx.array[idx] != nullptr); batch->idx.array[idx] = nullptr; } @@ -139,6 +139,7 @@ static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { GPR_ASSERT(!GRPC_MDISNULL(storage->md)); storage->prev = nullptr; storage->next = list->head; + storage->reserved = nullptr; if (list->head != nullptr) { list->head->prev = storage; } else { diff --git a/Sources/CgRPC/src/core/lib/transport/metadata_batch.h b/Sources/CgRPC/src/core/lib/transport/metadata_batch.h index 7068750b6..f6e8bbf20 100644 --- a/Sources/CgRPC/src/core/lib/transport/metadata_batch.h +++ b/Sources/CgRPC/src/core/lib/transport/metadata_batch.h @@ -31,9 +31,11 @@ #include "src/core/lib/transport/static_metadata.h" typedef struct grpc_linked_mdelem { + grpc_linked_mdelem() {} + grpc_mdelem md; - struct grpc_linked_mdelem* next; - struct grpc_linked_mdelem* prev; + struct grpc_linked_mdelem* next = nullptr; + struct grpc_linked_mdelem* prev = nullptr; void* reserved; } grpc_linked_mdelem; @@ -82,6 +84,7 @@ void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, grpc_error* grpc_metadata_batch_link_head(grpc_metadata_batch* batch, grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; + /** Add \a storage to the end of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the @@ -100,6 +103,7 @@ grpc_error* grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, grpc_error* grpc_metadata_batch_add_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; + /** Add \a elem_to_add as the last element in \a batch, using \a storage as backing storage for the linked list element. \a storage is owned by the caller and must survive for the diff --git a/Sources/CgRPC/src/core/lib/transport/service_config.cc b/Sources/CgRPC/src/core/lib/transport/service_config.cc index e1a55d98a..405e33602 100644 --- a/Sources/CgRPC/src/core/lib/transport/service_config.cc +++ b/Sources/CgRPC/src/core/lib/transport/service_config.cc @@ -65,8 +65,8 @@ const char* ServiceConfig::GetLoadBalancingPolicyName() const { return lb_policy_name; } -size_t ServiceConfig::CountNamesInMethodConfig(grpc_json* json) { - size_t num_names = 0; +int ServiceConfig::CountNamesInMethodConfig(grpc_json* json) { + int num_names = 0; for (grpc_json* field = json->child; field != nullptr; field = field->next) { if (field->key != nullptr && strcmp(field->key, "name") == 0) { if (field->type != GRPC_JSON_ARRAY) return -1; diff --git a/Sources/CgRPC/src/core/lib/transport/service_config.h b/Sources/CgRPC/src/core/lib/transport/service_config.h index a65b267d4..0d78016ab 100644 --- a/Sources/CgRPC/src/core/lib/transport/service_config.h +++ b/Sources/CgRPC/src/core/lib/transport/service_config.h @@ -103,7 +103,7 @@ class ServiceConfig { ServiceConfig(UniquePtr json_string, grpc_json* json_tree); // Returns the number of names specified in the method config \a json. - static size_t CountNamesInMethodConfig(grpc_json* json); + static int CountNamesInMethodConfig(grpc_json* json); // Returns a path string for the JSON name object specified by \a json. // Returns null on error. @@ -188,9 +188,9 @@ ServiceConfig::CreateMethodConfigTable(CreateValue create_value) { // Find number of entries. for (grpc_json* method = field->child; method != nullptr; method = method->next) { - size_t count = CountNamesInMethodConfig(method); + int count = CountNamesInMethodConfig(method); if (count <= 0) return nullptr; - num_entries += count; + num_entries += static_cast(count); } // Populate method config table entries. entries = static_cast>::Entry*>( @@ -240,6 +240,7 @@ RefCountedPtr ServiceConfig::MethodConfigTableLookup( value = table.Get(wildcard_path); grpc_slice_unref_internal(wildcard_path); gpr_free(path_str); + if (value == nullptr) return nullptr; } return RefCountedPtr(*value); } diff --git a/Sources/CgRPC/src/core/lib/transport/static_metadata.cc b/Sources/CgRPC/src/core/lib/transport/static_metadata.cc index 6a5144f21..963626a9d 100644 --- a/Sources/CgRPC/src/core/lib/transport/static_metadata.cc +++ b/Sources/CgRPC/src/core/lib/transport/static_metadata.cc @@ -63,51 +63,58 @@ static uint8_t g_bytes[] = { 115, 115, 97, 103, 101, 95, 98, 121, 116, 101, 115, 47, 103, 114, 112, 99, 46, 108, 98, 46, 118, 49, 46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99, 101, 114, 47, 66, 97, 108, 97, 110, 99, 101, 76, 111, - 97, 100, 100, 101, 102, 108, 97, 116, 101, 103, 122, 105, 112, 115, 116, - 114, 101, 97, 109, 47, 103, 122, 105, 112, 48, 105, 100, 101, 110, 116, - 105, 116, 121, 116, 114, 97, 105, 108, 101, 114, 115, 97, 112, 112, 108, - 105, 99, 97, 116, 105, 111, 110, 47, 103, 114, 112, 99, 80, 79, 83, - 84, 50, 48, 48, 52, 48, 52, 104, 116, 116, 112, 104, 116, 116, 112, - 115, 103, 114, 112, 99, 71, 69, 84, 80, 85, 84, 47, 47, 105, 110, - 100, 101, 120, 46, 104, 116, 109, 108, 50, 48, 52, 50, 48, 54, 51, - 48, 52, 52, 48, 48, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, - 99, 104, 97, 114, 115, 101, 116, 103, 122, 105, 112, 44, 32, 100, 101, - 102, 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, - 103, 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, - 103, 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, - 45, 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, - 111, 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, - 117, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, - 104, 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, - 110, 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, - 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, - 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99, - 111, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110, - 99, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111, - 111, 107, 105, 101, 100, 97, 116, 101, 101, 116, 97, 103, 101, 120, 112, - 101, 99, 116, 101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 105, - 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100, 105, 102, - 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102, 45, 110, 111, 110, - 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114, 97, 110, 103, 101, - 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105, 101, 100, 45, 115, - 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111, 100, 105, 102, 105, - 101, 100, 108, 98, 45, 99, 111, 115, 116, 45, 98, 105, 110, 108, 105, - 110, 107, 108, 111, 99, 97, 116, 105, 111, 110, 109, 97, 120, 45, 102, - 111, 114, 119, 97, 114, 100, 115, 112, 114, 111, 120, 121, 45, 97, 117, - 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 112, 114, 111, 120, 121, - 45, 97, 117, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 114, - 97, 110, 103, 101, 114, 101, 102, 101, 114, 101, 114, 114, 101, 102, 114, - 101, 115, 104, 114, 101, 116, 114, 121, 45, 97, 102, 116, 101, 114, 115, - 101, 114, 118, 101, 114, 115, 101, 116, 45, 99, 111, 111, 107, 105, 101, - 115, 116, 114, 105, 99, 116, 45, 116, 114, 97, 110, 115, 112, 111, 114, - 116, 45, 115, 101, 99, 117, 114, 105, 116, 121, 116, 114, 97, 110, 115, - 102, 101, 114, 45, 101, 110, 99, 111, 100, 105, 110, 103, 118, 97, 114, - 121, 118, 105, 97, 119, 119, 119, 45, 97, 117, 116, 104, 101, 110, 116, - 105, 99, 97, 116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, - 101, 102, 108, 97, 116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, - 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, - 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, - 116, 101, 44, 103, 122, 105, 112}; + 97, 100, 47, 103, 114, 112, 99, 46, 104, 101, 97, 108, 116, 104, 46, + 118, 49, 46, 72, 101, 97, 108, 116, 104, 47, 87, 97, 116, 99, 104, + 47, 101, 110, 118, 111, 121, 46, 115, 101, 114, 118, 105, 99, 101, 46, + 100, 105, 115, 99, 111, 118, 101, 114, 121, 46, 118, 50, 46, 65, 103, + 103, 114, 101, 103, 97, 116, 101, 100, 68, 105, 115, 99, 111, 118, 101, + 114, 121, 83, 101, 114, 118, 105, 99, 101, 47, 83, 116, 114, 101, 97, + 109, 65, 103, 103, 114, 101, 103, 97, 116, 101, 100, 82, 101, 115, 111, + 117, 114, 99, 101, 115, 100, 101, 102, 108, 97, 116, 101, 103, 122, 105, + 112, 115, 116, 114, 101, 97, 109, 47, 103, 122, 105, 112, 71, 69, 84, + 80, 79, 83, 84, 47, 47, 105, 110, 100, 101, 120, 46, 104, 116, 109, + 108, 104, 116, 116, 112, 104, 116, 116, 112, 115, 50, 48, 48, 50, 48, + 52, 50, 48, 54, 51, 48, 52, 52, 48, 48, 52, 48, 52, 53, 48, + 48, 97, 99, 99, 101, 112, 116, 45, 99, 104, 97, 114, 115, 101, 116, + 103, 122, 105, 112, 44, 32, 100, 101, 102, 108, 97, 116, 101, 97, 99, + 99, 101, 112, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 97, 99, + 99, 101, 112, 116, 45, 114, 97, 110, 103, 101, 115, 97, 99, 99, 101, + 112, 116, 97, 99, 99, 101, 115, 115, 45, 99, 111, 110, 116, 114, 111, + 108, 45, 97, 108, 108, 111, 119, 45, 111, 114, 105, 103, 105, 110, 97, + 103, 101, 97, 108, 108, 111, 119, 97, 117, 116, 104, 111, 114, 105, 122, + 97, 116, 105, 111, 110, 99, 97, 99, 104, 101, 45, 99, 111, 110, 116, + 114, 111, 108, 99, 111, 110, 116, 101, 110, 116, 45, 100, 105, 115, 112, + 111, 115, 105, 116, 105, 111, 110, 99, 111, 110, 116, 101, 110, 116, 45, + 108, 97, 110, 103, 117, 97, 103, 101, 99, 111, 110, 116, 101, 110, 116, + 45, 108, 101, 110, 103, 116, 104, 99, 111, 110, 116, 101, 110, 116, 45, + 108, 111, 99, 97, 116, 105, 111, 110, 99, 111, 110, 116, 101, 110, 116, + 45, 114, 97, 110, 103, 101, 99, 111, 111, 107, 105, 101, 100, 97, 116, + 101, 101, 116, 97, 103, 101, 120, 112, 101, 99, 116, 101, 120, 112, 105, + 114, 101, 115, 102, 114, 111, 109, 105, 102, 45, 109, 97, 116, 99, 104, + 105, 102, 45, 109, 111, 100, 105, 102, 105, 101, 100, 45, 115, 105, 110, + 99, 101, 105, 102, 45, 110, 111, 110, 101, 45, 109, 97, 116, 99, 104, + 105, 102, 45, 114, 97, 110, 103, 101, 105, 102, 45, 117, 110, 109, 111, + 100, 105, 102, 105, 101, 100, 45, 115, 105, 110, 99, 101, 108, 97, 115, + 116, 45, 109, 111, 100, 105, 102, 105, 101, 100, 108, 105, 110, 107, 108, + 111, 99, 97, 116, 105, 111, 110, 109, 97, 120, 45, 102, 111, 114, 119, + 97, 114, 100, 115, 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 101, + 110, 116, 105, 99, 97, 116, 101, 112, 114, 111, 120, 121, 45, 97, 117, + 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 114, 97, 110, 103, + 101, 114, 101, 102, 101, 114, 101, 114, 114, 101, 102, 114, 101, 115, 104, + 114, 101, 116, 114, 121, 45, 97, 102, 116, 101, 114, 115, 101, 114, 118, + 101, 114, 115, 101, 116, 45, 99, 111, 111, 107, 105, 101, 115, 116, 114, + 105, 99, 116, 45, 116, 114, 97, 110, 115, 112, 111, 114, 116, 45, 115, + 101, 99, 117, 114, 105, 116, 121, 116, 114, 97, 110, 115, 102, 101, 114, + 45, 101, 110, 99, 111, 100, 105, 110, 103, 118, 97, 114, 121, 118, 105, + 97, 119, 119, 119, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, + 116, 101, 48, 105, 100, 101, 110, 116, 105, 116, 121, 116, 114, 97, 105, + 108, 101, 114, 115, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, + 47, 103, 114, 112, 99, 103, 114, 112, 99, 80, 85, 84, 108, 98, 45, + 99, 111, 115, 116, 45, 98, 105, 110, 105, 100, 101, 110, 116, 105, 116, + 121, 44, 100, 101, 102, 108, 97, 116, 101, 105, 100, 101, 110, 116, 105, + 116, 121, 44, 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101, 44, + 103, 122, 105, 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, + 102, 108, 97, 116, 101, 44, 103, 122, 105, 112}; static void static_ref(void* unused) {} static void static_unref(void* unused) {} @@ -224,114 +231,118 @@ grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = { {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, }; const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = { - {&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[3], {{g_bytes + 19, 10}}}, - {&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[5], {{g_bytes + 36, 2}}}, - {&grpc_static_metadata_refcounts[6], {{g_bytes + 38, 12}}}, - {&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[8], {{g_bytes + 61, 16}}}, - {&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[11], {{g_bytes + 110, 21}}}, - {&grpc_static_metadata_refcounts[12], {{g_bytes + 131, 13}}}, - {&grpc_static_metadata_refcounts[13], {{g_bytes + 144, 14}}}, - {&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[17], {{g_bytes + 201, 30}}}, - {&grpc_static_metadata_refcounts[18], {{g_bytes + 231, 37}}}, - {&grpc_static_metadata_refcounts[19], {{g_bytes + 268, 10}}}, - {&grpc_static_metadata_refcounts[20], {{g_bytes + 278, 4}}}, - {&grpc_static_metadata_refcounts[21], {{g_bytes + 282, 8}}}, - {&grpc_static_metadata_refcounts[22], {{g_bytes + 290, 26}}}, - {&grpc_static_metadata_refcounts[23], {{g_bytes + 316, 22}}}, - {&grpc_static_metadata_refcounts[24], {{g_bytes + 338, 12}}}, - {&grpc_static_metadata_refcounts[25], {{g_bytes + 350, 1}}}, - {&grpc_static_metadata_refcounts[26], {{g_bytes + 351, 1}}}, - {&grpc_static_metadata_refcounts[27], {{g_bytes + 352, 1}}}, - {&grpc_static_metadata_refcounts[28], {{g_bytes + 353, 1}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}, - {&grpc_static_metadata_refcounts[30], {{g_bytes + 354, 19}}}, - {&grpc_static_metadata_refcounts[31], {{g_bytes + 373, 12}}}, - {&grpc_static_metadata_refcounts[32], {{g_bytes + 385, 30}}}, - {&grpc_static_metadata_refcounts[33], {{g_bytes + 415, 31}}}, - {&grpc_static_metadata_refcounts[34], {{g_bytes + 446, 36}}}, - {&grpc_static_metadata_refcounts[35], {{g_bytes + 482, 7}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 489, 4}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 493, 11}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 504, 1}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 505, 8}}}, - {&grpc_static_metadata_refcounts[40], {{g_bytes + 513, 8}}}, - {&grpc_static_metadata_refcounts[41], {{g_bytes + 521, 16}}}, - {&grpc_static_metadata_refcounts[42], {{g_bytes + 537, 4}}}, - {&grpc_static_metadata_refcounts[43], {{g_bytes + 541, 3}}}, - {&grpc_static_metadata_refcounts[44], {{g_bytes + 544, 3}}}, - {&grpc_static_metadata_refcounts[45], {{g_bytes + 547, 4}}}, - {&grpc_static_metadata_refcounts[46], {{g_bytes + 551, 5}}}, - {&grpc_static_metadata_refcounts[47], {{g_bytes + 556, 4}}}, - {&grpc_static_metadata_refcounts[48], {{g_bytes + 560, 3}}}, - {&grpc_static_metadata_refcounts[49], {{g_bytes + 563, 3}}}, - {&grpc_static_metadata_refcounts[50], {{g_bytes + 566, 1}}}, - {&grpc_static_metadata_refcounts[51], {{g_bytes + 567, 11}}}, - {&grpc_static_metadata_refcounts[52], {{g_bytes + 578, 3}}}, - {&grpc_static_metadata_refcounts[53], {{g_bytes + 581, 3}}}, - {&grpc_static_metadata_refcounts[54], {{g_bytes + 584, 3}}}, - {&grpc_static_metadata_refcounts[55], {{g_bytes + 587, 3}}}, - {&grpc_static_metadata_refcounts[56], {{g_bytes + 590, 3}}}, - {&grpc_static_metadata_refcounts[57], {{g_bytes + 593, 14}}}, - {&grpc_static_metadata_refcounts[58], {{g_bytes + 607, 13}}}, - {&grpc_static_metadata_refcounts[59], {{g_bytes + 620, 15}}}, - {&grpc_static_metadata_refcounts[60], {{g_bytes + 635, 13}}}, - {&grpc_static_metadata_refcounts[61], {{g_bytes + 648, 6}}}, - {&grpc_static_metadata_refcounts[62], {{g_bytes + 654, 27}}}, - {&grpc_static_metadata_refcounts[63], {{g_bytes + 681, 3}}}, - {&grpc_static_metadata_refcounts[64], {{g_bytes + 684, 5}}}, - {&grpc_static_metadata_refcounts[65], {{g_bytes + 689, 13}}}, - {&grpc_static_metadata_refcounts[66], {{g_bytes + 702, 13}}}, - {&grpc_static_metadata_refcounts[67], {{g_bytes + 715, 19}}}, - {&grpc_static_metadata_refcounts[68], {{g_bytes + 734, 16}}}, - {&grpc_static_metadata_refcounts[69], {{g_bytes + 750, 14}}}, - {&grpc_static_metadata_refcounts[70], {{g_bytes + 764, 16}}}, - {&grpc_static_metadata_refcounts[71], {{g_bytes + 780, 13}}}, - {&grpc_static_metadata_refcounts[72], {{g_bytes + 793, 6}}}, - {&grpc_static_metadata_refcounts[73], {{g_bytes + 799, 4}}}, - {&grpc_static_metadata_refcounts[74], {{g_bytes + 803, 4}}}, - {&grpc_static_metadata_refcounts[75], {{g_bytes + 807, 6}}}, - {&grpc_static_metadata_refcounts[76], {{g_bytes + 813, 7}}}, - {&grpc_static_metadata_refcounts[77], {{g_bytes + 820, 4}}}, - {&grpc_static_metadata_refcounts[78], {{g_bytes + 824, 8}}}, - {&grpc_static_metadata_refcounts[79], {{g_bytes + 832, 17}}}, - {&grpc_static_metadata_refcounts[80], {{g_bytes + 849, 13}}}, - {&grpc_static_metadata_refcounts[81], {{g_bytes + 862, 8}}}, - {&grpc_static_metadata_refcounts[82], {{g_bytes + 870, 19}}}, - {&grpc_static_metadata_refcounts[83], {{g_bytes + 889, 13}}}, - {&grpc_static_metadata_refcounts[84], {{g_bytes + 902, 11}}}, - {&grpc_static_metadata_refcounts[85], {{g_bytes + 913, 4}}}, - {&grpc_static_metadata_refcounts[86], {{g_bytes + 917, 8}}}, - {&grpc_static_metadata_refcounts[87], {{g_bytes + 925, 12}}}, - {&grpc_static_metadata_refcounts[88], {{g_bytes + 937, 18}}}, - {&grpc_static_metadata_refcounts[89], {{g_bytes + 955, 19}}}, - {&grpc_static_metadata_refcounts[90], {{g_bytes + 974, 5}}}, - {&grpc_static_metadata_refcounts[91], {{g_bytes + 979, 7}}}, - {&grpc_static_metadata_refcounts[92], {{g_bytes + 986, 7}}}, - {&grpc_static_metadata_refcounts[93], {{g_bytes + 993, 11}}}, - {&grpc_static_metadata_refcounts[94], {{g_bytes + 1004, 6}}}, - {&grpc_static_metadata_refcounts[95], {{g_bytes + 1010, 10}}}, - {&grpc_static_metadata_refcounts[96], {{g_bytes + 1020, 25}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1045, 17}}}, - {&grpc_static_metadata_refcounts[98], {{g_bytes + 1062, 4}}}, - {&grpc_static_metadata_refcounts[99], {{g_bytes + 1066, 3}}}, - {&grpc_static_metadata_refcounts[100], {{g_bytes + 1069, 16}}}, - {&grpc_static_metadata_refcounts[101], {{g_bytes + 1085, 16}}}, - {&grpc_static_metadata_refcounts[102], {{g_bytes + 1101, 13}}}, - {&grpc_static_metadata_refcounts[103], {{g_bytes + 1114, 12}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1126, 21}}}, + {&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}}, + {&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}}, + {&grpc_static_metadata_refcounts[6], {{12, g_bytes + 38}}}, + {&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[8], {{16, g_bytes + 61}}}, + {&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[11], {{21, g_bytes + 110}}}, + {&grpc_static_metadata_refcounts[12], {{13, g_bytes + 131}}}, + {&grpc_static_metadata_refcounts[13], {{14, g_bytes + 144}}}, + {&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[17], {{30, g_bytes + 201}}}, + {&grpc_static_metadata_refcounts[18], {{37, g_bytes + 231}}}, + {&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}}, + {&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}}, + {&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}}, + {&grpc_static_metadata_refcounts[22], {{26, g_bytes + 290}}}, + {&grpc_static_metadata_refcounts[23], {{22, g_bytes + 316}}}, + {&grpc_static_metadata_refcounts[24], {{12, g_bytes + 338}}}, + {&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}, + {&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}, + {&grpc_static_metadata_refcounts[27], {{1, g_bytes + 352}}}, + {&grpc_static_metadata_refcounts[28], {{1, g_bytes + 353}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, + {&grpc_static_metadata_refcounts[30], {{19, g_bytes + 354}}}, + {&grpc_static_metadata_refcounts[31], {{12, g_bytes + 373}}}, + {&grpc_static_metadata_refcounts[32], {{30, g_bytes + 385}}}, + {&grpc_static_metadata_refcounts[33], {{31, g_bytes + 415}}}, + {&grpc_static_metadata_refcounts[34], {{36, g_bytes + 446}}}, + {&grpc_static_metadata_refcounts[35], {{28, g_bytes + 482}}}, + {&grpc_static_metadata_refcounts[36], {{80, g_bytes + 510}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, + {&grpc_static_metadata_refcounts[39], {{11, g_bytes + 601}}}, + {&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}, + {&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}, + {&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}, + {&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}, + {&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}, + {&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}, + {&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}, + {&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}, + {&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}, + {&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}, + {&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}, + {&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}, + {&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}, + {&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}}, + {&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}, + {&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}}, + {&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}}, + {&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}}, + {&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}}, + {&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}}, + {&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}}, + {&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}}, + {&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}}, + {&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}}, + {&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}}, + {&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}}, + {&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}}, + {&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}}, + {&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}}, + {&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}}, + {&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}}, + {&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}}, + {&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}}, + {&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}}, + {&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}}, + {&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}}, + {&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}}, + {&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}}, + {&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}}, + {&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}}, + {&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}}, + {&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}}, + {&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}}, + {&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}}, + {&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}}, + {&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}}, + {&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}}, + {&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}}, + {&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}}, + {&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}}, + {&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}}, + {&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}}, + {&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}}, + {&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}}, + {&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}}, + {&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}}, + {&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, + {&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}, + {&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}, + {&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}, + {&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}, + {&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}}, + {&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}, + {&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}, + {&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}, }; uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { @@ -341,16 +352,17 @@ uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8, 2, 4, 4}; static const int8_t elems_r[] = { - 16, 11, -1, 0, 15, 2, -78, 24, 0, 18, -5, 0, 0, 0, 17, 14, -8, 0, - 0, 27, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -64, 0, -44, -43, -70, 0, 34, 33, 33, 32, 31, 30, 29, 28, 27, - 27, 26, 25, 24, 23, 22, 21, 20, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, - 11, 14, 13, 12, 11, 10, 9, 9, 8, 7, 6, 5, 0}; + 15, 10, -8, 0, 2, -42, -81, -43, 0, 6, -8, 0, 0, 0, 2, + -3, -10, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -64, 0, -67, -68, -69, -70, 0, + 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, + 5, 4, 5, 4, 4, 8, 8, 0, 0, 0, 0, 0, 0, -5, 0}; static uint32_t elems_phash(uint32_t i) { - i -= 50; - uint32_t x = i % 103; - uint32_t y = i / 103; + i -= 42; + uint32_t x = i % 105; + uint32_t y = i / 105; uint32_t h = x; if (y < GPR_ARRAY_SIZE(elems_r)) { uint32_t delta = (uint32_t)elems_r[y]; @@ -360,32 +372,29 @@ static uint32_t elems_phash(uint32_t i) { } static const uint16_t elem_keys[] = { - 1085, 1086, 565, 1709, 1089, 262, 263, 264, 265, 266, 1716, - 153, 154, 1719, 760, 761, 50, 51, 465, 466, 467, 980, - 981, 1604, 1499, 984, 773, 2129, 2234, 6014, 1611, 6434, 1738, - 1614, 6539, 6644, 1511, 6749, 6854, 6959, 7064, 7169, 7274, 7379, - 2024, 7484, 7589, 7694, 7799, 7904, 8009, 8114, 8219, 6224, 8324, - 8429, 6329, 8534, 8639, 8744, 8849, 8954, 9059, 9164, 9269, 9374, - 1151, 1152, 1153, 1154, 9479, 9584, 9689, 9794, 9899, 10004, 1782, - 10109, 10214, 10319, 10424, 10529, 0, 0, 0, 0, 0, 344, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 253, 254, 147, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0}; + 260, 261, 262, 263, 264, 265, 266, 1107, 1108, 1741, 147, 148, + 472, 473, 1634, 42, 43, 1527, 1750, 1000, 1001, 774, 775, 1643, + 633, 845, 2062, 2169, 2276, 5700, 5914, 6021, 6128, 6235, 1766, 6342, + 6449, 6556, 6663, 6770, 6877, 6984, 7091, 7198, 7305, 7412, 7519, 7626, + 7733, 7840, 7947, 8054, 8161, 8268, 8375, 8482, 8589, 8696, 8803, 8910, + 9017, 9124, 9231, 9338, 9445, 9552, 9659, 1167, 528, 9766, 9873, 208, + 9980, 1173, 1174, 1175, 1176, 1809, 10087, 1060, 10194, 10943, 1702, 0, + 1816, 0, 0, 1597, 0, 0, 350, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0}; static const uint8_t elem_idxs[] = { - 77, 79, 6, 25, 76, 19, 20, 21, 22, 23, 84, 15, 16, 83, 1, - 2, 17, 18, 11, 12, 13, 5, 4, 38, 43, 3, 0, 50, 57, 24, - 37, 29, 26, 36, 30, 31, 7, 32, 33, 34, 35, 39, 40, 41, 72, - 42, 44, 45, 46, 47, 48, 49, 51, 27, 52, 53, 28, 54, 55, 56, - 58, 59, 60, 61, 62, 63, 78, 80, 81, 82, 64, 65, 66, 67, 68, - 69, 85, 70, 71, 73, 74, 75, 255, 255, 255, 255, 255, 14, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 9, 10, 8}; + 7, 8, 9, 10, 11, 12, 13, 77, 79, 71, 1, 2, 5, 6, 25, 3, + 4, 30, 84, 66, 65, 62, 63, 73, 67, 61, 57, 37, 74, 14, 16, 17, + 18, 19, 15, 20, 21, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34, + 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 76, 69, 55, 56, 70, 58, 78, 80, 81, 82, 83, 59, 64, + 60, 75, 72, 255, 85, 255, 255, 68, 255, 255, 0}; grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) { if (a == -1 || b == -1) return GRPC_MDNULL; - uint32_t k = (uint32_t)(a * 105 + b); + uint32_t k = (uint32_t)(a * 107 + b); uint32_t h = elems_phash(k); return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k && elem_idxs[h] != 255 @@ -395,206 +404,179 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) { } grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 504, 1}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[25], {{g_bytes + 350, 1}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[26], {{g_bytes + 351, 1}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 505, 8}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 489, 4}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[35], {{g_bytes + 482, 7}}}}, - {{&grpc_static_metadata_refcounts[5], {{g_bytes + 36, 2}}}, - {&grpc_static_metadata_refcounts[40], {{g_bytes + 513, 8}}}}, - {{&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[41], {{g_bytes + 521, 16}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[42], {{g_bytes + 537, 4}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[43], {{g_bytes + 541, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[44], {{g_bytes + 544, 3}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[45], {{g_bytes + 547, 4}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[46], {{g_bytes + 551, 5}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[47], {{g_bytes + 556, 4}}}}, - {{&grpc_static_metadata_refcounts[3], {{g_bytes + 19, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[48], {{g_bytes + 560, 3}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[49], {{g_bytes + 563, 3}}}}, - {{&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[50], {{g_bytes + 566, 1}}}}, - {{&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[51], {{g_bytes + 567, 11}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[52], {{g_bytes + 578, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[53], {{g_bytes + 581, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[54], {{g_bytes + 584, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[55], {{g_bytes + 587, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[56], {{g_bytes + 590, 3}}}}, - {{&grpc_static_metadata_refcounts[57], {{g_bytes + 593, 14}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[58], {{g_bytes + 607, 13}}}}, - {{&grpc_static_metadata_refcounts[59], {{g_bytes + 620, 15}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[60], {{g_bytes + 635, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[61], {{g_bytes + 648, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[62], {{g_bytes + 654, 27}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[63], {{g_bytes + 681, 3}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[64], {{g_bytes + 684, 5}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[65], {{g_bytes + 689, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[66], {{g_bytes + 702, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[67], {{g_bytes + 715, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 505, 8}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 489, 4}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[68], {{g_bytes + 734, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[69], {{g_bytes + 750, 14}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[70], {{g_bytes + 764, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[71], {{g_bytes + 780, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[72], {{g_bytes + 793, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[73], {{g_bytes + 799, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[74], {{g_bytes + 803, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[75], {{g_bytes + 807, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[76], {{g_bytes + 813, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[77], {{g_bytes + 820, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[20], {{g_bytes + 278, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[78], {{g_bytes + 824, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[79], {{g_bytes + 832, 17}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[80], {{g_bytes + 849, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[81], {{g_bytes + 862, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[82], {{g_bytes + 870, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[83], {{g_bytes + 889, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[21], {{g_bytes + 282, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[84], {{g_bytes + 902, 11}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[85], {{g_bytes + 913, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[86], {{g_bytes + 917, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[87], {{g_bytes + 925, 12}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[88], {{g_bytes + 937, 18}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[89], {{g_bytes + 955, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[90], {{g_bytes + 974, 5}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[91], {{g_bytes + 979, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[92], {{g_bytes + 986, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[93], {{g_bytes + 993, 11}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[94], {{g_bytes + 1004, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[95], {{g_bytes + 1010, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[96], {{g_bytes + 1020, 25}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[97], {{g_bytes + 1045, 17}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[19], {{g_bytes + 268, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[98], {{g_bytes + 1062, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[99], {{g_bytes + 1066, 3}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[100], {{g_bytes + 1069, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 505, 8}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[35], {{g_bytes + 482, 7}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[101], {{g_bytes + 1085, 16}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 489, 4}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[102], {{g_bytes + 1101, 13}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[103], {{g_bytes + 1114, 12}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1126, 21}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 505, 8}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 489, 4}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[102], {{g_bytes + 1101, 13}}}}, + {{&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}}, + {{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}}, + {{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}}, + {{&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}}, + {{&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}}, + {{&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}}, + {&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}}, + {{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}}, }; -bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT] = { - true, // :path - true, // :method - true, // :status - true, // :authority - true, // :scheme - true, // te - true, // grpc-message - true, // grpc-status - true, // grpc-payload-bin - true, // grpc-encoding - true, // grpc-accept-encoding - true, // grpc-server-stats-bin - true, // grpc-tags-bin - true, // grpc-trace-bin - true, // content-type - true, // content-encoding - true, // accept-encoding - true, // grpc-internal-encoding-request - true, // grpc-internal-stream-encoding-request - true, // user-agent - true, // host - true, // lb-token - true, // grpc-previous-rpc-attempts - true, // grpc-retry-pushback-ms -}; - const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 76, 77, 78, 79, 80, 81, 82}; diff --git a/Sources/CgRPC/src/core/lib/transport/static_metadata.h b/Sources/CgRPC/src/core/lib/transport/static_metadata.h index b3a10f587..4f9670232 100644 --- a/Sources/CgRPC/src/core/lib/transport/static_metadata.h +++ b/Sources/CgRPC/src/core/lib/transport/static_metadata.h @@ -31,7 +31,7 @@ #include "src/core/lib/transport/metadata.h" -#define GRPC_STATIC_MDSTR_COUNT 105 +#define GRPC_STATIC_MDSTR_COUNT 107 extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT]; /* ":path" */ #define GRPC_MDSTR_PATH (grpc_static_slice_table[0]) @@ -107,147 +107,154 @@ extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT]; /* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */ #define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \ (grpc_static_slice_table[34]) +/* "/grpc.health.v1.Health/Watch" */ +#define GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH \ + (grpc_static_slice_table[35]) +/* "/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources" + */ +#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \ + (grpc_static_slice_table[36]) /* "deflate" */ -#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[35]) +#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[37]) /* "gzip" */ -#define GRPC_MDSTR_GZIP (grpc_static_slice_table[36]) +#define GRPC_MDSTR_GZIP (grpc_static_slice_table[38]) /* "stream/gzip" */ -#define GRPC_MDSTR_STREAM_SLASH_GZIP (grpc_static_slice_table[37]) -/* "0" */ -#define GRPC_MDSTR_0 (grpc_static_slice_table[38]) -/* "identity" */ -#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[39]) -/* "trailers" */ -#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[40]) -/* "application/grpc" */ -#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[41]) -/* "POST" */ -#define GRPC_MDSTR_POST (grpc_static_slice_table[42]) -/* "200" */ -#define GRPC_MDSTR_200 (grpc_static_slice_table[43]) -/* "404" */ -#define GRPC_MDSTR_404 (grpc_static_slice_table[44]) -/* "http" */ -#define GRPC_MDSTR_HTTP (grpc_static_slice_table[45]) -/* "https" */ -#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[46]) -/* "grpc" */ -#define GRPC_MDSTR_GRPC (grpc_static_slice_table[47]) +#define GRPC_MDSTR_STREAM_SLASH_GZIP (grpc_static_slice_table[39]) /* "GET" */ -#define GRPC_MDSTR_GET (grpc_static_slice_table[48]) -/* "PUT" */ -#define GRPC_MDSTR_PUT (grpc_static_slice_table[49]) +#define GRPC_MDSTR_GET (grpc_static_slice_table[40]) +/* "POST" */ +#define GRPC_MDSTR_POST (grpc_static_slice_table[41]) /* "/" */ -#define GRPC_MDSTR_SLASH (grpc_static_slice_table[50]) +#define GRPC_MDSTR_SLASH (grpc_static_slice_table[42]) /* "/index.html" */ -#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[51]) +#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[43]) +/* "http" */ +#define GRPC_MDSTR_HTTP (grpc_static_slice_table[44]) +/* "https" */ +#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[45]) +/* "200" */ +#define GRPC_MDSTR_200 (grpc_static_slice_table[46]) /* "204" */ -#define GRPC_MDSTR_204 (grpc_static_slice_table[52]) +#define GRPC_MDSTR_204 (grpc_static_slice_table[47]) /* "206" */ -#define GRPC_MDSTR_206 (grpc_static_slice_table[53]) +#define GRPC_MDSTR_206 (grpc_static_slice_table[48]) /* "304" */ -#define GRPC_MDSTR_304 (grpc_static_slice_table[54]) +#define GRPC_MDSTR_304 (grpc_static_slice_table[49]) /* "400" */ -#define GRPC_MDSTR_400 (grpc_static_slice_table[55]) +#define GRPC_MDSTR_400 (grpc_static_slice_table[50]) +/* "404" */ +#define GRPC_MDSTR_404 (grpc_static_slice_table[51]) /* "500" */ -#define GRPC_MDSTR_500 (grpc_static_slice_table[56]) +#define GRPC_MDSTR_500 (grpc_static_slice_table[52]) /* "accept-charset" */ -#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[57]) +#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[53]) /* "gzip, deflate" */ -#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[58]) +#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[54]) /* "accept-language" */ -#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[59]) +#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[55]) /* "accept-ranges" */ -#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[60]) +#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[56]) /* "accept" */ -#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[61]) +#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[57]) /* "access-control-allow-origin" */ -#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[62]) +#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[58]) /* "age" */ -#define GRPC_MDSTR_AGE (grpc_static_slice_table[63]) +#define GRPC_MDSTR_AGE (grpc_static_slice_table[59]) /* "allow" */ -#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[64]) +#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[60]) /* "authorization" */ -#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[65]) +#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[61]) /* "cache-control" */ -#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[66]) +#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[62]) /* "content-disposition" */ -#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[67]) +#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[63]) /* "content-language" */ -#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[68]) +#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[64]) /* "content-length" */ -#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[69]) +#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[65]) /* "content-location" */ -#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[70]) +#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[66]) /* "content-range" */ -#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[71]) +#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[67]) /* "cookie" */ -#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[72]) +#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[68]) /* "date" */ -#define GRPC_MDSTR_DATE (grpc_static_slice_table[73]) +#define GRPC_MDSTR_DATE (grpc_static_slice_table[69]) /* "etag" */ -#define GRPC_MDSTR_ETAG (grpc_static_slice_table[74]) +#define GRPC_MDSTR_ETAG (grpc_static_slice_table[70]) /* "expect" */ -#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[75]) +#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[71]) /* "expires" */ -#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[76]) +#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[72]) /* "from" */ -#define GRPC_MDSTR_FROM (grpc_static_slice_table[77]) +#define GRPC_MDSTR_FROM (grpc_static_slice_table[73]) /* "if-match" */ -#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[78]) +#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[74]) /* "if-modified-since" */ -#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[79]) +#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[75]) /* "if-none-match" */ -#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[80]) +#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[76]) /* "if-range" */ -#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[81]) +#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[77]) /* "if-unmodified-since" */ -#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[82]) +#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[78]) /* "last-modified" */ -#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[83]) -/* "lb-cost-bin" */ -#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[84]) +#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[79]) /* "link" */ -#define GRPC_MDSTR_LINK (grpc_static_slice_table[85]) +#define GRPC_MDSTR_LINK (grpc_static_slice_table[80]) /* "location" */ -#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[86]) +#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[81]) /* "max-forwards" */ -#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[87]) +#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[82]) /* "proxy-authenticate" */ -#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[88]) +#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[83]) /* "proxy-authorization" */ -#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[89]) +#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[84]) /* "range" */ -#define GRPC_MDSTR_RANGE (grpc_static_slice_table[90]) +#define GRPC_MDSTR_RANGE (grpc_static_slice_table[85]) /* "referer" */ -#define GRPC_MDSTR_REFERER (grpc_static_slice_table[91]) +#define GRPC_MDSTR_REFERER (grpc_static_slice_table[86]) /* "refresh" */ -#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[92]) +#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[87]) /* "retry-after" */ -#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[93]) +#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[88]) /* "server" */ -#define GRPC_MDSTR_SERVER (grpc_static_slice_table[94]) +#define GRPC_MDSTR_SERVER (grpc_static_slice_table[89]) /* "set-cookie" */ -#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[95]) +#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[90]) /* "strict-transport-security" */ -#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[96]) +#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[91]) /* "transfer-encoding" */ -#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[97]) +#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[92]) /* "vary" */ -#define GRPC_MDSTR_VARY (grpc_static_slice_table[98]) +#define GRPC_MDSTR_VARY (grpc_static_slice_table[93]) /* "via" */ -#define GRPC_MDSTR_VIA (grpc_static_slice_table[99]) +#define GRPC_MDSTR_VIA (grpc_static_slice_table[94]) /* "www-authenticate" */ -#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[100]) +#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[95]) +/* "0" */ +#define GRPC_MDSTR_0 (grpc_static_slice_table[96]) +/* "identity" */ +#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[97]) +/* "trailers" */ +#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[98]) +/* "application/grpc" */ +#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[99]) +/* "grpc" */ +#define GRPC_MDSTR_GRPC (grpc_static_slice_table[100]) +/* "PUT" */ +#define GRPC_MDSTR_PUT (grpc_static_slice_table[101]) +/* "lb-cost-bin" */ +#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[102]) /* "identity,deflate" */ -#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[101]) +#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[103]) /* "identity,gzip" */ -#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[102]) +#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[104]) /* "deflate,gzip" */ -#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[103]) +#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[105]) /* "identity,deflate,gzip" */ #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ - (grpc_static_slice_table[104]) + (grpc_static_slice_table[106]) extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable; extern grpc_slice_refcount @@ -262,233 +269,233 @@ extern grpc_slice_refcount #define GRPC_STATIC_MDELEM_COUNT 86 extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; -/* "grpc-status": "0" */ -#define GRPC_MDELEM_GRPC_STATUS_0 \ +/* ":authority": "" */ +#define GRPC_MDELEM_AUTHORITY_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[0], GRPC_MDELEM_STORAGE_STATIC)) -/* "grpc-status": "1" */ -#define GRPC_MDELEM_GRPC_STATUS_1 \ +/* ":method": "GET" */ +#define GRPC_MDELEM_METHOD_GET \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[1], GRPC_MDELEM_STORAGE_STATIC)) -/* "grpc-status": "2" */ -#define GRPC_MDELEM_GRPC_STATUS_2 \ +/* ":method": "POST" */ +#define GRPC_MDELEM_METHOD_POST \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[2], GRPC_MDELEM_STORAGE_STATIC)) -/* "grpc-encoding": "identity" */ -#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \ +/* ":path": "/" */ +#define GRPC_MDELEM_PATH_SLASH \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[3], GRPC_MDELEM_STORAGE_STATIC)) -/* "grpc-encoding": "gzip" */ -#define GRPC_MDELEM_GRPC_ENCODING_GZIP \ +/* ":path": "/index.html" */ +#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[4], GRPC_MDELEM_STORAGE_STATIC)) -/* "grpc-encoding": "deflate" */ -#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[5], GRPC_MDELEM_STORAGE_STATIC)) -/* "te": "trailers" */ -#define GRPC_MDELEM_TE_TRAILERS \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[6], GRPC_MDELEM_STORAGE_STATIC)) -/* "content-type": "application/grpc" */ -#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[7], GRPC_MDELEM_STORAGE_STATIC)) -/* ":method": "POST" */ -#define GRPC_MDELEM_METHOD_POST \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[8], GRPC_MDELEM_STORAGE_STATIC)) -/* ":status": "200" */ -#define GRPC_MDELEM_STATUS_200 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[9], GRPC_MDELEM_STORAGE_STATIC)) -/* ":status": "404" */ -#define GRPC_MDELEM_STATUS_404 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[10], GRPC_MDELEM_STORAGE_STATIC)) /* ":scheme": "http" */ #define GRPC_MDELEM_SCHEME_HTTP \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[11], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[5], GRPC_MDELEM_STORAGE_STATIC)) /* ":scheme": "https" */ #define GRPC_MDELEM_SCHEME_HTTPS \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[12], GRPC_MDELEM_STORAGE_STATIC)) -/* ":scheme": "grpc" */ -#define GRPC_MDELEM_SCHEME_GRPC \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[13], GRPC_MDELEM_STORAGE_STATIC)) -/* ":authority": "" */ -#define GRPC_MDELEM_AUTHORITY_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[14], GRPC_MDELEM_STORAGE_STATIC)) -/* ":method": "GET" */ -#define GRPC_MDELEM_METHOD_GET \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[15], GRPC_MDELEM_STORAGE_STATIC)) -/* ":method": "PUT" */ -#define GRPC_MDELEM_METHOD_PUT \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[16], GRPC_MDELEM_STORAGE_STATIC)) -/* ":path": "/" */ -#define GRPC_MDELEM_PATH_SLASH \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[17], GRPC_MDELEM_STORAGE_STATIC)) -/* ":path": "/index.html" */ -#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[18], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[6], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "200" */ +#define GRPC_MDELEM_STATUS_200 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[7], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "204" */ #define GRPC_MDELEM_STATUS_204 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[19], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[8], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "206" */ #define GRPC_MDELEM_STATUS_206 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[20], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[9], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "304" */ #define GRPC_MDELEM_STATUS_304 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[21], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[10], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "400" */ #define GRPC_MDELEM_STATUS_400 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[22], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[11], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "404" */ +#define GRPC_MDELEM_STATUS_404 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[12], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "500" */ #define GRPC_MDELEM_STATUS_500 \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[23], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[13], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-charset": "" */ #define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[24], GRPC_MDELEM_STORAGE_STATIC)) -/* "accept-encoding": "" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[25], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[14], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-encoding": "gzip, deflate" */ #define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[26], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[15], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-language": "" */ #define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[27], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[16], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-ranges": "" */ #define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[28], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[17], GRPC_MDELEM_STORAGE_STATIC)) /* "accept": "" */ #define GRPC_MDELEM_ACCEPT_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[29], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[18], GRPC_MDELEM_STORAGE_STATIC)) /* "access-control-allow-origin": "" */ #define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[30], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[19], GRPC_MDELEM_STORAGE_STATIC)) /* "age": "" */ #define GRPC_MDELEM_AGE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[31], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[20], GRPC_MDELEM_STORAGE_STATIC)) /* "allow": "" */ #define GRPC_MDELEM_ALLOW_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[32], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[21], GRPC_MDELEM_STORAGE_STATIC)) /* "authorization": "" */ #define GRPC_MDELEM_AUTHORIZATION_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[33], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[22], GRPC_MDELEM_STORAGE_STATIC)) /* "cache-control": "" */ #define GRPC_MDELEM_CACHE_CONTROL_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[34], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[23], GRPC_MDELEM_STORAGE_STATIC)) /* "content-disposition": "" */ #define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC)) -/* "content-encoding": "identity" */ -#define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC)) -/* "content-encoding": "gzip" */ -#define GRPC_MDELEM_CONTENT_ENCODING_GZIP \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[24], GRPC_MDELEM_STORAGE_STATIC)) /* "content-encoding": "" */ #define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[25], GRPC_MDELEM_STORAGE_STATIC)) /* "content-language": "" */ #define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[26], GRPC_MDELEM_STORAGE_STATIC)) /* "content-length": "" */ #define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[27], GRPC_MDELEM_STORAGE_STATIC)) /* "content-location": "" */ #define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[28], GRPC_MDELEM_STORAGE_STATIC)) /* "content-range": "" */ #define GRPC_MDELEM_CONTENT_RANGE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[29], GRPC_MDELEM_STORAGE_STATIC)) /* "content-type": "" */ #define GRPC_MDELEM_CONTENT_TYPE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[30], GRPC_MDELEM_STORAGE_STATIC)) /* "cookie": "" */ #define GRPC_MDELEM_COOKIE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[31], GRPC_MDELEM_STORAGE_STATIC)) /* "date": "" */ #define GRPC_MDELEM_DATE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[32], GRPC_MDELEM_STORAGE_STATIC)) /* "etag": "" */ #define GRPC_MDELEM_ETAG_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[33], GRPC_MDELEM_STORAGE_STATIC)) /* "expect": "" */ #define GRPC_MDELEM_EXPECT_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[34], GRPC_MDELEM_STORAGE_STATIC)) /* "expires": "" */ #define GRPC_MDELEM_EXPIRES_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC)) /* "from": "" */ #define GRPC_MDELEM_FROM_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC)) /* "host": "" */ #define GRPC_MDELEM_HOST_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC)) /* "if-match": "" */ #define GRPC_MDELEM_IF_MATCH_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC)) /* "if-modified-since": "" */ #define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC)) /* "if-none-match": "" */ #define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC)) /* "if-range": "" */ #define GRPC_MDELEM_IF_RANGE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC)) /* "if-unmodified-since": "" */ #define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC)) /* "last-modified": "" */ #define GRPC_MDELEM_LAST_MODIFIED_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC)) -/* "lb-token": "" */ -#define GRPC_MDELEM_LB_TOKEN_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC)) -/* "lb-cost-bin": "" */ -#define GRPC_MDELEM_LB_COST_BIN_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC)) /* "link": "" */ #define GRPC_MDELEM_LINK_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC)) /* "location": "" */ #define GRPC_MDELEM_LOCATION_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC)) /* "max-forwards": "" */ #define GRPC_MDELEM_MAX_FORWARDS_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC)) /* "proxy-authenticate": "" */ #define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC)) /* "proxy-authorization": "" */ #define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC)) /* "range": "" */ #define GRPC_MDELEM_RANGE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC)) /* "referer": "" */ #define GRPC_MDELEM_REFERER_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC)) /* "refresh": "" */ #define GRPC_MDELEM_REFRESH_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC)) /* "retry-after": "" */ #define GRPC_MDELEM_RETRY_AFTER_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC)) /* "server": "" */ #define GRPC_MDELEM_SERVER_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC)) /* "set-cookie": "" */ #define GRPC_MDELEM_SET_COOKIE_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC)) /* "strict-transport-security": "" */ #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC)) /* "transfer-encoding": "" */ #define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC)) /* "user-agent": "" */ #define GRPC_MDELEM_USER_AGENT_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC)) /* "vary": "" */ #define GRPC_MDELEM_VARY_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC)) /* "via": "" */ #define GRPC_MDELEM_VIA_EMPTY \ - (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC)) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC)) /* "www-authenticate": "" */ #define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-status": "0" */ +#define GRPC_MDELEM_GRPC_STATUS_0 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-status": "1" */ +#define GRPC_MDELEM_GRPC_STATUS_1 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-status": "2" */ +#define GRPC_MDELEM_GRPC_STATUS_2 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-encoding": "identity" */ +#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-encoding": "gzip" */ +#define GRPC_MDELEM_GRPC_ENCODING_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-encoding": "deflate" */ +#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC)) +/* "te": "trailers" */ +#define GRPC_MDELEM_TE_TRAILERS \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC)) +/* "content-type": "application/grpc" */ +#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC)) +/* ":scheme": "grpc" */ +#define GRPC_MDELEM_SCHEME_GRPC \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC)) +/* ":method": "PUT" */ +#define GRPC_MDELEM_METHOD_PUT \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC)) +/* "accept-encoding": "" */ +#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC)) +/* "content-encoding": "identity" */ +#define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC)) +/* "content-encoding": "gzip" */ +#define GRPC_MDELEM_CONTENT_ENCODING_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC)) +/* "lb-token": "" */ +#define GRPC_MDELEM_LB_TOKEN_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC)) +/* "lb-cost-bin": "" */ +#define GRPC_MDELEM_LB_COST_BIN_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "identity" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \ @@ -587,8 +594,6 @@ typedef union { GRPC_BATCH_CALLOUTS_COUNT) \ : GRPC_BATCH_CALLOUTS_COUNT) -extern bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT]; - extern const uint8_t grpc_static_accept_encoding_metadata[8]; #define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \ (GRPC_MAKE_MDELEM( \ diff --git a/Sources/CgRPC/src/core/lib/transport/transport.cc b/Sources/CgRPC/src/core/lib/transport/transport.cc index 6b41e4b37..8be0b91b6 100644 --- a/Sources/CgRPC/src/core/lib/transport/transport.cc +++ b/Sources/CgRPC/src/core/lib/transport/transport.cc @@ -27,8 +27,10 @@ #include #include +#include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/transport_impl.h" @@ -62,8 +64,9 @@ void grpc_stream_unref(grpc_stream_refcount* refcount, const char* reason) { void grpc_stream_unref(grpc_stream_refcount* refcount) { #endif if (gpr_unref(&refcount->refs)) { - if (grpc_core::ExecCtx::Get()->flags() & - GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP) { + if (!grpc_iomgr_is_any_background_poller_thread() && + (grpc_core::ExecCtx::Get()->flags() & + GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP)) { /* Ick. The thread we're running on MAY be owned (indirectly) by a call-stack. If that's the case, destroying the call-stack MAY try to destroy the @@ -72,7 +75,7 @@ void grpc_stream_unref(grpc_stream_refcount* refcount) { Throw this over to the executor (on a core-owned thread) and process it there. */ refcount->destroy.scheduler = - grpc_executor_scheduler(GRPC_EXECUTOR_SHORT); + grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT); } GRPC_CLOSURE_SCHED(&refcount->destroy, GRPC_ERROR_NONE); } @@ -149,7 +152,7 @@ void grpc_transport_move_stats(grpc_transport_stream_stats* from, } size_t grpc_transport_stream_size(grpc_transport* transport) { - return transport->vtable->sizeof_stream; + return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(transport->vtable->sizeof_stream); } void grpc_transport_destroy(grpc_transport* transport) { @@ -184,7 +187,8 @@ void grpc_transport_set_pops(grpc_transport* transport, grpc_stream* stream, nullptr) { transport->vtable->set_pollset_set(transport, stream, pollset_set); } else { - abort(); + // No-op for empty pollset. Empty pollset is possible when using + // non-fd-based event engines such as CFStream. } } @@ -211,21 +215,32 @@ void grpc_transport_stream_op_batch_finish_with_failure( if (batch->send_message) { batch->payload->send_message.send_message.reset(); } - if (batch->recv_message) { - GRPC_CALL_COMBINER_START( - call_combiner, batch->payload->recv_message.recv_message_ready, - GRPC_ERROR_REF(error), "failing recv_message_ready"); + if (batch->cancel_stream) { + GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error); } + // Construct a list of closures to execute. + grpc_core::CallCombinerClosureList closures; if (batch->recv_initial_metadata) { - GRPC_CALL_COMBINER_START( - call_combiner, + closures.Add( batch->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_REF(error), "failing recv_initial_metadata_ready"); } - GRPC_CLOSURE_SCHED(batch->on_complete, error); - if (batch->cancel_stream) { - GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error); + if (batch->recv_message) { + closures.Add(batch->payload->recv_message.recv_message_ready, + GRPC_ERROR_REF(error), "failing recv_message_ready"); + } + if (batch->recv_trailing_metadata) { + closures.Add( + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready, + GRPC_ERROR_REF(error), "failing recv_trailing_metadata_ready"); + } + if (batch->on_complete != nullptr) { + closures.Add(batch->on_complete, GRPC_ERROR_REF(error), + "failing on_complete"); } + // Execute closures. + closures.RunClosures(call_combiner); + GRPC_ERROR_UNREF(error); } typedef struct { diff --git a/Sources/CgRPC/src/core/lib/transport/transport.h b/Sources/CgRPC/src/core/lib/transport/transport.h index 10e9df0f7..5ce568834 100644 --- a/Sources/CgRPC/src/core/lib/transport/transport.h +++ b/Sources/CgRPC/src/core/lib/transport/transport.h @@ -81,16 +81,16 @@ void grpc_stream_unref(grpc_stream_refcount* refcount); grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount* refcount, void* buffer, size_t length); -typedef struct { - uint64_t framing_bytes; - uint64_t data_bytes; - uint64_t header_bytes; -} grpc_transport_one_way_stats; +struct grpc_transport_one_way_stats { + uint64_t framing_bytes = 0; + uint64_t data_bytes = 0; + uint64_t header_bytes = 0; +}; -typedef struct grpc_transport_stream_stats { +struct grpc_transport_stream_stats { grpc_transport_one_way_stats incoming; grpc_transport_one_way_stats outgoing; -} grpc_transport_stream_stats; +}; void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats* from, grpc_transport_one_way_stats* to); @@ -121,14 +121,30 @@ typedef struct grpc_transport_stream_op_batch_payload /* Transport stream op: a set of operations to perform on a transport against a single stream */ -typedef struct grpc_transport_stream_op_batch { - /** Should be enqueued when all requested operations (excluding recv_message - and recv_initial_metadata which have their own closures) in a given batch - have been completed. */ - grpc_closure* on_complete; +struct grpc_transport_stream_op_batch { + grpc_transport_stream_op_batch() + : send_initial_metadata(false), + send_trailing_metadata(false), + send_message(false), + recv_initial_metadata(false), + recv_message(false), + recv_trailing_metadata(false), + cancel_stream(false), + is_traced(false) {} + + /** Should be scheduled when all of the non-recv operations in the batch + are complete. + + The recv ops (recv_initial_metadata, recv_message, and + recv_trailing_metadata) each have their own callbacks. If a batch + contains both recv ops and non-recv ops, on_complete should be + scheduled as soon as the non-recv ops are complete, regardless of + whether or not the recv ops are complete. If a batch contains + only recv ops, on_complete can be null. */ + grpc_closure* on_complete = nullptr; /** Values for the stream op (fields set are determined by flags above) */ - grpc_transport_stream_op_batch_payload* payload; + grpc_transport_stream_op_batch_payload* payload = nullptr; /** Send initial metadata to the peer, from the provided metadata batch. */ bool send_initial_metadata : 1; @@ -149,37 +165,44 @@ typedef struct grpc_transport_stream_op_batch { */ bool recv_trailing_metadata : 1; - /** Collect any stats into provided buffer, zero internal stat counters */ - bool collect_stats : 1; - /** Cancel this stream with the provided error */ bool cancel_stream : 1; + /** Is this stream traced */ + bool is_traced : 1; + /*************************************************************************** * remaining fields are initialized and used at the discretion of the * current handler of the op */ grpc_handler_private_op_data handler_private; -} grpc_transport_stream_op_batch; +}; struct grpc_transport_stream_op_batch_payload { + explicit grpc_transport_stream_op_batch_payload( + grpc_call_context_element* context) + : context(context) {} + ~grpc_transport_stream_op_batch_payload() { + // We don't really own `send_message`, so release ownership and let the + // owner clean the data. + send_message.send_message.release(); + } + struct { - grpc_metadata_batch* send_initial_metadata; + grpc_metadata_batch* send_initial_metadata = nullptr; /** Iff send_initial_metadata != NULL, flags associated with send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */ - uint32_t send_initial_metadata_flags; - // If non-NULL, will be set by the transport to the peer string - // (a char*, which the caller takes ownership of). + uint32_t send_initial_metadata_flags = 0; + // If non-NULL, will be set by the transport to the peer string (a char*). + // The transport retains ownership of the string. // Note: This pointer may be used by the transport after the // send_initial_metadata op is completed. It must remain valid // until the call is destroyed. - // Note: When a transport sets this, it must free the previous - // value, if any. - gpr_atm* peer_string; + gpr_atm* peer_string = nullptr; } send_initial_metadata; struct { - grpc_metadata_batch* send_trailing_metadata; + grpc_metadata_batch* send_trailing_metadata = nullptr; } send_trailing_metadata; struct { @@ -191,44 +214,41 @@ struct grpc_transport_stream_op_batch_payload { } send_message; struct { - grpc_metadata_batch* recv_initial_metadata; + grpc_metadata_batch* recv_initial_metadata = nullptr; // Flags are used only on the server side. If non-null, will be set to // a bitfield of the GRPC_INITIAL_METADATA_xxx macros (e.g., to // indicate if the call is idempotent). - uint32_t* recv_flags; + uint32_t* recv_flags = nullptr; /** Should be enqueued when initial metadata is ready to be processed. */ - grpc_closure* recv_initial_metadata_ready; + grpc_closure* recv_initial_metadata_ready = nullptr; // If not NULL, will be set to true if trailing metadata is // immediately available. This may be a signal that we received a // Trailers-Only response. - bool* trailing_metadata_available; - // If non-NULL, will be set by the transport to the peer string - // (a char*, which the caller takes ownership of). + bool* trailing_metadata_available = nullptr; + // If non-NULL, will be set by the transport to the peer string (a char*). + // The transport retains ownership of the string. // Note: This pointer may be used by the transport after the // recv_initial_metadata op is completed. It must remain valid // until the call is destroyed. - // Note: When a transport sets this, it must free the previous - // value, if any. - gpr_atm* peer_string; + gpr_atm* peer_string = nullptr; } recv_initial_metadata; struct { // Will be set by the transport to point to the byte stream // containing a received message. // Will be NULL if trailing metadata is received instead of a message. - grpc_core::OrphanablePtr* recv_message; + grpc_core::OrphanablePtr* recv_message = nullptr; /** Should be enqueued when one message is ready to be processed. */ - grpc_closure* recv_message_ready; + grpc_closure* recv_message_ready = nullptr; } recv_message; struct { - grpc_metadata_batch* recv_trailing_metadata; + grpc_metadata_batch* recv_trailing_metadata = nullptr; + grpc_transport_stream_stats* collect_stats = nullptr; + /** Should be enqueued when initial metadata is ready to be processed. */ + grpc_closure* recv_trailing_metadata_ready = nullptr; } recv_trailing_metadata; - struct { - grpc_transport_stream_stats* collect_stats; - } collect_stats; - /** Forcefully close this stream. The HTTP2 semantics should be: - server side: if cancel_error has GRPC_ERROR_INT_GRPC_STATUS, and @@ -242,7 +262,7 @@ struct grpc_transport_stream_op_batch_payload { struct { // Error contract: the transport that gets this op must cause cancel_error // to be unref'ed after processing it - grpc_error* cancel_error; + grpc_error* cancel_error = GRPC_ERROR_NONE; } cancel_stream; /* Indexes correspond to grpc_context_index enum values */ @@ -284,6 +304,8 @@ typedef struct grpc_transport_op { /** Called when the ping ack is received */ grpc_closure* on_ack; } send_ping; + // If true, will reset the channel's connection backoff. + bool reset_connect_backoff; /*************************************************************************** * remaining fields are initialized and used at the discretion of the diff --git a/Sources/CgRPC/src/core/lib/transport/transport_op_string.cc b/Sources/CgRPC/src/core/lib/transport/transport_op_string.cc index 99af7c193..8c7db642a 100644 --- a/Sources/CgRPC/src/core/lib/transport/transport_op_string.cc +++ b/Sources/CgRPC/src/core/lib/transport/transport_op_string.cc @@ -52,7 +52,7 @@ static void put_metadata_list(gpr_strvec* b, grpc_metadata_batch md) { } if (md.deadline != GRPC_MILLIS_INF_FUTURE) { char* tmp; - gpr_asprintf(&tmp, " deadline=%" PRIdPTR, md.deadline); + gpr_asprintf(&tmp, " deadline=%" PRId64, md.deadline); gpr_strvec_add(b, tmp); } } @@ -120,13 +120,6 @@ char* grpc_transport_stream_op_batch_string( gpr_strvec_add(&b, tmp); } - if (op->collect_stats) { - gpr_strvec_add(&b, gpr_strdup(" ")); - gpr_asprintf(&tmp, "COLLECT_STATS:%p", - op->payload->collect_stats.collect_stats); - gpr_strvec_add(&b, tmp); - } - out = gpr_strvec_flatten(&b, nullptr); gpr_strvec_destroy(&b); diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/uri_parser.cc b/Sources/CgRPC/src/core/lib/uri/uri_parser.cc similarity index 99% rename from Sources/CgRPC/src/core/ext/filters/client_channel/uri_parser.cc rename to Sources/CgRPC/src/core/lib/uri/uri_parser.cc index 0572034a9..f212c7d2c 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/uri_parser.cc +++ b/Sources/CgRPC/src/core/lib/uri/uri_parser.cc @@ -18,7 +18,7 @@ #include -#include "src/core/ext/filters/client_channel/uri_parser.h" +#include "src/core/lib/uri/uri_parser.h" #include diff --git a/Sources/CgRPC/src/core/ext/filters/client_channel/uri_parser.h b/Sources/CgRPC/src/core/lib/uri/uri_parser.h similarity index 88% rename from Sources/CgRPC/src/core/ext/filters/client_channel/uri_parser.h rename to Sources/CgRPC/src/core/lib/uri/uri_parser.h index d749f2330..b6771bbde 100644 --- a/Sources/CgRPC/src/core/ext/filters/client_channel/uri_parser.h +++ b/Sources/CgRPC/src/core/lib/uri/uri_parser.h @@ -16,8 +16,8 @@ * */ -#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H +#ifndef GRPC_CORE_LIB_URI_URI_PARSER_H +#define GRPC_CORE_LIB_URI_URI_PARSER_H #include @@ -47,4 +47,4 @@ const char* grpc_uri_get_query_arg(const grpc_uri* uri, const char* key); /** destroy a uri */ void grpc_uri_destroy(grpc_uri* uri); -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H */ +#endif /* GRPC_CORE_LIB_URI_URI_PARSER_H */ diff --git a/Sources/CgRPC/src/core/plugin_registry/grpc_plugin_registry.cc b/Sources/CgRPC/src/core/plugin_registry/grpc_plugin_registry.cc index e371310fa..cde40ef65 100644 --- a/Sources/CgRPC/src/core/plugin_registry/grpc_plugin_registry.cc +++ b/Sources/CgRPC/src/core/plugin_registry/grpc_plugin_registry.cc @@ -28,14 +28,14 @@ void grpc_deadline_filter_init(void); void grpc_deadline_filter_shutdown(void); void grpc_client_channel_init(void); void grpc_client_channel_shutdown(void); -void grpc_tsi_alts_init(void); -void grpc_tsi_alts_shutdown(void); void grpc_inproc_plugin_init(void); void grpc_inproc_plugin_shutdown(void); void grpc_resolver_fake_init(void); void grpc_resolver_fake_shutdown(void); void grpc_lb_policy_grpclb_init(void); void grpc_lb_policy_grpclb_shutdown(void); +void grpc_lb_policy_xds_init(void); +void grpc_lb_policy_xds_shutdown(void); void grpc_lb_policy_pick_first_init(void); void grpc_lb_policy_pick_first_shutdown(void); void grpc_lb_policy_round_robin_init(void); @@ -46,8 +46,6 @@ void grpc_resolver_dns_native_init(void); void grpc_resolver_dns_native_shutdown(void); void grpc_resolver_sockaddr_init(void); void grpc_resolver_sockaddr_shutdown(void); -void grpc_server_load_reporting_plugin_init(void); -void grpc_server_load_reporting_plugin_shutdown(void); void grpc_max_age_filter_init(void); void grpc_max_age_filter_shutdown(void); void grpc_message_size_filter_init(void); @@ -66,14 +64,14 @@ void grpc_register_built_in_plugins(void) { grpc_deadline_filter_shutdown); grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown); - grpc_register_plugin(grpc_tsi_alts_init, - grpc_tsi_alts_shutdown); grpc_register_plugin(grpc_inproc_plugin_init, grpc_inproc_plugin_shutdown); grpc_register_plugin(grpc_resolver_fake_init, grpc_resolver_fake_shutdown); grpc_register_plugin(grpc_lb_policy_grpclb_init, grpc_lb_policy_grpclb_shutdown); + grpc_register_plugin(grpc_lb_policy_xds_init, + grpc_lb_policy_xds_shutdown); grpc_register_plugin(grpc_lb_policy_pick_first_init, grpc_lb_policy_pick_first_shutdown); grpc_register_plugin(grpc_lb_policy_round_robin_init, @@ -84,8 +82,6 @@ void grpc_register_built_in_plugins(void) { grpc_resolver_dns_native_shutdown); grpc_register_plugin(grpc_resolver_sockaddr_init, grpc_resolver_sockaddr_shutdown); - grpc_register_plugin(grpc_server_load_reporting_plugin_init, - grpc_server_load_reporting_plugin_shutdown); grpc_register_plugin(grpc_max_age_filter_init, grpc_max_age_filter_shutdown); grpc_register_plugin(grpc_message_size_filter_init, diff --git a/Sources/CgRPC/src/core/tsi/alts/crypt/aes_gcm.cc b/Sources/CgRPC/src/core/tsi/alts/crypt/aes_gcm.cc index 02b1ac449..c638ce76e 100644 --- a/Sources/CgRPC/src/core/tsi/alts/crypt/aes_gcm.cc +++ b/Sources/CgRPC/src/core/tsi/alts/crypt/aes_gcm.cc @@ -18,6 +18,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include "src/core/tsi/alts/crypt/gsec.h" #include diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.cc index 40f30e41c..43d0979f4 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.cc @@ -24,30 +24,173 @@ #include #include +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/channel.h" #include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h" +#include "src/core/tsi/alts/handshaker/alts_shared_resource.h" +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h" +#include "src/core/tsi/alts/handshaker/alts_tsi_utils.h" + +#define TSI_ALTS_INITIAL_BUFFER_SIZE 256 const int kHandshakerClientOpNum = 4; +struct alts_handshaker_client { + const alts_handshaker_client_vtable* vtable; +}; + typedef struct alts_grpc_handshaker_client { alts_handshaker_client base; + alts_tsi_handshaker* handshaker; grpc_call* call; + /* A pointer to a function handling the interaction with handshaker service. + * That is, it points to grpc_call_start_batch_and_execute when the handshaker + * client is used in a non-testing use case and points to a custom function + * that validates the data to be sent to handshaker service in a testing use + * case. */ alts_grpc_caller grpc_caller; + /* A callback function provided by gRPC to handle the response returned from + * handshaker service. It also serves to bring the control safely back to + * application when dedicated CQ and thread are used. */ + grpc_iomgr_cb_func grpc_cb; + /* A gRPC closure to be scheduled when the response from handshaker service + * is received. It will be initialized with grpc_cb. */ + grpc_closure on_handshaker_service_resp_recv; + /* Buffers containing information to be sent (or received) to (or from) the + * handshaker service. */ + grpc_byte_buffer* send_buffer; + grpc_byte_buffer* recv_buffer; + grpc_status_code status; + /* Initial metadata to be received from handshaker service. */ + grpc_metadata_array recv_initial_metadata; + /* A callback function provided by an application to be invoked when response + * is received from handshaker service. */ + tsi_handshaker_on_next_done_cb cb; + void* user_data; + /* ALTS credential options passed in from the caller. */ + grpc_alts_credentials_options* options; + /* target name information to be passed to handshaker service for server + * authorization check. */ + grpc_slice target_name; + /* boolean flag indicating if the handshaker client is used at client + * (is_client = true) or server (is_client = false) side. */ + bool is_client; + /* a temporary store for data received from handshaker service used to extract + * unused data. */ + grpc_slice recv_bytes; + /* a buffer containing data to be sent to the grpc client or server's peer. */ + unsigned char* buffer; + size_t buffer_size; } alts_grpc_handshaker_client; -static grpc_call_error grpc_start_batch(grpc_call* call, const grpc_op* ops, - size_t nops, void* tag) { - return grpc_call_start_batch(call, ops, nops, tag, nullptr); +static void handshaker_client_send_buffer_destroy( + alts_grpc_handshaker_client* client) { + GPR_ASSERT(client != nullptr); + grpc_byte_buffer_destroy(client->send_buffer); + client->send_buffer = nullptr; +} + +static bool is_handshake_finished_properly(grpc_gcp_handshaker_resp* resp) { + GPR_ASSERT(resp != nullptr); + if (resp->has_result) { + return true; + } + return false; +} + +void alts_handshaker_client_handle_response(alts_handshaker_client* c, + bool is_ok) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + grpc_byte_buffer* recv_buffer = client->recv_buffer; + grpc_status_code status = client->status; + tsi_handshaker_on_next_done_cb cb = client->cb; + void* user_data = client->user_data; + alts_tsi_handshaker* handshaker = client->handshaker; + + /* Invalid input check. */ + if (cb == nullptr) { + gpr_log(GPR_ERROR, + "cb is nullptr in alts_tsi_handshaker_handle_response()"); + return; + } + if (handshaker == nullptr) { + gpr_log(GPR_ERROR, + "handshaker is nullptr in alts_tsi_handshaker_handle_response()"); + cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); + return; + } + /* TSI handshake has been shutdown. */ + if (alts_tsi_handshaker_has_shutdown(handshaker)) { + gpr_log(GPR_ERROR, "TSI handshake shutdown"); + cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr); + return; + } + /* Failed grpc call check. */ + if (!is_ok || status != GRPC_STATUS_OK) { + gpr_log(GPR_ERROR, "grpc call made to handshaker service failed"); + cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); + return; + } + if (recv_buffer == nullptr) { + gpr_log(GPR_ERROR, + "recv_buffer is nullptr in alts_tsi_handshaker_handle_response()"); + cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); + return; + } + grpc_gcp_handshaker_resp* resp = + alts_tsi_utils_deserialize_response(recv_buffer); + grpc_byte_buffer_destroy(client->recv_buffer); + client->recv_buffer = nullptr; + /* Invalid handshaker response check. */ + if (resp == nullptr) { + gpr_log(GPR_ERROR, "alts_tsi_utils_deserialize_response() failed"); + cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr); + return; + } + grpc_slice* slice = static_cast(resp->out_frames.arg); + unsigned char* bytes_to_send = nullptr; + size_t bytes_to_send_size = 0; + if (slice != nullptr) { + bytes_to_send_size = GRPC_SLICE_LENGTH(*slice); + while (bytes_to_send_size > client->buffer_size) { + client->buffer_size *= 2; + client->buffer = static_cast( + gpr_realloc(client->buffer, client->buffer_size)); + } + memcpy(client->buffer, GRPC_SLICE_START_PTR(*slice), bytes_to_send_size); + bytes_to_send = client->buffer; + } + tsi_handshaker_result* result = nullptr; + if (is_handshake_finished_properly(resp)) { + alts_tsi_handshaker_result_create(resp, client->is_client, &result); + alts_tsi_handshaker_result_set_unused_bytes(result, &client->recv_bytes, + resp->bytes_consumed); + } + grpc_status_code code = static_cast(resp->status.code); + if (code != GRPC_STATUS_OK) { + grpc_slice* details = static_cast(resp->status.details.arg); + if (details != nullptr) { + char* error_details = grpc_slice_to_c_string(*details); + gpr_log(GPR_ERROR, "Error from handshaker service:%s", error_details); + gpr_free(error_details); + } + } + grpc_gcp_handshaker_resp_destroy(resp); + cb(alts_tsi_utils_convert_to_tsi_result(code), user_data, bytes_to_send, + bytes_to_send_size, result); } /** - * Populate grpc operation data with the fields of ALTS TSI event and make a - * grpc call. + * Populate grpc operation data with the fields of ALTS handshaker client and + * make a grpc call. */ -static tsi_result make_grpc_call(alts_handshaker_client* client, - alts_tsi_event* event, bool is_start) { - GPR_ASSERT(client != nullptr && event != nullptr); - alts_grpc_handshaker_client* grpc_client = - reinterpret_cast(client); +static tsi_result make_grpc_call(alts_handshaker_client* c, bool is_start) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); grpc_op ops[kHandshakerClientOpNum]; memset(ops, 0, sizeof(ops)); grpc_op* op = ops; @@ -58,22 +201,22 @@ static tsi_result make_grpc_call(alts_handshaker_client* client, GPR_ASSERT(op - ops <= kHandshakerClientOpNum); op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = - &event->initial_metadata; + &client->recv_initial_metadata; op++; GPR_ASSERT(op - ops <= kHandshakerClientOpNum); } op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = event->send_buffer; + op->data.send_message.send_message = client->send_buffer; op++; GPR_ASSERT(op - ops <= kHandshakerClientOpNum); op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &event->recv_buffer; + op->data.recv_message.recv_message = &client->recv_buffer; op++; GPR_ASSERT(op - ops <= kHandshakerClientOpNum); - GPR_ASSERT(grpc_client->grpc_caller != nullptr); - if (grpc_client->grpc_caller(grpc_client->call, ops, - static_cast(op - ops), - (void*)event) != GRPC_CALL_OK) { + GPR_ASSERT(client->grpc_caller != nullptr); + if (client->grpc_caller(client->call, ops, static_cast(op - ops), + &client->on_handshaker_service_resp_recv) != + GRPC_CALL_OK) { gpr_log(GPR_ERROR, "Start batch operation failed"); return TSI_INTERNAL_ERROR; } @@ -81,7 +224,11 @@ static tsi_result make_grpc_call(alts_handshaker_client* client, } /* Create and populate a client_start handshaker request, then serialize it. */ -static grpc_byte_buffer* get_serialized_start_client(alts_tsi_event* event) { +static grpc_byte_buffer* get_serialized_start_client( + alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); bool ok = true; grpc_gcp_handshaker_req* req = grpc_gcp_handshaker_req_create(CLIENT_START_REQ); @@ -90,14 +237,14 @@ static grpc_byte_buffer* get_serialized_start_client(alts_tsi_event* event) { ok &= grpc_gcp_handshaker_req_add_application_protocol( req, ALTS_APPLICATION_PROTOCOL); ok &= grpc_gcp_handshaker_req_add_record_protocol(req, ALTS_RECORD_PROTOCOL); - grpc_gcp_rpc_protocol_versions* versions = &event->options->rpc_versions; + grpc_gcp_rpc_protocol_versions* versions = &client->options->rpc_versions; ok &= grpc_gcp_handshaker_req_set_rpc_versions( req, versions->max_rpc_version.major, versions->max_rpc_version.minor, versions->min_rpc_version.major, versions->min_rpc_version.minor); - char* target_name = grpc_slice_to_c_string(event->target_name); + char* target_name = grpc_slice_to_c_string(client->target_name); ok &= grpc_gcp_handshaker_req_set_target_name(req, target_name); target_service_account* ptr = - (reinterpret_cast(event->options)) + (reinterpret_cast(client->options)) ->target_account_list_head; while (ptr != nullptr) { grpc_gcp_handshaker_req_add_target_identity_service_account(req, ptr->data); @@ -109,26 +256,27 @@ static grpc_byte_buffer* get_serialized_start_client(alts_tsi_event* event) { if (ok) { buffer = grpc_raw_byte_buffer_create(&slice, 1 /* number of slices */); } - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); gpr_free(target_name); grpc_gcp_handshaker_req_destroy(req); return buffer; } -static tsi_result handshaker_client_start_client(alts_handshaker_client* client, - alts_tsi_event* event) { - if (client == nullptr || event == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to alts_grpc_handshaker_client_start_client()"); +static tsi_result handshaker_client_start_client(alts_handshaker_client* c) { + if (c == nullptr) { + gpr_log(GPR_ERROR, "client is nullptr in handshaker_client_start_client()"); return TSI_INVALID_ARGUMENT; } - grpc_byte_buffer* buffer = get_serialized_start_client(event); + grpc_byte_buffer* buffer = get_serialized_start_client(c); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); if (buffer == nullptr) { gpr_log(GPR_ERROR, "get_serialized_start_client() failed"); return TSI_INTERNAL_ERROR; } - event->send_buffer = buffer; - tsi_result result = make_grpc_call(client, event, true /* is_start */); + handshaker_client_send_buffer_destroy(client); + client->send_buffer = buffer; + tsi_result result = make_grpc_call(&client->base, true /* is_start */); if (result != TSI_OK) { gpr_log(GPR_ERROR, "make_grpc_call() failed"); } @@ -137,8 +285,11 @@ static tsi_result handshaker_client_start_client(alts_handshaker_client* client, /* Create and populate a start_server handshaker request, then serialize it. */ static grpc_byte_buffer* get_serialized_start_server( - alts_tsi_event* event, grpc_slice* bytes_received) { + alts_handshaker_client* c, grpc_slice* bytes_received) { + GPR_ASSERT(c != nullptr); GPR_ASSERT(bytes_received != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); grpc_gcp_handshaker_req* req = grpc_gcp_handshaker_req_create(SERVER_START_REQ); bool ok = grpc_gcp_handshaker_req_add_application_protocol( @@ -148,7 +299,7 @@ static grpc_byte_buffer* get_serialized_start_server( ok &= grpc_gcp_handshaker_req_set_in_bytes( req, reinterpret_cast GRPC_SLICE_START_PTR(*bytes_received), GRPC_SLICE_LENGTH(*bytes_received)); - grpc_gcp_rpc_protocol_versions* versions = &event->options->rpc_versions; + grpc_gcp_rpc_protocol_versions* versions = &client->options->rpc_versions; ok &= grpc_gcp_handshaker_req_set_rpc_versions( req, versions->max_rpc_version.major, versions->max_rpc_version.minor, versions->min_rpc_version.major, versions->min_rpc_version.minor); @@ -158,26 +309,27 @@ static grpc_byte_buffer* get_serialized_start_server( if (ok) { buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */); } - grpc_slice_unref(req_slice); + grpc_slice_unref_internal(req_slice); grpc_gcp_handshaker_req_destroy(req); return buffer; } -static tsi_result handshaker_client_start_server(alts_handshaker_client* client, - alts_tsi_event* event, +static tsi_result handshaker_client_start_server(alts_handshaker_client* c, grpc_slice* bytes_received) { - if (client == nullptr || event == nullptr || bytes_received == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to alts_grpc_handshaker_client_start_server()"); + if (c == nullptr || bytes_received == nullptr) { + gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_server()"); return TSI_INVALID_ARGUMENT; } - grpc_byte_buffer* buffer = get_serialized_start_server(event, bytes_received); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + grpc_byte_buffer* buffer = get_serialized_start_server(c, bytes_received); if (buffer == nullptr) { gpr_log(GPR_ERROR, "get_serialized_start_server() failed"); return TSI_INTERNAL_ERROR; } - event->send_buffer = buffer; - tsi_result result = make_grpc_call(client, event, true /* is_start */); + handshaker_client_send_buffer_destroy(client); + client->send_buffer = buffer; + tsi_result result = make_grpc_call(&client->base, true /* is_start */); if (result != TSI_OK) { gpr_log(GPR_ERROR, "make_grpc_call() failed"); } @@ -197,63 +349,101 @@ static grpc_byte_buffer* get_serialized_next(grpc_slice* bytes_received) { if (ok) { buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */); } - grpc_slice_unref(req_slice); + grpc_slice_unref_internal(req_slice); grpc_gcp_handshaker_req_destroy(req); return buffer; } -static tsi_result handshaker_client_next(alts_handshaker_client* client, - alts_tsi_event* event, +static tsi_result handshaker_client_next(alts_handshaker_client* c, grpc_slice* bytes_received) { - if (client == nullptr || event == nullptr || bytes_received == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to alts_grpc_handshaker_client_next()"); + if (c == nullptr || bytes_received == nullptr) { + gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_next()"); return TSI_INVALID_ARGUMENT; } + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + grpc_slice_unref_internal(client->recv_bytes); + client->recv_bytes = grpc_slice_ref(*bytes_received); grpc_byte_buffer* buffer = get_serialized_next(bytes_received); if (buffer == nullptr) { gpr_log(GPR_ERROR, "get_serialized_next() failed"); return TSI_INTERNAL_ERROR; } - event->send_buffer = buffer; - tsi_result result = make_grpc_call(client, event, false /* is_start */); + handshaker_client_send_buffer_destroy(client); + client->send_buffer = buffer; + tsi_result result = make_grpc_call(&client->base, false /* is_start */); if (result != TSI_OK) { gpr_log(GPR_ERROR, "make_grpc_call() failed"); } return result; } -static void handshaker_client_destruct(alts_handshaker_client* client) { - if (client == nullptr) { +static void handshaker_client_shutdown(alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + if (client->call != nullptr) { + grpc_call_cancel_internal(client->call); + } +} + +static void handshaker_client_destruct(alts_handshaker_client* c) { + if (c == nullptr) { return; } - alts_grpc_handshaker_client* grpc_client = - reinterpret_cast(client); - grpc_call_unref(grpc_client->call); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + if (client->call != nullptr) { + grpc_call_unref(client->call); + } } static const alts_handshaker_client_vtable vtable = { handshaker_client_start_client, handshaker_client_start_server, - handshaker_client_next, handshaker_client_destruct}; + handshaker_client_next, handshaker_client_shutdown, + handshaker_client_destruct}; alts_handshaker_client* alts_grpc_handshaker_client_create( - grpc_channel* channel, grpc_completion_queue* queue, - const char* handshaker_service_url) { - if (channel == nullptr || queue == nullptr || - handshaker_service_url == nullptr) { + alts_tsi_handshaker* handshaker, grpc_channel* channel, + const char* handshaker_service_url, grpc_pollset_set* interested_parties, + grpc_alts_credentials_options* options, grpc_slice target_name, + grpc_iomgr_cb_func grpc_cb, tsi_handshaker_on_next_done_cb cb, + void* user_data, alts_handshaker_client_vtable* vtable_for_testing, + bool is_client) { + if (channel == nullptr || handshaker_service_url == nullptr) { gpr_log(GPR_ERROR, "Invalid arguments to alts_handshaker_client_create()"); return nullptr; } alts_grpc_handshaker_client* client = static_cast(gpr_zalloc(sizeof(*client))); - client->grpc_caller = grpc_start_batch; + client->grpc_caller = grpc_call_start_batch_and_execute; + client->handshaker = handshaker; + client->cb = cb; + client->user_data = user_data; + client->send_buffer = nullptr; + client->recv_buffer = nullptr; + client->options = grpc_alts_credentials_options_copy(options); + client->target_name = grpc_slice_copy(target_name); + client->recv_bytes = grpc_empty_slice(); + grpc_metadata_array_init(&client->recv_initial_metadata); + client->grpc_cb = grpc_cb; + client->is_client = is_client; + client->buffer_size = TSI_ALTS_INITIAL_BUFFER_SIZE; + client->buffer = static_cast(gpr_zalloc(client->buffer_size)); grpc_slice slice = grpc_slice_from_copied_string(handshaker_service_url); - client->call = grpc_channel_create_call( - channel, nullptr, GRPC_PROPAGATE_DEFAULTS, queue, - grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice, - gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); - client->base.vtable = &vtable; - grpc_slice_unref(slice); + client->call = + strcmp(handshaker_service_url, ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING) == + 0 + ? nullptr + : grpc_channel_create_pollset_set_call( + channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties, + grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice, + GRPC_MILLIS_INF_FUTURE, nullptr); + client->base.vtable = + vtable_for_testing == nullptr ? &vtable : vtable_for_testing; + GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, client->grpc_cb, + client, grpc_schedule_on_exec_ctx); + grpc_slice_unref_internal(slice); return &client->base; } @@ -261,21 +451,114 @@ namespace grpc_core { namespace internal { void alts_handshaker_client_set_grpc_caller_for_testing( - alts_handshaker_client* client, alts_grpc_caller caller) { - GPR_ASSERT(client != nullptr && caller != nullptr); - alts_grpc_handshaker_client* grpc_client = - reinterpret_cast(client); - grpc_client->grpc_caller = caller; + alts_handshaker_client* c, alts_grpc_caller caller) { + GPR_ASSERT(c != nullptr && caller != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + client->grpc_caller = caller; +} + +grpc_byte_buffer* alts_handshaker_client_get_send_buffer_for_testing( + alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + return client->send_buffer; +} + +grpc_byte_buffer** alts_handshaker_client_get_recv_buffer_addr_for_testing( + alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + return &client->recv_buffer; +} + +grpc_metadata_array* alts_handshaker_client_get_initial_metadata_for_testing( + alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + return &client->recv_initial_metadata; +} + +void alts_handshaker_client_set_recv_bytes_for_testing( + alts_handshaker_client* c, grpc_slice* recv_bytes) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + client->recv_bytes = grpc_slice_ref(*recv_bytes); +} + +void alts_handshaker_client_set_fields_for_testing( + alts_handshaker_client* c, alts_tsi_handshaker* handshaker, + tsi_handshaker_on_next_done_cb cb, void* user_data, + grpc_byte_buffer* recv_buffer, grpc_status_code status) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + client->handshaker = handshaker; + client->cb = cb; + client->user_data = user_data; + client->recv_buffer = recv_buffer; + client->status = status; +} + +void alts_handshaker_client_check_fields_for_testing( + alts_handshaker_client* c, tsi_handshaker_on_next_done_cb cb, + void* user_data, bool has_sent_start_message, grpc_slice* recv_bytes) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + GPR_ASSERT(client->cb == cb); + GPR_ASSERT(client->user_data == user_data); + if (recv_bytes != nullptr) { + GPR_ASSERT(grpc_slice_cmp(client->recv_bytes, *recv_bytes) == 0); + } + GPR_ASSERT(alts_tsi_handshaker_get_has_sent_start_message_for_testing( + client->handshaker) == has_sent_start_message); +} + +void alts_handshaker_client_set_vtable_for_testing( + alts_handshaker_client* c, alts_handshaker_client_vtable* vtable) { + GPR_ASSERT(c != nullptr); + GPR_ASSERT(vtable != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + client->base.vtable = vtable; +} + +alts_tsi_handshaker* alts_handshaker_client_get_handshaker_for_testing( + alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + return client->handshaker; +} + +void alts_handshaker_client_set_cb_for_testing( + alts_handshaker_client* c, tsi_handshaker_on_next_done_cb cb) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + client->cb = cb; +} + +grpc_closure* alts_handshaker_client_get_closure_for_testing( + alts_handshaker_client* c) { + GPR_ASSERT(c != nullptr); + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + return &client->on_handshaker_service_resp_recv; } } // namespace internal } // namespace grpc_core -tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client, - alts_tsi_event* event) { +tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client) { if (client != nullptr && client->vtable != nullptr && client->vtable->client_start != nullptr) { - return client->vtable->client_start(client, event); + return client->vtable->client_start(client); } gpr_log(GPR_ERROR, "client or client->vtable has not been initialized properly"); @@ -283,11 +566,10 @@ tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client, } tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client, - alts_tsi_event* event, grpc_slice* bytes_received) { if (client != nullptr && client->vtable != nullptr && client->vtable->server_start != nullptr) { - return client->vtable->server_start(client, event, bytes_received); + return client->vtable->server_start(client, bytes_received); } gpr_log(GPR_ERROR, "client or client->vtable has not been initialized properly"); @@ -295,22 +577,39 @@ tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client, } tsi_result alts_handshaker_client_next(alts_handshaker_client* client, - alts_tsi_event* event, grpc_slice* bytes_received) { if (client != nullptr && client->vtable != nullptr && client->vtable->next != nullptr) { - return client->vtable->next(client, event, bytes_received); + return client->vtable->next(client, bytes_received); } gpr_log(GPR_ERROR, "client or client->vtable has not been initialized properly"); return TSI_INVALID_ARGUMENT; } -void alts_handshaker_client_destroy(alts_handshaker_client* client) { - if (client != nullptr) { - if (client->vtable != nullptr && client->vtable->destruct != nullptr) { - client->vtable->destruct(client); +void alts_handshaker_client_shutdown(alts_handshaker_client* client) { + if (client != nullptr && client->vtable != nullptr && + client->vtable->shutdown != nullptr) { + client->vtable->shutdown(client); + } +} + +void alts_handshaker_client_destroy(alts_handshaker_client* c) { + if (c != nullptr) { + if (c->vtable != nullptr && c->vtable->destruct != nullptr) { + c->vtable->destruct(c); } + alts_grpc_handshaker_client* client = + reinterpret_cast(c); + grpc_byte_buffer_destroy(client->send_buffer); + grpc_byte_buffer_destroy(client->recv_buffer); + client->send_buffer = nullptr; + client->recv_buffer = nullptr; + grpc_metadata_array_destroy(&client->recv_initial_metadata); + grpc_slice_unref_internal(client->recv_bytes); + grpc_slice_unref_internal(client->target_name); + grpc_alts_credentials_options_destroy(client->options); + gpr_free(client->buffer); gpr_free(client); } } diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.h index fb2d2cf68..4b489875f 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_client.h @@ -21,16 +21,24 @@ #include +#include +#include #include -#include "src/core/tsi/alts/handshaker/alts_tsi_event.h" +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" +#include "src/core/tsi/transport_security_interface.h" + +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/pollset_set.h" #define ALTS_SERVICE_METHOD "/grpc.gcp.HandshakerService/DoHandshake" #define ALTS_APPLICATION_PROTOCOL "grpc" #define ALTS_RECORD_PROTOCOL "ALTSRP_GCM_AES128_REKEY" +#define ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING "lame" const size_t kAltsAes128GcmRekeyKeyLength = 44; +typedef struct alts_tsi_handshaker alts_tsi_handshaker; /** * A ALTS handshaker client interface. It is used to communicate with * ALTS handshaker service by scheduling a handshaker request that could be one @@ -41,97 +49,109 @@ typedef struct alts_handshaker_client alts_handshaker_client; /* A function that makes the grpc call to the handshaker service. */ typedef grpc_call_error (*alts_grpc_caller)(grpc_call* call, const grpc_op* ops, - size_t nops, void* tag); + size_t nops, grpc_closure* tag); /* V-table for ALTS handshaker client operations. */ typedef struct alts_handshaker_client_vtable { - tsi_result (*client_start)(alts_handshaker_client* client, - alts_tsi_event* event); + tsi_result (*client_start)(alts_handshaker_client* client); tsi_result (*server_start)(alts_handshaker_client* client, - alts_tsi_event* event, grpc_slice* bytes_received); - tsi_result (*next)(alts_handshaker_client* client, alts_tsi_event* event, + grpc_slice* bytes_received); + tsi_result (*next)(alts_handshaker_client* client, grpc_slice* bytes_received); + void (*shutdown)(alts_handshaker_client* client); void (*destruct)(alts_handshaker_client* client); } alts_handshaker_client_vtable; -struct alts_handshaker_client { - const alts_handshaker_client_vtable* vtable; -}; - /** * This method schedules a client_start handshaker request to ALTS handshaker * service. * * - client: ALTS handshaker client instance. - * - event: ALTS TSI event instance. * * It returns TSI_OK on success and an error status code on failure. */ -tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client, - alts_tsi_event* event); +tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client); /** * This method schedules a server_start handshaker request to ALTS handshaker * service. * * - client: ALTS handshaker client instance. - * - event: ALTS TSI event instance. * - bytes_received: bytes in out_frames returned from the peer's handshaker * response. * * It returns TSI_OK on success and an error status code on failure. */ tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client, - alts_tsi_event* event, grpc_slice* bytes_received); /** * This method schedules a next handshaker request to ALTS handshaker service. * * - client: ALTS handshaker client instance. - * - event: ALTS TSI event instance. * - bytes_received: bytes in out_frames returned from the peer's handshaker * response. * * It returns TSI_OK on success and an error status code on failure. */ tsi_result alts_handshaker_client_next(alts_handshaker_client* client, - alts_tsi_event* event, grpc_slice* bytes_received); /** - * This method destroys a ALTS handshaker client. + * This method cancels previously scheduled, but yet executed handshaker + * requests to ALTS handshaker service. After this operation, the handshake + * will be shutdown, and no more handshaker requests will get scheduled. * - * - client: a ALTS handshaker client instance. + * - client: ALTS handshaker client instance. + */ +void alts_handshaker_client_shutdown(alts_handshaker_client* client); + +/** + * This method destroys an ALTS handshaker client. + * + * - client: an ALTS handshaker client instance. */ void alts_handshaker_client_destroy(alts_handshaker_client* client); /** - * This method creates a ALTS handshaker client. + * This method creates an ALTS handshaker client. * + * - handshaker: ALTS TSI handshaker to which the created handshaker client + * belongs to. * - channel: grpc channel to ALTS handshaker service. - * - queue: grpc completion queue. * - handshaker_service_url: address of ALTS handshaker service in the format of * "host:port". - * - * It returns the created ALTS handshaker client on success, and NULL on - * failure. + * - interested_parties: set of pollsets interested in this connection. + * - options: ALTS credentials options containing information passed from TSI + * caller (e.g., rpc protocol versions) + * - target_name: the name of the endpoint that the channel is connecting to, + * and will be used for secure naming check + * - grpc_cb: gRPC provided callbacks passed from TSI handshaker. + * - cb: callback to be executed when tsi_handshaker_next API compltes. + * - user_data: argument passed to cb. + * - vtable_for_testing: ALTS handshaker client vtable instance used for + * testing purpose. + * - is_client: a boolean value indicating if the created handshaker client is + * used at the client (is_client = true) or server (is_client = false) side. It + * returns the created ALTS handshaker client on success, and NULL on failure. */ alts_handshaker_client* alts_grpc_handshaker_client_create( - grpc_channel* channel, grpc_completion_queue* queue, - const char* handshaker_service_url); - -namespace grpc_core { -namespace internal { + alts_tsi_handshaker* handshaker, grpc_channel* channel, + const char* handshaker_service_url, grpc_pollset_set* interested_parties, + grpc_alts_credentials_options* options, grpc_slice target_name, + grpc_iomgr_cb_func grpc_cb, tsi_handshaker_on_next_done_cb cb, + void* user_data, alts_handshaker_client_vtable* vtable_for_testing, + bool is_client); /** - * Unsafe, use for testing only. It allows the caller to change the way that - * GRPC calls are made to the handshaker service. + * This method handles handshaker response returned from ALTS handshaker + * service. Note that the only reason the API is exposed is that it is used in + * alts_shared_resources.cc. + * + * - client: an ALTS handshaker client instance. + * - is_ok: a boolean value indicating if the handshaker response is ok to read. */ -void alts_handshaker_client_set_grpc_caller_for_testing( - alts_handshaker_client* client, alts_grpc_caller caller); - -} // namespace internal -} // namespace grpc_core +void alts_handshaker_client_handle_response(alts_handshaker_client* client, + bool is_ok); #endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_CLIENT_H */ diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc index e0e418468..d63d3538c 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc @@ -20,6 +20,8 @@ #include "src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h" +#include "src/core/lib/slice/slice_internal.h" + void add_repeated_field(repeated_field** head, const void* data) { repeated_field* field = static_cast(gpr_zalloc(sizeof(*field))); @@ -67,7 +69,7 @@ grpc_slice* create_slice(const char* data, size_t size) { void destroy_slice(grpc_slice* slice) { if (slice != nullptr) { - grpc_slice_unref(*slice); + grpc_slice_unref_internal(*slice); gpr_free(slice); } } diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h index 8fe8f73f8..966ea4561 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h @@ -21,8 +21,8 @@ #include -#include "third_party/nanopb/pb_decode.h" -#include "third_party/nanopb/pb_encode.h" +#include "pb_decode.h" +#include "pb_encode.h" #include #include diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_shared_resource.cc b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_shared_resource.cc new file mode 100644 index 000000000..3501257f0 --- /dev/null +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_shared_resource.cc @@ -0,0 +1,83 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/tsi/alts/handshaker/alts_shared_resource.h" + +#include + +#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h" + +static alts_shared_resource_dedicated g_alts_resource_dedicated; + +alts_shared_resource_dedicated* grpc_alts_get_shared_resource_dedicated(void) { + return &g_alts_resource_dedicated; +} + +static void thread_worker(void* arg) { + while (true) { + grpc_event event = + grpc_completion_queue_next(g_alts_resource_dedicated.cq, + gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); + GPR_ASSERT(event.type != GRPC_QUEUE_TIMEOUT); + if (event.type == GRPC_QUEUE_SHUTDOWN) { + break; + } + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + alts_handshaker_client* client = + static_cast(event.tag); + alts_handshaker_client_handle_response(client, event.success); + } +} + +void grpc_alts_shared_resource_dedicated_init() { + g_alts_resource_dedicated.cq = nullptr; + gpr_mu_init(&g_alts_resource_dedicated.mu); +} + +void grpc_alts_shared_resource_dedicated_start( + const char* handshaker_service_url) { + gpr_mu_lock(&g_alts_resource_dedicated.mu); + if (g_alts_resource_dedicated.cq == nullptr) { + g_alts_resource_dedicated.channel = + grpc_insecure_channel_create(handshaker_service_url, nullptr, nullptr); + g_alts_resource_dedicated.cq = + grpc_completion_queue_create_for_next(nullptr); + g_alts_resource_dedicated.thread = + grpc_core::Thread("alts_tsi_handshaker", &thread_worker, nullptr); + g_alts_resource_dedicated.interested_parties = grpc_pollset_set_create(); + grpc_pollset_set_add_pollset(g_alts_resource_dedicated.interested_parties, + grpc_cq_pollset(g_alts_resource_dedicated.cq)); + g_alts_resource_dedicated.thread.Start(); + } + gpr_mu_unlock(&g_alts_resource_dedicated.mu); +} + +void grpc_alts_shared_resource_dedicated_shutdown() { + if (g_alts_resource_dedicated.cq != nullptr) { + grpc_pollset_set_del_pollset(g_alts_resource_dedicated.interested_parties, + grpc_cq_pollset(g_alts_resource_dedicated.cq)); + grpc_completion_queue_shutdown(g_alts_resource_dedicated.cq); + g_alts_resource_dedicated.thread.Join(); + grpc_pollset_set_destroy(g_alts_resource_dedicated.interested_parties); + grpc_completion_queue_destroy(g_alts_resource_dedicated.cq); + grpc_channel_destroy(g_alts_resource_dedicated.channel); + } + gpr_mu_destroy(&g_alts_resource_dedicated.mu); +} diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_shared_resource.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_shared_resource.h new file mode 100644 index 000000000..8ae0089a1 --- /dev/null +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_shared_resource.h @@ -0,0 +1,73 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_SHARED_RESOURCE_H +#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_SHARED_RESOURCE_H + +#include + +#include +#include + +#include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/surface/completion_queue.h" + +/** + * Main struct containing ALTS shared resources used when + * employing the dedicated completion queue and thread. + */ +typedef struct alts_shared_resource_dedicated { + grpc_core::Thread thread; + grpc_completion_queue* cq; + grpc_pollset_set* interested_parties; + grpc_cq_completion storage; + gpr_mu mu; + grpc_channel* channel; +} alts_shared_resource_dedicated; + +/* This method returns the address of alts_shared_resource_dedicated + * object shared by all TSI handshakes. + */ +alts_shared_resource_dedicated* grpc_alts_get_shared_resource_dedicated(void); + +/** + * This method destroys the alts_shared_resource_dedicated object + * shared by all TSI handshakes. The applicaiton is responsible for + * invoking the API before calling grpc_shutdown(). + */ +void grpc_alts_shared_resource_dedicated_shutdown(); + +/** + * This method initializes the alts_shared_resource_dedicated object + * shared by all TSI handshakes. The application is responsible for + * invoking the API after calling grpc_init(); + */ +void grpc_alts_shared_resource_dedicated_init(); + +/** + * This method populates various fields of the alts_shared_resource_dedicated + * object shared by all TSI handshakes and start the dedicated thread. + * The API will be invoked by the caller in a lazy manner. That is, + * it will get invoked when ALTS TSI handshake occurs for the first time. + */ +void grpc_alts_shared_resource_dedicated_start( + const char* handshaker_service_url); + +#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_SHARED_RESOURCE_H \ + */ diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_event.cc b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_event.cc deleted file mode 100644 index ec0bf12b9..000000000 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_event.cc +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/tsi/alts/handshaker/alts_tsi_event.h" - -#include -#include -#include - -tsi_result alts_tsi_event_create(alts_tsi_handshaker* handshaker, - tsi_handshaker_on_next_done_cb cb, - void* user_data, - grpc_alts_credentials_options* options, - grpc_slice target_name, - alts_tsi_event** event) { - if (event == nullptr || handshaker == nullptr || cb == nullptr) { - gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_event_create()"); - return TSI_INVALID_ARGUMENT; - } - alts_tsi_event* e = static_cast(gpr_zalloc(sizeof(*e))); - e->handshaker = handshaker; - e->cb = cb; - e->user_data = user_data; - e->options = grpc_alts_credentials_options_copy(options); - e->target_name = grpc_slice_copy(target_name); - grpc_metadata_array_init(&e->initial_metadata); - grpc_metadata_array_init(&e->trailing_metadata); - *event = e; - return TSI_OK; -} - -void alts_tsi_event_dispatch_to_handshaker(alts_tsi_event* event, bool is_ok) { - if (event == nullptr) { - gpr_log( - GPR_ERROR, - "ALTS TSI event is nullptr in alts_tsi_event_dispatch_to_handshaker()"); - return; - } - alts_tsi_handshaker_handle_response(event->handshaker, event->recv_buffer, - event->status, &event->details, event->cb, - event->user_data, is_ok); -} - -void alts_tsi_event_destroy(alts_tsi_event* event) { - if (event == nullptr) { - return; - } - grpc_byte_buffer_destroy(event->send_buffer); - grpc_byte_buffer_destroy(event->recv_buffer); - grpc_metadata_array_destroy(&event->initial_metadata); - grpc_metadata_array_destroy(&event->trailing_metadata); - grpc_slice_unref(event->details); - grpc_slice_unref(event->target_name); - grpc_alts_credentials_options_destroy(event->options); - gpr_free(event); -} diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_event.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_event.h deleted file mode 100644 index 043e75d4a..000000000 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_event.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_EVENT_H -#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_EVENT_H - -#include - -#include -#include - -#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" -#include "src/core/tsi/transport_security_interface.h" - -/** - * A ALTS TSI event interface. In asynchronous implementation of - * tsi_handshaker_next(), the function will exit after scheduling a handshaker - * request to ALTS handshaker service without waiting for response to return. - * The event is used to link the scheduled handshaker request with the - * corresponding response so that enough context information can be inferred - * from it to handle the response. All APIs in the header are thread-compatible. - */ - -/** - * Main struct for ALTS TSI event. It retains ownership on send_buffer and - * recv_buffer, but not on handshaker. - */ -typedef struct alts_tsi_event { - alts_tsi_handshaker* handshaker; - grpc_byte_buffer* send_buffer; - grpc_byte_buffer* recv_buffer; - grpc_status_code status; - grpc_slice details; - grpc_metadata_array initial_metadata; - grpc_metadata_array trailing_metadata; - tsi_handshaker_on_next_done_cb cb; - void* user_data; - grpc_alts_credentials_options* options; - grpc_slice target_name; -} alts_tsi_event; - -/** - * This method creates a ALTS TSI event. - * - * - handshaker: ALTS TSI handshaker instance associated with the event to be - * created. The created event does not own the handshaker instance. - * - cb: callback function to be called when handling data received from ALTS - * handshaker service. - * - user_data: argument to callback function. - * - options: ALTS credentials options. - * - target_name: name of endpoint used for secure naming check. - * - event: address of ALTS TSI event instance to be returned from the method. - * - * It returns TSI_OK on success and an error status code on failure. - */ -tsi_result alts_tsi_event_create(alts_tsi_handshaker* handshaker, - tsi_handshaker_on_next_done_cb cb, - void* user_data, - grpc_alts_credentials_options* options, - grpc_slice target_name, - alts_tsi_event** event); - -/** - * This method dispatches a ALTS TSI event received from the handshaker service, - * and a boolean flag indicating if the event is valid to read to ALTS TSI - * handshaker to process. It is called by TSI thread. - * - * - event: ALTS TSI event instance. - * - is_ok: a boolean value indicating if the event is valid to read. - */ -void alts_tsi_event_dispatch_to_handshaker(alts_tsi_event* event, bool is_ok); - -/** - * This method destroys the ALTS TSI event. - */ -void alts_tsi_event_destroy(alts_tsi_event* event); - -#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_EVENT_H */ diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc index 529f2103c..1b7e58d3c 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc @@ -26,33 +26,34 @@ #include #include +#include #include #include #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/alts/frame_protector/alts_frame_protector.h" #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h" +#include "src/core/tsi/alts/handshaker/alts_shared_resource.h" #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h" #include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h" -#include "src/core/tsi/alts_transport_security.h" - -#define TSI_ALTS_INITIAL_BUFFER_SIZE 256 - -static alts_shared_resource* kSharedResource = alts_get_shared_resource(); /* Main struct for ALTS TSI handshaker. */ -typedef struct alts_tsi_handshaker { +struct alts_tsi_handshaker { tsi_handshaker base; alts_handshaker_client* client; - grpc_slice recv_bytes; grpc_slice target_name; - unsigned char* buffer; - size_t buffer_size; bool is_client; bool has_sent_start_message; + bool has_created_handshaker_client; + char* handshaker_service_url; + grpc_pollset_set* interested_parties; grpc_alts_credentials_options* options; -} alts_tsi_handshaker; + alts_handshaker_client_vtable* client_vtable_for_testing; + grpc_channel* channel; +}; /* Main struct for ALTS TSI handshaker result. */ typedef struct alts_tsi_handshaker_result { @@ -127,7 +128,8 @@ static tsi_result handshaker_result_create_zero_copy_grpc_protector( tsi_result ok = alts_zero_copy_grpc_protector_create( reinterpret_cast(result->key_data), kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client, - /*is_integrity_only=*/false, max_output_protected_frame_size, protector); + /*is_integrity_only=*/false, /*enable_extra_copy=*/false, + max_output_protected_frame_size, protector); if (ok != TSI_OK) { gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector"); } @@ -181,7 +183,7 @@ static void handshaker_result_destroy(tsi_handshaker_result* self) { gpr_free(result->peer_identity); gpr_free(result->key_data); gpr_free(result->unused_bytes); - grpc_slice_unref(result->rpc_versions); + grpc_slice_unref_internal(result->rpc_versions); gpr_free(result); } @@ -191,9 +193,9 @@ static const tsi_handshaker_result_vtable result_vtable = { handshaker_result_create_frame_protector, handshaker_result_get_unused_bytes, handshaker_result_destroy}; -static tsi_result create_handshaker_result(grpc_gcp_handshaker_resp* resp, - bool is_client, - tsi_handshaker_result** self) { +tsi_result alts_tsi_handshaker_result_create(grpc_gcp_handshaker_resp* resp, + bool is_client, + tsi_handshaker_result** self) { if (self == nullptr || resp == nullptr) { gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()"); return TSI_INVALID_ARGUMENT; @@ -232,6 +234,27 @@ static tsi_result create_handshaker_result(grpc_gcp_handshaker_resp* resp, return TSI_OK; } +/* gRPC provided callback used when gRPC thread model is applied. */ +static void on_handshaker_service_resp_recv(void* arg, grpc_error* error) { + alts_handshaker_client* client = static_cast(arg); + if (client == nullptr) { + gpr_log(GPR_ERROR, "ALTS handshaker client is nullptr"); + return; + } + alts_handshaker_client_handle_response(client, true); +} + +/* gRPC provided callback used when dedicatd CQ and thread are used. + * It serves to safely bring the control back to application. */ +static void on_handshaker_service_resp_recv_dedicated(void* arg, + grpc_error* error) { + alts_shared_resource_dedicated* resource = + grpc_alts_get_shared_resource_dedicated(); + grpc_cq_end_op(resource->cq, arg, GRPC_ERROR_NONE, + [](void* done_arg, grpc_cq_completion* storage) {}, nullptr, + &resource->storage); +} + static tsi_result handshaker_next( tsi_handshaker* self, const unsigned char* received_bytes, size_t received_bytes_size, const unsigned char** bytes_to_send, @@ -241,15 +264,43 @@ static tsi_result handshaker_next( gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()"); return TSI_INVALID_ARGUMENT; } + if (self->handshake_shutdown) { + gpr_log(GPR_ERROR, "TSI handshake shutdown"); + return TSI_HANDSHAKE_SHUTDOWN; + } alts_tsi_handshaker* handshaker = reinterpret_cast(self); tsi_result ok = TSI_OK; - alts_tsi_event* event = nullptr; - ok = alts_tsi_event_create(handshaker, cb, user_data, handshaker->options, - handshaker->target_name, &event); - if (ok != TSI_OK) { - gpr_log(GPR_ERROR, "Failed to create ALTS TSI event"); - return ok; + if (!handshaker->has_created_handshaker_client) { + if (handshaker->channel == nullptr) { + grpc_alts_shared_resource_dedicated_start( + handshaker->handshaker_service_url); + handshaker->interested_parties = + grpc_alts_get_shared_resource_dedicated()->interested_parties; + GPR_ASSERT(handshaker->interested_parties != nullptr); + } + grpc_iomgr_cb_func grpc_cb = handshaker->channel == nullptr + ? on_handshaker_service_resp_recv_dedicated + : on_handshaker_service_resp_recv; + grpc_channel* channel = + handshaker->channel == nullptr + ? grpc_alts_get_shared_resource_dedicated()->channel + : handshaker->channel; + handshaker->client = alts_grpc_handshaker_client_create( + handshaker, channel, handshaker->handshaker_service_url, + handshaker->interested_parties, handshaker->options, + handshaker->target_name, grpc_cb, cb, user_data, + handshaker->client_vtable_for_testing, handshaker->is_client); + if (handshaker->client == nullptr) { + gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client"); + return TSI_FAILED_PRECONDITION; + } + handshaker->has_created_handshaker_client = true; + } + if (handshaker->channel == nullptr && + handshaker->client_vtable_for_testing == nullptr) { + GPR_ASSERT(grpc_cq_begin_op(grpc_alts_get_shared_resource_dedicated()->cq, + handshaker->client)); } grpc_slice slice = (received_bytes == nullptr || received_bytes_size == 0) ? grpc_empty_slice() @@ -258,18 +309,13 @@ static tsi_result handshaker_next( received_bytes_size); if (!handshaker->has_sent_start_message) { ok = handshaker->is_client - ? alts_handshaker_client_start_client(handshaker->client, event) - : alts_handshaker_client_start_server(handshaker->client, event, - &slice); + ? alts_handshaker_client_start_client(handshaker->client) + : alts_handshaker_client_start_server(handshaker->client, &slice); handshaker->has_sent_start_message = true; } else { - if (!GRPC_SLICE_IS_EMPTY(handshaker->recv_bytes)) { - grpc_slice_unref(handshaker->recv_bytes); - } - handshaker->recv_bytes = grpc_slice_ref(slice); - ok = alts_handshaker_client_next(handshaker->client, event, &slice); + ok = alts_handshaker_client_next(handshaker->client, &slice); } - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); if (ok != TSI_OK) { gpr_log(GPR_ERROR, "Failed to schedule ALTS handshaker requests"); return ok; @@ -277,6 +323,32 @@ static tsi_result handshaker_next( return TSI_ASYNC; } +/* + * This API will be invoked by a non-gRPC application, and an ExecCtx needs + * to be explicitly created in order to invoke ALTS handshaker client API's + * that assumes the caller is inside gRPC core. + */ +static tsi_result handshaker_next_dedicated( + tsi_handshaker* self, const unsigned char* received_bytes, + size_t received_bytes_size, const unsigned char** bytes_to_send, + size_t* bytes_to_send_size, tsi_handshaker_result** result, + tsi_handshaker_on_next_done_cb cb, void* user_data) { + grpc_core::ExecCtx exec_ctx; + return handshaker_next(self, received_bytes, received_bytes_size, + bytes_to_send, bytes_to_send_size, result, cb, + user_data); +} + +static void handshaker_shutdown(tsi_handshaker* self) { + GPR_ASSERT(self != nullptr); + if (self->handshake_shutdown) { + return; + } + alts_tsi_handshaker* handshaker = + reinterpret_cast(self); + alts_handshaker_client_shutdown(handshaker->client); +} + static void handshaker_destroy(tsi_handshaker* self) { if (self == nullptr) { return; @@ -284,91 +356,72 @@ static void handshaker_destroy(tsi_handshaker* self) { alts_tsi_handshaker* handshaker = reinterpret_cast(self); alts_handshaker_client_destroy(handshaker->client); - grpc_slice_unref(handshaker->recv_bytes); - grpc_slice_unref(handshaker->target_name); + grpc_slice_unref_internal(handshaker->target_name); grpc_alts_credentials_options_destroy(handshaker->options); - gpr_free(handshaker->buffer); + if (handshaker->channel != nullptr) { + grpc_channel_destroy(handshaker->channel); + } + gpr_free(handshaker->handshaker_service_url); gpr_free(handshaker); } static const tsi_handshaker_vtable handshaker_vtable = { - nullptr, nullptr, nullptr, nullptr, nullptr, handshaker_destroy, - handshaker_next}; - -static void thread_worker(void* arg) { - while (true) { - grpc_event event = grpc_completion_queue_next( - kSharedResource->cq, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); - GPR_ASSERT(event.type != GRPC_QUEUE_TIMEOUT); - if (event.type == GRPC_QUEUE_SHUTDOWN) { - /* signal alts_tsi_shutdown() to destroy completion queue. */ - grpc_tsi_alts_signal_for_cq_destroy(); - break; - } - /* event.type == GRPC_OP_COMPLETE. */ - alts_tsi_event* alts_event = static_cast(event.tag); - alts_tsi_event_dispatch_to_handshaker(alts_event, event.success); - alts_tsi_event_destroy(alts_event); - } -} - -static void init_shared_resources(const char* handshaker_service_url) { - GPR_ASSERT(handshaker_service_url != nullptr); - gpr_mu_lock(&kSharedResource->mu); - if (kSharedResource->channel == nullptr) { - gpr_cv_init(&kSharedResource->cv); - kSharedResource->channel = - grpc_insecure_channel_create(handshaker_service_url, nullptr, nullptr); - kSharedResource->cq = grpc_completion_queue_create_for_next(nullptr); - kSharedResource->thread = - grpc_core::Thread("alts_tsi_handshaker", &thread_worker, nullptr); - kSharedResource->thread.Start(); - } - gpr_mu_unlock(&kSharedResource->mu); + nullptr, nullptr, + nullptr, nullptr, + nullptr, handshaker_destroy, + handshaker_next, handshaker_shutdown}; + +static const tsi_handshaker_vtable handshaker_vtable_dedicated = { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + handshaker_destroy, + handshaker_next_dedicated, + handshaker_shutdown}; + +bool alts_tsi_handshaker_has_shutdown(alts_tsi_handshaker* handshaker) { + GPR_ASSERT(handshaker != nullptr); + return handshaker->base.handshake_shutdown; } tsi_result alts_tsi_handshaker_create( const grpc_alts_credentials_options* options, const char* target_name, - const char* handshaker_service_url, bool is_client, tsi_handshaker** self) { + const char* handshaker_service_url, bool is_client, + grpc_pollset_set* interested_parties, tsi_handshaker** self) { if (handshaker_service_url == nullptr || self == nullptr || options == nullptr || (is_client && target_name == nullptr)) { gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_handshaker_create()"); return TSI_INVALID_ARGUMENT; } - init_shared_resources(handshaker_service_url); - alts_handshaker_client* client = alts_grpc_handshaker_client_create( - kSharedResource->channel, kSharedResource->cq, handshaker_service_url); - if (client == nullptr) { - gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client"); - return TSI_FAILED_PRECONDITION; - } alts_tsi_handshaker* handshaker = static_cast(gpr_zalloc(sizeof(*handshaker))); - handshaker->client = client; - handshaker->buffer_size = TSI_ALTS_INITIAL_BUFFER_SIZE; - handshaker->buffer = - static_cast(gpr_zalloc(handshaker->buffer_size)); + bool use_dedicated_cq = interested_parties == nullptr; + handshaker->client = nullptr; handshaker->is_client = is_client; handshaker->has_sent_start_message = false; handshaker->target_name = target_name == nullptr ? grpc_empty_slice() : grpc_slice_from_static_string(target_name); + handshaker->interested_parties = interested_parties; + handshaker->has_created_handshaker_client = false; + handshaker->handshaker_service_url = gpr_strdup(handshaker_service_url); handshaker->options = grpc_alts_credentials_options_copy(options); - handshaker->base.vtable = &handshaker_vtable; + handshaker->base.vtable = + use_dedicated_cq ? &handshaker_vtable_dedicated : &handshaker_vtable; + handshaker->channel = + use_dedicated_cq + ? nullptr + : grpc_insecure_channel_create(handshaker->handshaker_service_url, + nullptr, nullptr); *self = &handshaker->base; return TSI_OK; } -static bool is_handshake_finished_properly(grpc_gcp_handshaker_resp* resp) { - GPR_ASSERT(resp != nullptr); - if (resp->has_result) { - return true; - } - return false; -} - -static void set_unused_bytes(tsi_handshaker_result* self, - grpc_slice* recv_bytes, size_t bytes_consumed) { +void alts_tsi_handshaker_result_set_unused_bytes(tsi_handshaker_result* self, + grpc_slice* recv_bytes, + size_t bytes_consumed) { GPR_ASSERT(recv_bytes != nullptr && self != nullptr); if (GRPC_SLICE_LENGTH(*recv_bytes) == bytes_consumed) { return; @@ -383,68 +436,6 @@ static void set_unused_bytes(tsi_handshaker_result* self, result->unused_bytes_size); } -void alts_tsi_handshaker_handle_response(alts_tsi_handshaker* handshaker, - grpc_byte_buffer* recv_buffer, - grpc_status_code status, - grpc_slice* details, - tsi_handshaker_on_next_done_cb cb, - void* user_data, bool is_ok) { - /* Invalid input check. */ - if (cb == nullptr) { - gpr_log(GPR_ERROR, - "cb is nullptr in alts_tsi_handshaker_handle_response()"); - return; - } - if (handshaker == nullptr || recv_buffer == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to alts_tsi_handshaker_handle_response()"); - cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); - return; - } - /* Failed grpc call check. */ - if (!is_ok || status != GRPC_STATUS_OK) { - gpr_log(GPR_ERROR, "grpc call made to handshaker service failed"); - if (details != nullptr) { - char* error_details = grpc_slice_to_c_string(*details); - gpr_log(GPR_ERROR, "error details:%s", error_details); - gpr_free(error_details); - } - cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); - return; - } - grpc_gcp_handshaker_resp* resp = - alts_tsi_utils_deserialize_response(recv_buffer); - /* Invalid handshaker response check. */ - if (resp == nullptr) { - gpr_log(GPR_ERROR, "alts_tsi_utils_deserialize_response() failed"); - cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr); - return; - } - grpc_slice* slice = static_cast(resp->out_frames.arg); - unsigned char* bytes_to_send = nullptr; - size_t bytes_to_send_size = 0; - if (slice != nullptr) { - bytes_to_send_size = GRPC_SLICE_LENGTH(*slice); - while (bytes_to_send_size > handshaker->buffer_size) { - handshaker->buffer_size *= 2; - handshaker->buffer = static_cast( - gpr_realloc(handshaker->buffer, handshaker->buffer_size)); - } - memcpy(handshaker->buffer, GRPC_SLICE_START_PTR(*slice), - bytes_to_send_size); - bytes_to_send = handshaker->buffer; - } - tsi_handshaker_result* result = nullptr; - if (is_handshake_finished_properly(resp)) { - create_handshaker_result(resp, handshaker->is_client, &result); - set_unused_bytes(result, &handshaker->recv_bytes, resp->bytes_consumed); - } - grpc_status_code code = static_cast(resp->status.code); - grpc_gcp_handshaker_resp_destroy(resp); - cb(alts_tsi_utils_convert_to_tsi_result(code), user_data, bytes_to_send, - bytes_to_send_size, result); -} - namespace grpc_core { namespace internal { @@ -454,29 +445,21 @@ bool alts_tsi_handshaker_get_has_sent_start_message_for_testing( return handshaker->has_sent_start_message; } -bool alts_tsi_handshaker_get_is_client_for_testing( - alts_tsi_handshaker* handshaker) { +void alts_tsi_handshaker_set_client_vtable_for_testing( + alts_tsi_handshaker* handshaker, alts_handshaker_client_vtable* vtable) { GPR_ASSERT(handshaker != nullptr); - return handshaker->is_client; -} - -void alts_tsi_handshaker_set_recv_bytes_for_testing( - alts_tsi_handshaker* handshaker, grpc_slice* slice) { - GPR_ASSERT(handshaker != nullptr && slice != nullptr); - handshaker->recv_bytes = grpc_slice_ref(*slice); + handshaker->client_vtable_for_testing = vtable; } -grpc_slice alts_tsi_handshaker_get_recv_bytes_for_testing( +bool alts_tsi_handshaker_get_is_client_for_testing( alts_tsi_handshaker* handshaker) { GPR_ASSERT(handshaker != nullptr); - return handshaker->recv_bytes; + return handshaker->is_client; } -void alts_tsi_handshaker_set_client_for_testing( - alts_tsi_handshaker* handshaker, alts_handshaker_client* client) { - GPR_ASSERT(handshaker != nullptr && client != nullptr); - alts_handshaker_client_destroy(handshaker->client); - handshaker->client = client; +alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing( + alts_tsi_handshaker* handshaker) { + return handshaker->client; } } // namespace internal diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h index 227b30ce5..32f94bc9d 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h @@ -23,8 +23,10 @@ #include +#include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h" -#include "src/core/tsi/alts_transport_security.h" +#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h" +#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h" #include "src/core/tsi/transport_security.h" #include "src/core/tsi/transport_security_interface.h" @@ -34,10 +36,6 @@ const size_t kTsiAltsNumOfPeerProperties = 3; -/** - * Main struct for ALTS TSI handshaker. All APIs in the header are - * thread-comptabile. - */ typedef struct alts_tsi_handshaker alts_tsi_handshaker; /** @@ -51,33 +49,46 @@ typedef struct alts_tsi_handshaker alts_tsi_handshaker; * "host:port". * - is_client: boolean value indicating if the handshaker is used at the client * (is_client = true) or server (is_client = false) side. + * - interested_parties: set of pollsets interested in this connection. * - self: address of ALTS TSI handshaker instance to be returned from the * method. * - * It returns TSI_OK on success and an error status code on failure. + * It returns TSI_OK on success and an error status code on failure. Note that + * if interested_parties is nullptr, a dedicated TSI thread will be created and + * used. */ tsi_result alts_tsi_handshaker_create( const grpc_alts_credentials_options* options, const char* target_name, - const char* handshaker_service_url, bool is_client, tsi_handshaker** self); + const char* handshaker_service_url, bool is_client, + grpc_pollset_set* interested_parties, tsi_handshaker** self); /** - * This method handles handshaker response returned from ALTS handshaker - * service. + * This method creates an ALTS TSI handshaker result instance. * - * - handshaker: ALTS TSI handshaker instance. - * - recv_buffer: buffer holding data received from the handshaker service. - * - status: status of the grpc call made to the handshaker service. - * - details: error details of the grpc call made to the handshaker service. - * - cb: callback function of ALTS TSI event. - * - user_data: argument of callback function. - * - is_ok: a boolean value indicating if the handshaker response is ok to read. + * - resp: data received from the handshaker service. + * - is_client: a boolean value indicating if the result belongs to a + * client or not. + * - result: address of ALTS TSI handshaker result instance. + */ +tsi_result alts_tsi_handshaker_result_create(grpc_gcp_handshaker_resp* resp, + bool is_client, + tsi_handshaker_result** result); + +/** + * This method sets unused bytes of ALTS TSI handshaker result instance. * + * - result: an ALTS TSI handshaker result instance. + * - recv_bytes: data received from the handshaker service. + * - bytes_consumed: size of data consumed by the handshaker service. + */ +void alts_tsi_handshaker_result_set_unused_bytes(tsi_handshaker_result* result, + grpc_slice* recv_bytes, + size_t bytes_consumed); + +/** + * This method returns a boolean value indicating if an ALTS TSI handshaker + * has been shutdown or not. */ -void alts_tsi_handshaker_handle_response(alts_tsi_handshaker* handshaker, - grpc_byte_buffer* recv_buffer, - grpc_status_code status, - grpc_slice* details, - tsi_handshaker_on_next_done_cb cb, - void* user_data, bool is_ok); +bool alts_tsi_handshaker_has_shutdown(alts_tsi_handshaker* handshaker); #endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_H */ diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h index 9b7b9bb6b..ec2616e95 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h @@ -27,24 +27,55 @@ namespace grpc_core { namespace internal { /** - * Unsafe, use for testing only. It allows the caller to change the way the - * ALTS TSI handshaker schedules handshaker requests. - */ -void alts_tsi_handshaker_set_client_for_testing(alts_tsi_handshaker* handshaker, - alts_handshaker_client* client); + * Unsafe, use for testing only. */ + +alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing( + alts_tsi_handshaker* handshaker); -/* For testing only. */ bool alts_tsi_handshaker_get_has_sent_start_message_for_testing( alts_tsi_handshaker* handshaker); +void alts_tsi_handshaker_set_client_vtable_for_testing( + alts_tsi_handshaker* handshaker, alts_handshaker_client_vtable* vtable); + bool alts_tsi_handshaker_get_is_client_for_testing( alts_tsi_handshaker* handshaker); -void alts_tsi_handshaker_set_recv_bytes_for_testing( - alts_tsi_handshaker* handshaker, grpc_slice* slice); +void alts_handshaker_client_set_grpc_caller_for_testing( + alts_handshaker_client* client, alts_grpc_caller caller); -grpc_slice alts_tsi_handshaker_get_recv_bytes_for_testing( - alts_tsi_handshaker* handshaker); +grpc_byte_buffer* alts_handshaker_client_get_send_buffer_for_testing( + alts_handshaker_client* client); + +grpc_byte_buffer** alts_handshaker_client_get_recv_buffer_addr_for_testing( + alts_handshaker_client* client); + +grpc_metadata_array* alts_handshaker_client_get_initial_metadata_for_testing( + alts_handshaker_client* client); + +void alts_handshaker_client_set_recv_bytes_for_testing( + alts_handshaker_client* client, grpc_slice* recv_bytes); + +void alts_handshaker_client_check_fields_for_testing( + alts_handshaker_client* client, tsi_handshaker_on_next_done_cb cb, + void* user_data, bool has_sent_start_message, grpc_slice* recv_bytes); + +void alts_handshaker_client_set_fields_for_testing( + alts_handshaker_client* client, alts_tsi_handshaker* handshaker, + tsi_handshaker_on_next_done_cb cb, void* user_data, + grpc_byte_buffer* recv_buffer, grpc_status_code status); + +void alts_handshaker_client_set_vtable_for_testing( + alts_handshaker_client* client, alts_handshaker_client_vtable* vtable); + +alts_tsi_handshaker* alts_handshaker_client_get_handshaker_for_testing( + alts_handshaker_client* client); + +void alts_handshaker_client_set_cb_for_testing( + alts_handshaker_client* client, tsi_handshaker_on_next_done_cb cb); + +grpc_closure* alts_handshaker_client_get_closure_for_testing( + alts_handshaker_client* client); } // namespace internal } // namespace grpc_core diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_utils.cc b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_utils.cc index d9b5e6c94..1747f1ad0 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/alts_tsi_utils.cc @@ -22,6 +22,8 @@ #include +#include "src/core/lib/slice/slice_internal.h" + tsi_result alts_tsi_utils_convert_to_tsi_result(grpc_status_code code) { switch (code) { case GRPC_STATUS_OK: @@ -47,7 +49,7 @@ grpc_gcp_handshaker_resp* alts_tsi_utils_deserialize_response( grpc_slice slice = grpc_byte_buffer_reader_readall(&bbr); grpc_gcp_handshaker_resp* resp = grpc_gcp_handshaker_resp_create(); bool ok = grpc_gcp_handshaker_resp_decode(slice, resp); - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); grpc_byte_buffer_reader_destroy(&bbr); if (!ok) { grpc_gcp_handshaker_resp_destroy(resp); diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.c b/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.c index 81a82f599..5fb152a55 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.c +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.c @@ -2,7 +2,6 @@ /* Generated by nanopb-0.3.7-dev */ #include "src/core/tsi/alts/handshaker/altscontext.pb.h" - /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.h index 3e72d7f67..632b20c0e 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/altscontext.pb.h @@ -3,9 +3,8 @@ #ifndef PB_GRPC_GCP_ALTSCONTEXT_PB_H_INCLUDED #define PB_GRPC_GCP_ALTSCONTEXT_PB_H_INCLUDED -#include "third_party/nanopb/pb.h" +#include "pb.h" #include "src/core/tsi/alts/handshaker/transport_security_common.pb.h" - /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.c b/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.c index bd992dfa4..5450b1602 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.c +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.c @@ -2,7 +2,6 @@ /* Generated by nanopb-0.3.7-dev */ #include "src/core/tsi/alts/handshaker/handshaker.pb.h" - /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.h index 0805a144d..5ee42a3c6 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/handshaker.pb.h @@ -3,9 +3,8 @@ #ifndef PB_GRPC_GCP_HANDSHAKER_PB_H_INCLUDED #define PB_GRPC_GCP_HANDSHAKER_PB_H_INCLUDED -#include "third_party/nanopb/pb.h" +#include "pb.h" #include "src/core/tsi/alts/handshaker/transport_security_common.pb.h" - /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.c b/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.c index 6063c7625..326b1b10a 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.c +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.c @@ -2,7 +2,6 @@ /* Generated by nanopb-0.3.7-dev */ #include "src/core/tsi/alts/handshaker/transport_security_common.pb.h" - /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.h index 49096dffa..87d9abf14 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common.pb.h @@ -3,7 +3,7 @@ #ifndef PB_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PB_H_INCLUDED #define PB_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PB_H_INCLUDED -#include "third_party/nanopb/pb.h" +#include "pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. diff --git a/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common_api.h b/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common_api.h index 68228cb3b..ec2a0b4b5 100644 --- a/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common_api.h +++ b/Sources/CgRPC/src/core/tsi/alts/handshaker/transport_security_common_api.h @@ -21,8 +21,8 @@ #include -#include "third_party/nanopb/pb_decode.h" -#include "third_party/nanopb/pb_encode.h" +#include "pb_decode.h" +#include "pb_encode.h" #include #include diff --git a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc index 7ba03eb7f..352561d46 100644 --- a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc +++ b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc @@ -23,6 +23,8 @@ #include #include +#include + #include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h" #include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h" @@ -30,12 +32,49 @@ /* Main struct for alts_grpc_integrity_only_record_protocol. */ typedef struct alts_grpc_integrity_only_record_protocol { alts_grpc_record_protocol base; + bool enable_extra_copy; grpc_slice_buffer data_sb; unsigned char* tag_buf; } alts_grpc_integrity_only_record_protocol; /* --- alts_grpc_record_protocol methods implementation. --- */ +static tsi_result alts_grpc_integrity_only_extra_copy_protect( + alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices, + grpc_slice_buffer* protected_slices) { + /* Allocates memory for protected frame and copies data. */ + size_t data_length = unprotected_slices->length; + size_t protected_frame_size = + unprotected_slices->length + rp->header_length + rp->tag_length; + grpc_slice protected_slice = GRPC_SLICE_MALLOC(protected_frame_size); + uint8_t* data = GRPC_SLICE_START_PTR(protected_slice) + rp->header_length; + for (size_t i = 0; i < unprotected_slices->count; i++) { + memcpy(data, GRPC_SLICE_START_PTR(unprotected_slices->slices[i]), + GRPC_SLICE_LENGTH(unprotected_slices->slices[i])); + data += GRPC_SLICE_LENGTH(unprotected_slices->slices[i]); + } + /* Calls alts_iovec_record_protocol protect. */ + char* error_details = nullptr; + iovec_t header_iovec = {GRPC_SLICE_START_PTR(protected_slice), + rp->header_length}; + iovec_t tag_iovec = { + GRPC_SLICE_START_PTR(protected_slice) + rp->header_length + data_length, + rp->tag_length}; + rp->iovec_buf[0].iov_base = + GRPC_SLICE_START_PTR(protected_slice) + rp->header_length; + rp->iovec_buf[0].iov_len = data_length; + grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect( + rp->iovec_rp, rp->iovec_buf, 1, header_iovec, tag_iovec, &error_details); + if (status != GRPC_STATUS_OK) { + gpr_log(GPR_ERROR, "Failed to protect, %s", error_details); + gpr_free(error_details); + return TSI_INTERNAL_ERROR; + } + grpc_slice_buffer_add(protected_slices, protected_slice); + grpc_slice_buffer_reset_and_unref_internal(unprotected_slices); + return TSI_OK; +} + static tsi_result alts_grpc_integrity_only_protect( alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices, grpc_slice_buffer* protected_slices) { @@ -46,6 +85,12 @@ static tsi_result alts_grpc_integrity_only_protect( "Invalid nullptr arguments to alts_grpc_record_protocol protect."); return TSI_INVALID_ARGUMENT; } + alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol = + reinterpret_cast(rp); + if (integrity_only_record_protocol->enable_extra_copy) { + return alts_grpc_integrity_only_extra_copy_protect(rp, unprotected_slices, + protected_slices); + } /* Allocates memory for header and tag slices. */ grpc_slice header_slice = GRPC_SLICE_MALLOC(rp->header_length); grpc_slice tag_slice = GRPC_SLICE_MALLOC(rp->tag_length); @@ -152,7 +197,7 @@ static const alts_grpc_record_protocol_vtable tsi_result alts_grpc_integrity_only_record_protocol_create( gsec_aead_crypter* crypter, size_t overflow_size, bool is_client, - bool is_protect, alts_grpc_record_protocol** rp) { + bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** rp) { if (crypter == nullptr || rp == nullptr) { gpr_log(GPR_ERROR, "Invalid nullptr arguments to alts_grpc_record_protocol create."); @@ -169,6 +214,7 @@ tsi_result alts_grpc_integrity_only_record_protocol_create( gpr_free(impl); return result; } + impl->enable_extra_copy = enable_extra_copy; /* Initializes slice buffer for data_sb. */ grpc_slice_buffer_init(&impl->data_sb); /* Allocates tag buffer. */ diff --git a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h index 8d68b27e0..5456d34fa 100644 --- a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h +++ b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h @@ -38,6 +38,8 @@ * be used at the client or server side. * - is_protect: a flag indicating if the alts_grpc_record_protocol instance * will be used for protect or unprotect. + *- enable_extra_copy: a flag indicating if the instance uses one-copy instead + * of zero-copy in the protect operation. * - rp: an alts_grpc_record_protocol instance to be returned from * the method. * @@ -46,7 +48,7 @@ */ tsi_result alts_grpc_integrity_only_record_protocol_create( gsec_aead_crypter* crypter, size_t overflow_size, bool is_client, - bool is_protect, alts_grpc_record_protocol** rp); + bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** rp); #endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_INTEGRITY_ONLY_RECORD_PROTOCOL_H \ */ diff --git a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc index d4fd88d1e..e7890903d 100644 --- a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc +++ b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc @@ -61,7 +61,7 @@ static tsi_result alts_grpc_privacy_integrity_protect( if (status != GRPC_STATUS_OK) { gpr_log(GPR_ERROR, "Failed to protect, %s", error_details); gpr_free(error_details); - grpc_slice_unref(protected_slice); + grpc_slice_unref_internal(protected_slice); return TSI_INTERNAL_ERROR; } grpc_slice_buffer_add(protected_slices, protected_slice); @@ -106,7 +106,7 @@ static tsi_result alts_grpc_privacy_integrity_unprotect( if (status != GRPC_STATUS_OK) { gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details); gpr_free(error_details); - grpc_slice_unref(unprotected_slice); + grpc_slice_unref_internal(unprotected_slice); return TSI_INTERNAL_ERROR; } grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb); diff --git a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc index 608213745..58aba9b74 100644 --- a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +++ b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc @@ -110,7 +110,7 @@ static bool read_frame_size(const grpc_slice_buffer* sb, */ static tsi_result create_alts_grpc_record_protocol( const uint8_t* key, size_t key_size, bool is_rekey, bool is_client, - bool is_integrity_only, bool is_protect, + bool is_integrity_only, bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** record_protocol) { if (key == nullptr || record_protocol == nullptr) { return TSI_INVALID_ARGUMENT; @@ -130,13 +130,13 @@ static tsi_result create_alts_grpc_record_protocol( : kAltsRecordProtocolFrameLimit; /* Creates alts_grpc_record_protocol with AEAD crypter ownership transferred. */ - tsi_result result = - is_integrity_only - ? alts_grpc_integrity_only_record_protocol_create( - crypter, overflow_limit, is_client, is_protect, record_protocol) - : alts_grpc_privacy_integrity_record_protocol_create( - crypter, overflow_limit, is_client, is_protect, - record_protocol); + tsi_result result = is_integrity_only + ? alts_grpc_integrity_only_record_protocol_create( + crypter, overflow_limit, is_client, is_protect, + enable_extra_copy, record_protocol) + : alts_grpc_privacy_integrity_record_protocol_create( + crypter, overflow_limit, is_client, is_protect, + record_protocol); if (result != TSI_OK) { gsec_aead_crypter_destroy(crypter); return result; @@ -241,7 +241,8 @@ static const tsi_zero_copy_grpc_protector_vtable tsi_result alts_zero_copy_grpc_protector_create( const uint8_t* key, size_t key_size, bool is_rekey, bool is_client, - bool is_integrity_only, size_t* max_protected_frame_size, + bool is_integrity_only, bool enable_extra_copy, + size_t* max_protected_frame_size, tsi_zero_copy_grpc_protector** protector) { if (grpc_core::ExecCtx::Get() == nullptr || key == nullptr || protector == nullptr) { @@ -257,11 +258,11 @@ tsi_result alts_zero_copy_grpc_protector_create( /* Creates alts_grpc_record_protocol objects. */ tsi_result status = create_alts_grpc_record_protocol( key, key_size, is_rekey, is_client, is_integrity_only, - /*is_protect=*/true, &impl->record_protocol); + /*is_protect=*/true, enable_extra_copy, &impl->record_protocol); if (status == TSI_OK) { status = create_alts_grpc_record_protocol( key, key_size, is_rekey, is_client, is_integrity_only, - /*is_protect=*/false, &impl->unrecord_protocol); + /*is_protect=*/false, enable_extra_copy, &impl->unrecord_protocol); if (status == TSI_OK) { /* Sets maximum frame size. */ size_t max_protected_frame_size_to_set = kDefaultFrameLength; diff --git a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h index 71e953cfc..515c27ea0 100644 --- a/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h +++ b/Sources/CgRPC/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h @@ -35,6 +35,11 @@ * server side. * - is_integrity_only: a flag indicating if the protector instance will be * used for integrity-only or privacy-integrity mode. + * - enable_extra_copy: a flag indicating if the protector instance does one + * extra memory copy during the protect operation for integrity_only mode. + * For the unprotect operation, it is still zero-copy. If application intends + * to modify the data buffer after the protect operation, we can turn on this + * mode to avoid integrity check failure. * - max_protected_frame_size: an in/out parameter indicating max frame size * to be used by the protector. If it is nullptr, the default frame size will * be used. Otherwise, the provided frame size will be adjusted (if not @@ -45,8 +50,8 @@ */ tsi_result alts_zero_copy_grpc_protector_create( const uint8_t* key, size_t key_size, bool is_rekey, bool is_client, - bool is_integrity_only, size_t* max_protected_frame_size, - tsi_zero_copy_grpc_protector** protector); + bool is_integrity_only, bool enable_extra_copy, + size_t* max_protected_frame_size, tsi_zero_copy_grpc_protector** protector); #endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_ZERO_COPY_GRPC_PROTECTOR_H \ */ diff --git a/Sources/CgRPC/src/core/tsi/alts_transport_security.cc b/Sources/CgRPC/src/core/tsi/alts_transport_security.cc deleted file mode 100644 index 2fd408103..000000000 --- a/Sources/CgRPC/src/core/tsi/alts_transport_security.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/tsi/alts_transport_security.h" - -#include - -static alts_shared_resource g_alts_resource; - -alts_shared_resource* alts_get_shared_resource(void) { - return &g_alts_resource; -} - -static void grpc_tsi_alts_wait_for_cq_drain() { - gpr_mu_lock(&g_alts_resource.mu); - while (!g_alts_resource.is_cq_drained) { - gpr_cv_wait(&g_alts_resource.cv, &g_alts_resource.mu, - gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&g_alts_resource.mu); -} - -void grpc_tsi_alts_signal_for_cq_destroy() { - gpr_mu_lock(&g_alts_resource.mu); - g_alts_resource.is_cq_drained = true; - gpr_cv_signal(&g_alts_resource.cv); - gpr_mu_unlock(&g_alts_resource.mu); -} - -void grpc_tsi_alts_init() { - memset(&g_alts_resource, 0, sizeof(alts_shared_resource)); - gpr_mu_init(&g_alts_resource.mu); - gpr_cv_init(&g_alts_resource.cv); -} - -void grpc_tsi_alts_shutdown() { - if (g_alts_resource.cq != nullptr) { - grpc_completion_queue_shutdown(g_alts_resource.cq); - grpc_tsi_alts_wait_for_cq_drain(); - grpc_completion_queue_destroy(g_alts_resource.cq); - grpc_channel_destroy(g_alts_resource.channel); - g_alts_resource.thread.Join(); - } - gpr_cv_destroy(&g_alts_resource.cv); - gpr_mu_destroy(&g_alts_resource.mu); -} diff --git a/Sources/CgRPC/src/core/tsi/alts_transport_security.h b/Sources/CgRPC/src/core/tsi/alts_transport_security.h deleted file mode 100644 index d6b8e1113..000000000 --- a/Sources/CgRPC/src/core/tsi/alts_transport_security.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_TSI_ALTS_TRANSPORT_SECURITY_H -#define GRPC_CORE_TSI_ALTS_TRANSPORT_SECURITY_H - -#include - -#include -#include - -#include "src/core/lib/gprpp/thd.h" - -typedef struct alts_shared_resource { - grpc_core::Thread thread; - grpc_channel* channel; - grpc_completion_queue* cq; - gpr_mu mu; - gpr_cv cv; - bool is_cq_drained; -} alts_shared_resource; - -/* This method returns the address of alts_shared_resource object shared by all - * TSI handshakes. */ -alts_shared_resource* alts_get_shared_resource(void); - -/* This method signals the thread that invokes grpc_tsi_alts_shutdown() to - * continue with destroying the cq as a part of shutdown process. */ - -void grpc_tsi_alts_signal_for_cq_destroy(void); - -#endif /* GRPC_CORE_TSI_ALTS_TRANSPORT_SECURITY_H */ diff --git a/Sources/CgRPC/src/core/tsi/fake_transport_security.cc b/Sources/CgRPC/src/core/tsi/fake_transport_security.cc index ad08b50ed..4d4c49504 100644 --- a/Sources/CgRPC/src/core/tsi/fake_transport_security.cc +++ b/Sources/CgRPC/src/core/tsi/fake_transport_security.cc @@ -738,6 +738,7 @@ static const tsi_handshaker_vtable handshaker_vtable = { nullptr, /* create_frame_protector -- deprecated */ fake_handshaker_destroy, fake_handshaker_next, + nullptr, /* shutdown */ }; tsi_handshaker* tsi_create_fake_handshaker(int is_client) { diff --git a/Sources/CgRPC/src/core/tsi/grpc_shadow_boringssl.h b/Sources/CgRPC/src/core/tsi/grpc_shadow_boringssl.h new file mode 100644 index 000000000..074be6d8d --- /dev/null +++ b/Sources/CgRPC/src/core/tsi/grpc_shadow_boringssl.h @@ -0,0 +1,3006 @@ + +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// This file is autogenerated from a template file. Please make +// modifications to +// `templates/src/objective-c/tsi/grpc_shadow_boringssl.h.template` +// instead. This file can be regenerated from the template by running +// `tools/buildgen/generate_projects.sh`. + +#ifndef GRPC_CORE_TSI_GRPC_SHADOW_BORINGSSL_H +#define GRPC_CORE_TSI_GRPC_SHADOW_BORINGSSL_H + +#ifdef GRPC_SHADOW_BORINGSSL_SYMBOLS + +#define BIO_f_ssl GRPC_SHADOW_BIO_f_ssl +#define BIO_set_ssl GRPC_SHADOW_BIO_set_ssl +#define SSL_CTX_add_client_custom_ext GRPC_SHADOW_SSL_CTX_add_client_custom_ext +#define SSL_CTX_add_server_custom_ext GRPC_SHADOW_SSL_CTX_add_server_custom_ext +#define DTLSv1_get_timeout GRPC_SHADOW_DTLSv1_get_timeout +#define DTLSv1_handle_timeout GRPC_SHADOW_DTLSv1_handle_timeout +#define DTLSv1_set_initial_timeout_duration GRPC_SHADOW_DTLSv1_set_initial_timeout_duration +#define SSL_CTX_set_srtp_profiles GRPC_SHADOW_SSL_CTX_set_srtp_profiles +#define SSL_CTX_set_tlsext_use_srtp GRPC_SHADOW_SSL_CTX_set_tlsext_use_srtp +#define SSL_get_selected_srtp_profile GRPC_SHADOW_SSL_get_selected_srtp_profile +#define SSL_get_srtp_profiles GRPC_SHADOW_SSL_get_srtp_profiles +#define SSL_set_srtp_profiles GRPC_SHADOW_SSL_set_srtp_profiles +#define SSL_set_tlsext_use_srtp GRPC_SHADOW_SSL_set_tlsext_use_srtp +#define DTLS_client_method GRPC_SHADOW_DTLS_client_method +#define DTLS_method GRPC_SHADOW_DTLS_method +#define DTLS_server_method GRPC_SHADOW_DTLS_server_method +#define DTLS_with_buffers_method GRPC_SHADOW_DTLS_with_buffers_method +#define DTLSv1_2_client_method GRPC_SHADOW_DTLSv1_2_client_method +#define DTLSv1_2_method GRPC_SHADOW_DTLSv1_2_method +#define DTLSv1_2_server_method GRPC_SHADOW_DTLSv1_2_server_method +#define DTLSv1_client_method GRPC_SHADOW_DTLSv1_client_method +#define DTLSv1_method GRPC_SHADOW_DTLSv1_method +#define DTLSv1_server_method GRPC_SHADOW_DTLSv1_server_method +#define SSL_SESSION_from_bytes GRPC_SHADOW_SSL_SESSION_from_bytes +#define SSL_SESSION_to_bytes GRPC_SHADOW_SSL_SESSION_to_bytes +#define SSL_SESSION_to_bytes_for_ticket GRPC_SHADOW_SSL_SESSION_to_bytes_for_ticket +#define i2d_SSL_SESSION GRPC_SHADOW_i2d_SSL_SESSION +#define SSL_CTX_set0_client_CAs GRPC_SHADOW_SSL_CTX_set0_client_CAs +#define SSL_CTX_set_cert_cb GRPC_SHADOW_SSL_CTX_set_cert_cb +#define SSL_CTX_set_chain_and_key GRPC_SHADOW_SSL_CTX_set_chain_and_key +#define SSL_CTX_set_ocsp_response GRPC_SHADOW_SSL_CTX_set_ocsp_response +#define SSL_CTX_set_signed_cert_timestamp_list GRPC_SHADOW_SSL_CTX_set_signed_cert_timestamp_list +#define SSL_CTX_use_certificate_ASN1 GRPC_SHADOW_SSL_CTX_use_certificate_ASN1 +#define SSL_get0_peer_certificates GRPC_SHADOW_SSL_get0_peer_certificates +#define SSL_get0_server_requested_CAs GRPC_SHADOW_SSL_get0_server_requested_CAs +#define SSL_set0_client_CAs GRPC_SHADOW_SSL_set0_client_CAs +#define SSL_set_cert_cb GRPC_SHADOW_SSL_set_cert_cb +#define SSL_set_chain_and_key GRPC_SHADOW_SSL_set_chain_and_key +#define SSL_set_ocsp_response GRPC_SHADOW_SSL_set_ocsp_response +#define SSL_set_signed_cert_timestamp_list GRPC_SHADOW_SSL_set_signed_cert_timestamp_list +#define SSL_use_certificate_ASN1 GRPC_SHADOW_SSL_use_certificate_ASN1 +#define SSL_CIPHER_description GRPC_SHADOW_SSL_CIPHER_description +#define SSL_CIPHER_get_auth_nid GRPC_SHADOW_SSL_CIPHER_get_auth_nid +#define SSL_CIPHER_get_bits GRPC_SHADOW_SSL_CIPHER_get_bits +#define SSL_CIPHER_get_cipher_nid GRPC_SHADOW_SSL_CIPHER_get_cipher_nid +#define SSL_CIPHER_get_digest_nid GRPC_SHADOW_SSL_CIPHER_get_digest_nid +#define SSL_CIPHER_get_id GRPC_SHADOW_SSL_CIPHER_get_id +#define SSL_CIPHER_get_kx_name GRPC_SHADOW_SSL_CIPHER_get_kx_name +#define SSL_CIPHER_get_kx_nid GRPC_SHADOW_SSL_CIPHER_get_kx_nid +#define SSL_CIPHER_get_max_version GRPC_SHADOW_SSL_CIPHER_get_max_version +#define SSL_CIPHER_get_min_version GRPC_SHADOW_SSL_CIPHER_get_min_version +#define SSL_CIPHER_get_name GRPC_SHADOW_SSL_CIPHER_get_name +#define SSL_CIPHER_get_prf_nid GRPC_SHADOW_SSL_CIPHER_get_prf_nid +#define SSL_CIPHER_get_rfc_name GRPC_SHADOW_SSL_CIPHER_get_rfc_name +#define SSL_CIPHER_get_version GRPC_SHADOW_SSL_CIPHER_get_version +#define SSL_CIPHER_is_aead GRPC_SHADOW_SSL_CIPHER_is_aead +#define SSL_CIPHER_is_block_cipher GRPC_SHADOW_SSL_CIPHER_is_block_cipher +#define SSL_CIPHER_standard_name GRPC_SHADOW_SSL_CIPHER_standard_name +#define SSL_COMP_add_compression_method GRPC_SHADOW_SSL_COMP_add_compression_method +#define SSL_COMP_free_compression_methods GRPC_SHADOW_SSL_COMP_free_compression_methods +#define SSL_COMP_get0_name GRPC_SHADOW_SSL_COMP_get0_name +#define SSL_COMP_get_compression_methods GRPC_SHADOW_SSL_COMP_get_compression_methods +#define SSL_COMP_get_id GRPC_SHADOW_SSL_COMP_get_id +#define SSL_COMP_get_name GRPC_SHADOW_SSL_COMP_get_name +#define SSL_get_cipher_by_value GRPC_SHADOW_SSL_get_cipher_by_value +#define SSL_CTX_get_default_passwd_cb GRPC_SHADOW_SSL_CTX_get_default_passwd_cb +#define SSL_CTX_get_default_passwd_cb_userdata GRPC_SHADOW_SSL_CTX_get_default_passwd_cb_userdata +#define SSL_CTX_set_default_passwd_cb GRPC_SHADOW_SSL_CTX_set_default_passwd_cb +#define SSL_CTX_set_default_passwd_cb_userdata GRPC_SHADOW_SSL_CTX_set_default_passwd_cb_userdata +#define SSL_CTX_use_PrivateKey_file GRPC_SHADOW_SSL_CTX_use_PrivateKey_file +#define SSL_CTX_use_RSAPrivateKey_file GRPC_SHADOW_SSL_CTX_use_RSAPrivateKey_file +#define SSL_CTX_use_certificate_chain_file GRPC_SHADOW_SSL_CTX_use_certificate_chain_file +#define SSL_CTX_use_certificate_file GRPC_SHADOW_SSL_CTX_use_certificate_file +#define SSL_add_file_cert_subjects_to_stack GRPC_SHADOW_SSL_add_file_cert_subjects_to_stack +#define SSL_load_client_CA_file GRPC_SHADOW_SSL_load_client_CA_file +#define SSL_use_PrivateKey_file GRPC_SHADOW_SSL_use_PrivateKey_file +#define SSL_use_RSAPrivateKey_file GRPC_SHADOW_SSL_use_RSAPrivateKey_file +#define SSL_use_certificate_file GRPC_SHADOW_SSL_use_certificate_file +#define SSL_get_curve_name GRPC_SHADOW_SSL_get_curve_name +#define ERR_load_SSL_strings GRPC_SHADOW_ERR_load_SSL_strings +#define OPENSSL_init_ssl GRPC_SHADOW_OPENSSL_init_ssl +#define SSL_CTX_check_private_key GRPC_SHADOW_SSL_CTX_check_private_key +#define SSL_CTX_cipher_in_group GRPC_SHADOW_SSL_CTX_cipher_in_group +#define SSL_CTX_clear_mode GRPC_SHADOW_SSL_CTX_clear_mode +#define SSL_CTX_clear_options GRPC_SHADOW_SSL_CTX_clear_options +#define SSL_CTX_enable_ocsp_stapling GRPC_SHADOW_SSL_CTX_enable_ocsp_stapling +#define SSL_CTX_enable_signed_cert_timestamps GRPC_SHADOW_SSL_CTX_enable_signed_cert_timestamps +#define SSL_CTX_enable_tls_channel_id GRPC_SHADOW_SSL_CTX_enable_tls_channel_id +#define SSL_CTX_free GRPC_SHADOW_SSL_CTX_free +#define SSL_CTX_get0_privatekey GRPC_SHADOW_SSL_CTX_get0_privatekey +#define SSL_CTX_get_ciphers GRPC_SHADOW_SSL_CTX_get_ciphers +#define SSL_CTX_get_ex_data GRPC_SHADOW_SSL_CTX_get_ex_data +#define SSL_CTX_get_ex_new_index GRPC_SHADOW_SSL_CTX_get_ex_new_index +#define SSL_CTX_get_keylog_callback GRPC_SHADOW_SSL_CTX_get_keylog_callback +#define SSL_CTX_get_max_cert_list GRPC_SHADOW_SSL_CTX_get_max_cert_list +#define SSL_CTX_get_mode GRPC_SHADOW_SSL_CTX_get_mode +#define SSL_CTX_get_options GRPC_SHADOW_SSL_CTX_get_options +#define SSL_CTX_get_quiet_shutdown GRPC_SHADOW_SSL_CTX_get_quiet_shutdown +#define SSL_CTX_get_read_ahead GRPC_SHADOW_SSL_CTX_get_read_ahead +#define SSL_CTX_get_session_cache_mode GRPC_SHADOW_SSL_CTX_get_session_cache_mode +#define SSL_CTX_get_tlsext_ticket_keys GRPC_SHADOW_SSL_CTX_get_tlsext_ticket_keys +#define SSL_CTX_need_tmp_RSA GRPC_SHADOW_SSL_CTX_need_tmp_RSA +#define SSL_CTX_new GRPC_SHADOW_SSL_CTX_new +#define SSL_CTX_sess_accept GRPC_SHADOW_SSL_CTX_sess_accept +#define SSL_CTX_sess_accept_good GRPC_SHADOW_SSL_CTX_sess_accept_good +#define SSL_CTX_sess_accept_renegotiate GRPC_SHADOW_SSL_CTX_sess_accept_renegotiate +#define SSL_CTX_sess_cache_full GRPC_SHADOW_SSL_CTX_sess_cache_full +#define SSL_CTX_sess_cb_hits GRPC_SHADOW_SSL_CTX_sess_cb_hits +#define SSL_CTX_sess_connect GRPC_SHADOW_SSL_CTX_sess_connect +#define SSL_CTX_sess_connect_good GRPC_SHADOW_SSL_CTX_sess_connect_good +#define SSL_CTX_sess_connect_renegotiate GRPC_SHADOW_SSL_CTX_sess_connect_renegotiate +#define SSL_CTX_sess_get_cache_size GRPC_SHADOW_SSL_CTX_sess_get_cache_size +#define SSL_CTX_sess_hits GRPC_SHADOW_SSL_CTX_sess_hits +#define SSL_CTX_sess_misses GRPC_SHADOW_SSL_CTX_sess_misses +#define SSL_CTX_sess_number GRPC_SHADOW_SSL_CTX_sess_number +#define SSL_CTX_sess_set_cache_size GRPC_SHADOW_SSL_CTX_sess_set_cache_size +#define SSL_CTX_sess_timeouts GRPC_SHADOW_SSL_CTX_sess_timeouts +#define SSL_CTX_set0_buffer_pool GRPC_SHADOW_SSL_CTX_set0_buffer_pool +#define SSL_CTX_set1_curves GRPC_SHADOW_SSL_CTX_set1_curves +#define SSL_CTX_set1_curves_list GRPC_SHADOW_SSL_CTX_set1_curves_list +#define SSL_CTX_set1_tls_channel_id GRPC_SHADOW_SSL_CTX_set1_tls_channel_id +#define SSL_CTX_set_allow_unknown_alpn_protos GRPC_SHADOW_SSL_CTX_set_allow_unknown_alpn_protos +#define SSL_CTX_set_alpn_protos GRPC_SHADOW_SSL_CTX_set_alpn_protos +#define SSL_CTX_set_alpn_select_cb GRPC_SHADOW_SSL_CTX_set_alpn_select_cb +#define SSL_CTX_set_cipher_list GRPC_SHADOW_SSL_CTX_set_cipher_list +#define SSL_CTX_set_current_time_cb GRPC_SHADOW_SSL_CTX_set_current_time_cb +#define SSL_CTX_set_custom_verify GRPC_SHADOW_SSL_CTX_set_custom_verify +#define SSL_CTX_set_dos_protection_cb GRPC_SHADOW_SSL_CTX_set_dos_protection_cb +#define SSL_CTX_set_early_data_enabled GRPC_SHADOW_SSL_CTX_set_early_data_enabled +#define SSL_CTX_set_ex_data GRPC_SHADOW_SSL_CTX_set_ex_data +#define SSL_CTX_set_false_start_allowed_without_alpn GRPC_SHADOW_SSL_CTX_set_false_start_allowed_without_alpn +#define SSL_CTX_set_grease_enabled GRPC_SHADOW_SSL_CTX_set_grease_enabled +#define SSL_CTX_set_keylog_callback GRPC_SHADOW_SSL_CTX_set_keylog_callback +#define SSL_CTX_set_max_cert_list GRPC_SHADOW_SSL_CTX_set_max_cert_list +#define SSL_CTX_set_max_send_fragment GRPC_SHADOW_SSL_CTX_set_max_send_fragment +#define SSL_CTX_set_mode GRPC_SHADOW_SSL_CTX_set_mode +#define SSL_CTX_set_msg_callback GRPC_SHADOW_SSL_CTX_set_msg_callback +#define SSL_CTX_set_msg_callback_arg GRPC_SHADOW_SSL_CTX_set_msg_callback_arg +#define SSL_CTX_set_next_proto_select_cb GRPC_SHADOW_SSL_CTX_set_next_proto_select_cb +#define SSL_CTX_set_next_protos_advertised_cb GRPC_SHADOW_SSL_CTX_set_next_protos_advertised_cb +#define SSL_CTX_set_options GRPC_SHADOW_SSL_CTX_set_options +#define SSL_CTX_set_psk_client_callback GRPC_SHADOW_SSL_CTX_set_psk_client_callback +#define SSL_CTX_set_psk_server_callback GRPC_SHADOW_SSL_CTX_set_psk_server_callback +#define SSL_CTX_set_quiet_shutdown GRPC_SHADOW_SSL_CTX_set_quiet_shutdown +#define SSL_CTX_set_read_ahead GRPC_SHADOW_SSL_CTX_set_read_ahead +#define SSL_CTX_set_retain_only_sha256_of_client_certs GRPC_SHADOW_SSL_CTX_set_retain_only_sha256_of_client_certs +#define SSL_CTX_set_select_certificate_cb GRPC_SHADOW_SSL_CTX_set_select_certificate_cb +#define SSL_CTX_set_session_cache_mode GRPC_SHADOW_SSL_CTX_set_session_cache_mode +#define SSL_CTX_set_session_id_context GRPC_SHADOW_SSL_CTX_set_session_id_context +#define SSL_CTX_set_strict_cipher_list GRPC_SHADOW_SSL_CTX_set_strict_cipher_list +#define SSL_CTX_set_ticket_aead_method GRPC_SHADOW_SSL_CTX_set_ticket_aead_method +#define SSL_CTX_set_tls13_variant GRPC_SHADOW_SSL_CTX_set_tls13_variant +#define SSL_CTX_set_tls_channel_id_enabled GRPC_SHADOW_SSL_CTX_set_tls_channel_id_enabled +#define SSL_CTX_set_tlsext_servername_arg GRPC_SHADOW_SSL_CTX_set_tlsext_servername_arg +#define SSL_CTX_set_tlsext_servername_callback GRPC_SHADOW_SSL_CTX_set_tlsext_servername_callback +#define SSL_CTX_set_tlsext_ticket_key_cb GRPC_SHADOW_SSL_CTX_set_tlsext_ticket_key_cb +#define SSL_CTX_set_tlsext_ticket_keys GRPC_SHADOW_SSL_CTX_set_tlsext_ticket_keys +#define SSL_CTX_set_tmp_dh GRPC_SHADOW_SSL_CTX_set_tmp_dh +#define SSL_CTX_set_tmp_dh_callback GRPC_SHADOW_SSL_CTX_set_tmp_dh_callback +#define SSL_CTX_set_tmp_ecdh GRPC_SHADOW_SSL_CTX_set_tmp_ecdh +#define SSL_CTX_set_tmp_rsa GRPC_SHADOW_SSL_CTX_set_tmp_rsa +#define SSL_CTX_set_tmp_rsa_callback GRPC_SHADOW_SSL_CTX_set_tmp_rsa_callback +#define SSL_CTX_up_ref GRPC_SHADOW_SSL_CTX_up_ref +#define SSL_CTX_use_psk_identity_hint GRPC_SHADOW_SSL_CTX_use_psk_identity_hint +#define SSL_accept GRPC_SHADOW_SSL_accept +#define SSL_cache_hit GRPC_SHADOW_SSL_cache_hit +#define SSL_certs_clear GRPC_SHADOW_SSL_certs_clear +#define SSL_check_private_key GRPC_SHADOW_SSL_check_private_key +#define SSL_clear GRPC_SHADOW_SSL_clear +#define SSL_clear_mode GRPC_SHADOW_SSL_clear_mode +#define SSL_clear_options GRPC_SHADOW_SSL_clear_options +#define SSL_connect GRPC_SHADOW_SSL_connect +#define SSL_cutthrough_complete GRPC_SHADOW_SSL_cutthrough_complete +#define SSL_do_handshake GRPC_SHADOW_SSL_do_handshake +#define SSL_dummy_pq_padding_used GRPC_SHADOW_SSL_dummy_pq_padding_used +#define SSL_early_data_accepted GRPC_SHADOW_SSL_early_data_accepted +#define SSL_enable_ocsp_stapling GRPC_SHADOW_SSL_enable_ocsp_stapling +#define SSL_enable_signed_cert_timestamps GRPC_SHADOW_SSL_enable_signed_cert_timestamps +#define SSL_enable_tls_channel_id GRPC_SHADOW_SSL_enable_tls_channel_id +#define SSL_free GRPC_SHADOW_SSL_free +#define SSL_get0_alpn_selected GRPC_SHADOW_SSL_get0_alpn_selected +#define SSL_get0_certificate_types GRPC_SHADOW_SSL_get0_certificate_types +#define SSL_get0_next_proto_negotiated GRPC_SHADOW_SSL_get0_next_proto_negotiated +#define SSL_get0_ocsp_response GRPC_SHADOW_SSL_get0_ocsp_response +#define SSL_get0_session_id_context GRPC_SHADOW_SSL_get0_session_id_context +#define SSL_get0_signed_cert_timestamp_list GRPC_SHADOW_SSL_get0_signed_cert_timestamp_list +#define SSL_get_SSL_CTX GRPC_SHADOW_SSL_get_SSL_CTX +#define SSL_get_cipher_list GRPC_SHADOW_SSL_get_cipher_list +#define SSL_get_ciphers GRPC_SHADOW_SSL_get_ciphers +#define SSL_get_client_random GRPC_SHADOW_SSL_get_client_random +#define SSL_get_current_cipher GRPC_SHADOW_SSL_get_current_cipher +#define SSL_get_current_compression GRPC_SHADOW_SSL_get_current_compression +#define SSL_get_current_expansion GRPC_SHADOW_SSL_get_current_expansion +#define SSL_get_curve_id GRPC_SHADOW_SSL_get_curve_id +#define SSL_get_default_timeout GRPC_SHADOW_SSL_get_default_timeout +#define SSL_get_error GRPC_SHADOW_SSL_get_error +#define SSL_get_ex_data GRPC_SHADOW_SSL_get_ex_data +#define SSL_get_ex_new_index GRPC_SHADOW_SSL_get_ex_new_index +#define SSL_get_extms_support GRPC_SHADOW_SSL_get_extms_support +#define SSL_get_fd GRPC_SHADOW_SSL_get_fd +#define SSL_get_finished GRPC_SHADOW_SSL_get_finished +#define SSL_get_info_callback GRPC_SHADOW_SSL_get_info_callback +#define SSL_get_ivs GRPC_SHADOW_SSL_get_ivs +#define SSL_get_max_cert_list GRPC_SHADOW_SSL_get_max_cert_list +#define SSL_get_mode GRPC_SHADOW_SSL_get_mode +#define SSL_get_negotiated_token_binding_param GRPC_SHADOW_SSL_get_negotiated_token_binding_param +#define SSL_get_options GRPC_SHADOW_SSL_get_options +#define SSL_get_peer_finished GRPC_SHADOW_SSL_get_peer_finished +#define SSL_get_peer_quic_transport_params GRPC_SHADOW_SSL_get_peer_quic_transport_params +#define SSL_get_peer_signature_algorithm GRPC_SHADOW_SSL_get_peer_signature_algorithm +#define SSL_get_pending_cipher GRPC_SHADOW_SSL_get_pending_cipher +#define SSL_get_privatekey GRPC_SHADOW_SSL_get_privatekey +#define SSL_get_psk_identity GRPC_SHADOW_SSL_get_psk_identity +#define SSL_get_psk_identity_hint GRPC_SHADOW_SSL_get_psk_identity_hint +#define SSL_get_quiet_shutdown GRPC_SHADOW_SSL_get_quiet_shutdown +#define SSL_get_rbio GRPC_SHADOW_SSL_get_rbio +#define SSL_get_read_ahead GRPC_SHADOW_SSL_get_read_ahead +#define SSL_get_read_sequence GRPC_SHADOW_SSL_get_read_sequence +#define SSL_get_rfd GRPC_SHADOW_SSL_get_rfd +#define SSL_get_secure_renegotiation_support GRPC_SHADOW_SSL_get_secure_renegotiation_support +#define SSL_get_server_random GRPC_SHADOW_SSL_get_server_random +#define SSL_get_server_tmp_key GRPC_SHADOW_SSL_get_server_tmp_key +#define SSL_get_servername GRPC_SHADOW_SSL_get_servername +#define SSL_get_servername_type GRPC_SHADOW_SSL_get_servername_type +#define SSL_get_shared_ciphers GRPC_SHADOW_SSL_get_shared_ciphers +#define SSL_get_shutdown GRPC_SHADOW_SSL_get_shutdown +#define SSL_get_structure_sizes GRPC_SHADOW_SSL_get_structure_sizes +#define SSL_get_ticket_age_skew GRPC_SHADOW_SSL_get_ticket_age_skew +#define SSL_get_tls_channel_id GRPC_SHADOW_SSL_get_tls_channel_id +#define SSL_get_tls_unique GRPC_SHADOW_SSL_get_tls_unique +#define SSL_get_verify_mode GRPC_SHADOW_SSL_get_verify_mode +#define SSL_get_wbio GRPC_SHADOW_SSL_get_wbio +#define SSL_get_wfd GRPC_SHADOW_SSL_get_wfd +#define SSL_get_write_sequence GRPC_SHADOW_SSL_get_write_sequence +#define SSL_in_early_data GRPC_SHADOW_SSL_in_early_data +#define SSL_in_false_start GRPC_SHADOW_SSL_in_false_start +#define SSL_in_init GRPC_SHADOW_SSL_in_init +#define SSL_is_draft_downgrade GRPC_SHADOW_SSL_is_draft_downgrade +#define SSL_is_dtls GRPC_SHADOW_SSL_is_dtls +#define SSL_is_init_finished GRPC_SHADOW_SSL_is_init_finished +#define SSL_is_server GRPC_SHADOW_SSL_is_server +#define SSL_is_token_binding_negotiated GRPC_SHADOW_SSL_is_token_binding_negotiated +#define SSL_library_init GRPC_SHADOW_SSL_library_init +#define SSL_load_error_strings GRPC_SHADOW_SSL_load_error_strings +#define SSL_need_tmp_RSA GRPC_SHADOW_SSL_need_tmp_RSA +#define SSL_new GRPC_SHADOW_SSL_new +#define SSL_num_renegotiations GRPC_SHADOW_SSL_num_renegotiations +#define SSL_peek GRPC_SHADOW_SSL_peek +#define SSL_pending GRPC_SHADOW_SSL_pending +#define SSL_read GRPC_SHADOW_SSL_read +#define SSL_renegotiate GRPC_SHADOW_SSL_renegotiate +#define SSL_renegotiate_pending GRPC_SHADOW_SSL_renegotiate_pending +#define SSL_reset_early_data_reject GRPC_SHADOW_SSL_reset_early_data_reject +#define SSL_select_next_proto GRPC_SHADOW_SSL_select_next_proto +#define SSL_send_fatal_alert GRPC_SHADOW_SSL_send_fatal_alert +#define SSL_session_reused GRPC_SHADOW_SSL_session_reused +#define SSL_set0_rbio GRPC_SHADOW_SSL_set0_rbio +#define SSL_set0_wbio GRPC_SHADOW_SSL_set0_wbio +#define SSL_set1_curves GRPC_SHADOW_SSL_set1_curves +#define SSL_set1_curves_list GRPC_SHADOW_SSL_set1_curves_list +#define SSL_set1_tls_channel_id GRPC_SHADOW_SSL_set1_tls_channel_id +#define SSL_set_SSL_CTX GRPC_SHADOW_SSL_set_SSL_CTX +#define SSL_set_accept_state GRPC_SHADOW_SSL_set_accept_state +#define SSL_set_alpn_protos GRPC_SHADOW_SSL_set_alpn_protos +#define SSL_set_bio GRPC_SHADOW_SSL_set_bio +#define SSL_set_cipher_list GRPC_SHADOW_SSL_set_cipher_list +#define SSL_set_connect_state GRPC_SHADOW_SSL_set_connect_state +#define SSL_set_custom_verify GRPC_SHADOW_SSL_set_custom_verify +#define SSL_set_dummy_pq_padding_size GRPC_SHADOW_SSL_set_dummy_pq_padding_size +#define SSL_set_early_data_enabled GRPC_SHADOW_SSL_set_early_data_enabled +#define SSL_set_ex_data GRPC_SHADOW_SSL_set_ex_data +#define SSL_set_fd GRPC_SHADOW_SSL_set_fd +#define SSL_set_info_callback GRPC_SHADOW_SSL_set_info_callback +#define SSL_set_max_cert_list GRPC_SHADOW_SSL_set_max_cert_list +#define SSL_set_max_send_fragment GRPC_SHADOW_SSL_set_max_send_fragment +#define SSL_set_mode GRPC_SHADOW_SSL_set_mode +#define SSL_set_msg_callback GRPC_SHADOW_SSL_set_msg_callback +#define SSL_set_msg_callback_arg GRPC_SHADOW_SSL_set_msg_callback_arg +#define SSL_set_mtu GRPC_SHADOW_SSL_set_mtu +#define SSL_set_options GRPC_SHADOW_SSL_set_options +#define SSL_set_psk_client_callback GRPC_SHADOW_SSL_set_psk_client_callback +#define SSL_set_psk_server_callback GRPC_SHADOW_SSL_set_psk_server_callback +#define SSL_set_quic_transport_params GRPC_SHADOW_SSL_set_quic_transport_params +#define SSL_set_quiet_shutdown GRPC_SHADOW_SSL_set_quiet_shutdown +#define SSL_set_read_ahead GRPC_SHADOW_SSL_set_read_ahead +#define SSL_set_renegotiate_mode GRPC_SHADOW_SSL_set_renegotiate_mode +#define SSL_set_retain_only_sha256_of_client_certs GRPC_SHADOW_SSL_set_retain_only_sha256_of_client_certs +#define SSL_set_rfd GRPC_SHADOW_SSL_set_rfd +#define SSL_set_session_id_context GRPC_SHADOW_SSL_set_session_id_context +#define SSL_set_shutdown GRPC_SHADOW_SSL_set_shutdown +#define SSL_set_state GRPC_SHADOW_SSL_set_state +#define SSL_set_strict_cipher_list GRPC_SHADOW_SSL_set_strict_cipher_list +#define SSL_set_tls13_variant GRPC_SHADOW_SSL_set_tls13_variant +#define SSL_set_tls_channel_id_enabled GRPC_SHADOW_SSL_set_tls_channel_id_enabled +#define SSL_set_tlsext_host_name GRPC_SHADOW_SSL_set_tlsext_host_name +#define SSL_set_tmp_dh GRPC_SHADOW_SSL_set_tmp_dh +#define SSL_set_tmp_dh_callback GRPC_SHADOW_SSL_set_tmp_dh_callback +#define SSL_set_tmp_ecdh GRPC_SHADOW_SSL_set_tmp_ecdh +#define SSL_set_tmp_rsa GRPC_SHADOW_SSL_set_tmp_rsa +#define SSL_set_tmp_rsa_callback GRPC_SHADOW_SSL_set_tmp_rsa_callback +#define SSL_set_token_binding_params GRPC_SHADOW_SSL_set_token_binding_params +#define SSL_set_wfd GRPC_SHADOW_SSL_set_wfd +#define SSL_shutdown GRPC_SHADOW_SSL_shutdown +#define SSL_state GRPC_SHADOW_SSL_state +#define SSL_total_renegotiations GRPC_SHADOW_SSL_total_renegotiations +#define SSL_use_psk_identity_hint GRPC_SHADOW_SSL_use_psk_identity_hint +#define SSL_want GRPC_SHADOW_SSL_want +#define SSL_write GRPC_SHADOW_SSL_write +#define SSL_CTX_set_private_key_method GRPC_SHADOW_SSL_CTX_set_private_key_method +#define SSL_CTX_set_signing_algorithm_prefs GRPC_SHADOW_SSL_CTX_set_signing_algorithm_prefs +#define SSL_CTX_set_verify_algorithm_prefs GRPC_SHADOW_SSL_CTX_set_verify_algorithm_prefs +#define SSL_CTX_use_PrivateKey GRPC_SHADOW_SSL_CTX_use_PrivateKey +#define SSL_CTX_use_PrivateKey_ASN1 GRPC_SHADOW_SSL_CTX_use_PrivateKey_ASN1 +#define SSL_CTX_use_RSAPrivateKey GRPC_SHADOW_SSL_CTX_use_RSAPrivateKey +#define SSL_CTX_use_RSAPrivateKey_ASN1 GRPC_SHADOW_SSL_CTX_use_RSAPrivateKey_ASN1 +#define SSL_get_signature_algorithm_digest GRPC_SHADOW_SSL_get_signature_algorithm_digest +#define SSL_get_signature_algorithm_key_type GRPC_SHADOW_SSL_get_signature_algorithm_key_type +#define SSL_get_signature_algorithm_name GRPC_SHADOW_SSL_get_signature_algorithm_name +#define SSL_is_signature_algorithm_rsa_pss GRPC_SHADOW_SSL_is_signature_algorithm_rsa_pss +#define SSL_set_private_key_method GRPC_SHADOW_SSL_set_private_key_method +#define SSL_set_signing_algorithm_prefs GRPC_SHADOW_SSL_set_signing_algorithm_prefs +#define SSL_use_PrivateKey GRPC_SHADOW_SSL_use_PrivateKey +#define SSL_use_PrivateKey_ASN1 GRPC_SHADOW_SSL_use_PrivateKey_ASN1 +#define SSL_use_RSAPrivateKey GRPC_SHADOW_SSL_use_RSAPrivateKey +#define SSL_use_RSAPrivateKey_ASN1 GRPC_SHADOW_SSL_use_RSAPrivateKey_ASN1 +#define SSL_CTX_add_session GRPC_SHADOW_SSL_CTX_add_session +#define SSL_CTX_flush_sessions GRPC_SHADOW_SSL_CTX_flush_sessions +#define SSL_CTX_get_channel_id_cb GRPC_SHADOW_SSL_CTX_get_channel_id_cb +#define SSL_CTX_get_info_callback GRPC_SHADOW_SSL_CTX_get_info_callback +#define SSL_CTX_get_timeout GRPC_SHADOW_SSL_CTX_get_timeout +#define SSL_CTX_remove_session GRPC_SHADOW_SSL_CTX_remove_session +#define SSL_CTX_sess_get_get_cb GRPC_SHADOW_SSL_CTX_sess_get_get_cb +#define SSL_CTX_sess_get_new_cb GRPC_SHADOW_SSL_CTX_sess_get_new_cb +#define SSL_CTX_sess_get_remove_cb GRPC_SHADOW_SSL_CTX_sess_get_remove_cb +#define SSL_CTX_sess_set_get_cb GRPC_SHADOW_SSL_CTX_sess_set_get_cb +#define SSL_CTX_sess_set_new_cb GRPC_SHADOW_SSL_CTX_sess_set_new_cb +#define SSL_CTX_sess_set_remove_cb GRPC_SHADOW_SSL_CTX_sess_set_remove_cb +#define SSL_CTX_set_channel_id_cb GRPC_SHADOW_SSL_CTX_set_channel_id_cb +#define SSL_CTX_set_info_callback GRPC_SHADOW_SSL_CTX_set_info_callback +#define SSL_CTX_set_session_psk_dhe_timeout GRPC_SHADOW_SSL_CTX_set_session_psk_dhe_timeout +#define SSL_CTX_set_timeout GRPC_SHADOW_SSL_CTX_set_timeout +#define SSL_SESSION_free GRPC_SHADOW_SSL_SESSION_free +#define SSL_SESSION_get0_peer GRPC_SHADOW_SSL_SESSION_get0_peer +#define SSL_SESSION_get0_ticket GRPC_SHADOW_SSL_SESSION_get0_ticket +#define SSL_SESSION_get_ex_data GRPC_SHADOW_SSL_SESSION_get_ex_data +#define SSL_SESSION_get_ex_new_index GRPC_SHADOW_SSL_SESSION_get_ex_new_index +#define SSL_SESSION_get_id GRPC_SHADOW_SSL_SESSION_get_id +#define SSL_SESSION_get_master_key GRPC_SHADOW_SSL_SESSION_get_master_key +#define SSL_SESSION_get_ticket_lifetime_hint GRPC_SHADOW_SSL_SESSION_get_ticket_lifetime_hint +#define SSL_SESSION_get_time GRPC_SHADOW_SSL_SESSION_get_time +#define SSL_SESSION_get_timeout GRPC_SHADOW_SSL_SESSION_get_timeout +#define SSL_SESSION_has_ticket GRPC_SHADOW_SSL_SESSION_has_ticket +#define SSL_SESSION_is_resumable GRPC_SHADOW_SSL_SESSION_is_resumable +#define SSL_SESSION_new GRPC_SHADOW_SSL_SESSION_new +#define SSL_SESSION_set1_id_context GRPC_SHADOW_SSL_SESSION_set1_id_context +#define SSL_SESSION_set_ex_data GRPC_SHADOW_SSL_SESSION_set_ex_data +#define SSL_SESSION_set_time GRPC_SHADOW_SSL_SESSION_set_time +#define SSL_SESSION_set_timeout GRPC_SHADOW_SSL_SESSION_set_timeout +#define SSL_SESSION_should_be_single_use GRPC_SHADOW_SSL_SESSION_should_be_single_use +#define SSL_SESSION_up_ref GRPC_SHADOW_SSL_SESSION_up_ref +#define SSL_get1_session GRPC_SHADOW_SSL_get1_session +#define SSL_get_session GRPC_SHADOW_SSL_get_session +#define SSL_magic_pending_session_ptr GRPC_SHADOW_SSL_magic_pending_session_ptr +#define SSL_set_session GRPC_SHADOW_SSL_set_session +#define SSL_alert_desc_string GRPC_SHADOW_SSL_alert_desc_string +#define SSL_alert_desc_string_long GRPC_SHADOW_SSL_alert_desc_string_long +#define SSL_alert_type_string GRPC_SHADOW_SSL_alert_type_string +#define SSL_alert_type_string_long GRPC_SHADOW_SSL_alert_type_string_long +#define SSL_state_string GRPC_SHADOW_SSL_state_string +#define SSL_state_string_long GRPC_SHADOW_SSL_state_string_long +#define SSL_CTX_set_max_proto_version GRPC_SHADOW_SSL_CTX_set_max_proto_version +#define SSL_CTX_set_min_proto_version GRPC_SHADOW_SSL_CTX_set_min_proto_version +#define SSL_SESSION_get_protocol_version GRPC_SHADOW_SSL_SESSION_get_protocol_version +#define SSL_SESSION_get_version GRPC_SHADOW_SSL_SESSION_get_version +#define SSL_SESSION_set_protocol_version GRPC_SHADOW_SSL_SESSION_set_protocol_version +#define SSL_get_version GRPC_SHADOW_SSL_get_version +#define SSL_set_max_proto_version GRPC_SHADOW_SSL_set_max_proto_version +#define SSL_set_min_proto_version GRPC_SHADOW_SSL_set_min_proto_version +#define SSL_version GRPC_SHADOW_SSL_version +#define PEM_read_SSL_SESSION GRPC_SHADOW_PEM_read_SSL_SESSION +#define PEM_read_bio_SSL_SESSION GRPC_SHADOW_PEM_read_bio_SSL_SESSION +#define PEM_write_SSL_SESSION GRPC_SHADOW_PEM_write_SSL_SESSION +#define PEM_write_bio_SSL_SESSION GRPC_SHADOW_PEM_write_bio_SSL_SESSION +#define SSL_CTX_add0_chain_cert GRPC_SHADOW_SSL_CTX_add0_chain_cert +#define SSL_CTX_add1_chain_cert GRPC_SHADOW_SSL_CTX_add1_chain_cert +#define SSL_CTX_add_client_CA GRPC_SHADOW_SSL_CTX_add_client_CA +#define SSL_CTX_add_extra_chain_cert GRPC_SHADOW_SSL_CTX_add_extra_chain_cert +#define SSL_CTX_clear_chain_certs GRPC_SHADOW_SSL_CTX_clear_chain_certs +#define SSL_CTX_clear_extra_chain_certs GRPC_SHADOW_SSL_CTX_clear_extra_chain_certs +#define SSL_CTX_get0_certificate GRPC_SHADOW_SSL_CTX_get0_certificate +#define SSL_CTX_get0_chain_certs GRPC_SHADOW_SSL_CTX_get0_chain_certs +#define SSL_CTX_get0_param GRPC_SHADOW_SSL_CTX_get0_param +#define SSL_CTX_get_cert_store GRPC_SHADOW_SSL_CTX_get_cert_store +#define SSL_CTX_get_client_CA_list GRPC_SHADOW_SSL_CTX_get_client_CA_list +#define SSL_CTX_get_extra_chain_certs GRPC_SHADOW_SSL_CTX_get_extra_chain_certs +#define SSL_CTX_get_verify_callback GRPC_SHADOW_SSL_CTX_get_verify_callback +#define SSL_CTX_get_verify_depth GRPC_SHADOW_SSL_CTX_get_verify_depth +#define SSL_CTX_get_verify_mode GRPC_SHADOW_SSL_CTX_get_verify_mode +#define SSL_CTX_load_verify_locations GRPC_SHADOW_SSL_CTX_load_verify_locations +#define SSL_CTX_set0_chain GRPC_SHADOW_SSL_CTX_set0_chain +#define SSL_CTX_set0_verify_cert_store GRPC_SHADOW_SSL_CTX_set0_verify_cert_store +#define SSL_CTX_set1_chain GRPC_SHADOW_SSL_CTX_set1_chain +#define SSL_CTX_set1_param GRPC_SHADOW_SSL_CTX_set1_param +#define SSL_CTX_set1_verify_cert_store GRPC_SHADOW_SSL_CTX_set1_verify_cert_store +#define SSL_CTX_set_cert_store GRPC_SHADOW_SSL_CTX_set_cert_store +#define SSL_CTX_set_cert_verify_callback GRPC_SHADOW_SSL_CTX_set_cert_verify_callback +#define SSL_CTX_set_client_CA_list GRPC_SHADOW_SSL_CTX_set_client_CA_list +#define SSL_CTX_set_client_cert_cb GRPC_SHADOW_SSL_CTX_set_client_cert_cb +#define SSL_CTX_set_default_verify_paths GRPC_SHADOW_SSL_CTX_set_default_verify_paths +#define SSL_CTX_set_purpose GRPC_SHADOW_SSL_CTX_set_purpose +#define SSL_CTX_set_trust GRPC_SHADOW_SSL_CTX_set_trust +#define SSL_CTX_set_verify GRPC_SHADOW_SSL_CTX_set_verify +#define SSL_CTX_set_verify_depth GRPC_SHADOW_SSL_CTX_set_verify_depth +#define SSL_CTX_use_certificate GRPC_SHADOW_SSL_CTX_use_certificate +#define SSL_add0_chain_cert GRPC_SHADOW_SSL_add0_chain_cert +#define SSL_add1_chain_cert GRPC_SHADOW_SSL_add1_chain_cert +#define SSL_add_client_CA GRPC_SHADOW_SSL_add_client_CA +#define SSL_alert_from_verify_result GRPC_SHADOW_SSL_alert_from_verify_result +#define SSL_clear_chain_certs GRPC_SHADOW_SSL_clear_chain_certs +#define SSL_dup_CA_list GRPC_SHADOW_SSL_dup_CA_list +#define SSL_get0_chain_certs GRPC_SHADOW_SSL_get0_chain_certs +#define SSL_get0_param GRPC_SHADOW_SSL_get0_param +#define SSL_get_certificate GRPC_SHADOW_SSL_get_certificate +#define SSL_get_client_CA_list GRPC_SHADOW_SSL_get_client_CA_list +#define SSL_get_ex_data_X509_STORE_CTX_idx GRPC_SHADOW_SSL_get_ex_data_X509_STORE_CTX_idx +#define SSL_get_peer_cert_chain GRPC_SHADOW_SSL_get_peer_cert_chain +#define SSL_get_peer_certificate GRPC_SHADOW_SSL_get_peer_certificate +#define SSL_get_peer_full_cert_chain GRPC_SHADOW_SSL_get_peer_full_cert_chain +#define SSL_get_verify_callback GRPC_SHADOW_SSL_get_verify_callback +#define SSL_get_verify_depth GRPC_SHADOW_SSL_get_verify_depth +#define SSL_get_verify_result GRPC_SHADOW_SSL_get_verify_result +#define SSL_set0_chain GRPC_SHADOW_SSL_set0_chain +#define SSL_set0_verify_cert_store GRPC_SHADOW_SSL_set0_verify_cert_store +#define SSL_set1_chain GRPC_SHADOW_SSL_set1_chain +#define SSL_set1_param GRPC_SHADOW_SSL_set1_param +#define SSL_set1_verify_cert_store GRPC_SHADOW_SSL_set1_verify_cert_store +#define SSL_set_client_CA_list GRPC_SHADOW_SSL_set_client_CA_list +#define SSL_set_purpose GRPC_SHADOW_SSL_set_purpose +#define SSL_set_trust GRPC_SHADOW_SSL_set_trust +#define SSL_set_verify GRPC_SHADOW_SSL_set_verify +#define SSL_set_verify_depth GRPC_SHADOW_SSL_set_verify_depth +#define SSL_set_verify_result GRPC_SHADOW_SSL_set_verify_result +#define SSL_use_certificate GRPC_SHADOW_SSL_use_certificate +#define d2i_SSL_SESSION GRPC_SHADOW_d2i_SSL_SESSION +#define d2i_SSL_SESSION_bio GRPC_SHADOW_d2i_SSL_SESSION_bio +#define i2d_SSL_SESSION_bio GRPC_SHADOW_i2d_SSL_SESSION_bio +#define SSL_export_early_keying_material GRPC_SHADOW_SSL_export_early_keying_material +#define SSL_export_keying_material GRPC_SHADOW_SSL_export_keying_material +#define SSL_generate_key_block GRPC_SHADOW_SSL_generate_key_block +#define SSL_get_key_block_len GRPC_SHADOW_SSL_get_key_block_len +#define SSL_CTX_set_ed25519_enabled GRPC_SHADOW_SSL_CTX_set_ed25519_enabled +#define SSL_early_callback_ctx_extension_get GRPC_SHADOW_SSL_early_callback_ctx_extension_get +#define SSL_extension_supported GRPC_SHADOW_SSL_extension_supported +#define SSLv23_client_method GRPC_SHADOW_SSLv23_client_method +#define SSLv23_method GRPC_SHADOW_SSLv23_method +#define SSLv23_server_method GRPC_SHADOW_SSLv23_server_method +#define TLS_client_method GRPC_SHADOW_TLS_client_method +#define TLS_method GRPC_SHADOW_TLS_method +#define TLS_server_method GRPC_SHADOW_TLS_server_method +#define TLS_with_buffers_method GRPC_SHADOW_TLS_with_buffers_method +#define TLSv1_1_client_method GRPC_SHADOW_TLSv1_1_client_method +#define TLSv1_1_method GRPC_SHADOW_TLSv1_1_method +#define TLSv1_1_server_method GRPC_SHADOW_TLSv1_1_server_method +#define TLSv1_2_client_method GRPC_SHADOW_TLSv1_2_client_method +#define TLSv1_2_method GRPC_SHADOW_TLSv1_2_method +#define TLSv1_2_server_method GRPC_SHADOW_TLSv1_2_server_method +#define TLSv1_client_method GRPC_SHADOW_TLSv1_client_method +#define TLSv1_method GRPC_SHADOW_TLSv1_method +#define TLSv1_server_method GRPC_SHADOW_TLSv1_server_method +#define SSL_max_seal_overhead GRPC_SHADOW_SSL_max_seal_overhead +#define OPENSSL_cpuid_setup GRPC_SHADOW_OPENSSL_cpuid_setup +#define CRYPTO_has_asm GRPC_SHADOW_CRYPTO_has_asm +#define CRYPTO_is_confidential_build GRPC_SHADOW_CRYPTO_is_confidential_build +#define CRYPTO_library_init GRPC_SHADOW_CRYPTO_library_init +#define CRYPTO_malloc_init GRPC_SHADOW_CRYPTO_malloc_init +#define ENGINE_load_builtin_engines GRPC_SHADOW_ENGINE_load_builtin_engines +#define ENGINE_register_all_complete GRPC_SHADOW_ENGINE_register_all_complete +#define OPENSSL_ia32cap_P GRPC_SHADOW_OPENSSL_ia32cap_P +#define OPENSSL_init_crypto GRPC_SHADOW_OPENSSL_init_crypto +#define OPENSSL_load_builtin_modules GRPC_SHADOW_OPENSSL_load_builtin_modules +#define OpenSSL_version GRPC_SHADOW_OpenSSL_version +#define OpenSSL_version_num GRPC_SHADOW_OpenSSL_version_num +#define SSLeay GRPC_SHADOW_SSLeay +#define SSLeay_version GRPC_SHADOW_SSLeay_version +#define CRYPTO_cleanup_all_ex_data GRPC_SHADOW_CRYPTO_cleanup_all_ex_data +#define CRYPTO_free_ex_data GRPC_SHADOW_CRYPTO_free_ex_data +#define CRYPTO_get_ex_data GRPC_SHADOW_CRYPTO_get_ex_data +#define CRYPTO_get_ex_new_index GRPC_SHADOW_CRYPTO_get_ex_new_index +#define CRYPTO_new_ex_data GRPC_SHADOW_CRYPTO_new_ex_data +#define CRYPTO_set_ex_data GRPC_SHADOW_CRYPTO_set_ex_data +#define BIO_snprintf GRPC_SHADOW_BIO_snprintf +#define BIO_vsnprintf GRPC_SHADOW_BIO_vsnprintf +#define CRYPTO_memcmp GRPC_SHADOW_CRYPTO_memcmp +#define OPENSSL_cleanse GRPC_SHADOW_OPENSSL_cleanse +#define OPENSSL_free GRPC_SHADOW_OPENSSL_free +#define OPENSSL_hash32 GRPC_SHADOW_OPENSSL_hash32 +#define OPENSSL_malloc GRPC_SHADOW_OPENSSL_malloc +#define OPENSSL_realloc GRPC_SHADOW_OPENSSL_realloc +#define OPENSSL_strcasecmp GRPC_SHADOW_OPENSSL_strcasecmp +#define OPENSSL_strdup GRPC_SHADOW_OPENSSL_strdup +#define OPENSSL_strncasecmp GRPC_SHADOW_OPENSSL_strncasecmp +#define OPENSSL_strnlen GRPC_SHADOW_OPENSSL_strnlen +#define OPENSSL_tolower GRPC_SHADOW_OPENSSL_tolower +#define CRYPTO_refcount_dec_and_test_zero GRPC_SHADOW_CRYPTO_refcount_dec_and_test_zero +#define CRYPTO_refcount_inc GRPC_SHADOW_CRYPTO_refcount_inc +#define CRYPTO_THREADID_current GRPC_SHADOW_CRYPTO_THREADID_current +#define CRYPTO_THREADID_set_callback GRPC_SHADOW_CRYPTO_THREADID_set_callback +#define CRYPTO_THREADID_set_numeric GRPC_SHADOW_CRYPTO_THREADID_set_numeric +#define CRYPTO_THREADID_set_pointer GRPC_SHADOW_CRYPTO_THREADID_set_pointer +#define CRYPTO_get_dynlock_create_callback GRPC_SHADOW_CRYPTO_get_dynlock_create_callback +#define CRYPTO_get_dynlock_destroy_callback GRPC_SHADOW_CRYPTO_get_dynlock_destroy_callback +#define CRYPTO_get_dynlock_lock_callback GRPC_SHADOW_CRYPTO_get_dynlock_lock_callback +#define CRYPTO_get_lock_name GRPC_SHADOW_CRYPTO_get_lock_name +#define CRYPTO_get_locking_callback GRPC_SHADOW_CRYPTO_get_locking_callback +#define CRYPTO_num_locks GRPC_SHADOW_CRYPTO_num_locks +#define CRYPTO_set_add_lock_callback GRPC_SHADOW_CRYPTO_set_add_lock_callback +#define CRYPTO_set_dynlock_create_callback GRPC_SHADOW_CRYPTO_set_dynlock_create_callback +#define CRYPTO_set_dynlock_destroy_callback GRPC_SHADOW_CRYPTO_set_dynlock_destroy_callback +#define CRYPTO_set_dynlock_lock_callback GRPC_SHADOW_CRYPTO_set_dynlock_lock_callback +#define CRYPTO_set_id_callback GRPC_SHADOW_CRYPTO_set_id_callback +#define CRYPTO_set_locking_callback GRPC_SHADOW_CRYPTO_set_locking_callback +#define CRYPTO_MUTEX_cleanup GRPC_SHADOW_CRYPTO_MUTEX_cleanup +#define CRYPTO_MUTEX_init GRPC_SHADOW_CRYPTO_MUTEX_init +#define CRYPTO_MUTEX_lock_read GRPC_SHADOW_CRYPTO_MUTEX_lock_read +#define CRYPTO_MUTEX_lock_write GRPC_SHADOW_CRYPTO_MUTEX_lock_write +#define CRYPTO_MUTEX_unlock_read GRPC_SHADOW_CRYPTO_MUTEX_unlock_read +#define CRYPTO_MUTEX_unlock_write GRPC_SHADOW_CRYPTO_MUTEX_unlock_write +#define CRYPTO_STATIC_MUTEX_lock_read GRPC_SHADOW_CRYPTO_STATIC_MUTEX_lock_read +#define CRYPTO_STATIC_MUTEX_lock_write GRPC_SHADOW_CRYPTO_STATIC_MUTEX_lock_write +#define CRYPTO_STATIC_MUTEX_unlock_read GRPC_SHADOW_CRYPTO_STATIC_MUTEX_unlock_read +#define CRYPTO_STATIC_MUTEX_unlock_write GRPC_SHADOW_CRYPTO_STATIC_MUTEX_unlock_write +#define CRYPTO_get_thread_local GRPC_SHADOW_CRYPTO_get_thread_local +#define CRYPTO_once GRPC_SHADOW_CRYPTO_once +#define CRYPTO_set_thread_local GRPC_SHADOW_CRYPTO_set_thread_local +#define sk_deep_copy GRPC_SHADOW_sk_deep_copy +#define sk_delete GRPC_SHADOW_sk_delete +#define sk_delete_ptr GRPC_SHADOW_sk_delete_ptr +#define sk_dup GRPC_SHADOW_sk_dup +#define sk_find GRPC_SHADOW_sk_find +#define sk_free GRPC_SHADOW_sk_free +#define sk_insert GRPC_SHADOW_sk_insert +#define sk_is_sorted GRPC_SHADOW_sk_is_sorted +#define sk_new GRPC_SHADOW_sk_new +#define sk_new_null GRPC_SHADOW_sk_new_null +#define sk_num GRPC_SHADOW_sk_num +#define sk_pop GRPC_SHADOW_sk_pop +#define sk_pop_free GRPC_SHADOW_sk_pop_free +#define sk_push GRPC_SHADOW_sk_push +#define sk_set GRPC_SHADOW_sk_set +#define sk_set_cmp_func GRPC_SHADOW_sk_set_cmp_func +#define sk_shift GRPC_SHADOW_sk_shift +#define sk_sort GRPC_SHADOW_sk_sort +#define sk_value GRPC_SHADOW_sk_value +#define sk_zero GRPC_SHADOW_sk_zero +#define lh_delete GRPC_SHADOW_lh_delete +#define lh_doall GRPC_SHADOW_lh_doall +#define lh_doall_arg GRPC_SHADOW_lh_doall_arg +#define lh_free GRPC_SHADOW_lh_free +#define lh_insert GRPC_SHADOW_lh_insert +#define lh_new GRPC_SHADOW_lh_new +#define lh_num_items GRPC_SHADOW_lh_num_items +#define lh_retrieve GRPC_SHADOW_lh_retrieve +#define lh_strhash GRPC_SHADOW_lh_strhash +#define ERR_SAVE_STATE_free GRPC_SHADOW_ERR_SAVE_STATE_free +#define ERR_add_error_data GRPC_SHADOW_ERR_add_error_data +#define ERR_add_error_dataf GRPC_SHADOW_ERR_add_error_dataf +#define ERR_clear_error GRPC_SHADOW_ERR_clear_error +#define ERR_clear_system_error GRPC_SHADOW_ERR_clear_system_error +#define ERR_error_string GRPC_SHADOW_ERR_error_string +#define ERR_error_string_n GRPC_SHADOW_ERR_error_string_n +#define ERR_free_strings GRPC_SHADOW_ERR_free_strings +#define ERR_func_error_string GRPC_SHADOW_ERR_func_error_string +#define ERR_get_error GRPC_SHADOW_ERR_get_error +#define ERR_get_error_line GRPC_SHADOW_ERR_get_error_line +#define ERR_get_error_line_data GRPC_SHADOW_ERR_get_error_line_data +#define ERR_get_next_error_library GRPC_SHADOW_ERR_get_next_error_library +#define ERR_lib_error_string GRPC_SHADOW_ERR_lib_error_string +#define ERR_load_BIO_strings GRPC_SHADOW_ERR_load_BIO_strings +#define ERR_load_ERR_strings GRPC_SHADOW_ERR_load_ERR_strings +#define ERR_load_crypto_strings GRPC_SHADOW_ERR_load_crypto_strings +#define ERR_peek_error GRPC_SHADOW_ERR_peek_error +#define ERR_peek_error_line GRPC_SHADOW_ERR_peek_error_line +#define ERR_peek_error_line_data GRPC_SHADOW_ERR_peek_error_line_data +#define ERR_peek_last_error GRPC_SHADOW_ERR_peek_last_error +#define ERR_peek_last_error_line GRPC_SHADOW_ERR_peek_last_error_line +#define ERR_peek_last_error_line_data GRPC_SHADOW_ERR_peek_last_error_line_data +#define ERR_pop_to_mark GRPC_SHADOW_ERR_pop_to_mark +#define ERR_print_errors_cb GRPC_SHADOW_ERR_print_errors_cb +#define ERR_print_errors_fp GRPC_SHADOW_ERR_print_errors_fp +#define ERR_put_error GRPC_SHADOW_ERR_put_error +#define ERR_reason_error_string GRPC_SHADOW_ERR_reason_error_string +#define ERR_remove_state GRPC_SHADOW_ERR_remove_state +#define ERR_remove_thread_state GRPC_SHADOW_ERR_remove_thread_state +#define ERR_restore_state GRPC_SHADOW_ERR_restore_state +#define ERR_save_state GRPC_SHADOW_ERR_save_state +#define ERR_set_mark GRPC_SHADOW_ERR_set_mark +#define kOpenSSLReasonStringData GRPC_SHADOW_kOpenSSLReasonStringData +#define kOpenSSLReasonValues GRPC_SHADOW_kOpenSSLReasonValues +#define kOpenSSLReasonValuesLen GRPC_SHADOW_kOpenSSLReasonValuesLen +#define EVP_DecodeBase64 GRPC_SHADOW_EVP_DecodeBase64 +#define EVP_DecodeBlock GRPC_SHADOW_EVP_DecodeBlock +#define EVP_DecodeFinal GRPC_SHADOW_EVP_DecodeFinal +#define EVP_DecodeInit GRPC_SHADOW_EVP_DecodeInit +#define EVP_DecodeUpdate GRPC_SHADOW_EVP_DecodeUpdate +#define EVP_DecodedLength GRPC_SHADOW_EVP_DecodedLength +#define EVP_EncodeBlock GRPC_SHADOW_EVP_EncodeBlock +#define EVP_EncodeFinal GRPC_SHADOW_EVP_EncodeFinal +#define EVP_EncodeInit GRPC_SHADOW_EVP_EncodeInit +#define EVP_EncodeUpdate GRPC_SHADOW_EVP_EncodeUpdate +#define EVP_EncodedLength GRPC_SHADOW_EVP_EncodedLength +#define CBB_finish_i2d GRPC_SHADOW_CBB_finish_i2d +#define CBS_asn1_ber_to_der GRPC_SHADOW_CBS_asn1_ber_to_der +#define CBS_get_asn1_implicit_string GRPC_SHADOW_CBS_get_asn1_implicit_string +#define CBS_asn1_bitstring_has_bit GRPC_SHADOW_CBS_asn1_bitstring_has_bit +#define CBS_asn1_oid_to_text GRPC_SHADOW_CBS_asn1_oid_to_text +#define CBS_contains_zero_byte GRPC_SHADOW_CBS_contains_zero_byte +#define CBS_copy_bytes GRPC_SHADOW_CBS_copy_bytes +#define CBS_data GRPC_SHADOW_CBS_data +#define CBS_get_any_asn1 GRPC_SHADOW_CBS_get_any_asn1 +#define CBS_get_any_asn1_element GRPC_SHADOW_CBS_get_any_asn1_element +#define CBS_get_any_ber_asn1_element GRPC_SHADOW_CBS_get_any_ber_asn1_element +#define CBS_get_asn1 GRPC_SHADOW_CBS_get_asn1 +#define CBS_get_asn1_bool GRPC_SHADOW_CBS_get_asn1_bool +#define CBS_get_asn1_element GRPC_SHADOW_CBS_get_asn1_element +#define CBS_get_asn1_uint64 GRPC_SHADOW_CBS_get_asn1_uint64 +#define CBS_get_bytes GRPC_SHADOW_CBS_get_bytes +#define CBS_get_last_u8 GRPC_SHADOW_CBS_get_last_u8 +#define CBS_get_optional_asn1 GRPC_SHADOW_CBS_get_optional_asn1 +#define CBS_get_optional_asn1_bool GRPC_SHADOW_CBS_get_optional_asn1_bool +#define CBS_get_optional_asn1_octet_string GRPC_SHADOW_CBS_get_optional_asn1_octet_string +#define CBS_get_optional_asn1_uint64 GRPC_SHADOW_CBS_get_optional_asn1_uint64 +#define CBS_get_u16 GRPC_SHADOW_CBS_get_u16 +#define CBS_get_u16_length_prefixed GRPC_SHADOW_CBS_get_u16_length_prefixed +#define CBS_get_u24 GRPC_SHADOW_CBS_get_u24 +#define CBS_get_u24_length_prefixed GRPC_SHADOW_CBS_get_u24_length_prefixed +#define CBS_get_u32 GRPC_SHADOW_CBS_get_u32 +#define CBS_get_u8 GRPC_SHADOW_CBS_get_u8 +#define CBS_get_u8_length_prefixed GRPC_SHADOW_CBS_get_u8_length_prefixed +#define CBS_init GRPC_SHADOW_CBS_init +#define CBS_is_valid_asn1_bitstring GRPC_SHADOW_CBS_is_valid_asn1_bitstring +#define CBS_len GRPC_SHADOW_CBS_len +#define CBS_mem_equal GRPC_SHADOW_CBS_mem_equal +#define CBS_peek_asn1_tag GRPC_SHADOW_CBS_peek_asn1_tag +#define CBS_skip GRPC_SHADOW_CBS_skip +#define CBS_stow GRPC_SHADOW_CBS_stow +#define CBS_strdup GRPC_SHADOW_CBS_strdup +#define CBB_add_asn1 GRPC_SHADOW_CBB_add_asn1 +#define CBB_add_asn1_bool GRPC_SHADOW_CBB_add_asn1_bool +#define CBB_add_asn1_octet_string GRPC_SHADOW_CBB_add_asn1_octet_string +#define CBB_add_asn1_oid_from_text GRPC_SHADOW_CBB_add_asn1_oid_from_text +#define CBB_add_asn1_uint64 GRPC_SHADOW_CBB_add_asn1_uint64 +#define CBB_add_bytes GRPC_SHADOW_CBB_add_bytes +#define CBB_add_space GRPC_SHADOW_CBB_add_space +#define CBB_add_u16 GRPC_SHADOW_CBB_add_u16 +#define CBB_add_u16_length_prefixed GRPC_SHADOW_CBB_add_u16_length_prefixed +#define CBB_add_u24 GRPC_SHADOW_CBB_add_u24 +#define CBB_add_u24_length_prefixed GRPC_SHADOW_CBB_add_u24_length_prefixed +#define CBB_add_u32 GRPC_SHADOW_CBB_add_u32 +#define CBB_add_u8 GRPC_SHADOW_CBB_add_u8 +#define CBB_add_u8_length_prefixed GRPC_SHADOW_CBB_add_u8_length_prefixed +#define CBB_cleanup GRPC_SHADOW_CBB_cleanup +#define CBB_data GRPC_SHADOW_CBB_data +#define CBB_did_write GRPC_SHADOW_CBB_did_write +#define CBB_discard_child GRPC_SHADOW_CBB_discard_child +#define CBB_finish GRPC_SHADOW_CBB_finish +#define CBB_flush GRPC_SHADOW_CBB_flush +#define CBB_flush_asn1_set_of GRPC_SHADOW_CBB_flush_asn1_set_of +#define CBB_init GRPC_SHADOW_CBB_init +#define CBB_init_fixed GRPC_SHADOW_CBB_init_fixed +#define CBB_len GRPC_SHADOW_CBB_len +#define CBB_reserve GRPC_SHADOW_CBB_reserve +#define CBB_zero GRPC_SHADOW_CBB_zero +#define CRYPTO_BUFFER_POOL_free GRPC_SHADOW_CRYPTO_BUFFER_POOL_free +#define CRYPTO_BUFFER_POOL_new GRPC_SHADOW_CRYPTO_BUFFER_POOL_new +#define CRYPTO_BUFFER_data GRPC_SHADOW_CRYPTO_BUFFER_data +#define CRYPTO_BUFFER_free GRPC_SHADOW_CRYPTO_BUFFER_free +#define CRYPTO_BUFFER_init_CBS GRPC_SHADOW_CRYPTO_BUFFER_init_CBS +#define CRYPTO_BUFFER_len GRPC_SHADOW_CRYPTO_BUFFER_len +#define CRYPTO_BUFFER_new GRPC_SHADOW_CRYPTO_BUFFER_new +#define CRYPTO_BUFFER_new_from_CBS GRPC_SHADOW_CRYPTO_BUFFER_new_from_CBS +#define CRYPTO_BUFFER_up_ref GRPC_SHADOW_CRYPTO_BUFFER_up_ref +#define AES_cbc_encrypt GRPC_SHADOW_AES_cbc_encrypt +#define AES_cfb128_encrypt GRPC_SHADOW_AES_cfb128_encrypt +#define AES_ctr128_encrypt GRPC_SHADOW_AES_ctr128_encrypt +#define AES_decrypt GRPC_SHADOW_AES_decrypt +#define AES_ecb_encrypt GRPC_SHADOW_AES_ecb_encrypt +#define AES_encrypt GRPC_SHADOW_AES_encrypt +#define AES_ofb128_encrypt GRPC_SHADOW_AES_ofb128_encrypt +#define AES_set_decrypt_key GRPC_SHADOW_AES_set_decrypt_key +#define AES_set_encrypt_key GRPC_SHADOW_AES_set_encrypt_key +#define AES_unwrap_key GRPC_SHADOW_AES_unwrap_key +#define AES_wrap_key GRPC_SHADOW_AES_wrap_key +#define BN_BLINDING_convert GRPC_SHADOW_BN_BLINDING_convert +#define BN_BLINDING_free GRPC_SHADOW_BN_BLINDING_free +#define BN_BLINDING_invert GRPC_SHADOW_BN_BLINDING_invert +#define BN_BLINDING_new GRPC_SHADOW_BN_BLINDING_new +#define BN_CTX_end GRPC_SHADOW_BN_CTX_end +#define BN_CTX_free GRPC_SHADOW_BN_CTX_free +#define BN_CTX_get GRPC_SHADOW_BN_CTX_get +#define BN_CTX_new GRPC_SHADOW_BN_CTX_new +#define BN_CTX_start GRPC_SHADOW_BN_CTX_start +#define BN_GENCB_call GRPC_SHADOW_BN_GENCB_call +#define BN_GENCB_set GRPC_SHADOW_BN_GENCB_set +#define BN_MONT_CTX_copy GRPC_SHADOW_BN_MONT_CTX_copy +#define BN_MONT_CTX_free GRPC_SHADOW_BN_MONT_CTX_free +#define BN_MONT_CTX_new GRPC_SHADOW_BN_MONT_CTX_new +#define BN_MONT_CTX_new_for_modulus GRPC_SHADOW_BN_MONT_CTX_new_for_modulus +#define BN_MONT_CTX_set GRPC_SHADOW_BN_MONT_CTX_set +#define BN_MONT_CTX_set_locked GRPC_SHADOW_BN_MONT_CTX_set_locked +#define BN_abs_is_word GRPC_SHADOW_BN_abs_is_word +#define BN_add GRPC_SHADOW_BN_add +#define BN_add_word GRPC_SHADOW_BN_add_word +#define BN_bin2bn GRPC_SHADOW_BN_bin2bn +#define BN_bn2bin GRPC_SHADOW_BN_bn2bin +#define BN_bn2bin_padded GRPC_SHADOW_BN_bn2bin_padded +#define BN_bn2le_padded GRPC_SHADOW_BN_bn2le_padded +#define BN_clear GRPC_SHADOW_BN_clear +#define BN_clear_bit GRPC_SHADOW_BN_clear_bit +#define BN_clear_free GRPC_SHADOW_BN_clear_free +#define BN_cmp GRPC_SHADOW_BN_cmp +#define BN_cmp_word GRPC_SHADOW_BN_cmp_word +#define BN_copy GRPC_SHADOW_BN_copy +#define BN_count_low_zero_bits GRPC_SHADOW_BN_count_low_zero_bits +#define BN_div GRPC_SHADOW_BN_div +#define BN_div_word GRPC_SHADOW_BN_div_word +#define BN_dup GRPC_SHADOW_BN_dup +#define BN_enhanced_miller_rabin_primality_test GRPC_SHADOW_BN_enhanced_miller_rabin_primality_test +#define BN_equal_consttime GRPC_SHADOW_BN_equal_consttime +#define BN_exp GRPC_SHADOW_BN_exp +#define BN_free GRPC_SHADOW_BN_free +#define BN_from_montgomery GRPC_SHADOW_BN_from_montgomery +#define BN_gcd GRPC_SHADOW_BN_gcd +#define BN_generate_prime_ex GRPC_SHADOW_BN_generate_prime_ex +#define BN_get_u64 GRPC_SHADOW_BN_get_u64 +#define BN_get_word GRPC_SHADOW_BN_get_word +#define BN_init GRPC_SHADOW_BN_init +#define BN_is_bit_set GRPC_SHADOW_BN_is_bit_set +#define BN_is_negative GRPC_SHADOW_BN_is_negative +#define BN_is_odd GRPC_SHADOW_BN_is_odd +#define BN_is_one GRPC_SHADOW_BN_is_one +#define BN_is_pow2 GRPC_SHADOW_BN_is_pow2 +#define BN_is_prime_ex GRPC_SHADOW_BN_is_prime_ex +#define BN_is_prime_fasttest_ex GRPC_SHADOW_BN_is_prime_fasttest_ex +#define BN_is_word GRPC_SHADOW_BN_is_word +#define BN_is_zero GRPC_SHADOW_BN_is_zero +#define BN_le2bn GRPC_SHADOW_BN_le2bn +#define BN_lshift GRPC_SHADOW_BN_lshift +#define BN_lshift1 GRPC_SHADOW_BN_lshift1 +#define BN_mask_bits GRPC_SHADOW_BN_mask_bits +#define BN_mod_add GRPC_SHADOW_BN_mod_add +#define BN_mod_add_quick GRPC_SHADOW_BN_mod_add_quick +#define BN_mod_exp GRPC_SHADOW_BN_mod_exp +#define BN_mod_exp2_mont GRPC_SHADOW_BN_mod_exp2_mont +#define BN_mod_exp_mont GRPC_SHADOW_BN_mod_exp_mont +#define BN_mod_exp_mont_consttime GRPC_SHADOW_BN_mod_exp_mont_consttime +#define BN_mod_exp_mont_word GRPC_SHADOW_BN_mod_exp_mont_word +#define BN_mod_inverse GRPC_SHADOW_BN_mod_inverse +#define BN_mod_inverse_blinded GRPC_SHADOW_BN_mod_inverse_blinded +#define BN_mod_inverse_odd GRPC_SHADOW_BN_mod_inverse_odd +#define BN_mod_lshift GRPC_SHADOW_BN_mod_lshift +#define BN_mod_lshift1 GRPC_SHADOW_BN_mod_lshift1 +#define BN_mod_lshift1_quick GRPC_SHADOW_BN_mod_lshift1_quick +#define BN_mod_lshift_quick GRPC_SHADOW_BN_mod_lshift_quick +#define BN_mod_mul GRPC_SHADOW_BN_mod_mul +#define BN_mod_mul_montgomery GRPC_SHADOW_BN_mod_mul_montgomery +#define BN_mod_pow2 GRPC_SHADOW_BN_mod_pow2 +#define BN_mod_sqr GRPC_SHADOW_BN_mod_sqr +#define BN_mod_sqrt GRPC_SHADOW_BN_mod_sqrt +#define BN_mod_sub GRPC_SHADOW_BN_mod_sub +#define BN_mod_sub_quick GRPC_SHADOW_BN_mod_sub_quick +#define BN_mod_word GRPC_SHADOW_BN_mod_word +#define BN_mul GRPC_SHADOW_BN_mul +#define BN_mul_word GRPC_SHADOW_BN_mul_word +#define BN_new GRPC_SHADOW_BN_new +#define BN_nnmod GRPC_SHADOW_BN_nnmod +#define BN_nnmod_pow2 GRPC_SHADOW_BN_nnmod_pow2 +#define BN_num_bits GRPC_SHADOW_BN_num_bits +#define BN_num_bits_word GRPC_SHADOW_BN_num_bits_word +#define BN_num_bytes GRPC_SHADOW_BN_num_bytes +#define BN_one GRPC_SHADOW_BN_one +#define BN_primality_test GRPC_SHADOW_BN_primality_test +#define BN_pseudo_rand GRPC_SHADOW_BN_pseudo_rand +#define BN_pseudo_rand_range GRPC_SHADOW_BN_pseudo_rand_range +#define BN_rand GRPC_SHADOW_BN_rand +#define BN_rand_range GRPC_SHADOW_BN_rand_range +#define BN_rand_range_ex GRPC_SHADOW_BN_rand_range_ex +#define BN_rshift GRPC_SHADOW_BN_rshift +#define BN_rshift1 GRPC_SHADOW_BN_rshift1 +#define BN_set_bit GRPC_SHADOW_BN_set_bit +#define BN_set_negative GRPC_SHADOW_BN_set_negative +#define BN_set_u64 GRPC_SHADOW_BN_set_u64 +#define BN_set_word GRPC_SHADOW_BN_set_word +#define BN_sqr GRPC_SHADOW_BN_sqr +#define BN_sqrt GRPC_SHADOW_BN_sqrt +#define BN_sub GRPC_SHADOW_BN_sub +#define BN_sub_word GRPC_SHADOW_BN_sub_word +#define BN_to_montgomery GRPC_SHADOW_BN_to_montgomery +#define BN_uadd GRPC_SHADOW_BN_uadd +#define BN_ucmp GRPC_SHADOW_BN_ucmp +#define BN_usub GRPC_SHADOW_BN_usub +#define BN_value_one GRPC_SHADOW_BN_value_one +#define BN_zero GRPC_SHADOW_BN_zero +#define BORINGSSL_self_test GRPC_SHADOW_BORINGSSL_self_test +#define CRYPTO_POLYVAL_finish GRPC_SHADOW_CRYPTO_POLYVAL_finish +#define CRYPTO_POLYVAL_init GRPC_SHADOW_CRYPTO_POLYVAL_init +#define CRYPTO_POLYVAL_update_blocks GRPC_SHADOW_CRYPTO_POLYVAL_update_blocks +#define CRYPTO_cbc128_decrypt GRPC_SHADOW_CRYPTO_cbc128_decrypt +#define CRYPTO_cbc128_encrypt GRPC_SHADOW_CRYPTO_cbc128_encrypt +#define CRYPTO_ccm128_decrypt GRPC_SHADOW_CRYPTO_ccm128_decrypt +#define CRYPTO_ccm128_encrypt GRPC_SHADOW_CRYPTO_ccm128_encrypt +#define CRYPTO_ccm128_init GRPC_SHADOW_CRYPTO_ccm128_init +#define CRYPTO_ccm128_max_input GRPC_SHADOW_CRYPTO_ccm128_max_input +#define CRYPTO_cfb128_1_encrypt GRPC_SHADOW_CRYPTO_cfb128_1_encrypt +#define CRYPTO_cfb128_8_encrypt GRPC_SHADOW_CRYPTO_cfb128_8_encrypt +#define CRYPTO_cfb128_encrypt GRPC_SHADOW_CRYPTO_cfb128_encrypt +#define CRYPTO_ctr128_encrypt GRPC_SHADOW_CRYPTO_ctr128_encrypt +#define CRYPTO_ctr128_encrypt_ctr32 GRPC_SHADOW_CRYPTO_ctr128_encrypt_ctr32 +#define CRYPTO_gcm128_aad GRPC_SHADOW_CRYPTO_gcm128_aad +#define CRYPTO_gcm128_decrypt GRPC_SHADOW_CRYPTO_gcm128_decrypt +#define CRYPTO_gcm128_decrypt_ctr32 GRPC_SHADOW_CRYPTO_gcm128_decrypt_ctr32 +#define CRYPTO_gcm128_encrypt GRPC_SHADOW_CRYPTO_gcm128_encrypt +#define CRYPTO_gcm128_encrypt_ctr32 GRPC_SHADOW_CRYPTO_gcm128_encrypt_ctr32 +#define CRYPTO_gcm128_finish GRPC_SHADOW_CRYPTO_gcm128_finish +#define CRYPTO_gcm128_init GRPC_SHADOW_CRYPTO_gcm128_init +#define CRYPTO_gcm128_setiv GRPC_SHADOW_CRYPTO_gcm128_setiv +#define CRYPTO_gcm128_tag GRPC_SHADOW_CRYPTO_gcm128_tag +#define CRYPTO_ghash_init GRPC_SHADOW_CRYPTO_ghash_init +#define CRYPTO_ofb128_encrypt GRPC_SHADOW_CRYPTO_ofb128_encrypt +#define CRYPTO_sysrand GRPC_SHADOW_CRYPTO_sysrand +#define CRYPTO_tls1_prf GRPC_SHADOW_CRYPTO_tls1_prf +#define CTR_DRBG_clear GRPC_SHADOW_CTR_DRBG_clear +#define CTR_DRBG_generate GRPC_SHADOW_CTR_DRBG_generate +#define CTR_DRBG_init GRPC_SHADOW_CTR_DRBG_init +#define CTR_DRBG_reseed GRPC_SHADOW_CTR_DRBG_reseed +#define DES_decrypt3 GRPC_SHADOW_DES_decrypt3 +#define DES_ecb3_encrypt GRPC_SHADOW_DES_ecb3_encrypt +#define DES_ecb_encrypt GRPC_SHADOW_DES_ecb_encrypt +#define DES_ede2_cbc_encrypt GRPC_SHADOW_DES_ede2_cbc_encrypt +#define DES_ede3_cbc_encrypt GRPC_SHADOW_DES_ede3_cbc_encrypt +#define DES_encrypt3 GRPC_SHADOW_DES_encrypt3 +#define DES_ncbc_encrypt GRPC_SHADOW_DES_ncbc_encrypt +#define DES_set_key GRPC_SHADOW_DES_set_key +#define DES_set_key_unchecked GRPC_SHADOW_DES_set_key_unchecked +#define DES_set_odd_parity GRPC_SHADOW_DES_set_odd_parity +#define ECDSA_SIG_free GRPC_SHADOW_ECDSA_SIG_free +#define ECDSA_SIG_get0 GRPC_SHADOW_ECDSA_SIG_get0 +#define ECDSA_SIG_new GRPC_SHADOW_ECDSA_SIG_new +#define ECDSA_SIG_set0 GRPC_SHADOW_ECDSA_SIG_set0 +#define ECDSA_do_sign GRPC_SHADOW_ECDSA_do_sign +#define ECDSA_do_verify GRPC_SHADOW_ECDSA_do_verify +#define EC_GFp_mont_method GRPC_SHADOW_EC_GFp_mont_method +#define EC_GFp_nistp224_method GRPC_SHADOW_EC_GFp_nistp224_method +#define EC_GFp_nistp256_method GRPC_SHADOW_EC_GFp_nistp256_method +#define EC_GFp_nistz256_method GRPC_SHADOW_EC_GFp_nistz256_method +#define EC_GROUP_cmp GRPC_SHADOW_EC_GROUP_cmp +#define EC_GROUP_dup GRPC_SHADOW_EC_GROUP_dup +#define EC_GROUP_free GRPC_SHADOW_EC_GROUP_free +#define EC_GROUP_get0_generator GRPC_SHADOW_EC_GROUP_get0_generator +#define EC_GROUP_get0_order GRPC_SHADOW_EC_GROUP_get0_order +#define EC_GROUP_get_cofactor GRPC_SHADOW_EC_GROUP_get_cofactor +#define EC_GROUP_get_curve_GFp GRPC_SHADOW_EC_GROUP_get_curve_GFp +#define EC_GROUP_get_curve_name GRPC_SHADOW_EC_GROUP_get_curve_name +#define EC_GROUP_get_degree GRPC_SHADOW_EC_GROUP_get_degree +#define EC_GROUP_get_order GRPC_SHADOW_EC_GROUP_get_order +#define EC_GROUP_method_of GRPC_SHADOW_EC_GROUP_method_of +#define EC_GROUP_new_by_curve_name GRPC_SHADOW_EC_GROUP_new_by_curve_name +#define EC_GROUP_new_curve_GFp GRPC_SHADOW_EC_GROUP_new_curve_GFp +#define EC_GROUP_set_asn1_flag GRPC_SHADOW_EC_GROUP_set_asn1_flag +#define EC_GROUP_set_generator GRPC_SHADOW_EC_GROUP_set_generator +#define EC_GROUP_set_point_conversion_form GRPC_SHADOW_EC_GROUP_set_point_conversion_form +#define EC_KEY_check_fips GRPC_SHADOW_EC_KEY_check_fips +#define EC_KEY_check_key GRPC_SHADOW_EC_KEY_check_key +#define EC_KEY_dup GRPC_SHADOW_EC_KEY_dup +#define EC_KEY_free GRPC_SHADOW_EC_KEY_free +#define EC_KEY_generate_key GRPC_SHADOW_EC_KEY_generate_key +#define EC_KEY_generate_key_fips GRPC_SHADOW_EC_KEY_generate_key_fips +#define EC_KEY_get0_group GRPC_SHADOW_EC_KEY_get0_group +#define EC_KEY_get0_private_key GRPC_SHADOW_EC_KEY_get0_private_key +#define EC_KEY_get0_public_key GRPC_SHADOW_EC_KEY_get0_public_key +#define EC_KEY_get_conv_form GRPC_SHADOW_EC_KEY_get_conv_form +#define EC_KEY_get_enc_flags GRPC_SHADOW_EC_KEY_get_enc_flags +#define EC_KEY_get_ex_data GRPC_SHADOW_EC_KEY_get_ex_data +#define EC_KEY_get_ex_new_index GRPC_SHADOW_EC_KEY_get_ex_new_index +#define EC_KEY_is_opaque GRPC_SHADOW_EC_KEY_is_opaque +#define EC_KEY_new GRPC_SHADOW_EC_KEY_new +#define EC_KEY_new_by_curve_name GRPC_SHADOW_EC_KEY_new_by_curve_name +#define EC_KEY_new_method GRPC_SHADOW_EC_KEY_new_method +#define EC_KEY_set_asn1_flag GRPC_SHADOW_EC_KEY_set_asn1_flag +#define EC_KEY_set_conv_form GRPC_SHADOW_EC_KEY_set_conv_form +#define EC_KEY_set_enc_flags GRPC_SHADOW_EC_KEY_set_enc_flags +#define EC_KEY_set_ex_data GRPC_SHADOW_EC_KEY_set_ex_data +#define EC_KEY_set_group GRPC_SHADOW_EC_KEY_set_group +#define EC_KEY_set_private_key GRPC_SHADOW_EC_KEY_set_private_key +#define EC_KEY_set_public_key GRPC_SHADOW_EC_KEY_set_public_key +#define EC_KEY_set_public_key_affine_coordinates GRPC_SHADOW_EC_KEY_set_public_key_affine_coordinates +#define EC_KEY_up_ref GRPC_SHADOW_EC_KEY_up_ref +#define EC_METHOD_get_field_type GRPC_SHADOW_EC_METHOD_get_field_type +#define EC_POINT_add GRPC_SHADOW_EC_POINT_add +#define EC_POINT_clear_free GRPC_SHADOW_EC_POINT_clear_free +#define EC_POINT_cmp GRPC_SHADOW_EC_POINT_cmp +#define EC_POINT_copy GRPC_SHADOW_EC_POINT_copy +#define EC_POINT_dbl GRPC_SHADOW_EC_POINT_dbl +#define EC_POINT_dup GRPC_SHADOW_EC_POINT_dup +#define EC_POINT_free GRPC_SHADOW_EC_POINT_free +#define EC_POINT_get_affine_coordinates_GFp GRPC_SHADOW_EC_POINT_get_affine_coordinates_GFp +#define EC_POINT_invert GRPC_SHADOW_EC_POINT_invert +#define EC_POINT_is_at_infinity GRPC_SHADOW_EC_POINT_is_at_infinity +#define EC_POINT_is_on_curve GRPC_SHADOW_EC_POINT_is_on_curve +#define EC_POINT_make_affine GRPC_SHADOW_EC_POINT_make_affine +#define EC_POINT_mul GRPC_SHADOW_EC_POINT_mul +#define EC_POINT_new GRPC_SHADOW_EC_POINT_new +#define EC_POINT_oct2point GRPC_SHADOW_EC_POINT_oct2point +#define EC_POINT_point2oct GRPC_SHADOW_EC_POINT_point2oct +#define EC_POINT_set_affine_coordinates_GFp GRPC_SHADOW_EC_POINT_set_affine_coordinates_GFp +#define EC_POINT_set_compressed_coordinates_GFp GRPC_SHADOW_EC_POINT_set_compressed_coordinates_GFp +#define EC_POINT_set_to_infinity GRPC_SHADOW_EC_POINT_set_to_infinity +#define EC_POINTs_make_affine GRPC_SHADOW_EC_POINTs_make_affine +#define EC_get_builtin_curves GRPC_SHADOW_EC_get_builtin_curves +#define EVP_AEAD_CTX_aead GRPC_SHADOW_EVP_AEAD_CTX_aead +#define EVP_AEAD_CTX_cleanup GRPC_SHADOW_EVP_AEAD_CTX_cleanup +#define EVP_AEAD_CTX_free GRPC_SHADOW_EVP_AEAD_CTX_free +#define EVP_AEAD_CTX_get_iv GRPC_SHADOW_EVP_AEAD_CTX_get_iv +#define EVP_AEAD_CTX_init GRPC_SHADOW_EVP_AEAD_CTX_init +#define EVP_AEAD_CTX_init_with_direction GRPC_SHADOW_EVP_AEAD_CTX_init_with_direction +#define EVP_AEAD_CTX_new GRPC_SHADOW_EVP_AEAD_CTX_new +#define EVP_AEAD_CTX_open GRPC_SHADOW_EVP_AEAD_CTX_open +#define EVP_AEAD_CTX_open_gather GRPC_SHADOW_EVP_AEAD_CTX_open_gather +#define EVP_AEAD_CTX_seal GRPC_SHADOW_EVP_AEAD_CTX_seal +#define EVP_AEAD_CTX_seal_scatter GRPC_SHADOW_EVP_AEAD_CTX_seal_scatter +#define EVP_AEAD_CTX_tag_len GRPC_SHADOW_EVP_AEAD_CTX_tag_len +#define EVP_AEAD_CTX_zero GRPC_SHADOW_EVP_AEAD_CTX_zero +#define EVP_AEAD_key_length GRPC_SHADOW_EVP_AEAD_key_length +#define EVP_AEAD_max_overhead GRPC_SHADOW_EVP_AEAD_max_overhead +#define EVP_AEAD_max_tag_len GRPC_SHADOW_EVP_AEAD_max_tag_len +#define EVP_AEAD_nonce_length GRPC_SHADOW_EVP_AEAD_nonce_length +#define EVP_CIPHER_CTX_block_size GRPC_SHADOW_EVP_CIPHER_CTX_block_size +#define EVP_CIPHER_CTX_cipher GRPC_SHADOW_EVP_CIPHER_CTX_cipher +#define EVP_CIPHER_CTX_cleanup GRPC_SHADOW_EVP_CIPHER_CTX_cleanup +#define EVP_CIPHER_CTX_copy GRPC_SHADOW_EVP_CIPHER_CTX_copy +#define EVP_CIPHER_CTX_ctrl GRPC_SHADOW_EVP_CIPHER_CTX_ctrl +#define EVP_CIPHER_CTX_flags GRPC_SHADOW_EVP_CIPHER_CTX_flags +#define EVP_CIPHER_CTX_free GRPC_SHADOW_EVP_CIPHER_CTX_free +#define EVP_CIPHER_CTX_get_app_data GRPC_SHADOW_EVP_CIPHER_CTX_get_app_data +#define EVP_CIPHER_CTX_init GRPC_SHADOW_EVP_CIPHER_CTX_init +#define EVP_CIPHER_CTX_iv_length GRPC_SHADOW_EVP_CIPHER_CTX_iv_length +#define EVP_CIPHER_CTX_key_length GRPC_SHADOW_EVP_CIPHER_CTX_key_length +#define EVP_CIPHER_CTX_mode GRPC_SHADOW_EVP_CIPHER_CTX_mode +#define EVP_CIPHER_CTX_new GRPC_SHADOW_EVP_CIPHER_CTX_new +#define EVP_CIPHER_CTX_nid GRPC_SHADOW_EVP_CIPHER_CTX_nid +#define EVP_CIPHER_CTX_reset GRPC_SHADOW_EVP_CIPHER_CTX_reset +#define EVP_CIPHER_CTX_set_app_data GRPC_SHADOW_EVP_CIPHER_CTX_set_app_data +#define EVP_CIPHER_CTX_set_flags GRPC_SHADOW_EVP_CIPHER_CTX_set_flags +#define EVP_CIPHER_CTX_set_key_length GRPC_SHADOW_EVP_CIPHER_CTX_set_key_length +#define EVP_CIPHER_CTX_set_padding GRPC_SHADOW_EVP_CIPHER_CTX_set_padding +#define EVP_CIPHER_block_size GRPC_SHADOW_EVP_CIPHER_block_size +#define EVP_CIPHER_flags GRPC_SHADOW_EVP_CIPHER_flags +#define EVP_CIPHER_iv_length GRPC_SHADOW_EVP_CIPHER_iv_length +#define EVP_CIPHER_key_length GRPC_SHADOW_EVP_CIPHER_key_length +#define EVP_CIPHER_mode GRPC_SHADOW_EVP_CIPHER_mode +#define EVP_CIPHER_nid GRPC_SHADOW_EVP_CIPHER_nid +#define EVP_Cipher GRPC_SHADOW_EVP_Cipher +#define EVP_CipherFinal_ex GRPC_SHADOW_EVP_CipherFinal_ex +#define EVP_CipherInit GRPC_SHADOW_EVP_CipherInit +#define EVP_CipherInit_ex GRPC_SHADOW_EVP_CipherInit_ex +#define EVP_CipherUpdate GRPC_SHADOW_EVP_CipherUpdate +#define EVP_DecryptFinal_ex GRPC_SHADOW_EVP_DecryptFinal_ex +#define EVP_DecryptInit GRPC_SHADOW_EVP_DecryptInit +#define EVP_DecryptInit_ex GRPC_SHADOW_EVP_DecryptInit_ex +#define EVP_DecryptUpdate GRPC_SHADOW_EVP_DecryptUpdate +#define EVP_Digest GRPC_SHADOW_EVP_Digest +#define EVP_DigestFinal GRPC_SHADOW_EVP_DigestFinal +#define EVP_DigestFinal_ex GRPC_SHADOW_EVP_DigestFinal_ex +#define EVP_DigestInit GRPC_SHADOW_EVP_DigestInit +#define EVP_DigestInit_ex GRPC_SHADOW_EVP_DigestInit_ex +#define EVP_DigestUpdate GRPC_SHADOW_EVP_DigestUpdate +#define EVP_EncryptFinal_ex GRPC_SHADOW_EVP_EncryptFinal_ex +#define EVP_EncryptInit GRPC_SHADOW_EVP_EncryptInit +#define EVP_EncryptInit_ex GRPC_SHADOW_EVP_EncryptInit_ex +#define EVP_EncryptUpdate GRPC_SHADOW_EVP_EncryptUpdate +#define EVP_MD_CTX_block_size GRPC_SHADOW_EVP_MD_CTX_block_size +#define EVP_MD_CTX_cleanup GRPC_SHADOW_EVP_MD_CTX_cleanup +#define EVP_MD_CTX_copy GRPC_SHADOW_EVP_MD_CTX_copy +#define EVP_MD_CTX_copy_ex GRPC_SHADOW_EVP_MD_CTX_copy_ex +#define EVP_MD_CTX_create GRPC_SHADOW_EVP_MD_CTX_create +#define EVP_MD_CTX_destroy GRPC_SHADOW_EVP_MD_CTX_destroy +#define EVP_MD_CTX_free GRPC_SHADOW_EVP_MD_CTX_free +#define EVP_MD_CTX_init GRPC_SHADOW_EVP_MD_CTX_init +#define EVP_MD_CTX_md GRPC_SHADOW_EVP_MD_CTX_md +#define EVP_MD_CTX_new GRPC_SHADOW_EVP_MD_CTX_new +#define EVP_MD_CTX_reset GRPC_SHADOW_EVP_MD_CTX_reset +#define EVP_MD_CTX_size GRPC_SHADOW_EVP_MD_CTX_size +#define EVP_MD_CTX_type GRPC_SHADOW_EVP_MD_CTX_type +#define EVP_MD_block_size GRPC_SHADOW_EVP_MD_block_size +#define EVP_MD_flags GRPC_SHADOW_EVP_MD_flags +#define EVP_MD_size GRPC_SHADOW_EVP_MD_size +#define EVP_MD_type GRPC_SHADOW_EVP_MD_type +#define EVP_add_cipher_alias GRPC_SHADOW_EVP_add_cipher_alias +#define EVP_add_digest GRPC_SHADOW_EVP_add_digest +#define EVP_aead_aes_128_gcm GRPC_SHADOW_EVP_aead_aes_128_gcm +#define EVP_aead_aes_128_gcm_tls12 GRPC_SHADOW_EVP_aead_aes_128_gcm_tls12 +#define EVP_aead_aes_256_gcm GRPC_SHADOW_EVP_aead_aes_256_gcm +#define EVP_aead_aes_256_gcm_tls12 GRPC_SHADOW_EVP_aead_aes_256_gcm_tls12 +#define EVP_aes_128_cbc GRPC_SHADOW_EVP_aes_128_cbc +#define EVP_aes_128_ctr GRPC_SHADOW_EVP_aes_128_ctr +#define EVP_aes_128_ecb GRPC_SHADOW_EVP_aes_128_ecb +#define EVP_aes_128_gcm GRPC_SHADOW_EVP_aes_128_gcm +#define EVP_aes_128_ofb GRPC_SHADOW_EVP_aes_128_ofb +#define EVP_aes_192_cbc GRPC_SHADOW_EVP_aes_192_cbc +#define EVP_aes_192_ctr GRPC_SHADOW_EVP_aes_192_ctr +#define EVP_aes_192_ecb GRPC_SHADOW_EVP_aes_192_ecb +#define EVP_aes_192_gcm GRPC_SHADOW_EVP_aes_192_gcm +#define EVP_aes_256_cbc GRPC_SHADOW_EVP_aes_256_cbc +#define EVP_aes_256_ctr GRPC_SHADOW_EVP_aes_256_ctr +#define EVP_aes_256_ecb GRPC_SHADOW_EVP_aes_256_ecb +#define EVP_aes_256_gcm GRPC_SHADOW_EVP_aes_256_gcm +#define EVP_aes_256_ofb GRPC_SHADOW_EVP_aes_256_ofb +#define EVP_des_cbc GRPC_SHADOW_EVP_des_cbc +#define EVP_des_ecb GRPC_SHADOW_EVP_des_ecb +#define EVP_des_ede GRPC_SHADOW_EVP_des_ede +#define EVP_des_ede3 GRPC_SHADOW_EVP_des_ede3 +#define EVP_des_ede3_cbc GRPC_SHADOW_EVP_des_ede3_cbc +#define EVP_des_ede_cbc GRPC_SHADOW_EVP_des_ede_cbc +#define EVP_has_aes_hardware GRPC_SHADOW_EVP_has_aes_hardware +#define EVP_md4 GRPC_SHADOW_EVP_md4 +#define EVP_md5 GRPC_SHADOW_EVP_md5 +#define EVP_md5_sha1 GRPC_SHADOW_EVP_md5_sha1 +#define EVP_sha1 GRPC_SHADOW_EVP_sha1 +#define EVP_sha224 GRPC_SHADOW_EVP_sha224 +#define EVP_sha256 GRPC_SHADOW_EVP_sha256 +#define EVP_sha384 GRPC_SHADOW_EVP_sha384 +#define EVP_sha512 GRPC_SHADOW_EVP_sha512 +#define HMAC GRPC_SHADOW_HMAC +#define HMAC_CTX_cleanup GRPC_SHADOW_HMAC_CTX_cleanup +#define HMAC_CTX_copy GRPC_SHADOW_HMAC_CTX_copy +#define HMAC_CTX_copy_ex GRPC_SHADOW_HMAC_CTX_copy_ex +#define HMAC_CTX_free GRPC_SHADOW_HMAC_CTX_free +#define HMAC_CTX_init GRPC_SHADOW_HMAC_CTX_init +#define HMAC_CTX_new GRPC_SHADOW_HMAC_CTX_new +#define HMAC_CTX_reset GRPC_SHADOW_HMAC_CTX_reset +#define HMAC_Final GRPC_SHADOW_HMAC_Final +#define HMAC_Init GRPC_SHADOW_HMAC_Init +#define HMAC_Init_ex GRPC_SHADOW_HMAC_Init_ex +#define HMAC_Update GRPC_SHADOW_HMAC_Update +#define HMAC_size GRPC_SHADOW_HMAC_size +#define MD4 GRPC_SHADOW_MD4 +#define MD4_Final GRPC_SHADOW_MD4_Final +#define MD4_Init GRPC_SHADOW_MD4_Init +#define MD4_Transform GRPC_SHADOW_MD4_Transform +#define MD4_Update GRPC_SHADOW_MD4_Update +#define MD5 GRPC_SHADOW_MD5 +#define MD5_Final GRPC_SHADOW_MD5_Final +#define MD5_Init GRPC_SHADOW_MD5_Init +#define MD5_Transform GRPC_SHADOW_MD5_Transform +#define MD5_Update GRPC_SHADOW_MD5_Update +#define OPENSSL_built_in_curves GRPC_SHADOW_OPENSSL_built_in_curves +#define RAND_bytes GRPC_SHADOW_RAND_bytes +#define RAND_bytes_with_additional_data GRPC_SHADOW_RAND_bytes_with_additional_data +#define RAND_pseudo_bytes GRPC_SHADOW_RAND_pseudo_bytes +#define RAND_set_urandom_fd GRPC_SHADOW_RAND_set_urandom_fd +#define RSAZ_1024_mod_exp_avx2 GRPC_SHADOW_RSAZ_1024_mod_exp_avx2 +#define RSA_add_pkcs1_prefix GRPC_SHADOW_RSA_add_pkcs1_prefix +#define RSA_bits GRPC_SHADOW_RSA_bits +#define RSA_blinding_on GRPC_SHADOW_RSA_blinding_on +#define RSA_check_fips GRPC_SHADOW_RSA_check_fips +#define RSA_check_key GRPC_SHADOW_RSA_check_key +#define RSA_decrypt GRPC_SHADOW_RSA_decrypt +#define RSA_default_method GRPC_SHADOW_RSA_default_method +#define RSA_encrypt GRPC_SHADOW_RSA_encrypt +#define RSA_flags GRPC_SHADOW_RSA_flags +#define RSA_free GRPC_SHADOW_RSA_free +#define RSA_generate_key_ex GRPC_SHADOW_RSA_generate_key_ex +#define RSA_generate_key_fips GRPC_SHADOW_RSA_generate_key_fips +#define RSA_get0_crt_params GRPC_SHADOW_RSA_get0_crt_params +#define RSA_get0_factors GRPC_SHADOW_RSA_get0_factors +#define RSA_get0_key GRPC_SHADOW_RSA_get0_key +#define RSA_get_ex_data GRPC_SHADOW_RSA_get_ex_data +#define RSA_get_ex_new_index GRPC_SHADOW_RSA_get_ex_new_index +#define RSA_is_opaque GRPC_SHADOW_RSA_is_opaque +#define RSA_new GRPC_SHADOW_RSA_new +#define RSA_new_method GRPC_SHADOW_RSA_new_method +#define RSA_padding_add_PKCS1_OAEP_mgf1 GRPC_SHADOW_RSA_padding_add_PKCS1_OAEP_mgf1 +#define RSA_padding_add_PKCS1_PSS_mgf1 GRPC_SHADOW_RSA_padding_add_PKCS1_PSS_mgf1 +#define RSA_padding_add_PKCS1_type_1 GRPC_SHADOW_RSA_padding_add_PKCS1_type_1 +#define RSA_padding_add_PKCS1_type_2 GRPC_SHADOW_RSA_padding_add_PKCS1_type_2 +#define RSA_padding_add_none GRPC_SHADOW_RSA_padding_add_none +#define RSA_padding_check_PKCS1_OAEP_mgf1 GRPC_SHADOW_RSA_padding_check_PKCS1_OAEP_mgf1 +#define RSA_padding_check_PKCS1_type_1 GRPC_SHADOW_RSA_padding_check_PKCS1_type_1 +#define RSA_padding_check_PKCS1_type_2 GRPC_SHADOW_RSA_padding_check_PKCS1_type_2 +#define RSA_private_decrypt GRPC_SHADOW_RSA_private_decrypt +#define RSA_private_encrypt GRPC_SHADOW_RSA_private_encrypt +#define RSA_private_transform GRPC_SHADOW_RSA_private_transform +#define RSA_public_decrypt GRPC_SHADOW_RSA_public_decrypt +#define RSA_public_encrypt GRPC_SHADOW_RSA_public_encrypt +#define RSA_set0_crt_params GRPC_SHADOW_RSA_set0_crt_params +#define RSA_set0_factors GRPC_SHADOW_RSA_set0_factors +#define RSA_set0_key GRPC_SHADOW_RSA_set0_key +#define RSA_set_ex_data GRPC_SHADOW_RSA_set_ex_data +#define RSA_sign GRPC_SHADOW_RSA_sign +#define RSA_sign_pss_mgf1 GRPC_SHADOW_RSA_sign_pss_mgf1 +#define RSA_sign_raw GRPC_SHADOW_RSA_sign_raw +#define RSA_size GRPC_SHADOW_RSA_size +#define RSA_up_ref GRPC_SHADOW_RSA_up_ref +#define RSA_verify GRPC_SHADOW_RSA_verify +#define RSA_verify_PKCS1_PSS_mgf1 GRPC_SHADOW_RSA_verify_PKCS1_PSS_mgf1 +#define RSA_verify_pss_mgf1 GRPC_SHADOW_RSA_verify_pss_mgf1 +#define RSA_verify_raw GRPC_SHADOW_RSA_verify_raw +#define SHA1 GRPC_SHADOW_SHA1 +#define SHA1_Final GRPC_SHADOW_SHA1_Final +#define SHA1_Init GRPC_SHADOW_SHA1_Init +#define SHA1_Transform GRPC_SHADOW_SHA1_Transform +#define SHA1_Update GRPC_SHADOW_SHA1_Update +#define SHA224 GRPC_SHADOW_SHA224 +#define SHA224_Final GRPC_SHADOW_SHA224_Final +#define SHA224_Init GRPC_SHADOW_SHA224_Init +#define SHA224_Update GRPC_SHADOW_SHA224_Update +#define SHA256 GRPC_SHADOW_SHA256 +#define SHA256_Final GRPC_SHADOW_SHA256_Final +#define SHA256_Init GRPC_SHADOW_SHA256_Init +#define SHA256_Transform GRPC_SHADOW_SHA256_Transform +#define SHA256_Update GRPC_SHADOW_SHA256_Update +#define SHA384 GRPC_SHADOW_SHA384 +#define SHA384_Final GRPC_SHADOW_SHA384_Final +#define SHA384_Init GRPC_SHADOW_SHA384_Init +#define SHA384_Update GRPC_SHADOW_SHA384_Update +#define SHA512 GRPC_SHADOW_SHA512 +#define SHA512_Final GRPC_SHADOW_SHA512_Final +#define SHA512_Init GRPC_SHADOW_SHA512_Init +#define SHA512_Transform GRPC_SHADOW_SHA512_Transform +#define SHA512_Update GRPC_SHADOW_SHA512_Update +#define aes_ctr_set_key GRPC_SHADOW_aes_ctr_set_key +#define bn_abs_sub_consttime GRPC_SHADOW_bn_abs_sub_consttime +#define bn_add_words GRPC_SHADOW_bn_add_words +#define bn_copy_words GRPC_SHADOW_bn_copy_words +#define bn_div_consttime GRPC_SHADOW_bn_div_consttime +#define bn_expand GRPC_SHADOW_bn_expand +#define bn_fits_in_words GRPC_SHADOW_bn_fits_in_words +#define bn_from_montgomery_small GRPC_SHADOW_bn_from_montgomery_small +#define bn_in_range_words GRPC_SHADOW_bn_in_range_words +#define bn_is_bit_set_words GRPC_SHADOW_bn_is_bit_set_words +#define bn_is_relatively_prime GRPC_SHADOW_bn_is_relatively_prime +#define bn_jacobi GRPC_SHADOW_bn_jacobi +#define bn_lcm_consttime GRPC_SHADOW_bn_lcm_consttime +#define bn_less_than_montgomery_R GRPC_SHADOW_bn_less_than_montgomery_R +#define bn_less_than_words GRPC_SHADOW_bn_less_than_words +#define bn_minimal_width GRPC_SHADOW_bn_minimal_width +#define bn_mod_add_consttime GRPC_SHADOW_bn_mod_add_consttime +#define bn_mod_exp_base_2_consttime GRPC_SHADOW_bn_mod_exp_base_2_consttime +#define bn_mod_exp_mont_small GRPC_SHADOW_bn_mod_exp_mont_small +#define bn_mod_inverse_consttime GRPC_SHADOW_bn_mod_inverse_consttime +#define bn_mod_inverse_prime GRPC_SHADOW_bn_mod_inverse_prime +#define bn_mod_inverse_prime_mont_small GRPC_SHADOW_bn_mod_inverse_prime_mont_small +#define bn_mod_inverse_secret_prime GRPC_SHADOW_bn_mod_inverse_secret_prime +#define bn_mod_lshift1_consttime GRPC_SHADOW_bn_mod_lshift1_consttime +#define bn_mod_lshift_consttime GRPC_SHADOW_bn_mod_lshift_consttime +#define bn_mod_mul_montgomery_small GRPC_SHADOW_bn_mod_mul_montgomery_small +#define bn_mod_sub_consttime GRPC_SHADOW_bn_mod_sub_consttime +#define bn_mod_u16_consttime GRPC_SHADOW_bn_mod_u16_consttime +#define bn_mont_n0 GRPC_SHADOW_bn_mont_n0 +#define bn_mul_add_words GRPC_SHADOW_bn_mul_add_words +#define bn_mul_comba4 GRPC_SHADOW_bn_mul_comba4 +#define bn_mul_comba8 GRPC_SHADOW_bn_mul_comba8 +#define bn_mul_consttime GRPC_SHADOW_bn_mul_consttime +#define bn_mul_small GRPC_SHADOW_bn_mul_small +#define bn_mul_words GRPC_SHADOW_bn_mul_words +#define bn_odd_number_is_obviously_composite GRPC_SHADOW_bn_odd_number_is_obviously_composite +#define bn_one_to_montgomery GRPC_SHADOW_bn_one_to_montgomery +#define bn_one_to_montgomery_small GRPC_SHADOW_bn_one_to_montgomery_small +#define bn_rand_range_words GRPC_SHADOW_bn_rand_range_words +#define bn_rand_secret_range GRPC_SHADOW_bn_rand_secret_range +#define bn_resize_words GRPC_SHADOW_bn_resize_words +#define bn_rshift1_words GRPC_SHADOW_bn_rshift1_words +#define bn_rshift_secret_shift GRPC_SHADOW_bn_rshift_secret_shift +#define bn_select_words GRPC_SHADOW_bn_select_words +#define bn_set_minimal_width GRPC_SHADOW_bn_set_minimal_width +#define bn_set_words GRPC_SHADOW_bn_set_words +#define bn_sqr_comba4 GRPC_SHADOW_bn_sqr_comba4 +#define bn_sqr_comba8 GRPC_SHADOW_bn_sqr_comba8 +#define bn_sqr_consttime GRPC_SHADOW_bn_sqr_consttime +#define bn_sqr_small GRPC_SHADOW_bn_sqr_small +#define bn_sqr_words GRPC_SHADOW_bn_sqr_words +#define bn_sub_words GRPC_SHADOW_bn_sub_words +#define bn_to_montgomery_small GRPC_SHADOW_bn_to_montgomery_small +#define bn_uadd_consttime GRPC_SHADOW_bn_uadd_consttime +#define bn_usub_consttime GRPC_SHADOW_bn_usub_consttime +#define bn_wexpand GRPC_SHADOW_bn_wexpand +#define crypto_gcm_clmul_enabled GRPC_SHADOW_crypto_gcm_clmul_enabled +#define ec_GFp_mont_field_decode GRPC_SHADOW_ec_GFp_mont_field_decode +#define ec_GFp_mont_field_encode GRPC_SHADOW_ec_GFp_mont_field_encode +#define ec_GFp_mont_field_mul GRPC_SHADOW_ec_GFp_mont_field_mul +#define ec_GFp_mont_field_sqr GRPC_SHADOW_ec_GFp_mont_field_sqr +#define ec_GFp_mont_group_finish GRPC_SHADOW_ec_GFp_mont_group_finish +#define ec_GFp_mont_group_init GRPC_SHADOW_ec_GFp_mont_group_init +#define ec_GFp_mont_group_set_curve GRPC_SHADOW_ec_GFp_mont_group_set_curve +#define ec_GFp_nistp_recode_scalar_bits GRPC_SHADOW_ec_GFp_nistp_recode_scalar_bits +#define ec_GFp_simple_add GRPC_SHADOW_ec_GFp_simple_add +#define ec_GFp_simple_cmp GRPC_SHADOW_ec_GFp_simple_cmp +#define ec_GFp_simple_dbl GRPC_SHADOW_ec_GFp_simple_dbl +#define ec_GFp_simple_field_mul GRPC_SHADOW_ec_GFp_simple_field_mul +#define ec_GFp_simple_field_sqr GRPC_SHADOW_ec_GFp_simple_field_sqr +#define ec_GFp_simple_group_finish GRPC_SHADOW_ec_GFp_simple_group_finish +#define ec_GFp_simple_group_get_curve GRPC_SHADOW_ec_GFp_simple_group_get_curve +#define ec_GFp_simple_group_get_degree GRPC_SHADOW_ec_GFp_simple_group_get_degree +#define ec_GFp_simple_group_init GRPC_SHADOW_ec_GFp_simple_group_init +#define ec_GFp_simple_group_set_curve GRPC_SHADOW_ec_GFp_simple_group_set_curve +#define ec_GFp_simple_invert GRPC_SHADOW_ec_GFp_simple_invert +#define ec_GFp_simple_is_at_infinity GRPC_SHADOW_ec_GFp_simple_is_at_infinity +#define ec_GFp_simple_is_on_curve GRPC_SHADOW_ec_GFp_simple_is_on_curve +#define ec_GFp_simple_make_affine GRPC_SHADOW_ec_GFp_simple_make_affine +#define ec_GFp_simple_point_copy GRPC_SHADOW_ec_GFp_simple_point_copy +#define ec_GFp_simple_point_finish GRPC_SHADOW_ec_GFp_simple_point_finish +#define ec_GFp_simple_point_init GRPC_SHADOW_ec_GFp_simple_point_init +#define ec_GFp_simple_point_set_affine_coordinates GRPC_SHADOW_ec_GFp_simple_point_set_affine_coordinates +#define ec_GFp_simple_point_set_to_infinity GRPC_SHADOW_ec_GFp_simple_point_set_to_infinity +#define ec_GFp_simple_points_make_affine GRPC_SHADOW_ec_GFp_simple_points_make_affine +#define ec_bignum_to_scalar GRPC_SHADOW_ec_bignum_to_scalar +#define ec_bignum_to_scalar_unchecked GRPC_SHADOW_ec_bignum_to_scalar_unchecked +#define ec_compute_wNAF GRPC_SHADOW_ec_compute_wNAF +#define ec_group_new GRPC_SHADOW_ec_group_new +#define ec_point_mul_scalar GRPC_SHADOW_ec_point_mul_scalar +#define ec_point_mul_scalar_public GRPC_SHADOW_ec_point_mul_scalar_public +#define ec_random_nonzero_scalar GRPC_SHADOW_ec_random_nonzero_scalar +#define ec_wNAF_mul GRPC_SHADOW_ec_wNAF_mul +#define kBoringSSLRSASqrtTwo GRPC_SHADOW_kBoringSSLRSASqrtTwo +#define kBoringSSLRSASqrtTwoLen GRPC_SHADOW_kBoringSSLRSASqrtTwoLen +#define md4_block_data_order GRPC_SHADOW_md4_block_data_order +#define rsa_default_decrypt GRPC_SHADOW_rsa_default_decrypt +#define rsa_default_private_transform GRPC_SHADOW_rsa_default_private_transform +#define rsa_default_sign_raw GRPC_SHADOW_rsa_default_sign_raw +#define rsa_default_size GRPC_SHADOW_rsa_default_size +#define FIPS_mode GRPC_SHADOW_FIPS_mode +#define aesni_gcm_decrypt GRPC_SHADOW_aesni_gcm_decrypt +#define aesni_gcm_encrypt GRPC_SHADOW_aesni_gcm_encrypt +#define aesni_cbc_encrypt GRPC_SHADOW_aesni_cbc_encrypt +#define aesni_ccm64_decrypt_blocks GRPC_SHADOW_aesni_ccm64_decrypt_blocks +#define aesni_ccm64_encrypt_blocks GRPC_SHADOW_aesni_ccm64_encrypt_blocks +#define aesni_ctr32_encrypt_blocks GRPC_SHADOW_aesni_ctr32_encrypt_blocks +#define aesni_decrypt GRPC_SHADOW_aesni_decrypt +#define aesni_ecb_encrypt GRPC_SHADOW_aesni_ecb_encrypt +#define aesni_encrypt GRPC_SHADOW_aesni_encrypt +#define aesni_ocb_decrypt GRPC_SHADOW_aesni_ocb_decrypt +#define aesni_ocb_encrypt GRPC_SHADOW_aesni_ocb_encrypt +#define aesni_set_decrypt_key GRPC_SHADOW_aesni_set_decrypt_key +#define aesni_set_encrypt_key GRPC_SHADOW_aesni_set_encrypt_key +#define aesni_xts_decrypt GRPC_SHADOW_aesni_xts_decrypt +#define aesni_xts_encrypt GRPC_SHADOW_aesni_xts_encrypt +#define asm_AES_cbc_encrypt GRPC_SHADOW_asm_AES_cbc_encrypt +#define asm_AES_decrypt GRPC_SHADOW_asm_AES_decrypt +#define asm_AES_encrypt GRPC_SHADOW_asm_AES_encrypt +#define asm_AES_set_decrypt_key GRPC_SHADOW_asm_AES_set_decrypt_key +#define asm_AES_set_encrypt_key GRPC_SHADOW_asm_AES_set_encrypt_key +#define bsaes_cbc_encrypt GRPC_SHADOW_bsaes_cbc_encrypt +#define bsaes_ctr32_encrypt_blocks GRPC_SHADOW_bsaes_ctr32_encrypt_blocks +#define bsaes_xts_decrypt GRPC_SHADOW_bsaes_xts_decrypt +#define bsaes_xts_encrypt GRPC_SHADOW_bsaes_xts_encrypt +#define gcm_ghash_4bit GRPC_SHADOW_gcm_ghash_4bit +#define gcm_ghash_avx GRPC_SHADOW_gcm_ghash_avx +#define gcm_ghash_clmul GRPC_SHADOW_gcm_ghash_clmul +#define gcm_gmult_4bit GRPC_SHADOW_gcm_gmult_4bit +#define gcm_gmult_avx GRPC_SHADOW_gcm_gmult_avx +#define gcm_gmult_clmul GRPC_SHADOW_gcm_gmult_clmul +#define gcm_init_avx GRPC_SHADOW_gcm_init_avx +#define gcm_init_clmul GRPC_SHADOW_gcm_init_clmul +#define md5_block_asm_data_order GRPC_SHADOW_md5_block_asm_data_order +#define ecp_nistz256_avx2_select_w7 GRPC_SHADOW_ecp_nistz256_avx2_select_w7 +#define ecp_nistz256_mul_mont GRPC_SHADOW_ecp_nistz256_mul_mont +#define ecp_nistz256_neg GRPC_SHADOW_ecp_nistz256_neg +#define ecp_nistz256_point_add GRPC_SHADOW_ecp_nistz256_point_add +#define ecp_nistz256_point_add_affine GRPC_SHADOW_ecp_nistz256_point_add_affine +#define ecp_nistz256_point_double GRPC_SHADOW_ecp_nistz256_point_double +#define ecp_nistz256_select_w5 GRPC_SHADOW_ecp_nistz256_select_w5 +#define ecp_nistz256_select_w7 GRPC_SHADOW_ecp_nistz256_select_w7 +#define ecp_nistz256_sqr_mont GRPC_SHADOW_ecp_nistz256_sqr_mont +#define CRYPTO_rdrand GRPC_SHADOW_CRYPTO_rdrand +#define CRYPTO_rdrand_multiple8_buf GRPC_SHADOW_CRYPTO_rdrand_multiple8_buf +#define rsaz_1024_gather5_avx2 GRPC_SHADOW_rsaz_1024_gather5_avx2 +#define rsaz_1024_mul_avx2 GRPC_SHADOW_rsaz_1024_mul_avx2 +#define rsaz_1024_norm2red_avx2 GRPC_SHADOW_rsaz_1024_norm2red_avx2 +#define rsaz_1024_red2norm_avx2 GRPC_SHADOW_rsaz_1024_red2norm_avx2 +#define rsaz_1024_scatter5_avx2 GRPC_SHADOW_rsaz_1024_scatter5_avx2 +#define rsaz_1024_sqr_avx2 GRPC_SHADOW_rsaz_1024_sqr_avx2 +#define rsaz_avx2_eligible GRPC_SHADOW_rsaz_avx2_eligible +#define sha1_block_data_order GRPC_SHADOW_sha1_block_data_order +#define sha256_block_data_order GRPC_SHADOW_sha256_block_data_order +#define sha512_block_data_order GRPC_SHADOW_sha512_block_data_order +#define vpaes_cbc_encrypt GRPC_SHADOW_vpaes_cbc_encrypt +#define vpaes_decrypt GRPC_SHADOW_vpaes_decrypt +#define vpaes_encrypt GRPC_SHADOW_vpaes_encrypt +#define vpaes_set_decrypt_key GRPC_SHADOW_vpaes_set_decrypt_key +#define vpaes_set_encrypt_key GRPC_SHADOW_vpaes_set_encrypt_key +#define bn_from_montgomery GRPC_SHADOW_bn_from_montgomery +#define bn_gather5 GRPC_SHADOW_bn_gather5 +#define bn_mul_mont_gather5 GRPC_SHADOW_bn_mul_mont_gather5 +#define bn_power5 GRPC_SHADOW_bn_power5 +#define bn_scatter5 GRPC_SHADOW_bn_scatter5 +#define bn_sqr8x_internal GRPC_SHADOW_bn_sqr8x_internal +#define bn_mul_mont GRPC_SHADOW_bn_mul_mont +#define EVP_get_digestbyname GRPC_SHADOW_EVP_get_digestbyname +#define EVP_get_digestbynid GRPC_SHADOW_EVP_get_digestbynid +#define EVP_get_digestbyobj GRPC_SHADOW_EVP_get_digestbyobj +#define EVP_marshal_digest_algorithm GRPC_SHADOW_EVP_marshal_digest_algorithm +#define EVP_parse_digest_algorithm GRPC_SHADOW_EVP_parse_digest_algorithm +#define EVP_get_cipherbyname GRPC_SHADOW_EVP_get_cipherbyname +#define EVP_get_cipherbynid GRPC_SHADOW_EVP_get_cipherbynid +#define EVP_BytesToKey GRPC_SHADOW_EVP_BytesToKey +#define EVP_enc_null GRPC_SHADOW_EVP_enc_null +#define EVP_rc2_40_cbc GRPC_SHADOW_EVP_rc2_40_cbc +#define EVP_rc2_cbc GRPC_SHADOW_EVP_rc2_cbc +#define EVP_rc4 GRPC_SHADOW_EVP_rc4 +#define EVP_aead_aes_128_gcm_siv GRPC_SHADOW_EVP_aead_aes_128_gcm_siv +#define EVP_aead_aes_256_gcm_siv GRPC_SHADOW_EVP_aead_aes_256_gcm_siv +#define EVP_aead_aes_128_ctr_hmac_sha256 GRPC_SHADOW_EVP_aead_aes_128_ctr_hmac_sha256 +#define EVP_aead_aes_256_ctr_hmac_sha256 GRPC_SHADOW_EVP_aead_aes_256_ctr_hmac_sha256 +#define EVP_aead_aes_128_ccm_bluetooth GRPC_SHADOW_EVP_aead_aes_128_ccm_bluetooth +#define EVP_aead_aes_128_ccm_bluetooth_8 GRPC_SHADOW_EVP_aead_aes_128_ccm_bluetooth_8 +#define EVP_aead_chacha20_poly1305 GRPC_SHADOW_EVP_aead_chacha20_poly1305 +#define EVP_tls_cbc_copy_mac GRPC_SHADOW_EVP_tls_cbc_copy_mac +#define EVP_tls_cbc_digest_record GRPC_SHADOW_EVP_tls_cbc_digest_record +#define EVP_tls_cbc_record_digest_supported GRPC_SHADOW_EVP_tls_cbc_record_digest_supported +#define EVP_tls_cbc_remove_padding GRPC_SHADOW_EVP_tls_cbc_remove_padding +#define EVP_aead_aes_128_cbc_sha1_tls GRPC_SHADOW_EVP_aead_aes_128_cbc_sha1_tls +#define EVP_aead_aes_128_cbc_sha1_tls_implicit_iv GRPC_SHADOW_EVP_aead_aes_128_cbc_sha1_tls_implicit_iv +#define EVP_aead_aes_128_cbc_sha256_tls GRPC_SHADOW_EVP_aead_aes_128_cbc_sha256_tls +#define EVP_aead_aes_256_cbc_sha1_tls GRPC_SHADOW_EVP_aead_aes_256_cbc_sha1_tls +#define EVP_aead_aes_256_cbc_sha1_tls_implicit_iv GRPC_SHADOW_EVP_aead_aes_256_cbc_sha1_tls_implicit_iv +#define EVP_aead_aes_256_cbc_sha256_tls GRPC_SHADOW_EVP_aead_aes_256_cbc_sha256_tls +#define EVP_aead_aes_256_cbc_sha384_tls GRPC_SHADOW_EVP_aead_aes_256_cbc_sha384_tls +#define EVP_aead_des_ede3_cbc_sha1_tls GRPC_SHADOW_EVP_aead_des_ede3_cbc_sha1_tls +#define EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv GRPC_SHADOW_EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv +#define EVP_aead_null_sha1_tls GRPC_SHADOW_EVP_aead_null_sha1_tls +#define EVP_aead_aes_128_cbc_sha1_ssl3 GRPC_SHADOW_EVP_aead_aes_128_cbc_sha1_ssl3 +#define EVP_aead_aes_256_cbc_sha1_ssl3 GRPC_SHADOW_EVP_aead_aes_256_cbc_sha1_ssl3 +#define EVP_aead_des_ede3_cbc_sha1_ssl3 GRPC_SHADOW_EVP_aead_des_ede3_cbc_sha1_ssl3 +#define EVP_aead_null_sha1_ssl3 GRPC_SHADOW_EVP_aead_null_sha1_ssl3 +#define aes128gcmsiv_aes_ks GRPC_SHADOW_aes128gcmsiv_aes_ks +#define aes128gcmsiv_aes_ks_enc_x1 GRPC_SHADOW_aes128gcmsiv_aes_ks_enc_x1 +#define aes128gcmsiv_dec GRPC_SHADOW_aes128gcmsiv_dec +#define aes128gcmsiv_ecb_enc_block GRPC_SHADOW_aes128gcmsiv_ecb_enc_block +#define aes128gcmsiv_enc_msg_x4 GRPC_SHADOW_aes128gcmsiv_enc_msg_x4 +#define aes128gcmsiv_enc_msg_x8 GRPC_SHADOW_aes128gcmsiv_enc_msg_x8 +#define aes128gcmsiv_kdf GRPC_SHADOW_aes128gcmsiv_kdf +#define aes256gcmsiv_aes_ks GRPC_SHADOW_aes256gcmsiv_aes_ks +#define aes256gcmsiv_aes_ks_enc_x1 GRPC_SHADOW_aes256gcmsiv_aes_ks_enc_x1 +#define aes256gcmsiv_dec GRPC_SHADOW_aes256gcmsiv_dec +#define aes256gcmsiv_ecb_enc_block GRPC_SHADOW_aes256gcmsiv_ecb_enc_block +#define aes256gcmsiv_enc_msg_x4 GRPC_SHADOW_aes256gcmsiv_enc_msg_x4 +#define aes256gcmsiv_enc_msg_x8 GRPC_SHADOW_aes256gcmsiv_enc_msg_x8 +#define aes256gcmsiv_kdf GRPC_SHADOW_aes256gcmsiv_kdf +#define aesgcmsiv_htable6_init GRPC_SHADOW_aesgcmsiv_htable6_init +#define aesgcmsiv_htable_init GRPC_SHADOW_aesgcmsiv_htable_init +#define aesgcmsiv_htable_polyval GRPC_SHADOW_aesgcmsiv_htable_polyval +#define aesgcmsiv_polyval_horner GRPC_SHADOW_aesgcmsiv_polyval_horner +#define chacha20_poly1305_open GRPC_SHADOW_chacha20_poly1305_open +#define chacha20_poly1305_seal GRPC_SHADOW_chacha20_poly1305_seal +#define RC4 GRPC_SHADOW_RC4 +#define RC4_set_key GRPC_SHADOW_RC4_set_key +#define CONF_VALUE_new GRPC_SHADOW_CONF_VALUE_new +#define CONF_modules_free GRPC_SHADOW_CONF_modules_free +#define CONF_modules_load_file GRPC_SHADOW_CONF_modules_load_file +#define CONF_parse_list GRPC_SHADOW_CONF_parse_list +#define NCONF_free GRPC_SHADOW_NCONF_free +#define NCONF_get_section GRPC_SHADOW_NCONF_get_section +#define NCONF_get_string GRPC_SHADOW_NCONF_get_string +#define NCONF_load GRPC_SHADOW_NCONF_load +#define NCONF_load_bio GRPC_SHADOW_NCONF_load_bio +#define NCONF_new GRPC_SHADOW_NCONF_new +#define OPENSSL_config GRPC_SHADOW_OPENSSL_config +#define OPENSSL_no_config GRPC_SHADOW_OPENSSL_no_config +#define CRYPTO_chacha_20 GRPC_SHADOW_CRYPTO_chacha_20 +#define ChaCha20_ctr32 GRPC_SHADOW_ChaCha20_ctr32 +#define CRYPTO_poly1305_finish GRPC_SHADOW_CRYPTO_poly1305_finish +#define CRYPTO_poly1305_init GRPC_SHADOW_CRYPTO_poly1305_init +#define CRYPTO_poly1305_update GRPC_SHADOW_CRYPTO_poly1305_update +#define SPAKE2_CTX_free GRPC_SHADOW_SPAKE2_CTX_free +#define SPAKE2_CTX_new GRPC_SHADOW_SPAKE2_CTX_new +#define SPAKE2_generate_msg GRPC_SHADOW_SPAKE2_generate_msg +#define SPAKE2_process_msg GRPC_SHADOW_SPAKE2_process_msg +#define ED25519_keypair GRPC_SHADOW_ED25519_keypair +#define ED25519_keypair_from_seed GRPC_SHADOW_ED25519_keypair_from_seed +#define ED25519_sign GRPC_SHADOW_ED25519_sign +#define ED25519_verify GRPC_SHADOW_ED25519_verify +#define X25519 GRPC_SHADOW_X25519 +#define X25519_keypair GRPC_SHADOW_X25519_keypair +#define X25519_public_from_private GRPC_SHADOW_X25519_public_from_private +#define x25519_ge_add GRPC_SHADOW_x25519_ge_add +#define x25519_ge_frombytes_vartime GRPC_SHADOW_x25519_ge_frombytes_vartime +#define x25519_ge_p1p1_to_p2 GRPC_SHADOW_x25519_ge_p1p1_to_p2 +#define x25519_ge_p1p1_to_p3 GRPC_SHADOW_x25519_ge_p1p1_to_p3 +#define x25519_ge_p3_to_cached GRPC_SHADOW_x25519_ge_p3_to_cached +#define x25519_ge_scalarmult GRPC_SHADOW_x25519_ge_scalarmult +#define x25519_ge_scalarmult_base GRPC_SHADOW_x25519_ge_scalarmult_base +#define x25519_ge_scalarmult_small_precomp GRPC_SHADOW_x25519_ge_scalarmult_small_precomp +#define x25519_ge_sub GRPC_SHADOW_x25519_ge_sub +#define x25519_ge_tobytes GRPC_SHADOW_x25519_ge_tobytes +#define x25519_sc_reduce GRPC_SHADOW_x25519_sc_reduce +#define BUF_MEM_append GRPC_SHADOW_BUF_MEM_append +#define BUF_MEM_free GRPC_SHADOW_BUF_MEM_free +#define BUF_MEM_grow GRPC_SHADOW_BUF_MEM_grow +#define BUF_MEM_grow_clean GRPC_SHADOW_BUF_MEM_grow_clean +#define BUF_MEM_new GRPC_SHADOW_BUF_MEM_new +#define BUF_MEM_reserve GRPC_SHADOW_BUF_MEM_reserve +#define BUF_memdup GRPC_SHADOW_BUF_memdup +#define BUF_strdup GRPC_SHADOW_BUF_strdup +#define BUF_strlcat GRPC_SHADOW_BUF_strlcat +#define BUF_strlcpy GRPC_SHADOW_BUF_strlcpy +#define BUF_strndup GRPC_SHADOW_BUF_strndup +#define BUF_strnlen GRPC_SHADOW_BUF_strnlen +#define BN_marshal_asn1 GRPC_SHADOW_BN_marshal_asn1 +#define BN_parse_asn1_unsigned GRPC_SHADOW_BN_parse_asn1_unsigned +#define BN_asc2bn GRPC_SHADOW_BN_asc2bn +#define BN_bn2cbb_padded GRPC_SHADOW_BN_bn2cbb_padded +#define BN_bn2dec GRPC_SHADOW_BN_bn2dec +#define BN_bn2hex GRPC_SHADOW_BN_bn2hex +#define BN_bn2mpi GRPC_SHADOW_BN_bn2mpi +#define BN_dec2bn GRPC_SHADOW_BN_dec2bn +#define BN_hex2bn GRPC_SHADOW_BN_hex2bn +#define BN_mpi2bn GRPC_SHADOW_BN_mpi2bn +#define BN_print GRPC_SHADOW_BN_print +#define BN_print_fp GRPC_SHADOW_BN_print_fp +#define BIO_callback_ctrl GRPC_SHADOW_BIO_callback_ctrl +#define BIO_clear_flags GRPC_SHADOW_BIO_clear_flags +#define BIO_clear_retry_flags GRPC_SHADOW_BIO_clear_retry_flags +#define BIO_copy_next_retry GRPC_SHADOW_BIO_copy_next_retry +#define BIO_ctrl GRPC_SHADOW_BIO_ctrl +#define BIO_ctrl_pending GRPC_SHADOW_BIO_ctrl_pending +#define BIO_eof GRPC_SHADOW_BIO_eof +#define BIO_find_type GRPC_SHADOW_BIO_find_type +#define BIO_flush GRPC_SHADOW_BIO_flush +#define BIO_free GRPC_SHADOW_BIO_free +#define BIO_free_all GRPC_SHADOW_BIO_free_all +#define BIO_get_data GRPC_SHADOW_BIO_get_data +#define BIO_get_init GRPC_SHADOW_BIO_get_init +#define BIO_get_new_index GRPC_SHADOW_BIO_get_new_index +#define BIO_get_retry_flags GRPC_SHADOW_BIO_get_retry_flags +#define BIO_get_retry_reason GRPC_SHADOW_BIO_get_retry_reason +#define BIO_get_shutdown GRPC_SHADOW_BIO_get_shutdown +#define BIO_gets GRPC_SHADOW_BIO_gets +#define BIO_indent GRPC_SHADOW_BIO_indent +#define BIO_int_ctrl GRPC_SHADOW_BIO_int_ctrl +#define BIO_meth_free GRPC_SHADOW_BIO_meth_free +#define BIO_meth_new GRPC_SHADOW_BIO_meth_new +#define BIO_meth_set_create GRPC_SHADOW_BIO_meth_set_create +#define BIO_meth_set_ctrl GRPC_SHADOW_BIO_meth_set_ctrl +#define BIO_meth_set_destroy GRPC_SHADOW_BIO_meth_set_destroy +#define BIO_meth_set_gets GRPC_SHADOW_BIO_meth_set_gets +#define BIO_meth_set_puts GRPC_SHADOW_BIO_meth_set_puts +#define BIO_meth_set_read GRPC_SHADOW_BIO_meth_set_read +#define BIO_meth_set_write GRPC_SHADOW_BIO_meth_set_write +#define BIO_method_type GRPC_SHADOW_BIO_method_type +#define BIO_new GRPC_SHADOW_BIO_new +#define BIO_next GRPC_SHADOW_BIO_next +#define BIO_number_read GRPC_SHADOW_BIO_number_read +#define BIO_number_written GRPC_SHADOW_BIO_number_written +#define BIO_pending GRPC_SHADOW_BIO_pending +#define BIO_pop GRPC_SHADOW_BIO_pop +#define BIO_ptr_ctrl GRPC_SHADOW_BIO_ptr_ctrl +#define BIO_push GRPC_SHADOW_BIO_push +#define BIO_puts GRPC_SHADOW_BIO_puts +#define BIO_read GRPC_SHADOW_BIO_read +#define BIO_read_asn1 GRPC_SHADOW_BIO_read_asn1 +#define BIO_reset GRPC_SHADOW_BIO_reset +#define BIO_set_close GRPC_SHADOW_BIO_set_close +#define BIO_set_data GRPC_SHADOW_BIO_set_data +#define BIO_set_flags GRPC_SHADOW_BIO_set_flags +#define BIO_set_init GRPC_SHADOW_BIO_set_init +#define BIO_set_retry_read GRPC_SHADOW_BIO_set_retry_read +#define BIO_set_retry_special GRPC_SHADOW_BIO_set_retry_special +#define BIO_set_retry_write GRPC_SHADOW_BIO_set_retry_write +#define BIO_set_shutdown GRPC_SHADOW_BIO_set_shutdown +#define BIO_set_write_buffer_size GRPC_SHADOW_BIO_set_write_buffer_size +#define BIO_should_io_special GRPC_SHADOW_BIO_should_io_special +#define BIO_should_read GRPC_SHADOW_BIO_should_read +#define BIO_should_retry GRPC_SHADOW_BIO_should_retry +#define BIO_should_write GRPC_SHADOW_BIO_should_write +#define BIO_test_flags GRPC_SHADOW_BIO_test_flags +#define BIO_up_ref GRPC_SHADOW_BIO_up_ref +#define BIO_vfree GRPC_SHADOW_BIO_vfree +#define BIO_wpending GRPC_SHADOW_BIO_wpending +#define BIO_write GRPC_SHADOW_BIO_write +#define ERR_print_errors GRPC_SHADOW_ERR_print_errors +#define BIO_get_mem_data GRPC_SHADOW_BIO_get_mem_data +#define BIO_get_mem_ptr GRPC_SHADOW_BIO_get_mem_ptr +#define BIO_mem_contents GRPC_SHADOW_BIO_mem_contents +#define BIO_new_mem_buf GRPC_SHADOW_BIO_new_mem_buf +#define BIO_s_mem GRPC_SHADOW_BIO_s_mem +#define BIO_set_mem_buf GRPC_SHADOW_BIO_set_mem_buf +#define BIO_set_mem_eof_return GRPC_SHADOW_BIO_set_mem_eof_return +#define BIO_do_connect GRPC_SHADOW_BIO_do_connect +#define BIO_new_connect GRPC_SHADOW_BIO_new_connect +#define BIO_s_connect GRPC_SHADOW_BIO_s_connect +#define BIO_set_conn_hostname GRPC_SHADOW_BIO_set_conn_hostname +#define BIO_set_conn_int_port GRPC_SHADOW_BIO_set_conn_int_port +#define BIO_set_conn_port GRPC_SHADOW_BIO_set_conn_port +#define BIO_set_nbio GRPC_SHADOW_BIO_set_nbio +#define BIO_get_fd GRPC_SHADOW_BIO_get_fd +#define BIO_new_fd GRPC_SHADOW_BIO_new_fd +#define BIO_s_fd GRPC_SHADOW_BIO_s_fd +#define BIO_set_fd GRPC_SHADOW_BIO_set_fd +#define bio_fd_should_retry GRPC_SHADOW_bio_fd_should_retry +#define BIO_append_filename GRPC_SHADOW_BIO_append_filename +#define BIO_get_fp GRPC_SHADOW_BIO_get_fp +#define BIO_new_file GRPC_SHADOW_BIO_new_file +#define BIO_new_fp GRPC_SHADOW_BIO_new_fp +#define BIO_read_filename GRPC_SHADOW_BIO_read_filename +#define BIO_rw_filename GRPC_SHADOW_BIO_rw_filename +#define BIO_s_file GRPC_SHADOW_BIO_s_file +#define BIO_set_fp GRPC_SHADOW_BIO_set_fp +#define BIO_write_filename GRPC_SHADOW_BIO_write_filename +#define BIO_hexdump GRPC_SHADOW_BIO_hexdump +#define BIO_ctrl_get_read_request GRPC_SHADOW_BIO_ctrl_get_read_request +#define BIO_ctrl_get_write_guarantee GRPC_SHADOW_BIO_ctrl_get_write_guarantee +#define BIO_new_bio_pair GRPC_SHADOW_BIO_new_bio_pair +#define BIO_shutdown_wr GRPC_SHADOW_BIO_shutdown_wr +#define BIO_printf GRPC_SHADOW_BIO_printf +#define BIO_new_socket GRPC_SHADOW_BIO_new_socket +#define BIO_s_socket GRPC_SHADOW_BIO_s_socket +#define bio_clear_socket_error GRPC_SHADOW_bio_clear_socket_error +#define bio_ip_and_port_to_socket_and_addr GRPC_SHADOW_bio_ip_and_port_to_socket_and_addr +#define bio_sock_error GRPC_SHADOW_bio_sock_error +#define bio_socket_nbio GRPC_SHADOW_bio_socket_nbio +#define RAND_enable_fork_unsafe_buffering GRPC_SHADOW_RAND_enable_fork_unsafe_buffering +#define rand_fork_unsafe_buffering_enabled GRPC_SHADOW_rand_fork_unsafe_buffering_enabled +#define RAND_SSLeay GRPC_SHADOW_RAND_SSLeay +#define RAND_add GRPC_SHADOW_RAND_add +#define RAND_cleanup GRPC_SHADOW_RAND_cleanup +#define RAND_egd GRPC_SHADOW_RAND_egd +#define RAND_file_name GRPC_SHADOW_RAND_file_name +#define RAND_get_rand_method GRPC_SHADOW_RAND_get_rand_method +#define RAND_load_file GRPC_SHADOW_RAND_load_file +#define RAND_poll GRPC_SHADOW_RAND_poll +#define RAND_seed GRPC_SHADOW_RAND_seed +#define RAND_set_rand_method GRPC_SHADOW_RAND_set_rand_method +#define RAND_status GRPC_SHADOW_RAND_status +#define OBJ_cbs2nid GRPC_SHADOW_OBJ_cbs2nid +#define OBJ_cmp GRPC_SHADOW_OBJ_cmp +#define OBJ_create GRPC_SHADOW_OBJ_create +#define OBJ_dup GRPC_SHADOW_OBJ_dup +#define OBJ_get0_data GRPC_SHADOW_OBJ_get0_data +#define OBJ_length GRPC_SHADOW_OBJ_length +#define OBJ_ln2nid GRPC_SHADOW_OBJ_ln2nid +#define OBJ_nid2cbb GRPC_SHADOW_OBJ_nid2cbb +#define OBJ_nid2ln GRPC_SHADOW_OBJ_nid2ln +#define OBJ_nid2obj GRPC_SHADOW_OBJ_nid2obj +#define OBJ_nid2sn GRPC_SHADOW_OBJ_nid2sn +#define OBJ_obj2nid GRPC_SHADOW_OBJ_obj2nid +#define OBJ_obj2txt GRPC_SHADOW_OBJ_obj2txt +#define OBJ_sn2nid GRPC_SHADOW_OBJ_sn2nid +#define OBJ_txt2nid GRPC_SHADOW_OBJ_txt2nid +#define OBJ_txt2obj GRPC_SHADOW_OBJ_txt2obj +#define OBJ_find_sigid_algs GRPC_SHADOW_OBJ_find_sigid_algs +#define OBJ_find_sigid_by_algs GRPC_SHADOW_OBJ_find_sigid_by_algs +#define ASN1_BIT_STRING_check GRPC_SHADOW_ASN1_BIT_STRING_check +#define ASN1_BIT_STRING_get_bit GRPC_SHADOW_ASN1_BIT_STRING_get_bit +#define ASN1_BIT_STRING_set GRPC_SHADOW_ASN1_BIT_STRING_set +#define ASN1_BIT_STRING_set_bit GRPC_SHADOW_ASN1_BIT_STRING_set_bit +#define c2i_ASN1_BIT_STRING GRPC_SHADOW_c2i_ASN1_BIT_STRING +#define i2c_ASN1_BIT_STRING GRPC_SHADOW_i2c_ASN1_BIT_STRING +#define d2i_ASN1_BOOLEAN GRPC_SHADOW_d2i_ASN1_BOOLEAN +#define i2d_ASN1_BOOLEAN GRPC_SHADOW_i2d_ASN1_BOOLEAN +#define ASN1_d2i_bio GRPC_SHADOW_ASN1_d2i_bio +#define ASN1_d2i_fp GRPC_SHADOW_ASN1_d2i_fp +#define ASN1_item_d2i_bio GRPC_SHADOW_ASN1_item_d2i_bio +#define ASN1_item_d2i_fp GRPC_SHADOW_ASN1_item_d2i_fp +#define ASN1_dup GRPC_SHADOW_ASN1_dup +#define ASN1_item_dup GRPC_SHADOW_ASN1_item_dup +#define ASN1_ENUMERATED_get GRPC_SHADOW_ASN1_ENUMERATED_get +#define ASN1_ENUMERATED_set GRPC_SHADOW_ASN1_ENUMERATED_set +#define ASN1_ENUMERATED_to_BN GRPC_SHADOW_ASN1_ENUMERATED_to_BN +#define BN_to_ASN1_ENUMERATED GRPC_SHADOW_BN_to_ASN1_ENUMERATED +#define ASN1_GENERALIZEDTIME_adj GRPC_SHADOW_ASN1_GENERALIZEDTIME_adj +#define ASN1_GENERALIZEDTIME_check GRPC_SHADOW_ASN1_GENERALIZEDTIME_check +#define ASN1_GENERALIZEDTIME_set GRPC_SHADOW_ASN1_GENERALIZEDTIME_set +#define ASN1_GENERALIZEDTIME_set_string GRPC_SHADOW_ASN1_GENERALIZEDTIME_set_string +#define asn1_generalizedtime_to_tm GRPC_SHADOW_asn1_generalizedtime_to_tm +#define ASN1_i2d_bio GRPC_SHADOW_ASN1_i2d_bio +#define ASN1_i2d_fp GRPC_SHADOW_ASN1_i2d_fp +#define ASN1_item_i2d_bio GRPC_SHADOW_ASN1_item_i2d_bio +#define ASN1_item_i2d_fp GRPC_SHADOW_ASN1_item_i2d_fp +#define ASN1_INTEGER_cmp GRPC_SHADOW_ASN1_INTEGER_cmp +#define ASN1_INTEGER_dup GRPC_SHADOW_ASN1_INTEGER_dup +#define ASN1_INTEGER_get GRPC_SHADOW_ASN1_INTEGER_get +#define ASN1_INTEGER_set GRPC_SHADOW_ASN1_INTEGER_set +#define ASN1_INTEGER_set_uint64 GRPC_SHADOW_ASN1_INTEGER_set_uint64 +#define ASN1_INTEGER_to_BN GRPC_SHADOW_ASN1_INTEGER_to_BN +#define BN_to_ASN1_INTEGER GRPC_SHADOW_BN_to_ASN1_INTEGER +#define c2i_ASN1_INTEGER GRPC_SHADOW_c2i_ASN1_INTEGER +#define d2i_ASN1_UINTEGER GRPC_SHADOW_d2i_ASN1_UINTEGER +#define i2c_ASN1_INTEGER GRPC_SHADOW_i2c_ASN1_INTEGER +#define ASN1_mbstring_copy GRPC_SHADOW_ASN1_mbstring_copy +#define ASN1_mbstring_ncopy GRPC_SHADOW_ASN1_mbstring_ncopy +#define ASN1_OBJECT_create GRPC_SHADOW_ASN1_OBJECT_create +#define ASN1_OBJECT_free GRPC_SHADOW_ASN1_OBJECT_free +#define ASN1_OBJECT_new GRPC_SHADOW_ASN1_OBJECT_new +#define c2i_ASN1_OBJECT GRPC_SHADOW_c2i_ASN1_OBJECT +#define d2i_ASN1_OBJECT GRPC_SHADOW_d2i_ASN1_OBJECT +#define i2a_ASN1_OBJECT GRPC_SHADOW_i2a_ASN1_OBJECT +#define i2d_ASN1_OBJECT GRPC_SHADOW_i2d_ASN1_OBJECT +#define i2t_ASN1_OBJECT GRPC_SHADOW_i2t_ASN1_OBJECT +#define ASN1_OCTET_STRING_cmp GRPC_SHADOW_ASN1_OCTET_STRING_cmp +#define ASN1_OCTET_STRING_dup GRPC_SHADOW_ASN1_OCTET_STRING_dup +#define ASN1_OCTET_STRING_set GRPC_SHADOW_ASN1_OCTET_STRING_set +#define ASN1_PRINTABLE_type GRPC_SHADOW_ASN1_PRINTABLE_type +#define ASN1_STRING_TABLE_add GRPC_SHADOW_ASN1_STRING_TABLE_add +#define ASN1_STRING_TABLE_cleanup GRPC_SHADOW_ASN1_STRING_TABLE_cleanup +#define ASN1_STRING_TABLE_get GRPC_SHADOW_ASN1_STRING_TABLE_get +#define ASN1_STRING_get_default_mask GRPC_SHADOW_ASN1_STRING_get_default_mask +#define ASN1_STRING_set_by_NID GRPC_SHADOW_ASN1_STRING_set_by_NID +#define ASN1_STRING_set_default_mask GRPC_SHADOW_ASN1_STRING_set_default_mask +#define ASN1_STRING_set_default_mask_asc GRPC_SHADOW_ASN1_STRING_set_default_mask_asc +#define ASN1_TIME_adj GRPC_SHADOW_ASN1_TIME_adj +#define ASN1_TIME_check GRPC_SHADOW_ASN1_TIME_check +#define ASN1_TIME_diff GRPC_SHADOW_ASN1_TIME_diff +#define ASN1_TIME_free GRPC_SHADOW_ASN1_TIME_free +#define ASN1_TIME_it GRPC_SHADOW_ASN1_TIME_it +#define ASN1_TIME_new GRPC_SHADOW_ASN1_TIME_new +#define ASN1_TIME_set GRPC_SHADOW_ASN1_TIME_set +#define ASN1_TIME_set_string GRPC_SHADOW_ASN1_TIME_set_string +#define ASN1_TIME_to_generalizedtime GRPC_SHADOW_ASN1_TIME_to_generalizedtime +#define d2i_ASN1_TIME GRPC_SHADOW_d2i_ASN1_TIME +#define i2d_ASN1_TIME GRPC_SHADOW_i2d_ASN1_TIME +#define ASN1_TYPE_cmp GRPC_SHADOW_ASN1_TYPE_cmp +#define ASN1_TYPE_get GRPC_SHADOW_ASN1_TYPE_get +#define ASN1_TYPE_set GRPC_SHADOW_ASN1_TYPE_set +#define ASN1_TYPE_set1 GRPC_SHADOW_ASN1_TYPE_set1 +#define ASN1_UTCTIME_adj GRPC_SHADOW_ASN1_UTCTIME_adj +#define ASN1_UTCTIME_check GRPC_SHADOW_ASN1_UTCTIME_check +#define ASN1_UTCTIME_cmp_time_t GRPC_SHADOW_ASN1_UTCTIME_cmp_time_t +#define ASN1_UTCTIME_set GRPC_SHADOW_ASN1_UTCTIME_set +#define ASN1_UTCTIME_set_string GRPC_SHADOW_ASN1_UTCTIME_set_string +#define asn1_utctime_to_tm GRPC_SHADOW_asn1_utctime_to_tm +#define UTF8_getc GRPC_SHADOW_UTF8_getc +#define UTF8_putc GRPC_SHADOW_UTF8_putc +#define ASN1_STRING_cmp GRPC_SHADOW_ASN1_STRING_cmp +#define ASN1_STRING_copy GRPC_SHADOW_ASN1_STRING_copy +#define ASN1_STRING_data GRPC_SHADOW_ASN1_STRING_data +#define ASN1_STRING_dup GRPC_SHADOW_ASN1_STRING_dup +#define ASN1_STRING_free GRPC_SHADOW_ASN1_STRING_free +#define ASN1_STRING_get0_data GRPC_SHADOW_ASN1_STRING_get0_data +#define ASN1_STRING_length GRPC_SHADOW_ASN1_STRING_length +#define ASN1_STRING_length_set GRPC_SHADOW_ASN1_STRING_length_set +#define ASN1_STRING_new GRPC_SHADOW_ASN1_STRING_new +#define ASN1_STRING_set GRPC_SHADOW_ASN1_STRING_set +#define ASN1_STRING_set0 GRPC_SHADOW_ASN1_STRING_set0 +#define ASN1_STRING_type GRPC_SHADOW_ASN1_STRING_type +#define ASN1_STRING_type_new GRPC_SHADOW_ASN1_STRING_type_new +#define ASN1_get_object GRPC_SHADOW_ASN1_get_object +#define ASN1_object_size GRPC_SHADOW_ASN1_object_size +#define ASN1_put_eoc GRPC_SHADOW_ASN1_put_eoc +#define ASN1_put_object GRPC_SHADOW_ASN1_put_object +#define ASN1_tag2str GRPC_SHADOW_ASN1_tag2str +#define ASN1_item_pack GRPC_SHADOW_ASN1_item_pack +#define ASN1_item_unpack GRPC_SHADOW_ASN1_item_unpack +#define i2a_ASN1_ENUMERATED GRPC_SHADOW_i2a_ASN1_ENUMERATED +#define i2a_ASN1_INTEGER GRPC_SHADOW_i2a_ASN1_INTEGER +#define i2a_ASN1_STRING GRPC_SHADOW_i2a_ASN1_STRING +#define ASN1_item_d2i GRPC_SHADOW_ASN1_item_d2i +#define ASN1_item_ex_d2i GRPC_SHADOW_ASN1_item_ex_d2i +#define ASN1_tag2bit GRPC_SHADOW_ASN1_tag2bit +#define asn1_ex_c2i GRPC_SHADOW_asn1_ex_c2i +#define ASN1_item_ex_i2d GRPC_SHADOW_ASN1_item_ex_i2d +#define ASN1_item_i2d GRPC_SHADOW_ASN1_item_i2d +#define ASN1_item_ndef_i2d GRPC_SHADOW_ASN1_item_ndef_i2d +#define asn1_ex_i2c GRPC_SHADOW_asn1_ex_i2c +#define ASN1_item_ex_free GRPC_SHADOW_ASN1_item_ex_free +#define ASN1_item_free GRPC_SHADOW_ASN1_item_free +#define ASN1_primitive_free GRPC_SHADOW_ASN1_primitive_free +#define ASN1_template_free GRPC_SHADOW_ASN1_template_free +#define asn1_item_combine_free GRPC_SHADOW_asn1_item_combine_free +#define ASN1_item_ex_new GRPC_SHADOW_ASN1_item_ex_new +#define ASN1_item_new GRPC_SHADOW_ASN1_item_new +#define ASN1_primitive_new GRPC_SHADOW_ASN1_primitive_new +#define ASN1_template_new GRPC_SHADOW_ASN1_template_new +#define ASN1_ANY_it GRPC_SHADOW_ASN1_ANY_it +#define ASN1_BIT_STRING_free GRPC_SHADOW_ASN1_BIT_STRING_free +#define ASN1_BIT_STRING_it GRPC_SHADOW_ASN1_BIT_STRING_it +#define ASN1_BIT_STRING_new GRPC_SHADOW_ASN1_BIT_STRING_new +#define ASN1_BMPSTRING_free GRPC_SHADOW_ASN1_BMPSTRING_free +#define ASN1_BMPSTRING_it GRPC_SHADOW_ASN1_BMPSTRING_it +#define ASN1_BMPSTRING_new GRPC_SHADOW_ASN1_BMPSTRING_new +#define ASN1_BOOLEAN_it GRPC_SHADOW_ASN1_BOOLEAN_it +#define ASN1_ENUMERATED_free GRPC_SHADOW_ASN1_ENUMERATED_free +#define ASN1_ENUMERATED_it GRPC_SHADOW_ASN1_ENUMERATED_it +#define ASN1_ENUMERATED_new GRPC_SHADOW_ASN1_ENUMERATED_new +#define ASN1_FBOOLEAN_it GRPC_SHADOW_ASN1_FBOOLEAN_it +#define ASN1_GENERALIZEDTIME_free GRPC_SHADOW_ASN1_GENERALIZEDTIME_free +#define ASN1_GENERALIZEDTIME_it GRPC_SHADOW_ASN1_GENERALIZEDTIME_it +#define ASN1_GENERALIZEDTIME_new GRPC_SHADOW_ASN1_GENERALIZEDTIME_new +#define ASN1_GENERALSTRING_free GRPC_SHADOW_ASN1_GENERALSTRING_free +#define ASN1_GENERALSTRING_it GRPC_SHADOW_ASN1_GENERALSTRING_it +#define ASN1_GENERALSTRING_new GRPC_SHADOW_ASN1_GENERALSTRING_new +#define ASN1_IA5STRING_free GRPC_SHADOW_ASN1_IA5STRING_free +#define ASN1_IA5STRING_it GRPC_SHADOW_ASN1_IA5STRING_it +#define ASN1_IA5STRING_new GRPC_SHADOW_ASN1_IA5STRING_new +#define ASN1_INTEGER_free GRPC_SHADOW_ASN1_INTEGER_free +#define ASN1_INTEGER_it GRPC_SHADOW_ASN1_INTEGER_it +#define ASN1_INTEGER_new GRPC_SHADOW_ASN1_INTEGER_new +#define ASN1_NULL_free GRPC_SHADOW_ASN1_NULL_free +#define ASN1_NULL_it GRPC_SHADOW_ASN1_NULL_it +#define ASN1_NULL_new GRPC_SHADOW_ASN1_NULL_new +#define ASN1_OBJECT_it GRPC_SHADOW_ASN1_OBJECT_it +#define ASN1_OCTET_STRING_NDEF_it GRPC_SHADOW_ASN1_OCTET_STRING_NDEF_it +#define ASN1_OCTET_STRING_free GRPC_SHADOW_ASN1_OCTET_STRING_free +#define ASN1_OCTET_STRING_it GRPC_SHADOW_ASN1_OCTET_STRING_it +#define ASN1_OCTET_STRING_new GRPC_SHADOW_ASN1_OCTET_STRING_new +#define ASN1_PRINTABLESTRING_free GRPC_SHADOW_ASN1_PRINTABLESTRING_free +#define ASN1_PRINTABLESTRING_it GRPC_SHADOW_ASN1_PRINTABLESTRING_it +#define ASN1_PRINTABLESTRING_new GRPC_SHADOW_ASN1_PRINTABLESTRING_new +#define ASN1_PRINTABLE_free GRPC_SHADOW_ASN1_PRINTABLE_free +#define ASN1_PRINTABLE_it GRPC_SHADOW_ASN1_PRINTABLE_it +#define ASN1_PRINTABLE_new GRPC_SHADOW_ASN1_PRINTABLE_new +#define ASN1_SEQUENCE_ANY_it GRPC_SHADOW_ASN1_SEQUENCE_ANY_it +#define ASN1_SEQUENCE_it GRPC_SHADOW_ASN1_SEQUENCE_it +#define ASN1_SET_ANY_it GRPC_SHADOW_ASN1_SET_ANY_it +#define ASN1_T61STRING_free GRPC_SHADOW_ASN1_T61STRING_free +#define ASN1_T61STRING_it GRPC_SHADOW_ASN1_T61STRING_it +#define ASN1_T61STRING_new GRPC_SHADOW_ASN1_T61STRING_new +#define ASN1_TBOOLEAN_it GRPC_SHADOW_ASN1_TBOOLEAN_it +#define ASN1_TYPE_free GRPC_SHADOW_ASN1_TYPE_free +#define ASN1_TYPE_new GRPC_SHADOW_ASN1_TYPE_new +#define ASN1_UNIVERSALSTRING_free GRPC_SHADOW_ASN1_UNIVERSALSTRING_free +#define ASN1_UNIVERSALSTRING_it GRPC_SHADOW_ASN1_UNIVERSALSTRING_it +#define ASN1_UNIVERSALSTRING_new GRPC_SHADOW_ASN1_UNIVERSALSTRING_new +#define ASN1_UTCTIME_free GRPC_SHADOW_ASN1_UTCTIME_free +#define ASN1_UTCTIME_it GRPC_SHADOW_ASN1_UTCTIME_it +#define ASN1_UTCTIME_new GRPC_SHADOW_ASN1_UTCTIME_new +#define ASN1_UTF8STRING_free GRPC_SHADOW_ASN1_UTF8STRING_free +#define ASN1_UTF8STRING_it GRPC_SHADOW_ASN1_UTF8STRING_it +#define ASN1_UTF8STRING_new GRPC_SHADOW_ASN1_UTF8STRING_new +#define ASN1_VISIBLESTRING_free GRPC_SHADOW_ASN1_VISIBLESTRING_free +#define ASN1_VISIBLESTRING_it GRPC_SHADOW_ASN1_VISIBLESTRING_it +#define ASN1_VISIBLESTRING_new GRPC_SHADOW_ASN1_VISIBLESTRING_new +#define DIRECTORYSTRING_free GRPC_SHADOW_DIRECTORYSTRING_free +#define DIRECTORYSTRING_it GRPC_SHADOW_DIRECTORYSTRING_it +#define DIRECTORYSTRING_new GRPC_SHADOW_DIRECTORYSTRING_new +#define DISPLAYTEXT_free GRPC_SHADOW_DISPLAYTEXT_free +#define DISPLAYTEXT_it GRPC_SHADOW_DISPLAYTEXT_it +#define DISPLAYTEXT_new GRPC_SHADOW_DISPLAYTEXT_new +#define d2i_ASN1_BIT_STRING GRPC_SHADOW_d2i_ASN1_BIT_STRING +#define d2i_ASN1_BMPSTRING GRPC_SHADOW_d2i_ASN1_BMPSTRING +#define d2i_ASN1_ENUMERATED GRPC_SHADOW_d2i_ASN1_ENUMERATED +#define d2i_ASN1_GENERALIZEDTIME GRPC_SHADOW_d2i_ASN1_GENERALIZEDTIME +#define d2i_ASN1_GENERALSTRING GRPC_SHADOW_d2i_ASN1_GENERALSTRING +#define d2i_ASN1_IA5STRING GRPC_SHADOW_d2i_ASN1_IA5STRING +#define d2i_ASN1_INTEGER GRPC_SHADOW_d2i_ASN1_INTEGER +#define d2i_ASN1_NULL GRPC_SHADOW_d2i_ASN1_NULL +#define d2i_ASN1_OCTET_STRING GRPC_SHADOW_d2i_ASN1_OCTET_STRING +#define d2i_ASN1_PRINTABLE GRPC_SHADOW_d2i_ASN1_PRINTABLE +#define d2i_ASN1_PRINTABLESTRING GRPC_SHADOW_d2i_ASN1_PRINTABLESTRING +#define d2i_ASN1_SEQUENCE_ANY GRPC_SHADOW_d2i_ASN1_SEQUENCE_ANY +#define d2i_ASN1_SET_ANY GRPC_SHADOW_d2i_ASN1_SET_ANY +#define d2i_ASN1_T61STRING GRPC_SHADOW_d2i_ASN1_T61STRING +#define d2i_ASN1_TYPE GRPC_SHADOW_d2i_ASN1_TYPE +#define d2i_ASN1_UNIVERSALSTRING GRPC_SHADOW_d2i_ASN1_UNIVERSALSTRING +#define d2i_ASN1_UTCTIME GRPC_SHADOW_d2i_ASN1_UTCTIME +#define d2i_ASN1_UTF8STRING GRPC_SHADOW_d2i_ASN1_UTF8STRING +#define d2i_ASN1_VISIBLESTRING GRPC_SHADOW_d2i_ASN1_VISIBLESTRING +#define d2i_DIRECTORYSTRING GRPC_SHADOW_d2i_DIRECTORYSTRING +#define d2i_DISPLAYTEXT GRPC_SHADOW_d2i_DISPLAYTEXT +#define i2d_ASN1_BIT_STRING GRPC_SHADOW_i2d_ASN1_BIT_STRING +#define i2d_ASN1_BMPSTRING GRPC_SHADOW_i2d_ASN1_BMPSTRING +#define i2d_ASN1_ENUMERATED GRPC_SHADOW_i2d_ASN1_ENUMERATED +#define i2d_ASN1_GENERALIZEDTIME GRPC_SHADOW_i2d_ASN1_GENERALIZEDTIME +#define i2d_ASN1_GENERALSTRING GRPC_SHADOW_i2d_ASN1_GENERALSTRING +#define i2d_ASN1_IA5STRING GRPC_SHADOW_i2d_ASN1_IA5STRING +#define i2d_ASN1_INTEGER GRPC_SHADOW_i2d_ASN1_INTEGER +#define i2d_ASN1_NULL GRPC_SHADOW_i2d_ASN1_NULL +#define i2d_ASN1_OCTET_STRING GRPC_SHADOW_i2d_ASN1_OCTET_STRING +#define i2d_ASN1_PRINTABLE GRPC_SHADOW_i2d_ASN1_PRINTABLE +#define i2d_ASN1_PRINTABLESTRING GRPC_SHADOW_i2d_ASN1_PRINTABLESTRING +#define i2d_ASN1_SEQUENCE_ANY GRPC_SHADOW_i2d_ASN1_SEQUENCE_ANY +#define i2d_ASN1_SET_ANY GRPC_SHADOW_i2d_ASN1_SET_ANY +#define i2d_ASN1_T61STRING GRPC_SHADOW_i2d_ASN1_T61STRING +#define i2d_ASN1_TYPE GRPC_SHADOW_i2d_ASN1_TYPE +#define i2d_ASN1_UNIVERSALSTRING GRPC_SHADOW_i2d_ASN1_UNIVERSALSTRING +#define i2d_ASN1_UTCTIME GRPC_SHADOW_i2d_ASN1_UTCTIME +#define i2d_ASN1_UTF8STRING GRPC_SHADOW_i2d_ASN1_UTF8STRING +#define i2d_ASN1_VISIBLESTRING GRPC_SHADOW_i2d_ASN1_VISIBLESTRING +#define i2d_DIRECTORYSTRING GRPC_SHADOW_i2d_DIRECTORYSTRING +#define i2d_DISPLAYTEXT GRPC_SHADOW_i2d_DISPLAYTEXT +#define asn1_do_adb GRPC_SHADOW_asn1_do_adb +#define asn1_enc_free GRPC_SHADOW_asn1_enc_free +#define asn1_enc_init GRPC_SHADOW_asn1_enc_init +#define asn1_enc_restore GRPC_SHADOW_asn1_enc_restore +#define asn1_enc_save GRPC_SHADOW_asn1_enc_save +#define asn1_get_choice_selector GRPC_SHADOW_asn1_get_choice_selector +#define asn1_get_field_ptr GRPC_SHADOW_asn1_get_field_ptr +#define asn1_refcount_dec_and_test_zero GRPC_SHADOW_asn1_refcount_dec_and_test_zero +#define asn1_refcount_set_one GRPC_SHADOW_asn1_refcount_set_one +#define asn1_set_choice_selector GRPC_SHADOW_asn1_set_choice_selector +#define OPENSSL_gmtime GRPC_SHADOW_OPENSSL_gmtime +#define OPENSSL_gmtime_adj GRPC_SHADOW_OPENSSL_gmtime_adj +#define OPENSSL_gmtime_diff GRPC_SHADOW_OPENSSL_gmtime_diff +#define ENGINE_free GRPC_SHADOW_ENGINE_free +#define ENGINE_get_ECDSA_method GRPC_SHADOW_ENGINE_get_ECDSA_method +#define ENGINE_get_RSA_method GRPC_SHADOW_ENGINE_get_RSA_method +#define ENGINE_new GRPC_SHADOW_ENGINE_new +#define ENGINE_set_ECDSA_method GRPC_SHADOW_ENGINE_set_ECDSA_method +#define ENGINE_set_RSA_method GRPC_SHADOW_ENGINE_set_RSA_method +#define METHOD_ref GRPC_SHADOW_METHOD_ref +#define METHOD_unref GRPC_SHADOW_METHOD_unref +#define DH_compute_key GRPC_SHADOW_DH_compute_key +#define DH_free GRPC_SHADOW_DH_free +#define DH_generate_key GRPC_SHADOW_DH_generate_key +#define DH_generate_parameters_ex GRPC_SHADOW_DH_generate_parameters_ex +#define DH_get0_key GRPC_SHADOW_DH_get0_key +#define DH_get0_pqg GRPC_SHADOW_DH_get0_pqg +#define DH_get_ex_data GRPC_SHADOW_DH_get_ex_data +#define DH_get_ex_new_index GRPC_SHADOW_DH_get_ex_new_index +#define DH_new GRPC_SHADOW_DH_new +#define DH_num_bits GRPC_SHADOW_DH_num_bits +#define DH_set0_key GRPC_SHADOW_DH_set0_key +#define DH_set0_pqg GRPC_SHADOW_DH_set0_pqg +#define DH_set_ex_data GRPC_SHADOW_DH_set_ex_data +#define DH_size GRPC_SHADOW_DH_size +#define DH_up_ref GRPC_SHADOW_DH_up_ref +#define DHparams_dup GRPC_SHADOW_DHparams_dup +#define BN_get_rfc3526_prime_1536 GRPC_SHADOW_BN_get_rfc3526_prime_1536 +#define DH_check GRPC_SHADOW_DH_check +#define DH_check_pub_key GRPC_SHADOW_DH_check_pub_key +#define DH_marshal_parameters GRPC_SHADOW_DH_marshal_parameters +#define DH_parse_parameters GRPC_SHADOW_DH_parse_parameters +#define d2i_DHparams GRPC_SHADOW_d2i_DHparams +#define i2d_DHparams GRPC_SHADOW_i2d_DHparams +#define DSA_SIG_free GRPC_SHADOW_DSA_SIG_free +#define DSA_SIG_new GRPC_SHADOW_DSA_SIG_new +#define DSA_check_signature GRPC_SHADOW_DSA_check_signature +#define DSA_do_check_signature GRPC_SHADOW_DSA_do_check_signature +#define DSA_do_sign GRPC_SHADOW_DSA_do_sign +#define DSA_do_verify GRPC_SHADOW_DSA_do_verify +#define DSA_dup_DH GRPC_SHADOW_DSA_dup_DH +#define DSA_free GRPC_SHADOW_DSA_free +#define DSA_generate_key GRPC_SHADOW_DSA_generate_key +#define DSA_generate_parameters_ex GRPC_SHADOW_DSA_generate_parameters_ex +#define DSA_get0_key GRPC_SHADOW_DSA_get0_key +#define DSA_get0_pqg GRPC_SHADOW_DSA_get0_pqg +#define DSA_get_ex_data GRPC_SHADOW_DSA_get_ex_data +#define DSA_get_ex_new_index GRPC_SHADOW_DSA_get_ex_new_index +#define DSA_new GRPC_SHADOW_DSA_new +#define DSA_set0_key GRPC_SHADOW_DSA_set0_key +#define DSA_set0_pqg GRPC_SHADOW_DSA_set0_pqg +#define DSA_set_ex_data GRPC_SHADOW_DSA_set_ex_data +#define DSA_sign GRPC_SHADOW_DSA_sign +#define DSA_size GRPC_SHADOW_DSA_size +#define DSA_up_ref GRPC_SHADOW_DSA_up_ref +#define DSA_verify GRPC_SHADOW_DSA_verify +#define DSAparams_dup GRPC_SHADOW_DSAparams_dup +#define DSA_SIG_marshal GRPC_SHADOW_DSA_SIG_marshal +#define DSA_SIG_parse GRPC_SHADOW_DSA_SIG_parse +#define DSA_marshal_parameters GRPC_SHADOW_DSA_marshal_parameters +#define DSA_marshal_private_key GRPC_SHADOW_DSA_marshal_private_key +#define DSA_marshal_public_key GRPC_SHADOW_DSA_marshal_public_key +#define DSA_parse_parameters GRPC_SHADOW_DSA_parse_parameters +#define DSA_parse_private_key GRPC_SHADOW_DSA_parse_private_key +#define DSA_parse_public_key GRPC_SHADOW_DSA_parse_public_key +#define d2i_DSAPrivateKey GRPC_SHADOW_d2i_DSAPrivateKey +#define d2i_DSAPublicKey GRPC_SHADOW_d2i_DSAPublicKey +#define d2i_DSA_SIG GRPC_SHADOW_d2i_DSA_SIG +#define d2i_DSAparams GRPC_SHADOW_d2i_DSAparams +#define i2d_DSAPrivateKey GRPC_SHADOW_i2d_DSAPrivateKey +#define i2d_DSAPublicKey GRPC_SHADOW_i2d_DSAPublicKey +#define i2d_DSA_SIG GRPC_SHADOW_i2d_DSA_SIG +#define i2d_DSAparams GRPC_SHADOW_i2d_DSAparams +#define RSAPrivateKey_dup GRPC_SHADOW_RSAPrivateKey_dup +#define RSAPublicKey_dup GRPC_SHADOW_RSAPublicKey_dup +#define RSA_marshal_private_key GRPC_SHADOW_RSA_marshal_private_key +#define RSA_marshal_public_key GRPC_SHADOW_RSA_marshal_public_key +#define RSA_parse_private_key GRPC_SHADOW_RSA_parse_private_key +#define RSA_parse_public_key GRPC_SHADOW_RSA_parse_public_key +#define RSA_private_key_from_bytes GRPC_SHADOW_RSA_private_key_from_bytes +#define RSA_private_key_to_bytes GRPC_SHADOW_RSA_private_key_to_bytes +#define RSA_public_key_from_bytes GRPC_SHADOW_RSA_public_key_from_bytes +#define RSA_public_key_to_bytes GRPC_SHADOW_RSA_public_key_to_bytes +#define d2i_RSAPrivateKey GRPC_SHADOW_d2i_RSAPrivateKey +#define d2i_RSAPublicKey GRPC_SHADOW_d2i_RSAPublicKey +#define i2d_RSAPrivateKey GRPC_SHADOW_i2d_RSAPrivateKey +#define i2d_RSAPublicKey GRPC_SHADOW_i2d_RSAPublicKey +#define EC_KEY_marshal_curve_name GRPC_SHADOW_EC_KEY_marshal_curve_name +#define EC_KEY_marshal_private_key GRPC_SHADOW_EC_KEY_marshal_private_key +#define EC_KEY_parse_curve_name GRPC_SHADOW_EC_KEY_parse_curve_name +#define EC_KEY_parse_parameters GRPC_SHADOW_EC_KEY_parse_parameters +#define EC_KEY_parse_private_key GRPC_SHADOW_EC_KEY_parse_private_key +#define EC_POINT_point2cbb GRPC_SHADOW_EC_POINT_point2cbb +#define d2i_ECParameters GRPC_SHADOW_d2i_ECParameters +#define d2i_ECPrivateKey GRPC_SHADOW_d2i_ECPrivateKey +#define i2d_ECParameters GRPC_SHADOW_i2d_ECParameters +#define i2d_ECPrivateKey GRPC_SHADOW_i2d_ECPrivateKey +#define i2o_ECPublicKey GRPC_SHADOW_i2o_ECPublicKey +#define o2i_ECPublicKey GRPC_SHADOW_o2i_ECPublicKey +#define ECDH_compute_key GRPC_SHADOW_ECDH_compute_key +#define ECDSA_SIG_from_bytes GRPC_SHADOW_ECDSA_SIG_from_bytes +#define ECDSA_SIG_marshal GRPC_SHADOW_ECDSA_SIG_marshal +#define ECDSA_SIG_max_len GRPC_SHADOW_ECDSA_SIG_max_len +#define ECDSA_SIG_parse GRPC_SHADOW_ECDSA_SIG_parse +#define ECDSA_SIG_to_bytes GRPC_SHADOW_ECDSA_SIG_to_bytes +#define ECDSA_sign GRPC_SHADOW_ECDSA_sign +#define ECDSA_size GRPC_SHADOW_ECDSA_size +#define ECDSA_verify GRPC_SHADOW_ECDSA_verify +#define d2i_ECDSA_SIG GRPC_SHADOW_d2i_ECDSA_SIG +#define i2d_ECDSA_SIG GRPC_SHADOW_i2d_ECDSA_SIG +#define AES_CMAC GRPC_SHADOW_AES_CMAC +#define CMAC_CTX_free GRPC_SHADOW_CMAC_CTX_free +#define CMAC_CTX_new GRPC_SHADOW_CMAC_CTX_new +#define CMAC_Final GRPC_SHADOW_CMAC_Final +#define CMAC_Init GRPC_SHADOW_CMAC_Init +#define CMAC_Reset GRPC_SHADOW_CMAC_Reset +#define CMAC_Update GRPC_SHADOW_CMAC_Update +#define EVP_DigestSign GRPC_SHADOW_EVP_DigestSign +#define EVP_DigestSignFinal GRPC_SHADOW_EVP_DigestSignFinal +#define EVP_DigestSignInit GRPC_SHADOW_EVP_DigestSignInit +#define EVP_DigestSignUpdate GRPC_SHADOW_EVP_DigestSignUpdate +#define EVP_DigestVerify GRPC_SHADOW_EVP_DigestVerify +#define EVP_DigestVerifyFinal GRPC_SHADOW_EVP_DigestVerifyFinal +#define EVP_DigestVerifyInit GRPC_SHADOW_EVP_DigestVerifyInit +#define EVP_DigestVerifyUpdate GRPC_SHADOW_EVP_DigestVerifyUpdate +#define EVP_PKEY_CTX_get_signature_md GRPC_SHADOW_EVP_PKEY_CTX_get_signature_md +#define EVP_PKEY_CTX_set_signature_md GRPC_SHADOW_EVP_PKEY_CTX_set_signature_md +#define EVP_PKEY_assign GRPC_SHADOW_EVP_PKEY_assign +#define EVP_PKEY_assign_DSA GRPC_SHADOW_EVP_PKEY_assign_DSA +#define EVP_PKEY_assign_EC_KEY GRPC_SHADOW_EVP_PKEY_assign_EC_KEY +#define EVP_PKEY_assign_RSA GRPC_SHADOW_EVP_PKEY_assign_RSA +#define EVP_PKEY_bits GRPC_SHADOW_EVP_PKEY_bits +#define EVP_PKEY_cmp GRPC_SHADOW_EVP_PKEY_cmp +#define EVP_PKEY_cmp_parameters GRPC_SHADOW_EVP_PKEY_cmp_parameters +#define EVP_PKEY_copy_parameters GRPC_SHADOW_EVP_PKEY_copy_parameters +#define EVP_PKEY_free GRPC_SHADOW_EVP_PKEY_free +#define EVP_PKEY_get0_DH GRPC_SHADOW_EVP_PKEY_get0_DH +#define EVP_PKEY_get0_DSA GRPC_SHADOW_EVP_PKEY_get0_DSA +#define EVP_PKEY_get0_EC_KEY GRPC_SHADOW_EVP_PKEY_get0_EC_KEY +#define EVP_PKEY_get0_RSA GRPC_SHADOW_EVP_PKEY_get0_RSA +#define EVP_PKEY_get1_DSA GRPC_SHADOW_EVP_PKEY_get1_DSA +#define EVP_PKEY_get1_EC_KEY GRPC_SHADOW_EVP_PKEY_get1_EC_KEY +#define EVP_PKEY_get1_RSA GRPC_SHADOW_EVP_PKEY_get1_RSA +#define EVP_PKEY_id GRPC_SHADOW_EVP_PKEY_id +#define EVP_PKEY_is_opaque GRPC_SHADOW_EVP_PKEY_is_opaque +#define EVP_PKEY_missing_parameters GRPC_SHADOW_EVP_PKEY_missing_parameters +#define EVP_PKEY_new GRPC_SHADOW_EVP_PKEY_new +#define EVP_PKEY_set1_DSA GRPC_SHADOW_EVP_PKEY_set1_DSA +#define EVP_PKEY_set1_EC_KEY GRPC_SHADOW_EVP_PKEY_set1_EC_KEY +#define EVP_PKEY_set1_RSA GRPC_SHADOW_EVP_PKEY_set1_RSA +#define EVP_PKEY_set_type GRPC_SHADOW_EVP_PKEY_set_type +#define EVP_PKEY_size GRPC_SHADOW_EVP_PKEY_size +#define EVP_PKEY_type GRPC_SHADOW_EVP_PKEY_type +#define EVP_PKEY_up_ref GRPC_SHADOW_EVP_PKEY_up_ref +#define EVP_cleanup GRPC_SHADOW_EVP_cleanup +#define OPENSSL_add_all_algorithms_conf GRPC_SHADOW_OPENSSL_add_all_algorithms_conf +#define OpenSSL_add_all_algorithms GRPC_SHADOW_OpenSSL_add_all_algorithms +#define OpenSSL_add_all_ciphers GRPC_SHADOW_OpenSSL_add_all_ciphers +#define OpenSSL_add_all_digests GRPC_SHADOW_OpenSSL_add_all_digests +#define EVP_marshal_private_key GRPC_SHADOW_EVP_marshal_private_key +#define EVP_marshal_public_key GRPC_SHADOW_EVP_marshal_public_key +#define EVP_parse_private_key GRPC_SHADOW_EVP_parse_private_key +#define EVP_parse_public_key GRPC_SHADOW_EVP_parse_public_key +#define d2i_AutoPrivateKey GRPC_SHADOW_d2i_AutoPrivateKey +#define d2i_PrivateKey GRPC_SHADOW_d2i_PrivateKey +#define i2d_PublicKey GRPC_SHADOW_i2d_PublicKey +#define EVP_PKEY_CTX_ctrl GRPC_SHADOW_EVP_PKEY_CTX_ctrl +#define EVP_PKEY_CTX_dup GRPC_SHADOW_EVP_PKEY_CTX_dup +#define EVP_PKEY_CTX_free GRPC_SHADOW_EVP_PKEY_CTX_free +#define EVP_PKEY_CTX_get0_pkey GRPC_SHADOW_EVP_PKEY_CTX_get0_pkey +#define EVP_PKEY_CTX_new GRPC_SHADOW_EVP_PKEY_CTX_new +#define EVP_PKEY_CTX_new_id GRPC_SHADOW_EVP_PKEY_CTX_new_id +#define EVP_PKEY_decrypt GRPC_SHADOW_EVP_PKEY_decrypt +#define EVP_PKEY_decrypt_init GRPC_SHADOW_EVP_PKEY_decrypt_init +#define EVP_PKEY_derive GRPC_SHADOW_EVP_PKEY_derive +#define EVP_PKEY_derive_init GRPC_SHADOW_EVP_PKEY_derive_init +#define EVP_PKEY_derive_set_peer GRPC_SHADOW_EVP_PKEY_derive_set_peer +#define EVP_PKEY_encrypt GRPC_SHADOW_EVP_PKEY_encrypt +#define EVP_PKEY_encrypt_init GRPC_SHADOW_EVP_PKEY_encrypt_init +#define EVP_PKEY_keygen GRPC_SHADOW_EVP_PKEY_keygen +#define EVP_PKEY_keygen_init GRPC_SHADOW_EVP_PKEY_keygen_init +#define EVP_PKEY_sign GRPC_SHADOW_EVP_PKEY_sign +#define EVP_PKEY_sign_init GRPC_SHADOW_EVP_PKEY_sign_init +#define EVP_PKEY_verify GRPC_SHADOW_EVP_PKEY_verify +#define EVP_PKEY_verify_init GRPC_SHADOW_EVP_PKEY_verify_init +#define EVP_PKEY_verify_recover GRPC_SHADOW_EVP_PKEY_verify_recover +#define EVP_PKEY_verify_recover_init GRPC_SHADOW_EVP_PKEY_verify_recover_init +#define dsa_asn1_meth GRPC_SHADOW_dsa_asn1_meth +#define ec_pkey_meth GRPC_SHADOW_ec_pkey_meth +#define ec_asn1_meth GRPC_SHADOW_ec_asn1_meth +#define ed25519_pkey_meth GRPC_SHADOW_ed25519_pkey_meth +#define EVP_PKEY_new_ed25519_private GRPC_SHADOW_EVP_PKEY_new_ed25519_private +#define EVP_PKEY_new_ed25519_public GRPC_SHADOW_EVP_PKEY_new_ed25519_public +#define ed25519_asn1_meth GRPC_SHADOW_ed25519_asn1_meth +#define EVP_PKEY_CTX_get0_rsa_oaep_label GRPC_SHADOW_EVP_PKEY_CTX_get0_rsa_oaep_label +#define EVP_PKEY_CTX_get_rsa_mgf1_md GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_mgf1_md +#define EVP_PKEY_CTX_get_rsa_oaep_md GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_oaep_md +#define EVP_PKEY_CTX_get_rsa_padding GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_padding +#define EVP_PKEY_CTX_get_rsa_pss_saltlen GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_pss_saltlen +#define EVP_PKEY_CTX_set0_rsa_oaep_label GRPC_SHADOW_EVP_PKEY_CTX_set0_rsa_oaep_label +#define EVP_PKEY_CTX_set_rsa_keygen_bits GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_keygen_bits +#define EVP_PKEY_CTX_set_rsa_keygen_pubexp GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_keygen_pubexp +#define EVP_PKEY_CTX_set_rsa_mgf1_md GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_mgf1_md +#define EVP_PKEY_CTX_set_rsa_oaep_md GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_oaep_md +#define EVP_PKEY_CTX_set_rsa_padding GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_padding +#define EVP_PKEY_CTX_set_rsa_pss_saltlen GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_pss_saltlen +#define rsa_pkey_meth GRPC_SHADOW_rsa_pkey_meth +#define rsa_asn1_meth GRPC_SHADOW_rsa_asn1_meth +#define PKCS5_PBKDF2_HMAC GRPC_SHADOW_PKCS5_PBKDF2_HMAC +#define PKCS5_PBKDF2_HMAC_SHA1 GRPC_SHADOW_PKCS5_PBKDF2_HMAC_SHA1 +#define EVP_PKEY_print_params GRPC_SHADOW_EVP_PKEY_print_params +#define EVP_PKEY_print_private GRPC_SHADOW_EVP_PKEY_print_private +#define EVP_PKEY_print_public GRPC_SHADOW_EVP_PKEY_print_public +#define EVP_PBE_scrypt GRPC_SHADOW_EVP_PBE_scrypt +#define EVP_SignFinal GRPC_SHADOW_EVP_SignFinal +#define EVP_SignInit GRPC_SHADOW_EVP_SignInit +#define EVP_SignInit_ex GRPC_SHADOW_EVP_SignInit_ex +#define EVP_SignUpdate GRPC_SHADOW_EVP_SignUpdate +#define EVP_VerifyFinal GRPC_SHADOW_EVP_VerifyFinal +#define EVP_VerifyInit GRPC_SHADOW_EVP_VerifyInit +#define EVP_VerifyInit_ex GRPC_SHADOW_EVP_VerifyInit_ex +#define EVP_VerifyUpdate GRPC_SHADOW_EVP_VerifyUpdate +#define HKDF GRPC_SHADOW_HKDF +#define HKDF_expand GRPC_SHADOW_HKDF_expand +#define HKDF_extract GRPC_SHADOW_HKDF_extract +#define PEM_read_DSAPrivateKey GRPC_SHADOW_PEM_read_DSAPrivateKey +#define PEM_read_DSA_PUBKEY GRPC_SHADOW_PEM_read_DSA_PUBKEY +#define PEM_read_DSAparams GRPC_SHADOW_PEM_read_DSAparams +#define PEM_read_ECPrivateKey GRPC_SHADOW_PEM_read_ECPrivateKey +#define PEM_read_EC_PUBKEY GRPC_SHADOW_PEM_read_EC_PUBKEY +#define PEM_read_PUBKEY GRPC_SHADOW_PEM_read_PUBKEY +#define PEM_read_RSAPrivateKey GRPC_SHADOW_PEM_read_RSAPrivateKey +#define PEM_read_RSAPublicKey GRPC_SHADOW_PEM_read_RSAPublicKey +#define PEM_read_RSA_PUBKEY GRPC_SHADOW_PEM_read_RSA_PUBKEY +#define PEM_read_X509_CRL GRPC_SHADOW_PEM_read_X509_CRL +#define PEM_read_X509_REQ GRPC_SHADOW_PEM_read_X509_REQ +#define PEM_read_bio_DSAPrivateKey GRPC_SHADOW_PEM_read_bio_DSAPrivateKey +#define PEM_read_bio_DSA_PUBKEY GRPC_SHADOW_PEM_read_bio_DSA_PUBKEY +#define PEM_read_bio_DSAparams GRPC_SHADOW_PEM_read_bio_DSAparams +#define PEM_read_bio_ECPrivateKey GRPC_SHADOW_PEM_read_bio_ECPrivateKey +#define PEM_read_bio_EC_PUBKEY GRPC_SHADOW_PEM_read_bio_EC_PUBKEY +#define PEM_read_bio_PUBKEY GRPC_SHADOW_PEM_read_bio_PUBKEY +#define PEM_read_bio_RSAPrivateKey GRPC_SHADOW_PEM_read_bio_RSAPrivateKey +#define PEM_read_bio_RSAPublicKey GRPC_SHADOW_PEM_read_bio_RSAPublicKey +#define PEM_read_bio_RSA_PUBKEY GRPC_SHADOW_PEM_read_bio_RSA_PUBKEY +#define PEM_read_bio_X509_CRL GRPC_SHADOW_PEM_read_bio_X509_CRL +#define PEM_read_bio_X509_REQ GRPC_SHADOW_PEM_read_bio_X509_REQ +#define PEM_write_DHparams GRPC_SHADOW_PEM_write_DHparams +#define PEM_write_DSAPrivateKey GRPC_SHADOW_PEM_write_DSAPrivateKey +#define PEM_write_DSA_PUBKEY GRPC_SHADOW_PEM_write_DSA_PUBKEY +#define PEM_write_DSAparams GRPC_SHADOW_PEM_write_DSAparams +#define PEM_write_ECPrivateKey GRPC_SHADOW_PEM_write_ECPrivateKey +#define PEM_write_EC_PUBKEY GRPC_SHADOW_PEM_write_EC_PUBKEY +#define PEM_write_PUBKEY GRPC_SHADOW_PEM_write_PUBKEY +#define PEM_write_RSAPrivateKey GRPC_SHADOW_PEM_write_RSAPrivateKey +#define PEM_write_RSAPublicKey GRPC_SHADOW_PEM_write_RSAPublicKey +#define PEM_write_RSA_PUBKEY GRPC_SHADOW_PEM_write_RSA_PUBKEY +#define PEM_write_X509_CRL GRPC_SHADOW_PEM_write_X509_CRL +#define PEM_write_X509_REQ GRPC_SHADOW_PEM_write_X509_REQ +#define PEM_write_X509_REQ_NEW GRPC_SHADOW_PEM_write_X509_REQ_NEW +#define PEM_write_bio_DHparams GRPC_SHADOW_PEM_write_bio_DHparams +#define PEM_write_bio_DSAPrivateKey GRPC_SHADOW_PEM_write_bio_DSAPrivateKey +#define PEM_write_bio_DSA_PUBKEY GRPC_SHADOW_PEM_write_bio_DSA_PUBKEY +#define PEM_write_bio_DSAparams GRPC_SHADOW_PEM_write_bio_DSAparams +#define PEM_write_bio_ECPrivateKey GRPC_SHADOW_PEM_write_bio_ECPrivateKey +#define PEM_write_bio_EC_PUBKEY GRPC_SHADOW_PEM_write_bio_EC_PUBKEY +#define PEM_write_bio_PUBKEY GRPC_SHADOW_PEM_write_bio_PUBKEY +#define PEM_write_bio_RSAPrivateKey GRPC_SHADOW_PEM_write_bio_RSAPrivateKey +#define PEM_write_bio_RSAPublicKey GRPC_SHADOW_PEM_write_bio_RSAPublicKey +#define PEM_write_bio_RSA_PUBKEY GRPC_SHADOW_PEM_write_bio_RSA_PUBKEY +#define PEM_write_bio_X509_CRL GRPC_SHADOW_PEM_write_bio_X509_CRL +#define PEM_write_bio_X509_REQ GRPC_SHADOW_PEM_write_bio_X509_REQ +#define PEM_write_bio_X509_REQ_NEW GRPC_SHADOW_PEM_write_bio_X509_REQ_NEW +#define PEM_X509_INFO_read GRPC_SHADOW_PEM_X509_INFO_read +#define PEM_X509_INFO_read_bio GRPC_SHADOW_PEM_X509_INFO_read_bio +#define PEM_X509_INFO_write_bio GRPC_SHADOW_PEM_X509_INFO_write_bio +#define PEM_ASN1_read GRPC_SHADOW_PEM_ASN1_read +#define PEM_ASN1_write GRPC_SHADOW_PEM_ASN1_write +#define PEM_ASN1_write_bio GRPC_SHADOW_PEM_ASN1_write_bio +#define PEM_bytes_read_bio GRPC_SHADOW_PEM_bytes_read_bio +#define PEM_def_callback GRPC_SHADOW_PEM_def_callback +#define PEM_dek_info GRPC_SHADOW_PEM_dek_info +#define PEM_do_header GRPC_SHADOW_PEM_do_header +#define PEM_get_EVP_CIPHER_INFO GRPC_SHADOW_PEM_get_EVP_CIPHER_INFO +#define PEM_proc_type GRPC_SHADOW_PEM_proc_type +#define PEM_read GRPC_SHADOW_PEM_read +#define PEM_read_bio GRPC_SHADOW_PEM_read_bio +#define PEM_write GRPC_SHADOW_PEM_write +#define PEM_write_bio GRPC_SHADOW_PEM_write_bio +#define PEM_ASN1_read_bio GRPC_SHADOW_PEM_ASN1_read_bio +#define PEM_read_PKCS8 GRPC_SHADOW_PEM_read_PKCS8 +#define PEM_read_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_read_PKCS8_PRIV_KEY_INFO +#define PEM_read_bio_PKCS8 GRPC_SHADOW_PEM_read_bio_PKCS8 +#define PEM_read_bio_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_read_bio_PKCS8_PRIV_KEY_INFO +#define PEM_write_PKCS8 GRPC_SHADOW_PEM_write_PKCS8 +#define PEM_write_PKCS8PrivateKey GRPC_SHADOW_PEM_write_PKCS8PrivateKey +#define PEM_write_PKCS8PrivateKey_nid GRPC_SHADOW_PEM_write_PKCS8PrivateKey_nid +#define PEM_write_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_write_PKCS8_PRIV_KEY_INFO +#define PEM_write_bio_PKCS8 GRPC_SHADOW_PEM_write_bio_PKCS8 +#define PEM_write_bio_PKCS8PrivateKey GRPC_SHADOW_PEM_write_bio_PKCS8PrivateKey +#define PEM_write_bio_PKCS8PrivateKey_nid GRPC_SHADOW_PEM_write_bio_PKCS8PrivateKey_nid +#define PEM_write_bio_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_write_bio_PKCS8_PRIV_KEY_INFO +#define d2i_PKCS8PrivateKey_bio GRPC_SHADOW_d2i_PKCS8PrivateKey_bio +#define d2i_PKCS8PrivateKey_fp GRPC_SHADOW_d2i_PKCS8PrivateKey_fp +#define i2d_PKCS8PrivateKey_bio GRPC_SHADOW_i2d_PKCS8PrivateKey_bio +#define i2d_PKCS8PrivateKey_fp GRPC_SHADOW_i2d_PKCS8PrivateKey_fp +#define i2d_PKCS8PrivateKey_nid_bio GRPC_SHADOW_i2d_PKCS8PrivateKey_nid_bio +#define i2d_PKCS8PrivateKey_nid_fp GRPC_SHADOW_i2d_PKCS8PrivateKey_nid_fp +#define PEM_read_DHparams GRPC_SHADOW_PEM_read_DHparams +#define PEM_read_PrivateKey GRPC_SHADOW_PEM_read_PrivateKey +#define PEM_read_bio_DHparams GRPC_SHADOW_PEM_read_bio_DHparams +#define PEM_read_bio_PrivateKey GRPC_SHADOW_PEM_read_bio_PrivateKey +#define PEM_write_PrivateKey GRPC_SHADOW_PEM_write_PrivateKey +#define PEM_write_bio_PrivateKey GRPC_SHADOW_PEM_write_bio_PrivateKey +#define PEM_read_X509 GRPC_SHADOW_PEM_read_X509 +#define PEM_read_bio_X509 GRPC_SHADOW_PEM_read_bio_X509 +#define PEM_write_X509 GRPC_SHADOW_PEM_write_X509 +#define PEM_write_bio_X509 GRPC_SHADOW_PEM_write_bio_X509 +#define PEM_read_X509_AUX GRPC_SHADOW_PEM_read_X509_AUX +#define PEM_read_bio_X509_AUX GRPC_SHADOW_PEM_read_bio_X509_AUX +#define PEM_write_X509_AUX GRPC_SHADOW_PEM_write_X509_AUX +#define PEM_write_bio_X509_AUX GRPC_SHADOW_PEM_write_bio_X509_AUX +#define ASN1_digest GRPC_SHADOW_ASN1_digest +#define ASN1_item_digest GRPC_SHADOW_ASN1_item_digest +#define ASN1_item_sign GRPC_SHADOW_ASN1_item_sign +#define ASN1_item_sign_ctx GRPC_SHADOW_ASN1_item_sign_ctx +#define ASN1_STRING_print_ex GRPC_SHADOW_ASN1_STRING_print_ex +#define ASN1_STRING_print_ex_fp GRPC_SHADOW_ASN1_STRING_print_ex_fp +#define ASN1_STRING_to_UTF8 GRPC_SHADOW_ASN1_STRING_to_UTF8 +#define X509_NAME_print_ex GRPC_SHADOW_X509_NAME_print_ex +#define X509_NAME_print_ex_fp GRPC_SHADOW_X509_NAME_print_ex_fp +#define ASN1_item_verify GRPC_SHADOW_ASN1_item_verify +#define x509_digest_sign_algorithm GRPC_SHADOW_x509_digest_sign_algorithm +#define x509_digest_verify_init GRPC_SHADOW_x509_digest_verify_init +#define ASN1_generate_nconf GRPC_SHADOW_ASN1_generate_nconf +#define ASN1_generate_v3 GRPC_SHADOW_ASN1_generate_v3 +#define X509_LOOKUP_hash_dir GRPC_SHADOW_X509_LOOKUP_hash_dir +#define X509_LOOKUP_file GRPC_SHADOW_X509_LOOKUP_file +#define X509_load_cert_crl_file GRPC_SHADOW_X509_load_cert_crl_file +#define X509_load_cert_file GRPC_SHADOW_X509_load_cert_file +#define X509_load_crl_file GRPC_SHADOW_X509_load_crl_file +#define i2d_PrivateKey GRPC_SHADOW_i2d_PrivateKey +#define RSA_PSS_PARAMS_free GRPC_SHADOW_RSA_PSS_PARAMS_free +#define RSA_PSS_PARAMS_it GRPC_SHADOW_RSA_PSS_PARAMS_it +#define RSA_PSS_PARAMS_new GRPC_SHADOW_RSA_PSS_PARAMS_new +#define d2i_RSA_PSS_PARAMS GRPC_SHADOW_d2i_RSA_PSS_PARAMS +#define i2d_RSA_PSS_PARAMS GRPC_SHADOW_i2d_RSA_PSS_PARAMS +#define x509_print_rsa_pss_params GRPC_SHADOW_x509_print_rsa_pss_params +#define x509_rsa_ctx_to_pss GRPC_SHADOW_x509_rsa_ctx_to_pss +#define x509_rsa_pss_to_ctx GRPC_SHADOW_x509_rsa_pss_to_ctx +#define X509_CRL_print GRPC_SHADOW_X509_CRL_print +#define X509_CRL_print_fp GRPC_SHADOW_X509_CRL_print_fp +#define X509_REQ_print GRPC_SHADOW_X509_REQ_print +#define X509_REQ_print_ex GRPC_SHADOW_X509_REQ_print_ex +#define X509_REQ_print_fp GRPC_SHADOW_X509_REQ_print_fp +#define ASN1_GENERALIZEDTIME_print GRPC_SHADOW_ASN1_GENERALIZEDTIME_print +#define ASN1_STRING_print GRPC_SHADOW_ASN1_STRING_print +#define ASN1_TIME_print GRPC_SHADOW_ASN1_TIME_print +#define ASN1_UTCTIME_print GRPC_SHADOW_ASN1_UTCTIME_print +#define X509_NAME_print GRPC_SHADOW_X509_NAME_print +#define X509_ocspid_print GRPC_SHADOW_X509_ocspid_print +#define X509_print GRPC_SHADOW_X509_print +#define X509_print_ex GRPC_SHADOW_X509_print_ex +#define X509_print_ex_fp GRPC_SHADOW_X509_print_ex_fp +#define X509_print_fp GRPC_SHADOW_X509_print_fp +#define X509_signature_print GRPC_SHADOW_X509_signature_print +#define X509_CERT_AUX_print GRPC_SHADOW_X509_CERT_AUX_print +#define PKCS8_pkey_get0 GRPC_SHADOW_PKCS8_pkey_get0 +#define PKCS8_pkey_set0 GRPC_SHADOW_PKCS8_pkey_set0 +#define X509_signature_dump GRPC_SHADOW_X509_signature_dump +#define X509_ATTRIBUTE_count GRPC_SHADOW_X509_ATTRIBUTE_count +#define X509_ATTRIBUTE_create_by_NID GRPC_SHADOW_X509_ATTRIBUTE_create_by_NID +#define X509_ATTRIBUTE_create_by_OBJ GRPC_SHADOW_X509_ATTRIBUTE_create_by_OBJ +#define X509_ATTRIBUTE_create_by_txt GRPC_SHADOW_X509_ATTRIBUTE_create_by_txt +#define X509_ATTRIBUTE_get0_data GRPC_SHADOW_X509_ATTRIBUTE_get0_data +#define X509_ATTRIBUTE_get0_object GRPC_SHADOW_X509_ATTRIBUTE_get0_object +#define X509_ATTRIBUTE_get0_type GRPC_SHADOW_X509_ATTRIBUTE_get0_type +#define X509_ATTRIBUTE_set1_data GRPC_SHADOW_X509_ATTRIBUTE_set1_data +#define X509_ATTRIBUTE_set1_object GRPC_SHADOW_X509_ATTRIBUTE_set1_object +#define X509at_add1_attr GRPC_SHADOW_X509at_add1_attr +#define X509at_add1_attr_by_NID GRPC_SHADOW_X509at_add1_attr_by_NID +#define X509at_add1_attr_by_OBJ GRPC_SHADOW_X509at_add1_attr_by_OBJ +#define X509at_add1_attr_by_txt GRPC_SHADOW_X509at_add1_attr_by_txt +#define X509at_delete_attr GRPC_SHADOW_X509at_delete_attr +#define X509at_get0_data_by_OBJ GRPC_SHADOW_X509at_get0_data_by_OBJ +#define X509at_get_attr GRPC_SHADOW_X509at_get_attr +#define X509at_get_attr_by_NID GRPC_SHADOW_X509at_get_attr_by_NID +#define X509at_get_attr_by_OBJ GRPC_SHADOW_X509at_get_attr_by_OBJ +#define X509at_get_attr_count GRPC_SHADOW_X509at_get_attr_count +#define X509_CRL_check_suiteb GRPC_SHADOW_X509_CRL_check_suiteb +#define X509_CRL_cmp GRPC_SHADOW_X509_CRL_cmp +#define X509_CRL_match GRPC_SHADOW_X509_CRL_match +#define X509_NAME_cmp GRPC_SHADOW_X509_NAME_cmp +#define X509_NAME_hash GRPC_SHADOW_X509_NAME_hash +#define X509_NAME_hash_old GRPC_SHADOW_X509_NAME_hash_old +#define X509_chain_check_suiteb GRPC_SHADOW_X509_chain_check_suiteb +#define X509_chain_up_ref GRPC_SHADOW_X509_chain_up_ref +#define X509_check_private_key GRPC_SHADOW_X509_check_private_key +#define X509_cmp GRPC_SHADOW_X509_cmp +#define X509_find_by_issuer_and_serial GRPC_SHADOW_X509_find_by_issuer_and_serial +#define X509_find_by_subject GRPC_SHADOW_X509_find_by_subject +#define X509_get0_pubkey_bitstr GRPC_SHADOW_X509_get0_pubkey_bitstr +#define X509_get_issuer_name GRPC_SHADOW_X509_get_issuer_name +#define X509_get_pubkey GRPC_SHADOW_X509_get_pubkey +#define X509_get_serialNumber GRPC_SHADOW_X509_get_serialNumber +#define X509_get_subject_name GRPC_SHADOW_X509_get_subject_name +#define X509_issuer_and_serial_cmp GRPC_SHADOW_X509_issuer_and_serial_cmp +#define X509_issuer_and_serial_hash GRPC_SHADOW_X509_issuer_and_serial_hash +#define X509_issuer_name_cmp GRPC_SHADOW_X509_issuer_name_cmp +#define X509_issuer_name_hash GRPC_SHADOW_X509_issuer_name_hash +#define X509_issuer_name_hash_old GRPC_SHADOW_X509_issuer_name_hash_old +#define X509_subject_name_cmp GRPC_SHADOW_X509_subject_name_cmp +#define X509_subject_name_hash GRPC_SHADOW_X509_subject_name_hash +#define X509_subject_name_hash_old GRPC_SHADOW_X509_subject_name_hash_old +#define X509_STORE_load_locations GRPC_SHADOW_X509_STORE_load_locations +#define X509_STORE_set_default_paths GRPC_SHADOW_X509_STORE_set_default_paths +#define X509_get_default_cert_area GRPC_SHADOW_X509_get_default_cert_area +#define X509_get_default_cert_dir GRPC_SHADOW_X509_get_default_cert_dir +#define X509_get_default_cert_dir_env GRPC_SHADOW_X509_get_default_cert_dir_env +#define X509_get_default_cert_file GRPC_SHADOW_X509_get_default_cert_file +#define X509_get_default_cert_file_env GRPC_SHADOW_X509_get_default_cert_file_env +#define X509_get_default_private_dir GRPC_SHADOW_X509_get_default_private_dir +#define X509_CRL_add1_ext_i2d GRPC_SHADOW_X509_CRL_add1_ext_i2d +#define X509_CRL_add_ext GRPC_SHADOW_X509_CRL_add_ext +#define X509_CRL_delete_ext GRPC_SHADOW_X509_CRL_delete_ext +#define X509_CRL_get_ext GRPC_SHADOW_X509_CRL_get_ext +#define X509_CRL_get_ext_by_NID GRPC_SHADOW_X509_CRL_get_ext_by_NID +#define X509_CRL_get_ext_by_OBJ GRPC_SHADOW_X509_CRL_get_ext_by_OBJ +#define X509_CRL_get_ext_by_critical GRPC_SHADOW_X509_CRL_get_ext_by_critical +#define X509_CRL_get_ext_count GRPC_SHADOW_X509_CRL_get_ext_count +#define X509_CRL_get_ext_d2i GRPC_SHADOW_X509_CRL_get_ext_d2i +#define X509_REVOKED_add1_ext_i2d GRPC_SHADOW_X509_REVOKED_add1_ext_i2d +#define X509_REVOKED_add_ext GRPC_SHADOW_X509_REVOKED_add_ext +#define X509_REVOKED_delete_ext GRPC_SHADOW_X509_REVOKED_delete_ext +#define X509_REVOKED_get_ext GRPC_SHADOW_X509_REVOKED_get_ext +#define X509_REVOKED_get_ext_by_NID GRPC_SHADOW_X509_REVOKED_get_ext_by_NID +#define X509_REVOKED_get_ext_by_OBJ GRPC_SHADOW_X509_REVOKED_get_ext_by_OBJ +#define X509_REVOKED_get_ext_by_critical GRPC_SHADOW_X509_REVOKED_get_ext_by_critical +#define X509_REVOKED_get_ext_count GRPC_SHADOW_X509_REVOKED_get_ext_count +#define X509_REVOKED_get_ext_d2i GRPC_SHADOW_X509_REVOKED_get_ext_d2i +#define X509_add1_ext_i2d GRPC_SHADOW_X509_add1_ext_i2d +#define X509_add_ext GRPC_SHADOW_X509_add_ext +#define X509_delete_ext GRPC_SHADOW_X509_delete_ext +#define X509_get_ext GRPC_SHADOW_X509_get_ext +#define X509_get_ext_by_NID GRPC_SHADOW_X509_get_ext_by_NID +#define X509_get_ext_by_OBJ GRPC_SHADOW_X509_get_ext_by_OBJ +#define X509_get_ext_by_critical GRPC_SHADOW_X509_get_ext_by_critical +#define X509_get_ext_count GRPC_SHADOW_X509_get_ext_count +#define X509_get_ext_d2i GRPC_SHADOW_X509_get_ext_d2i +#define X509_LOOKUP_by_alias GRPC_SHADOW_X509_LOOKUP_by_alias +#define X509_LOOKUP_by_fingerprint GRPC_SHADOW_X509_LOOKUP_by_fingerprint +#define X509_LOOKUP_by_issuer_serial GRPC_SHADOW_X509_LOOKUP_by_issuer_serial +#define X509_LOOKUP_by_subject GRPC_SHADOW_X509_LOOKUP_by_subject +#define X509_LOOKUP_ctrl GRPC_SHADOW_X509_LOOKUP_ctrl +#define X509_LOOKUP_free GRPC_SHADOW_X509_LOOKUP_free +#define X509_LOOKUP_init GRPC_SHADOW_X509_LOOKUP_init +#define X509_LOOKUP_new GRPC_SHADOW_X509_LOOKUP_new +#define X509_LOOKUP_shutdown GRPC_SHADOW_X509_LOOKUP_shutdown +#define X509_OBJECT_free_contents GRPC_SHADOW_X509_OBJECT_free_contents +#define X509_OBJECT_get0_X509 GRPC_SHADOW_X509_OBJECT_get0_X509 +#define X509_OBJECT_get_type GRPC_SHADOW_X509_OBJECT_get_type +#define X509_OBJECT_idx_by_subject GRPC_SHADOW_X509_OBJECT_idx_by_subject +#define X509_OBJECT_retrieve_by_subject GRPC_SHADOW_X509_OBJECT_retrieve_by_subject +#define X509_OBJECT_retrieve_match GRPC_SHADOW_X509_OBJECT_retrieve_match +#define X509_OBJECT_up_ref_count GRPC_SHADOW_X509_OBJECT_up_ref_count +#define X509_STORE_CTX_get0_store GRPC_SHADOW_X509_STORE_CTX_get0_store +#define X509_STORE_CTX_get1_issuer GRPC_SHADOW_X509_STORE_CTX_get1_issuer +#define X509_STORE_add_cert GRPC_SHADOW_X509_STORE_add_cert +#define X509_STORE_add_crl GRPC_SHADOW_X509_STORE_add_crl +#define X509_STORE_add_lookup GRPC_SHADOW_X509_STORE_add_lookup +#define X509_STORE_free GRPC_SHADOW_X509_STORE_free +#define X509_STORE_get0_objects GRPC_SHADOW_X509_STORE_get0_objects +#define X509_STORE_get0_param GRPC_SHADOW_X509_STORE_get0_param +#define X509_STORE_get1_certs GRPC_SHADOW_X509_STORE_get1_certs +#define X509_STORE_get1_crls GRPC_SHADOW_X509_STORE_get1_crls +#define X509_STORE_get_by_subject GRPC_SHADOW_X509_STORE_get_by_subject +#define X509_STORE_new GRPC_SHADOW_X509_STORE_new +#define X509_STORE_set0_additional_untrusted GRPC_SHADOW_X509_STORE_set0_additional_untrusted +#define X509_STORE_set1_param GRPC_SHADOW_X509_STORE_set1_param +#define X509_STORE_set_depth GRPC_SHADOW_X509_STORE_set_depth +#define X509_STORE_set_flags GRPC_SHADOW_X509_STORE_set_flags +#define X509_STORE_set_lookup_crls_cb GRPC_SHADOW_X509_STORE_set_lookup_crls_cb +#define X509_STORE_set_purpose GRPC_SHADOW_X509_STORE_set_purpose +#define X509_STORE_set_trust GRPC_SHADOW_X509_STORE_set_trust +#define X509_STORE_set_verify_cb GRPC_SHADOW_X509_STORE_set_verify_cb +#define X509_STORE_up_ref GRPC_SHADOW_X509_STORE_up_ref +#define X509_NAME_oneline GRPC_SHADOW_X509_NAME_oneline +#define X509_REQ_to_X509 GRPC_SHADOW_X509_REQ_to_X509 +#define X509_REQ_add1_attr GRPC_SHADOW_X509_REQ_add1_attr +#define X509_REQ_add1_attr_by_NID GRPC_SHADOW_X509_REQ_add1_attr_by_NID +#define X509_REQ_add1_attr_by_OBJ GRPC_SHADOW_X509_REQ_add1_attr_by_OBJ +#define X509_REQ_add1_attr_by_txt GRPC_SHADOW_X509_REQ_add1_attr_by_txt +#define X509_REQ_add_extensions GRPC_SHADOW_X509_REQ_add_extensions +#define X509_REQ_add_extensions_nid GRPC_SHADOW_X509_REQ_add_extensions_nid +#define X509_REQ_check_private_key GRPC_SHADOW_X509_REQ_check_private_key +#define X509_REQ_delete_attr GRPC_SHADOW_X509_REQ_delete_attr +#define X509_REQ_extension_nid GRPC_SHADOW_X509_REQ_extension_nid +#define X509_REQ_get_attr GRPC_SHADOW_X509_REQ_get_attr +#define X509_REQ_get_attr_by_NID GRPC_SHADOW_X509_REQ_get_attr_by_NID +#define X509_REQ_get_attr_by_OBJ GRPC_SHADOW_X509_REQ_get_attr_by_OBJ +#define X509_REQ_get_attr_count GRPC_SHADOW_X509_REQ_get_attr_count +#define X509_REQ_get_extension_nids GRPC_SHADOW_X509_REQ_get_extension_nids +#define X509_REQ_get_extensions GRPC_SHADOW_X509_REQ_get_extensions +#define X509_REQ_get_pubkey GRPC_SHADOW_X509_REQ_get_pubkey +#define X509_REQ_set_extension_nids GRPC_SHADOW_X509_REQ_set_extension_nids +#define X509_to_X509_REQ GRPC_SHADOW_X509_to_X509_REQ +#define X509_get0_extensions GRPC_SHADOW_X509_get0_extensions +#define X509_get0_notAfter GRPC_SHADOW_X509_get0_notAfter +#define X509_get0_notBefore GRPC_SHADOW_X509_get0_notBefore +#define X509_set_issuer_name GRPC_SHADOW_X509_set_issuer_name +#define X509_set_notAfter GRPC_SHADOW_X509_set_notAfter +#define X509_set_notBefore GRPC_SHADOW_X509_set_notBefore +#define X509_set_pubkey GRPC_SHADOW_X509_set_pubkey +#define X509_set_serialNumber GRPC_SHADOW_X509_set_serialNumber +#define X509_set_subject_name GRPC_SHADOW_X509_set_subject_name +#define X509_set_version GRPC_SHADOW_X509_set_version +#define X509_TRUST_add GRPC_SHADOW_X509_TRUST_add +#define X509_TRUST_cleanup GRPC_SHADOW_X509_TRUST_cleanup +#define X509_TRUST_get0 GRPC_SHADOW_X509_TRUST_get0 +#define X509_TRUST_get0_name GRPC_SHADOW_X509_TRUST_get0_name +#define X509_TRUST_get_by_id GRPC_SHADOW_X509_TRUST_get_by_id +#define X509_TRUST_get_count GRPC_SHADOW_X509_TRUST_get_count +#define X509_TRUST_get_flags GRPC_SHADOW_X509_TRUST_get_flags +#define X509_TRUST_get_trust GRPC_SHADOW_X509_TRUST_get_trust +#define X509_TRUST_set GRPC_SHADOW_X509_TRUST_set +#define X509_TRUST_set_default GRPC_SHADOW_X509_TRUST_set_default +#define X509_check_trust GRPC_SHADOW_X509_check_trust +#define X509_verify_cert_error_string GRPC_SHADOW_X509_verify_cert_error_string +#define X509_EXTENSION_create_by_NID GRPC_SHADOW_X509_EXTENSION_create_by_NID +#define X509_EXTENSION_create_by_OBJ GRPC_SHADOW_X509_EXTENSION_create_by_OBJ +#define X509_EXTENSION_get_critical GRPC_SHADOW_X509_EXTENSION_get_critical +#define X509_EXTENSION_get_data GRPC_SHADOW_X509_EXTENSION_get_data +#define X509_EXTENSION_get_object GRPC_SHADOW_X509_EXTENSION_get_object +#define X509_EXTENSION_set_critical GRPC_SHADOW_X509_EXTENSION_set_critical +#define X509_EXTENSION_set_data GRPC_SHADOW_X509_EXTENSION_set_data +#define X509_EXTENSION_set_object GRPC_SHADOW_X509_EXTENSION_set_object +#define X509v3_add_ext GRPC_SHADOW_X509v3_add_ext +#define X509v3_delete_ext GRPC_SHADOW_X509v3_delete_ext +#define X509v3_get_ext GRPC_SHADOW_X509v3_get_ext +#define X509v3_get_ext_by_NID GRPC_SHADOW_X509v3_get_ext_by_NID +#define X509v3_get_ext_by_OBJ GRPC_SHADOW_X509v3_get_ext_by_OBJ +#define X509v3_get_ext_by_critical GRPC_SHADOW_X509v3_get_ext_by_critical +#define X509v3_get_ext_count GRPC_SHADOW_X509v3_get_ext_count +#define X509_CRL_diff GRPC_SHADOW_X509_CRL_diff +#define X509_STORE_CTX_cleanup GRPC_SHADOW_X509_STORE_CTX_cleanup +#define X509_STORE_CTX_free GRPC_SHADOW_X509_STORE_CTX_free +#define X509_STORE_CTX_get0_current_crl GRPC_SHADOW_X509_STORE_CTX_get0_current_crl +#define X509_STORE_CTX_get0_current_issuer GRPC_SHADOW_X509_STORE_CTX_get0_current_issuer +#define X509_STORE_CTX_get0_param GRPC_SHADOW_X509_STORE_CTX_get0_param +#define X509_STORE_CTX_get0_parent_ctx GRPC_SHADOW_X509_STORE_CTX_get0_parent_ctx +#define X509_STORE_CTX_get0_policy_tree GRPC_SHADOW_X509_STORE_CTX_get0_policy_tree +#define X509_STORE_CTX_get0_untrusted GRPC_SHADOW_X509_STORE_CTX_get0_untrusted +#define X509_STORE_CTX_get1_chain GRPC_SHADOW_X509_STORE_CTX_get1_chain +#define X509_STORE_CTX_get_chain GRPC_SHADOW_X509_STORE_CTX_get_chain +#define X509_STORE_CTX_get_current_cert GRPC_SHADOW_X509_STORE_CTX_get_current_cert +#define X509_STORE_CTX_get_error GRPC_SHADOW_X509_STORE_CTX_get_error +#define X509_STORE_CTX_get_error_depth GRPC_SHADOW_X509_STORE_CTX_get_error_depth +#define X509_STORE_CTX_get_ex_data GRPC_SHADOW_X509_STORE_CTX_get_ex_data +#define X509_STORE_CTX_get_ex_new_index GRPC_SHADOW_X509_STORE_CTX_get_ex_new_index +#define X509_STORE_CTX_get_explicit_policy GRPC_SHADOW_X509_STORE_CTX_get_explicit_policy +#define X509_STORE_CTX_init GRPC_SHADOW_X509_STORE_CTX_init +#define X509_STORE_CTX_new GRPC_SHADOW_X509_STORE_CTX_new +#define X509_STORE_CTX_purpose_inherit GRPC_SHADOW_X509_STORE_CTX_purpose_inherit +#define X509_STORE_CTX_set0_crls GRPC_SHADOW_X509_STORE_CTX_set0_crls +#define X509_STORE_CTX_set0_param GRPC_SHADOW_X509_STORE_CTX_set0_param +#define X509_STORE_CTX_set_cert GRPC_SHADOW_X509_STORE_CTX_set_cert +#define X509_STORE_CTX_set_chain GRPC_SHADOW_X509_STORE_CTX_set_chain +#define X509_STORE_CTX_set_default GRPC_SHADOW_X509_STORE_CTX_set_default +#define X509_STORE_CTX_set_depth GRPC_SHADOW_X509_STORE_CTX_set_depth +#define X509_STORE_CTX_set_error GRPC_SHADOW_X509_STORE_CTX_set_error +#define X509_STORE_CTX_set_ex_data GRPC_SHADOW_X509_STORE_CTX_set_ex_data +#define X509_STORE_CTX_set_flags GRPC_SHADOW_X509_STORE_CTX_set_flags +#define X509_STORE_CTX_set_purpose GRPC_SHADOW_X509_STORE_CTX_set_purpose +#define X509_STORE_CTX_set_time GRPC_SHADOW_X509_STORE_CTX_set_time +#define X509_STORE_CTX_set_trust GRPC_SHADOW_X509_STORE_CTX_set_trust +#define X509_STORE_CTX_set_verify_cb GRPC_SHADOW_X509_STORE_CTX_set_verify_cb +#define X509_STORE_CTX_trusted_stack GRPC_SHADOW_X509_STORE_CTX_trusted_stack +#define X509_STORE_CTX_zero GRPC_SHADOW_X509_STORE_CTX_zero +#define X509_cmp_current_time GRPC_SHADOW_X509_cmp_current_time +#define X509_cmp_time GRPC_SHADOW_X509_cmp_time +#define X509_gmtime_adj GRPC_SHADOW_X509_gmtime_adj +#define X509_time_adj GRPC_SHADOW_X509_time_adj +#define X509_time_adj_ex GRPC_SHADOW_X509_time_adj_ex +#define X509_verify_cert GRPC_SHADOW_X509_verify_cert +#define X509_VERIFY_PARAM_add0_policy GRPC_SHADOW_X509_VERIFY_PARAM_add0_policy +#define X509_VERIFY_PARAM_add0_table GRPC_SHADOW_X509_VERIFY_PARAM_add0_table +#define X509_VERIFY_PARAM_add1_host GRPC_SHADOW_X509_VERIFY_PARAM_add1_host +#define X509_VERIFY_PARAM_clear_flags GRPC_SHADOW_X509_VERIFY_PARAM_clear_flags +#define X509_VERIFY_PARAM_free GRPC_SHADOW_X509_VERIFY_PARAM_free +#define X509_VERIFY_PARAM_get0 GRPC_SHADOW_X509_VERIFY_PARAM_get0 +#define X509_VERIFY_PARAM_get0_name GRPC_SHADOW_X509_VERIFY_PARAM_get0_name +#define X509_VERIFY_PARAM_get0_peername GRPC_SHADOW_X509_VERIFY_PARAM_get0_peername +#define X509_VERIFY_PARAM_get_count GRPC_SHADOW_X509_VERIFY_PARAM_get_count +#define X509_VERIFY_PARAM_get_depth GRPC_SHADOW_X509_VERIFY_PARAM_get_depth +#define X509_VERIFY_PARAM_get_flags GRPC_SHADOW_X509_VERIFY_PARAM_get_flags +#define X509_VERIFY_PARAM_inherit GRPC_SHADOW_X509_VERIFY_PARAM_inherit +#define X509_VERIFY_PARAM_lookup GRPC_SHADOW_X509_VERIFY_PARAM_lookup +#define X509_VERIFY_PARAM_new GRPC_SHADOW_X509_VERIFY_PARAM_new +#define X509_VERIFY_PARAM_set1 GRPC_SHADOW_X509_VERIFY_PARAM_set1 +#define X509_VERIFY_PARAM_set1_email GRPC_SHADOW_X509_VERIFY_PARAM_set1_email +#define X509_VERIFY_PARAM_set1_host GRPC_SHADOW_X509_VERIFY_PARAM_set1_host +#define X509_VERIFY_PARAM_set1_ip GRPC_SHADOW_X509_VERIFY_PARAM_set1_ip +#define X509_VERIFY_PARAM_set1_ip_asc GRPC_SHADOW_X509_VERIFY_PARAM_set1_ip_asc +#define X509_VERIFY_PARAM_set1_name GRPC_SHADOW_X509_VERIFY_PARAM_set1_name +#define X509_VERIFY_PARAM_set1_policies GRPC_SHADOW_X509_VERIFY_PARAM_set1_policies +#define X509_VERIFY_PARAM_set_depth GRPC_SHADOW_X509_VERIFY_PARAM_set_depth +#define X509_VERIFY_PARAM_set_flags GRPC_SHADOW_X509_VERIFY_PARAM_set_flags +#define X509_VERIFY_PARAM_set_hostflags GRPC_SHADOW_X509_VERIFY_PARAM_set_hostflags +#define X509_VERIFY_PARAM_set_purpose GRPC_SHADOW_X509_VERIFY_PARAM_set_purpose +#define X509_VERIFY_PARAM_set_time GRPC_SHADOW_X509_VERIFY_PARAM_set_time +#define X509_VERIFY_PARAM_set_trust GRPC_SHADOW_X509_VERIFY_PARAM_set_trust +#define X509_VERIFY_PARAM_table_cleanup GRPC_SHADOW_X509_VERIFY_PARAM_table_cleanup +#define X509_CRL_set_issuer_name GRPC_SHADOW_X509_CRL_set_issuer_name +#define X509_CRL_set_lastUpdate GRPC_SHADOW_X509_CRL_set_lastUpdate +#define X509_CRL_set_nextUpdate GRPC_SHADOW_X509_CRL_set_nextUpdate +#define X509_CRL_set_version GRPC_SHADOW_X509_CRL_set_version +#define X509_CRL_sort GRPC_SHADOW_X509_CRL_sort +#define X509_CRL_up_ref GRPC_SHADOW_X509_CRL_up_ref +#define X509_REVOKED_set_revocationDate GRPC_SHADOW_X509_REVOKED_set_revocationDate +#define X509_REVOKED_set_serialNumber GRPC_SHADOW_X509_REVOKED_set_serialNumber +#define X509_NAME_ENTRY_create_by_NID GRPC_SHADOW_X509_NAME_ENTRY_create_by_NID +#define X509_NAME_ENTRY_create_by_OBJ GRPC_SHADOW_X509_NAME_ENTRY_create_by_OBJ +#define X509_NAME_ENTRY_create_by_txt GRPC_SHADOW_X509_NAME_ENTRY_create_by_txt +#define X509_NAME_ENTRY_get_data GRPC_SHADOW_X509_NAME_ENTRY_get_data +#define X509_NAME_ENTRY_get_object GRPC_SHADOW_X509_NAME_ENTRY_get_object +#define X509_NAME_ENTRY_set_data GRPC_SHADOW_X509_NAME_ENTRY_set_data +#define X509_NAME_ENTRY_set_object GRPC_SHADOW_X509_NAME_ENTRY_set_object +#define X509_NAME_add_entry GRPC_SHADOW_X509_NAME_add_entry +#define X509_NAME_add_entry_by_NID GRPC_SHADOW_X509_NAME_add_entry_by_NID +#define X509_NAME_add_entry_by_OBJ GRPC_SHADOW_X509_NAME_add_entry_by_OBJ +#define X509_NAME_add_entry_by_txt GRPC_SHADOW_X509_NAME_add_entry_by_txt +#define X509_NAME_delete_entry GRPC_SHADOW_X509_NAME_delete_entry +#define X509_NAME_entry_count GRPC_SHADOW_X509_NAME_entry_count +#define X509_NAME_get_entry GRPC_SHADOW_X509_NAME_get_entry +#define X509_NAME_get_index_by_NID GRPC_SHADOW_X509_NAME_get_index_by_NID +#define X509_NAME_get_index_by_OBJ GRPC_SHADOW_X509_NAME_get_index_by_OBJ +#define X509_NAME_get_text_by_NID GRPC_SHADOW_X509_NAME_get_text_by_NID +#define X509_NAME_get_text_by_OBJ GRPC_SHADOW_X509_NAME_get_text_by_OBJ +#define X509_REQ_set_pubkey GRPC_SHADOW_X509_REQ_set_pubkey +#define X509_REQ_set_subject_name GRPC_SHADOW_X509_REQ_set_subject_name +#define X509_REQ_set_version GRPC_SHADOW_X509_REQ_set_version +#define NETSCAPE_SPKI_b64_decode GRPC_SHADOW_NETSCAPE_SPKI_b64_decode +#define NETSCAPE_SPKI_b64_encode GRPC_SHADOW_NETSCAPE_SPKI_b64_encode +#define NETSCAPE_SPKI_get_pubkey GRPC_SHADOW_NETSCAPE_SPKI_get_pubkey +#define NETSCAPE_SPKI_set_pubkey GRPC_SHADOW_NETSCAPE_SPKI_set_pubkey +#define X509_ALGORS_it GRPC_SHADOW_X509_ALGORS_it +#define X509_ALGOR_cmp GRPC_SHADOW_X509_ALGOR_cmp +#define X509_ALGOR_dup GRPC_SHADOW_X509_ALGOR_dup +#define X509_ALGOR_free GRPC_SHADOW_X509_ALGOR_free +#define X509_ALGOR_get0 GRPC_SHADOW_X509_ALGOR_get0 +#define X509_ALGOR_it GRPC_SHADOW_X509_ALGOR_it +#define X509_ALGOR_new GRPC_SHADOW_X509_ALGOR_new +#define X509_ALGOR_set0 GRPC_SHADOW_X509_ALGOR_set0 +#define X509_ALGOR_set_md GRPC_SHADOW_X509_ALGOR_set_md +#define d2i_X509_ALGOR GRPC_SHADOW_d2i_X509_ALGOR +#define d2i_X509_ALGORS GRPC_SHADOW_d2i_X509_ALGORS +#define i2d_X509_ALGOR GRPC_SHADOW_i2d_X509_ALGOR +#define i2d_X509_ALGORS GRPC_SHADOW_i2d_X509_ALGORS +#define NETSCAPE_SPKI_sign GRPC_SHADOW_NETSCAPE_SPKI_sign +#define NETSCAPE_SPKI_verify GRPC_SHADOW_NETSCAPE_SPKI_verify +#define X509_CRL_digest GRPC_SHADOW_X509_CRL_digest +#define X509_CRL_sign GRPC_SHADOW_X509_CRL_sign +#define X509_CRL_sign_ctx GRPC_SHADOW_X509_CRL_sign_ctx +#define X509_NAME_digest GRPC_SHADOW_X509_NAME_digest +#define X509_REQ_digest GRPC_SHADOW_X509_REQ_digest +#define X509_REQ_sign GRPC_SHADOW_X509_REQ_sign +#define X509_REQ_sign_ctx GRPC_SHADOW_X509_REQ_sign_ctx +#define X509_REQ_verify GRPC_SHADOW_X509_REQ_verify +#define X509_digest GRPC_SHADOW_X509_digest +#define X509_pubkey_digest GRPC_SHADOW_X509_pubkey_digest +#define X509_sign GRPC_SHADOW_X509_sign +#define X509_sign_ctx GRPC_SHADOW_X509_sign_ctx +#define X509_verify GRPC_SHADOW_X509_verify +#define d2i_DSAPrivateKey_bio GRPC_SHADOW_d2i_DSAPrivateKey_bio +#define d2i_DSAPrivateKey_fp GRPC_SHADOW_d2i_DSAPrivateKey_fp +#define d2i_DSA_PUBKEY_bio GRPC_SHADOW_d2i_DSA_PUBKEY_bio +#define d2i_DSA_PUBKEY_fp GRPC_SHADOW_d2i_DSA_PUBKEY_fp +#define d2i_ECPrivateKey_bio GRPC_SHADOW_d2i_ECPrivateKey_bio +#define d2i_ECPrivateKey_fp GRPC_SHADOW_d2i_ECPrivateKey_fp +#define d2i_EC_PUBKEY_bio GRPC_SHADOW_d2i_EC_PUBKEY_bio +#define d2i_EC_PUBKEY_fp GRPC_SHADOW_d2i_EC_PUBKEY_fp +#define d2i_PKCS8_PRIV_KEY_INFO_bio GRPC_SHADOW_d2i_PKCS8_PRIV_KEY_INFO_bio +#define d2i_PKCS8_PRIV_KEY_INFO_fp GRPC_SHADOW_d2i_PKCS8_PRIV_KEY_INFO_fp +#define d2i_PKCS8_bio GRPC_SHADOW_d2i_PKCS8_bio +#define d2i_PKCS8_fp GRPC_SHADOW_d2i_PKCS8_fp +#define d2i_PUBKEY_bio GRPC_SHADOW_d2i_PUBKEY_bio +#define d2i_PUBKEY_fp GRPC_SHADOW_d2i_PUBKEY_fp +#define d2i_PrivateKey_bio GRPC_SHADOW_d2i_PrivateKey_bio +#define d2i_PrivateKey_fp GRPC_SHADOW_d2i_PrivateKey_fp +#define d2i_RSAPrivateKey_bio GRPC_SHADOW_d2i_RSAPrivateKey_bio +#define d2i_RSAPrivateKey_fp GRPC_SHADOW_d2i_RSAPrivateKey_fp +#define d2i_RSAPublicKey_bio GRPC_SHADOW_d2i_RSAPublicKey_bio +#define d2i_RSAPublicKey_fp GRPC_SHADOW_d2i_RSAPublicKey_fp +#define d2i_RSA_PUBKEY_bio GRPC_SHADOW_d2i_RSA_PUBKEY_bio +#define d2i_RSA_PUBKEY_fp GRPC_SHADOW_d2i_RSA_PUBKEY_fp +#define d2i_X509_CRL_bio GRPC_SHADOW_d2i_X509_CRL_bio +#define d2i_X509_CRL_fp GRPC_SHADOW_d2i_X509_CRL_fp +#define d2i_X509_REQ_bio GRPC_SHADOW_d2i_X509_REQ_bio +#define d2i_X509_REQ_fp GRPC_SHADOW_d2i_X509_REQ_fp +#define d2i_X509_bio GRPC_SHADOW_d2i_X509_bio +#define d2i_X509_fp GRPC_SHADOW_d2i_X509_fp +#define i2d_DSAPrivateKey_bio GRPC_SHADOW_i2d_DSAPrivateKey_bio +#define i2d_DSAPrivateKey_fp GRPC_SHADOW_i2d_DSAPrivateKey_fp +#define i2d_DSA_PUBKEY_bio GRPC_SHADOW_i2d_DSA_PUBKEY_bio +#define i2d_DSA_PUBKEY_fp GRPC_SHADOW_i2d_DSA_PUBKEY_fp +#define i2d_ECPrivateKey_bio GRPC_SHADOW_i2d_ECPrivateKey_bio +#define i2d_ECPrivateKey_fp GRPC_SHADOW_i2d_ECPrivateKey_fp +#define i2d_EC_PUBKEY_bio GRPC_SHADOW_i2d_EC_PUBKEY_bio +#define i2d_EC_PUBKEY_fp GRPC_SHADOW_i2d_EC_PUBKEY_fp +#define i2d_PKCS8PrivateKeyInfo_bio GRPC_SHADOW_i2d_PKCS8PrivateKeyInfo_bio +#define i2d_PKCS8PrivateKeyInfo_fp GRPC_SHADOW_i2d_PKCS8PrivateKeyInfo_fp +#define i2d_PKCS8_PRIV_KEY_INFO_bio GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO_bio +#define i2d_PKCS8_PRIV_KEY_INFO_fp GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO_fp +#define i2d_PKCS8_bio GRPC_SHADOW_i2d_PKCS8_bio +#define i2d_PKCS8_fp GRPC_SHADOW_i2d_PKCS8_fp +#define i2d_PUBKEY_bio GRPC_SHADOW_i2d_PUBKEY_bio +#define i2d_PUBKEY_fp GRPC_SHADOW_i2d_PUBKEY_fp +#define i2d_PrivateKey_bio GRPC_SHADOW_i2d_PrivateKey_bio +#define i2d_PrivateKey_fp GRPC_SHADOW_i2d_PrivateKey_fp +#define i2d_RSAPrivateKey_bio GRPC_SHADOW_i2d_RSAPrivateKey_bio +#define i2d_RSAPrivateKey_fp GRPC_SHADOW_i2d_RSAPrivateKey_fp +#define i2d_RSAPublicKey_bio GRPC_SHADOW_i2d_RSAPublicKey_bio +#define i2d_RSAPublicKey_fp GRPC_SHADOW_i2d_RSAPublicKey_fp +#define i2d_RSA_PUBKEY_bio GRPC_SHADOW_i2d_RSA_PUBKEY_bio +#define i2d_RSA_PUBKEY_fp GRPC_SHADOW_i2d_RSA_PUBKEY_fp +#define i2d_X509_CRL_bio GRPC_SHADOW_i2d_X509_CRL_bio +#define i2d_X509_CRL_fp GRPC_SHADOW_i2d_X509_CRL_fp +#define i2d_X509_REQ_bio GRPC_SHADOW_i2d_X509_REQ_bio +#define i2d_X509_REQ_fp GRPC_SHADOW_i2d_X509_REQ_fp +#define i2d_X509_bio GRPC_SHADOW_i2d_X509_bio +#define i2d_X509_fp GRPC_SHADOW_i2d_X509_fp +#define X509_ATTRIBUTE_SET_it GRPC_SHADOW_X509_ATTRIBUTE_SET_it +#define X509_ATTRIBUTE_create GRPC_SHADOW_X509_ATTRIBUTE_create +#define X509_ATTRIBUTE_dup GRPC_SHADOW_X509_ATTRIBUTE_dup +#define X509_ATTRIBUTE_free GRPC_SHADOW_X509_ATTRIBUTE_free +#define X509_ATTRIBUTE_it GRPC_SHADOW_X509_ATTRIBUTE_it +#define X509_ATTRIBUTE_new GRPC_SHADOW_X509_ATTRIBUTE_new +#define d2i_X509_ATTRIBUTE GRPC_SHADOW_d2i_X509_ATTRIBUTE +#define i2d_X509_ATTRIBUTE GRPC_SHADOW_i2d_X509_ATTRIBUTE +#define X509_CRL_INFO_free GRPC_SHADOW_X509_CRL_INFO_free +#define X509_CRL_INFO_it GRPC_SHADOW_X509_CRL_INFO_it +#define X509_CRL_INFO_new GRPC_SHADOW_X509_CRL_INFO_new +#define X509_CRL_METHOD_free GRPC_SHADOW_X509_CRL_METHOD_free +#define X509_CRL_METHOD_new GRPC_SHADOW_X509_CRL_METHOD_new +#define X509_CRL_add0_revoked GRPC_SHADOW_X509_CRL_add0_revoked +#define X509_CRL_dup GRPC_SHADOW_X509_CRL_dup +#define X509_CRL_free GRPC_SHADOW_X509_CRL_free +#define X509_CRL_get0_by_cert GRPC_SHADOW_X509_CRL_get0_by_cert +#define X509_CRL_get0_by_serial GRPC_SHADOW_X509_CRL_get0_by_serial +#define X509_CRL_get_meth_data GRPC_SHADOW_X509_CRL_get_meth_data +#define X509_CRL_it GRPC_SHADOW_X509_CRL_it +#define X509_CRL_new GRPC_SHADOW_X509_CRL_new +#define X509_CRL_set_default_method GRPC_SHADOW_X509_CRL_set_default_method +#define X509_CRL_set_meth_data GRPC_SHADOW_X509_CRL_set_meth_data +#define X509_CRL_verify GRPC_SHADOW_X509_CRL_verify +#define X509_REVOKED_dup GRPC_SHADOW_X509_REVOKED_dup +#define X509_REVOKED_free GRPC_SHADOW_X509_REVOKED_free +#define X509_REVOKED_it GRPC_SHADOW_X509_REVOKED_it +#define X509_REVOKED_new GRPC_SHADOW_X509_REVOKED_new +#define d2i_X509_CRL GRPC_SHADOW_d2i_X509_CRL +#define d2i_X509_CRL_INFO GRPC_SHADOW_d2i_X509_CRL_INFO +#define d2i_X509_REVOKED GRPC_SHADOW_d2i_X509_REVOKED +#define i2d_X509_CRL GRPC_SHADOW_i2d_X509_CRL +#define i2d_X509_CRL_INFO GRPC_SHADOW_i2d_X509_CRL_INFO +#define i2d_X509_REVOKED GRPC_SHADOW_i2d_X509_REVOKED +#define X509_EXTENSIONS_it GRPC_SHADOW_X509_EXTENSIONS_it +#define X509_EXTENSION_dup GRPC_SHADOW_X509_EXTENSION_dup +#define X509_EXTENSION_free GRPC_SHADOW_X509_EXTENSION_free +#define X509_EXTENSION_it GRPC_SHADOW_X509_EXTENSION_it +#define X509_EXTENSION_new GRPC_SHADOW_X509_EXTENSION_new +#define d2i_X509_EXTENSION GRPC_SHADOW_d2i_X509_EXTENSION +#define d2i_X509_EXTENSIONS GRPC_SHADOW_d2i_X509_EXTENSIONS +#define i2d_X509_EXTENSION GRPC_SHADOW_i2d_X509_EXTENSION +#define i2d_X509_EXTENSIONS GRPC_SHADOW_i2d_X509_EXTENSIONS +#define X509_INFO_free GRPC_SHADOW_X509_INFO_free +#define X509_INFO_new GRPC_SHADOW_X509_INFO_new +#define X509_NAME_ENTRIES_it GRPC_SHADOW_X509_NAME_ENTRIES_it +#define X509_NAME_ENTRY_dup GRPC_SHADOW_X509_NAME_ENTRY_dup +#define X509_NAME_ENTRY_free GRPC_SHADOW_X509_NAME_ENTRY_free +#define X509_NAME_ENTRY_it GRPC_SHADOW_X509_NAME_ENTRY_it +#define X509_NAME_ENTRY_new GRPC_SHADOW_X509_NAME_ENTRY_new +#define X509_NAME_ENTRY_set GRPC_SHADOW_X509_NAME_ENTRY_set +#define X509_NAME_INTERNAL_it GRPC_SHADOW_X509_NAME_INTERNAL_it +#define X509_NAME_dup GRPC_SHADOW_X509_NAME_dup +#define X509_NAME_free GRPC_SHADOW_X509_NAME_free +#define X509_NAME_get0_der GRPC_SHADOW_X509_NAME_get0_der +#define X509_NAME_it GRPC_SHADOW_X509_NAME_it +#define X509_NAME_new GRPC_SHADOW_X509_NAME_new +#define X509_NAME_set GRPC_SHADOW_X509_NAME_set +#define d2i_X509_NAME GRPC_SHADOW_d2i_X509_NAME +#define d2i_X509_NAME_ENTRY GRPC_SHADOW_d2i_X509_NAME_ENTRY +#define i2d_X509_NAME GRPC_SHADOW_i2d_X509_NAME +#define i2d_X509_NAME_ENTRY GRPC_SHADOW_i2d_X509_NAME_ENTRY +#define X509_PKEY_free GRPC_SHADOW_X509_PKEY_free +#define X509_PKEY_new GRPC_SHADOW_X509_PKEY_new +#define X509_PUBKEY_free GRPC_SHADOW_X509_PUBKEY_free +#define X509_PUBKEY_get GRPC_SHADOW_X509_PUBKEY_get +#define X509_PUBKEY_get0_param GRPC_SHADOW_X509_PUBKEY_get0_param +#define X509_PUBKEY_it GRPC_SHADOW_X509_PUBKEY_it +#define X509_PUBKEY_new GRPC_SHADOW_X509_PUBKEY_new +#define X509_PUBKEY_set GRPC_SHADOW_X509_PUBKEY_set +#define X509_PUBKEY_set0_param GRPC_SHADOW_X509_PUBKEY_set0_param +#define d2i_DSA_PUBKEY GRPC_SHADOW_d2i_DSA_PUBKEY +#define d2i_EC_PUBKEY GRPC_SHADOW_d2i_EC_PUBKEY +#define d2i_PUBKEY GRPC_SHADOW_d2i_PUBKEY +#define d2i_RSA_PUBKEY GRPC_SHADOW_d2i_RSA_PUBKEY +#define d2i_X509_PUBKEY GRPC_SHADOW_d2i_X509_PUBKEY +#define i2d_DSA_PUBKEY GRPC_SHADOW_i2d_DSA_PUBKEY +#define i2d_EC_PUBKEY GRPC_SHADOW_i2d_EC_PUBKEY +#define i2d_PUBKEY GRPC_SHADOW_i2d_PUBKEY +#define i2d_RSA_PUBKEY GRPC_SHADOW_i2d_RSA_PUBKEY +#define i2d_X509_PUBKEY GRPC_SHADOW_i2d_X509_PUBKEY +#define X509_REQ_INFO_free GRPC_SHADOW_X509_REQ_INFO_free +#define X509_REQ_INFO_it GRPC_SHADOW_X509_REQ_INFO_it +#define X509_REQ_INFO_new GRPC_SHADOW_X509_REQ_INFO_new +#define X509_REQ_dup GRPC_SHADOW_X509_REQ_dup +#define X509_REQ_free GRPC_SHADOW_X509_REQ_free +#define X509_REQ_it GRPC_SHADOW_X509_REQ_it +#define X509_REQ_new GRPC_SHADOW_X509_REQ_new +#define d2i_X509_REQ GRPC_SHADOW_d2i_X509_REQ +#define d2i_X509_REQ_INFO GRPC_SHADOW_d2i_X509_REQ_INFO +#define i2d_X509_REQ GRPC_SHADOW_i2d_X509_REQ +#define i2d_X509_REQ_INFO GRPC_SHADOW_i2d_X509_REQ_INFO +#define X509_SIG_free GRPC_SHADOW_X509_SIG_free +#define X509_SIG_it GRPC_SHADOW_X509_SIG_it +#define X509_SIG_new GRPC_SHADOW_X509_SIG_new +#define d2i_X509_SIG GRPC_SHADOW_d2i_X509_SIG +#define i2d_X509_SIG GRPC_SHADOW_i2d_X509_SIG +#define NETSCAPE_SPKAC_free GRPC_SHADOW_NETSCAPE_SPKAC_free +#define NETSCAPE_SPKAC_it GRPC_SHADOW_NETSCAPE_SPKAC_it +#define NETSCAPE_SPKAC_new GRPC_SHADOW_NETSCAPE_SPKAC_new +#define NETSCAPE_SPKI_free GRPC_SHADOW_NETSCAPE_SPKI_free +#define NETSCAPE_SPKI_it GRPC_SHADOW_NETSCAPE_SPKI_it +#define NETSCAPE_SPKI_new GRPC_SHADOW_NETSCAPE_SPKI_new +#define d2i_NETSCAPE_SPKAC GRPC_SHADOW_d2i_NETSCAPE_SPKAC +#define d2i_NETSCAPE_SPKI GRPC_SHADOW_d2i_NETSCAPE_SPKI +#define i2d_NETSCAPE_SPKAC GRPC_SHADOW_i2d_NETSCAPE_SPKAC +#define i2d_NETSCAPE_SPKI GRPC_SHADOW_i2d_NETSCAPE_SPKI +#define X509_VAL_free GRPC_SHADOW_X509_VAL_free +#define X509_VAL_it GRPC_SHADOW_X509_VAL_it +#define X509_VAL_new GRPC_SHADOW_X509_VAL_new +#define d2i_X509_VAL GRPC_SHADOW_d2i_X509_VAL +#define i2d_X509_VAL GRPC_SHADOW_i2d_X509_VAL +#define X509_CINF_free GRPC_SHADOW_X509_CINF_free +#define X509_CINF_it GRPC_SHADOW_X509_CINF_it +#define X509_CINF_new GRPC_SHADOW_X509_CINF_new +#define X509_dup GRPC_SHADOW_X509_dup +#define X509_free GRPC_SHADOW_X509_free +#define X509_get0_signature GRPC_SHADOW_X509_get0_signature +#define X509_get_ex_data GRPC_SHADOW_X509_get_ex_data +#define X509_get_ex_new_index GRPC_SHADOW_X509_get_ex_new_index +#define X509_get_signature_nid GRPC_SHADOW_X509_get_signature_nid +#define X509_it GRPC_SHADOW_X509_it +#define X509_new GRPC_SHADOW_X509_new +#define X509_parse_from_buffer GRPC_SHADOW_X509_parse_from_buffer +#define X509_set_ex_data GRPC_SHADOW_X509_set_ex_data +#define X509_up_ref GRPC_SHADOW_X509_up_ref +#define d2i_X509 GRPC_SHADOW_d2i_X509 +#define d2i_X509_AUX GRPC_SHADOW_d2i_X509_AUX +#define d2i_X509_CINF GRPC_SHADOW_d2i_X509_CINF +#define i2d_X509 GRPC_SHADOW_i2d_X509 +#define i2d_X509_AUX GRPC_SHADOW_i2d_X509_AUX +#define i2d_X509_CINF GRPC_SHADOW_i2d_X509_CINF +#define X509_CERT_AUX_free GRPC_SHADOW_X509_CERT_AUX_free +#define X509_CERT_AUX_it GRPC_SHADOW_X509_CERT_AUX_it +#define X509_CERT_AUX_new GRPC_SHADOW_X509_CERT_AUX_new +#define X509_add1_reject_object GRPC_SHADOW_X509_add1_reject_object +#define X509_add1_trust_object GRPC_SHADOW_X509_add1_trust_object +#define X509_alias_get0 GRPC_SHADOW_X509_alias_get0 +#define X509_alias_set1 GRPC_SHADOW_X509_alias_set1 +#define X509_keyid_get0 GRPC_SHADOW_X509_keyid_get0 +#define X509_keyid_set1 GRPC_SHADOW_X509_keyid_set1 +#define X509_reject_clear GRPC_SHADOW_X509_reject_clear +#define X509_trust_clear GRPC_SHADOW_X509_trust_clear +#define d2i_X509_CERT_AUX GRPC_SHADOW_d2i_X509_CERT_AUX +#define i2d_X509_CERT_AUX GRPC_SHADOW_i2d_X509_CERT_AUX +#define policy_cache_find_data GRPC_SHADOW_policy_cache_find_data +#define policy_cache_free GRPC_SHADOW_policy_cache_free +#define policy_cache_set GRPC_SHADOW_policy_cache_set +#define policy_data_free GRPC_SHADOW_policy_data_free +#define policy_data_new GRPC_SHADOW_policy_data_new +#define X509_policy_level_get0_node GRPC_SHADOW_X509_policy_level_get0_node +#define X509_policy_level_node_count GRPC_SHADOW_X509_policy_level_node_count +#define X509_policy_node_get0_parent GRPC_SHADOW_X509_policy_node_get0_parent +#define X509_policy_node_get0_policy GRPC_SHADOW_X509_policy_node_get0_policy +#define X509_policy_node_get0_qualifiers GRPC_SHADOW_X509_policy_node_get0_qualifiers +#define X509_policy_tree_get0_level GRPC_SHADOW_X509_policy_tree_get0_level +#define X509_policy_tree_get0_policies GRPC_SHADOW_X509_policy_tree_get0_policies +#define X509_policy_tree_get0_user_policies GRPC_SHADOW_X509_policy_tree_get0_user_policies +#define X509_policy_tree_level_count GRPC_SHADOW_X509_policy_tree_level_count +#define policy_cache_set_mapping GRPC_SHADOW_policy_cache_set_mapping +#define level_add_node GRPC_SHADOW_level_add_node +#define level_find_node GRPC_SHADOW_level_find_node +#define policy_node_cmp_new GRPC_SHADOW_policy_node_cmp_new +#define policy_node_free GRPC_SHADOW_policy_node_free +#define policy_node_match GRPC_SHADOW_policy_node_match +#define tree_find_sk GRPC_SHADOW_tree_find_sk +#define X509_policy_check GRPC_SHADOW_X509_policy_check +#define X509_policy_tree_free GRPC_SHADOW_X509_policy_tree_free +#define v3_akey_id GRPC_SHADOW_v3_akey_id +#define AUTHORITY_KEYID_free GRPC_SHADOW_AUTHORITY_KEYID_free +#define AUTHORITY_KEYID_it GRPC_SHADOW_AUTHORITY_KEYID_it +#define AUTHORITY_KEYID_new GRPC_SHADOW_AUTHORITY_KEYID_new +#define d2i_AUTHORITY_KEYID GRPC_SHADOW_d2i_AUTHORITY_KEYID +#define i2d_AUTHORITY_KEYID GRPC_SHADOW_i2d_AUTHORITY_KEYID +#define GENERAL_NAME_print GRPC_SHADOW_GENERAL_NAME_print +#define a2i_GENERAL_NAME GRPC_SHADOW_a2i_GENERAL_NAME +#define i2v_GENERAL_NAME GRPC_SHADOW_i2v_GENERAL_NAME +#define i2v_GENERAL_NAMES GRPC_SHADOW_i2v_GENERAL_NAMES +#define v2i_GENERAL_NAME GRPC_SHADOW_v2i_GENERAL_NAME +#define v2i_GENERAL_NAMES GRPC_SHADOW_v2i_GENERAL_NAMES +#define v2i_GENERAL_NAME_ex GRPC_SHADOW_v2i_GENERAL_NAME_ex +#define v3_alt GRPC_SHADOW_v3_alt +#define BASIC_CONSTRAINTS_free GRPC_SHADOW_BASIC_CONSTRAINTS_free +#define BASIC_CONSTRAINTS_it GRPC_SHADOW_BASIC_CONSTRAINTS_it +#define BASIC_CONSTRAINTS_new GRPC_SHADOW_BASIC_CONSTRAINTS_new +#define d2i_BASIC_CONSTRAINTS GRPC_SHADOW_d2i_BASIC_CONSTRAINTS +#define i2d_BASIC_CONSTRAINTS GRPC_SHADOW_i2d_BASIC_CONSTRAINTS +#define v3_bcons GRPC_SHADOW_v3_bcons +#define i2v_ASN1_BIT_STRING GRPC_SHADOW_i2v_ASN1_BIT_STRING +#define v2i_ASN1_BIT_STRING GRPC_SHADOW_v2i_ASN1_BIT_STRING +#define v3_key_usage GRPC_SHADOW_v3_key_usage +#define v3_nscert GRPC_SHADOW_v3_nscert +#define X509V3_EXT_CRL_add_nconf GRPC_SHADOW_X509V3_EXT_CRL_add_nconf +#define X509V3_EXT_REQ_add_nconf GRPC_SHADOW_X509V3_EXT_REQ_add_nconf +#define X509V3_EXT_add_nconf GRPC_SHADOW_X509V3_EXT_add_nconf +#define X509V3_EXT_add_nconf_sk GRPC_SHADOW_X509V3_EXT_add_nconf_sk +#define X509V3_EXT_i2d GRPC_SHADOW_X509V3_EXT_i2d +#define X509V3_EXT_nconf GRPC_SHADOW_X509V3_EXT_nconf +#define X509V3_EXT_nconf_nid GRPC_SHADOW_X509V3_EXT_nconf_nid +#define X509V3_get_section GRPC_SHADOW_X509V3_get_section +#define X509V3_get_string GRPC_SHADOW_X509V3_get_string +#define X509V3_section_free GRPC_SHADOW_X509V3_section_free +#define X509V3_set_ctx GRPC_SHADOW_X509V3_set_ctx +#define X509V3_set_nconf GRPC_SHADOW_X509V3_set_nconf +#define X509V3_string_free GRPC_SHADOW_X509V3_string_free +#define CERTIFICATEPOLICIES_free GRPC_SHADOW_CERTIFICATEPOLICIES_free +#define CERTIFICATEPOLICIES_it GRPC_SHADOW_CERTIFICATEPOLICIES_it +#define CERTIFICATEPOLICIES_new GRPC_SHADOW_CERTIFICATEPOLICIES_new +#define NOTICEREF_free GRPC_SHADOW_NOTICEREF_free +#define NOTICEREF_it GRPC_SHADOW_NOTICEREF_it +#define NOTICEREF_new GRPC_SHADOW_NOTICEREF_new +#define POLICYINFO_free GRPC_SHADOW_POLICYINFO_free +#define POLICYINFO_it GRPC_SHADOW_POLICYINFO_it +#define POLICYINFO_new GRPC_SHADOW_POLICYINFO_new +#define POLICYQUALINFO_free GRPC_SHADOW_POLICYQUALINFO_free +#define POLICYQUALINFO_it GRPC_SHADOW_POLICYQUALINFO_it +#define POLICYQUALINFO_new GRPC_SHADOW_POLICYQUALINFO_new +#define USERNOTICE_free GRPC_SHADOW_USERNOTICE_free +#define USERNOTICE_it GRPC_SHADOW_USERNOTICE_it +#define USERNOTICE_new GRPC_SHADOW_USERNOTICE_new +#define X509_POLICY_NODE_print GRPC_SHADOW_X509_POLICY_NODE_print +#define d2i_CERTIFICATEPOLICIES GRPC_SHADOW_d2i_CERTIFICATEPOLICIES +#define d2i_NOTICEREF GRPC_SHADOW_d2i_NOTICEREF +#define d2i_POLICYINFO GRPC_SHADOW_d2i_POLICYINFO +#define d2i_POLICYQUALINFO GRPC_SHADOW_d2i_POLICYQUALINFO +#define d2i_USERNOTICE GRPC_SHADOW_d2i_USERNOTICE +#define i2d_CERTIFICATEPOLICIES GRPC_SHADOW_i2d_CERTIFICATEPOLICIES +#define i2d_NOTICEREF GRPC_SHADOW_i2d_NOTICEREF +#define i2d_POLICYINFO GRPC_SHADOW_i2d_POLICYINFO +#define i2d_POLICYQUALINFO GRPC_SHADOW_i2d_POLICYQUALINFO +#define i2d_USERNOTICE GRPC_SHADOW_i2d_USERNOTICE +#define v3_cpols GRPC_SHADOW_v3_cpols +#define CRL_DIST_POINTS_free GRPC_SHADOW_CRL_DIST_POINTS_free +#define CRL_DIST_POINTS_it GRPC_SHADOW_CRL_DIST_POINTS_it +#define CRL_DIST_POINTS_new GRPC_SHADOW_CRL_DIST_POINTS_new +#define DIST_POINT_NAME_free GRPC_SHADOW_DIST_POINT_NAME_free +#define DIST_POINT_NAME_it GRPC_SHADOW_DIST_POINT_NAME_it +#define DIST_POINT_NAME_new GRPC_SHADOW_DIST_POINT_NAME_new +#define DIST_POINT_free GRPC_SHADOW_DIST_POINT_free +#define DIST_POINT_it GRPC_SHADOW_DIST_POINT_it +#define DIST_POINT_new GRPC_SHADOW_DIST_POINT_new +#define DIST_POINT_set_dpname GRPC_SHADOW_DIST_POINT_set_dpname +#define ISSUING_DIST_POINT_free GRPC_SHADOW_ISSUING_DIST_POINT_free +#define ISSUING_DIST_POINT_it GRPC_SHADOW_ISSUING_DIST_POINT_it +#define ISSUING_DIST_POINT_new GRPC_SHADOW_ISSUING_DIST_POINT_new +#define d2i_CRL_DIST_POINTS GRPC_SHADOW_d2i_CRL_DIST_POINTS +#define d2i_DIST_POINT GRPC_SHADOW_d2i_DIST_POINT +#define d2i_DIST_POINT_NAME GRPC_SHADOW_d2i_DIST_POINT_NAME +#define d2i_ISSUING_DIST_POINT GRPC_SHADOW_d2i_ISSUING_DIST_POINT +#define i2d_CRL_DIST_POINTS GRPC_SHADOW_i2d_CRL_DIST_POINTS +#define i2d_DIST_POINT GRPC_SHADOW_i2d_DIST_POINT +#define i2d_DIST_POINT_NAME GRPC_SHADOW_i2d_DIST_POINT_NAME +#define i2d_ISSUING_DIST_POINT GRPC_SHADOW_i2d_ISSUING_DIST_POINT +#define v3_crld GRPC_SHADOW_v3_crld +#define v3_freshest_crl GRPC_SHADOW_v3_freshest_crl +#define v3_idp GRPC_SHADOW_v3_idp +#define i2s_ASN1_ENUMERATED_TABLE GRPC_SHADOW_i2s_ASN1_ENUMERATED_TABLE +#define v3_crl_reason GRPC_SHADOW_v3_crl_reason +#define EXTENDED_KEY_USAGE_free GRPC_SHADOW_EXTENDED_KEY_USAGE_free +#define EXTENDED_KEY_USAGE_it GRPC_SHADOW_EXTENDED_KEY_USAGE_it +#define EXTENDED_KEY_USAGE_new GRPC_SHADOW_EXTENDED_KEY_USAGE_new +#define d2i_EXTENDED_KEY_USAGE GRPC_SHADOW_d2i_EXTENDED_KEY_USAGE +#define i2d_EXTENDED_KEY_USAGE GRPC_SHADOW_i2d_EXTENDED_KEY_USAGE +#define v3_ext_ku GRPC_SHADOW_v3_ext_ku +#define v3_ocsp_accresp GRPC_SHADOW_v3_ocsp_accresp +#define EDIPARTYNAME_free GRPC_SHADOW_EDIPARTYNAME_free +#define EDIPARTYNAME_it GRPC_SHADOW_EDIPARTYNAME_it +#define EDIPARTYNAME_new GRPC_SHADOW_EDIPARTYNAME_new +#define GENERAL_NAMES_free GRPC_SHADOW_GENERAL_NAMES_free +#define GENERAL_NAMES_it GRPC_SHADOW_GENERAL_NAMES_it +#define GENERAL_NAMES_new GRPC_SHADOW_GENERAL_NAMES_new +#define GENERAL_NAME_cmp GRPC_SHADOW_GENERAL_NAME_cmp +#define GENERAL_NAME_dup GRPC_SHADOW_GENERAL_NAME_dup +#define GENERAL_NAME_free GRPC_SHADOW_GENERAL_NAME_free +#define GENERAL_NAME_get0_otherName GRPC_SHADOW_GENERAL_NAME_get0_otherName +#define GENERAL_NAME_get0_value GRPC_SHADOW_GENERAL_NAME_get0_value +#define GENERAL_NAME_it GRPC_SHADOW_GENERAL_NAME_it +#define GENERAL_NAME_new GRPC_SHADOW_GENERAL_NAME_new +#define GENERAL_NAME_set0_othername GRPC_SHADOW_GENERAL_NAME_set0_othername +#define GENERAL_NAME_set0_value GRPC_SHADOW_GENERAL_NAME_set0_value +#define OTHERNAME_cmp GRPC_SHADOW_OTHERNAME_cmp +#define OTHERNAME_free GRPC_SHADOW_OTHERNAME_free +#define OTHERNAME_it GRPC_SHADOW_OTHERNAME_it +#define OTHERNAME_new GRPC_SHADOW_OTHERNAME_new +#define d2i_EDIPARTYNAME GRPC_SHADOW_d2i_EDIPARTYNAME +#define d2i_GENERAL_NAME GRPC_SHADOW_d2i_GENERAL_NAME +#define d2i_GENERAL_NAMES GRPC_SHADOW_d2i_GENERAL_NAMES +#define d2i_OTHERNAME GRPC_SHADOW_d2i_OTHERNAME +#define i2d_EDIPARTYNAME GRPC_SHADOW_i2d_EDIPARTYNAME +#define i2d_GENERAL_NAME GRPC_SHADOW_i2d_GENERAL_NAME +#define i2d_GENERAL_NAMES GRPC_SHADOW_i2d_GENERAL_NAMES +#define i2d_OTHERNAME GRPC_SHADOW_i2d_OTHERNAME +#define v3_ns_ia5_list GRPC_SHADOW_v3_ns_ia5_list +#define ACCESS_DESCRIPTION_free GRPC_SHADOW_ACCESS_DESCRIPTION_free +#define ACCESS_DESCRIPTION_it GRPC_SHADOW_ACCESS_DESCRIPTION_it +#define ACCESS_DESCRIPTION_new GRPC_SHADOW_ACCESS_DESCRIPTION_new +#define AUTHORITY_INFO_ACCESS_free GRPC_SHADOW_AUTHORITY_INFO_ACCESS_free +#define AUTHORITY_INFO_ACCESS_it GRPC_SHADOW_AUTHORITY_INFO_ACCESS_it +#define AUTHORITY_INFO_ACCESS_new GRPC_SHADOW_AUTHORITY_INFO_ACCESS_new +#define d2i_ACCESS_DESCRIPTION GRPC_SHADOW_d2i_ACCESS_DESCRIPTION +#define d2i_AUTHORITY_INFO_ACCESS GRPC_SHADOW_d2i_AUTHORITY_INFO_ACCESS +#define i2a_ACCESS_DESCRIPTION GRPC_SHADOW_i2a_ACCESS_DESCRIPTION +#define i2d_ACCESS_DESCRIPTION GRPC_SHADOW_i2d_ACCESS_DESCRIPTION +#define i2d_AUTHORITY_INFO_ACCESS GRPC_SHADOW_i2d_AUTHORITY_INFO_ACCESS +#define v3_info GRPC_SHADOW_v3_info +#define v3_sinfo GRPC_SHADOW_v3_sinfo +#define v3_crl_num GRPC_SHADOW_v3_crl_num +#define v3_delta_crl GRPC_SHADOW_v3_delta_crl +#define v3_inhibit_anyp GRPC_SHADOW_v3_inhibit_anyp +#define X509V3_EXT_add GRPC_SHADOW_X509V3_EXT_add +#define X509V3_EXT_add_alias GRPC_SHADOW_X509V3_EXT_add_alias +#define X509V3_EXT_add_list GRPC_SHADOW_X509V3_EXT_add_list +#define X509V3_EXT_cleanup GRPC_SHADOW_X509V3_EXT_cleanup +#define X509V3_EXT_d2i GRPC_SHADOW_X509V3_EXT_d2i +#define X509V3_EXT_free GRPC_SHADOW_X509V3_EXT_free +#define X509V3_EXT_get GRPC_SHADOW_X509V3_EXT_get +#define X509V3_EXT_get_nid GRPC_SHADOW_X509V3_EXT_get_nid +#define X509V3_add1_i2d GRPC_SHADOW_X509V3_add1_i2d +#define X509V3_add_standard_extensions GRPC_SHADOW_X509V3_add_standard_extensions +#define X509V3_get_d2i GRPC_SHADOW_X509V3_get_d2i +#define GENERAL_SUBTREE_free GRPC_SHADOW_GENERAL_SUBTREE_free +#define GENERAL_SUBTREE_it GRPC_SHADOW_GENERAL_SUBTREE_it +#define GENERAL_SUBTREE_new GRPC_SHADOW_GENERAL_SUBTREE_new +#define NAME_CONSTRAINTS_check GRPC_SHADOW_NAME_CONSTRAINTS_check +#define NAME_CONSTRAINTS_free GRPC_SHADOW_NAME_CONSTRAINTS_free +#define NAME_CONSTRAINTS_it GRPC_SHADOW_NAME_CONSTRAINTS_it +#define NAME_CONSTRAINTS_new GRPC_SHADOW_NAME_CONSTRAINTS_new +#define v3_name_constraints GRPC_SHADOW_v3_name_constraints +#define v3_pci GRPC_SHADOW_v3_pci +#define PROXY_CERT_INFO_EXTENSION_free GRPC_SHADOW_PROXY_CERT_INFO_EXTENSION_free +#define PROXY_CERT_INFO_EXTENSION_it GRPC_SHADOW_PROXY_CERT_INFO_EXTENSION_it +#define PROXY_CERT_INFO_EXTENSION_new GRPC_SHADOW_PROXY_CERT_INFO_EXTENSION_new +#define PROXY_POLICY_free GRPC_SHADOW_PROXY_POLICY_free +#define PROXY_POLICY_it GRPC_SHADOW_PROXY_POLICY_it +#define PROXY_POLICY_new GRPC_SHADOW_PROXY_POLICY_new +#define d2i_PROXY_CERT_INFO_EXTENSION GRPC_SHADOW_d2i_PROXY_CERT_INFO_EXTENSION +#define d2i_PROXY_POLICY GRPC_SHADOW_d2i_PROXY_POLICY +#define i2d_PROXY_CERT_INFO_EXTENSION GRPC_SHADOW_i2d_PROXY_CERT_INFO_EXTENSION +#define i2d_PROXY_POLICY GRPC_SHADOW_i2d_PROXY_POLICY +#define POLICY_CONSTRAINTS_free GRPC_SHADOW_POLICY_CONSTRAINTS_free +#define POLICY_CONSTRAINTS_it GRPC_SHADOW_POLICY_CONSTRAINTS_it +#define POLICY_CONSTRAINTS_new GRPC_SHADOW_POLICY_CONSTRAINTS_new +#define v3_policy_constraints GRPC_SHADOW_v3_policy_constraints +#define PKEY_USAGE_PERIOD_free GRPC_SHADOW_PKEY_USAGE_PERIOD_free +#define PKEY_USAGE_PERIOD_it GRPC_SHADOW_PKEY_USAGE_PERIOD_it +#define PKEY_USAGE_PERIOD_new GRPC_SHADOW_PKEY_USAGE_PERIOD_new +#define d2i_PKEY_USAGE_PERIOD GRPC_SHADOW_d2i_PKEY_USAGE_PERIOD +#define i2d_PKEY_USAGE_PERIOD GRPC_SHADOW_i2d_PKEY_USAGE_PERIOD +#define v3_pkey_usage_period GRPC_SHADOW_v3_pkey_usage_period +#define POLICY_MAPPINGS_it GRPC_SHADOW_POLICY_MAPPINGS_it +#define POLICY_MAPPING_free GRPC_SHADOW_POLICY_MAPPING_free +#define POLICY_MAPPING_it GRPC_SHADOW_POLICY_MAPPING_it +#define POLICY_MAPPING_new GRPC_SHADOW_POLICY_MAPPING_new +#define v3_policy_mappings GRPC_SHADOW_v3_policy_mappings +#define X509V3_EXT_print GRPC_SHADOW_X509V3_EXT_print +#define X509V3_EXT_print_fp GRPC_SHADOW_X509V3_EXT_print_fp +#define X509V3_EXT_val_prn GRPC_SHADOW_X509V3_EXT_val_prn +#define X509V3_extensions_print GRPC_SHADOW_X509V3_extensions_print +#define X509_PURPOSE_add GRPC_SHADOW_X509_PURPOSE_add +#define X509_PURPOSE_cleanup GRPC_SHADOW_X509_PURPOSE_cleanup +#define X509_PURPOSE_get0 GRPC_SHADOW_X509_PURPOSE_get0 +#define X509_PURPOSE_get0_name GRPC_SHADOW_X509_PURPOSE_get0_name +#define X509_PURPOSE_get0_sname GRPC_SHADOW_X509_PURPOSE_get0_sname +#define X509_PURPOSE_get_by_id GRPC_SHADOW_X509_PURPOSE_get_by_id +#define X509_PURPOSE_get_by_sname GRPC_SHADOW_X509_PURPOSE_get_by_sname +#define X509_PURPOSE_get_count GRPC_SHADOW_X509_PURPOSE_get_count +#define X509_PURPOSE_get_id GRPC_SHADOW_X509_PURPOSE_get_id +#define X509_PURPOSE_get_trust GRPC_SHADOW_X509_PURPOSE_get_trust +#define X509_PURPOSE_set GRPC_SHADOW_X509_PURPOSE_set +#define X509_check_akid GRPC_SHADOW_X509_check_akid +#define X509_check_ca GRPC_SHADOW_X509_check_ca +#define X509_check_issued GRPC_SHADOW_X509_check_issued +#define X509_check_purpose GRPC_SHADOW_X509_check_purpose +#define X509_supported_extension GRPC_SHADOW_X509_supported_extension +#define i2s_ASN1_OCTET_STRING GRPC_SHADOW_i2s_ASN1_OCTET_STRING +#define s2i_ASN1_OCTET_STRING GRPC_SHADOW_s2i_ASN1_OCTET_STRING +#define v3_skey_id GRPC_SHADOW_v3_skey_id +#define SXNETID_free GRPC_SHADOW_SXNETID_free +#define SXNETID_it GRPC_SHADOW_SXNETID_it +#define SXNETID_new GRPC_SHADOW_SXNETID_new +#define SXNET_add_id_INTEGER GRPC_SHADOW_SXNET_add_id_INTEGER +#define SXNET_add_id_asc GRPC_SHADOW_SXNET_add_id_asc +#define SXNET_add_id_ulong GRPC_SHADOW_SXNET_add_id_ulong +#define SXNET_free GRPC_SHADOW_SXNET_free +#define SXNET_get_id_INTEGER GRPC_SHADOW_SXNET_get_id_INTEGER +#define SXNET_get_id_asc GRPC_SHADOW_SXNET_get_id_asc +#define SXNET_get_id_ulong GRPC_SHADOW_SXNET_get_id_ulong +#define SXNET_it GRPC_SHADOW_SXNET_it +#define SXNET_new GRPC_SHADOW_SXNET_new +#define d2i_SXNET GRPC_SHADOW_d2i_SXNET +#define d2i_SXNETID GRPC_SHADOW_d2i_SXNETID +#define i2d_SXNET GRPC_SHADOW_i2d_SXNET +#define i2d_SXNETID GRPC_SHADOW_i2d_SXNETID +#define v3_sxnet GRPC_SHADOW_v3_sxnet +#define X509V3_NAME_from_section GRPC_SHADOW_X509V3_NAME_from_section +#define X509V3_add_value GRPC_SHADOW_X509V3_add_value +#define X509V3_add_value_bool GRPC_SHADOW_X509V3_add_value_bool +#define X509V3_add_value_bool_nf GRPC_SHADOW_X509V3_add_value_bool_nf +#define X509V3_add_value_int GRPC_SHADOW_X509V3_add_value_int +#define X509V3_add_value_uchar GRPC_SHADOW_X509V3_add_value_uchar +#define X509V3_conf_free GRPC_SHADOW_X509V3_conf_free +#define X509V3_get_value_bool GRPC_SHADOW_X509V3_get_value_bool +#define X509V3_get_value_int GRPC_SHADOW_X509V3_get_value_int +#define X509V3_parse_list GRPC_SHADOW_X509V3_parse_list +#define X509_REQ_get1_email GRPC_SHADOW_X509_REQ_get1_email +#define X509_check_email GRPC_SHADOW_X509_check_email +#define X509_check_host GRPC_SHADOW_X509_check_host +#define X509_check_ip GRPC_SHADOW_X509_check_ip +#define X509_check_ip_asc GRPC_SHADOW_X509_check_ip_asc +#define X509_email_free GRPC_SHADOW_X509_email_free +#define X509_get1_email GRPC_SHADOW_X509_get1_email +#define X509_get1_ocsp GRPC_SHADOW_X509_get1_ocsp +#define a2i_IPADDRESS GRPC_SHADOW_a2i_IPADDRESS +#define a2i_IPADDRESS_NC GRPC_SHADOW_a2i_IPADDRESS_NC +#define a2i_ipadd GRPC_SHADOW_a2i_ipadd +#define hex_to_string GRPC_SHADOW_hex_to_string +#define i2s_ASN1_ENUMERATED GRPC_SHADOW_i2s_ASN1_ENUMERATED +#define i2s_ASN1_INTEGER GRPC_SHADOW_i2s_ASN1_INTEGER +#define name_cmp GRPC_SHADOW_name_cmp +#define s2i_ASN1_INTEGER GRPC_SHADOW_s2i_ASN1_INTEGER +#define string_to_hex GRPC_SHADOW_string_to_hex +#define PKCS7_get_raw_certificates GRPC_SHADOW_PKCS7_get_raw_certificates +#define pkcs7_bundle GRPC_SHADOW_pkcs7_bundle +#define pkcs7_parse_header GRPC_SHADOW_pkcs7_parse_header +#define PKCS7_bundle_CRLs GRPC_SHADOW_PKCS7_bundle_CRLs +#define PKCS7_bundle_certificates GRPC_SHADOW_PKCS7_bundle_certificates +#define PKCS7_get_CRLs GRPC_SHADOW_PKCS7_get_CRLs +#define PKCS7_get_PEM_CRLs GRPC_SHADOW_PKCS7_get_PEM_CRLs +#define PKCS7_get_PEM_certificates GRPC_SHADOW_PKCS7_get_PEM_certificates +#define PKCS7_get_certificates GRPC_SHADOW_PKCS7_get_certificates +#define PKCS8_marshal_encrypted_private_key GRPC_SHADOW_PKCS8_marshal_encrypted_private_key +#define PKCS8_parse_encrypted_private_key GRPC_SHADOW_PKCS8_parse_encrypted_private_key +#define pkcs12_key_gen GRPC_SHADOW_pkcs12_key_gen +#define pkcs8_pbe_decrypt GRPC_SHADOW_pkcs8_pbe_decrypt +#define EVP_PKCS82PKEY GRPC_SHADOW_EVP_PKCS82PKEY +#define EVP_PKEY2PKCS8 GRPC_SHADOW_EVP_PKEY2PKCS8 +#define PKCS12_PBE_add GRPC_SHADOW_PKCS12_PBE_add +#define PKCS12_free GRPC_SHADOW_PKCS12_free +#define PKCS12_get_key_and_certs GRPC_SHADOW_PKCS12_get_key_and_certs +#define PKCS12_parse GRPC_SHADOW_PKCS12_parse +#define PKCS12_verify_mac GRPC_SHADOW_PKCS12_verify_mac +#define PKCS8_PRIV_KEY_INFO_free GRPC_SHADOW_PKCS8_PRIV_KEY_INFO_free +#define PKCS8_PRIV_KEY_INFO_it GRPC_SHADOW_PKCS8_PRIV_KEY_INFO_it +#define PKCS8_PRIV_KEY_INFO_new GRPC_SHADOW_PKCS8_PRIV_KEY_INFO_new +#define PKCS8_decrypt GRPC_SHADOW_PKCS8_decrypt +#define PKCS8_encrypt GRPC_SHADOW_PKCS8_encrypt +#define d2i_PKCS12 GRPC_SHADOW_d2i_PKCS12 +#define d2i_PKCS12_bio GRPC_SHADOW_d2i_PKCS12_bio +#define d2i_PKCS12_fp GRPC_SHADOW_d2i_PKCS12_fp +#define d2i_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_d2i_PKCS8_PRIV_KEY_INFO +#define i2d_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO +#define PKCS5_pbe2_decrypt_init GRPC_SHADOW_PKCS5_pbe2_decrypt_init +#define PKCS5_pbe2_encrypt_init GRPC_SHADOW_PKCS5_pbe2_encrypt_init + +#endif /* GRPC_SHADOW_BORINGSSL_SYMBOLS */ + +#endif /* GRPC_CORE_TSI_GRPC_SHADOW_BORINGSSL_H */ diff --git a/Sources/CgRPC/src/core/tsi/local_transport_security.cc b/Sources/CgRPC/src/core/tsi/local_transport_security.cc new file mode 100644 index 000000000..99fd56dbd --- /dev/null +++ b/Sources/CgRPC/src/core/tsi/local_transport_security.cc @@ -0,0 +1,209 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/tsi/local_transport_security.h" + +#include +#include +#include + +#include +#include +#include + +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/tsi/transport_security_grpc.h" + +/* Main struct for local TSI zero-copy frame protector. */ +typedef struct local_zero_copy_grpc_protector { + tsi_zero_copy_grpc_protector base; +} local_zero_copy_grpc_protector; + +/* Main struct for local TSI handshaker result. */ +typedef struct local_tsi_handshaker_result { + tsi_handshaker_result base; + bool is_client; +} local_tsi_handshaker_result; + +/* Main struct for local TSI handshaker. */ +typedef struct local_tsi_handshaker { + tsi_handshaker base; + bool is_client; +} local_tsi_handshaker; + +/* --- tsi_zero_copy_grpc_protector methods implementation. --- */ + +static tsi_result local_zero_copy_grpc_protector_protect( + tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices, + grpc_slice_buffer* protected_slices) { + if (self == nullptr || unprotected_slices == nullptr || + protected_slices == nullptr) { + gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect."); + return TSI_INVALID_ARGUMENT; + } + grpc_slice_buffer_move_into(unprotected_slices, protected_slices); + return TSI_OK; +} + +static tsi_result local_zero_copy_grpc_protector_unprotect( + tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices, + grpc_slice_buffer* unprotected_slices) { + if (self == nullptr || unprotected_slices == nullptr || + protected_slices == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to zero-copy grpc unprotect."); + return TSI_INVALID_ARGUMENT; + } + grpc_slice_buffer_move_into(protected_slices, unprotected_slices); + return TSI_OK; +} + +static void local_zero_copy_grpc_protector_destroy( + tsi_zero_copy_grpc_protector* self) { + gpr_free(self); +} + +static const tsi_zero_copy_grpc_protector_vtable + local_zero_copy_grpc_protector_vtable = { + local_zero_copy_grpc_protector_protect, + local_zero_copy_grpc_protector_unprotect, + local_zero_copy_grpc_protector_destroy}; + +tsi_result local_zero_copy_grpc_protector_create( + tsi_zero_copy_grpc_protector** protector) { + if (grpc_core::ExecCtx::Get() == nullptr || protector == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid nullptr arguments to local_zero_copy_grpc_protector create."); + return TSI_INVALID_ARGUMENT; + } + local_zero_copy_grpc_protector* impl = + static_cast(gpr_zalloc(sizeof(*impl))); + impl->base.vtable = &local_zero_copy_grpc_protector_vtable; + *protector = &impl->base; + return TSI_OK; +} + +/* --- tsi_handshaker_result methods implementation. --- */ + +static tsi_result handshaker_result_extract_peer( + const tsi_handshaker_result* self, tsi_peer* peer) { + return TSI_OK; +} + +static tsi_result handshaker_result_create_zero_copy_grpc_protector( + const tsi_handshaker_result* self, size_t* max_output_protected_frame_size, + tsi_zero_copy_grpc_protector** protector) { + if (self == nullptr || protector == nullptr) { + gpr_log(GPR_ERROR, + "Invalid arguments to create_zero_copy_grpc_protector()"); + return TSI_INVALID_ARGUMENT; + } + tsi_result ok = local_zero_copy_grpc_protector_create(protector); + if (ok != TSI_OK) { + gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector"); + } + return ok; +} + +static void handshaker_result_destroy(tsi_handshaker_result* self) { + if (self == nullptr) { + return; + } + local_tsi_handshaker_result* result = + reinterpret_cast( + const_cast(self)); + gpr_free(result); +} + +static const tsi_handshaker_result_vtable result_vtable = { + handshaker_result_extract_peer, + handshaker_result_create_zero_copy_grpc_protector, + nullptr, /* handshaker_result_create_frame_protector */ + nullptr, /* handshaker_result_get_unused_bytes */ + handshaker_result_destroy}; + +static tsi_result create_handshaker_result(bool is_client, + tsi_handshaker_result** self) { + if (self == nullptr) { + gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()"); + return TSI_INVALID_ARGUMENT; + } + local_tsi_handshaker_result* result = + static_cast(gpr_zalloc(sizeof(*result))); + result->is_client = is_client; + result->base.vtable = &result_vtable; + *self = &result->base; + return TSI_OK; +} + +/* --- tsi_handshaker methods implementation. --- */ + +static tsi_result handshaker_next( + tsi_handshaker* self, const unsigned char* received_bytes, + size_t received_bytes_size, const unsigned char** bytes_to_send, + size_t* bytes_to_send_size, tsi_handshaker_result** result, + tsi_handshaker_on_next_done_cb cb, void* user_data) { + if (self == nullptr) { + gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()"); + return TSI_INVALID_ARGUMENT; + } + /* Note that there is no interaction between TSI peers, and all operations are + * local. + */ + local_tsi_handshaker* handshaker = + reinterpret_cast(self); + *bytes_to_send_size = 0; + create_handshaker_result(handshaker->is_client, result); + return TSI_OK; +} + +static void handshaker_destroy(tsi_handshaker* self) { + if (self == nullptr) { + return; + } + local_tsi_handshaker* handshaker = + reinterpret_cast(self); + gpr_free(handshaker); +} + +static const tsi_handshaker_vtable handshaker_vtable = { + nullptr, /* get_bytes_to_send_to_peer -- deprecated */ + nullptr, /* process_bytes_from_peer -- deprecated */ + nullptr, /* get_result -- deprecated */ + nullptr, /* extract_peer -- deprecated */ + nullptr, /* create_frame_protector -- deprecated */ + handshaker_destroy, + handshaker_next, + nullptr, /* shutdown */ +}; + +tsi_result local_tsi_handshaker_create(bool is_client, tsi_handshaker** self) { + if (self == nullptr) { + gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()"); + return TSI_INVALID_ARGUMENT; + } + local_tsi_handshaker* handshaker = + static_cast(gpr_zalloc(sizeof(*handshaker))); + handshaker->is_client = is_client; + handshaker->base.vtable = &handshaker_vtable; + *self = &handshaker->base; + return TSI_OK; +} diff --git a/Sources/CgRPC/src/core/tsi/local_transport_security.h b/Sources/CgRPC/src/core/tsi/local_transport_security.h new file mode 100644 index 000000000..17213ecf3 --- /dev/null +++ b/Sources/CgRPC/src/core/tsi/local_transport_security.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_TSI_LOCAL_TRANSPORT_SECURITY_H +#define GRPC_CORE_TSI_LOCAL_TRANSPORT_SECURITY_H + +#include + +#include + +#include "src/core/tsi/transport_security.h" +#include "src/core/tsi/transport_security_interface.h" + +#define TSI_LOCAL_NUM_OF_PEER_PROPERTIES 1 +#define TSI_LOCAL_PROCESS_ID_PEER_PROPERTY "process_id" + +/** + * Main struct for local TSI handshaker. All APIs in the header are + * thread-comptabile. + */ +typedef struct local_tsi_handshaker local_tsi_handshaker; + +/** + * This method creates a local TSI handshaker instance. + * + * - is_client: boolean value indicating if the handshaker is used at the client + * (is_client = true) or server (is_client = false) side. The parameter is + * added for future extension. + * - self: address of local TSI handshaker instance to be returned from the + * method. + * + * It returns TSI_OK on success and an error status code on failure. + */ +tsi_result local_tsi_handshaker_create(bool is_client, tsi_handshaker** self); + +#endif /* GRPC_CORE_TSI_LOCAL_TRANSPORT_SECURITY_H */ diff --git a/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session.h b/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session.h index 115221ec0..e847267cb 100644 --- a/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session.h +++ b/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session.h @@ -21,6 +21,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include extern "C" { diff --git a/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.cc index fe4f83a13..f9184bcc3 100644 --- a/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +++ b/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.cc @@ -18,9 +18,10 @@ #include -#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" - +#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl/session_cache/ssl_session.h" +#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" #include #include @@ -53,7 +54,7 @@ class SslSessionLRUCache::Node { SetSession(std::move(session)); } - ~Node() { grpc_slice_unref(key_); } + ~Node() { grpc_slice_unref_internal(key_); } // Not copyable nor movable. Node(const Node&) = delete; @@ -97,7 +98,7 @@ SslSessionLRUCache::~SslSessionLRUCache() { } size_t SslSessionLRUCache::Size() { - grpc_core::mu_guard guard(&lock_); + grpc_core::MutexLock lock(&lock_); return use_order_list_size_; } @@ -117,7 +118,7 @@ SslSessionLRUCache::Node* SslSessionLRUCache::FindLocked( } void SslSessionLRUCache::Put(const char* key, SslSessionPtr session) { - grpc_core::mu_guard guard(&lock_); + grpc_core::MutexLock lock(&lock_); Node* node = FindLocked(grpc_slice_from_static_string(key)); if (node != nullptr) { node->SetSession(std::move(session)); @@ -140,7 +141,7 @@ void SslSessionLRUCache::Put(const char* key, SslSessionPtr session) { } SslSessionPtr SslSessionLRUCache::Get(const char* key) { - grpc_core::mu_guard guard(&lock_); + grpc_core::MutexLock lock(&lock_); // Key is only used for lookups. grpc_slice key_slice = grpc_slice_from_static_string(key); Node* node = FindLocked(key_slice); diff --git a/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.h b/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.h index a90cca1a2..37fa2d124 100644 --- a/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.h +++ b/Sources/CgRPC/src/core/tsi/ssl/session_cache/ssl_session_cache.h @@ -21,6 +21,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include #include diff --git a/Sources/CgRPC/src/core/tsi/ssl_transport_security.cc b/Sources/CgRPC/src/core/tsi/ssl_transport_security.cc index 7662a5538..ddecf0ab1 100644 --- a/Sources/CgRPC/src/core/tsi/ssl_transport_security.cc +++ b/Sources/CgRPC/src/core/tsi/ssl_transport_security.cc @@ -18,6 +18,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include "src/core/tsi/ssl_transport_security.h" #include @@ -57,6 +59,7 @@ extern "C" { #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384 #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024 +#define TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE 1024 /* Putting a macro like this and littering the source file with #if is really bad practice. @@ -105,9 +108,19 @@ typedef struct { SSL* ssl; BIO* network_io; tsi_result result; + unsigned char* outgoing_bytes_buffer; + size_t outgoing_bytes_buffer_size; tsi_ssl_handshaker_factory* factory_ref; } tsi_ssl_handshaker; +typedef struct { + tsi_handshaker_result base; + SSL* ssl; + BIO* network_io; + unsigned char* unused_bytes; + size_t unused_bytes_size; +} tsi_ssl_handshaker_result; + typedef struct { tsi_frame_protector base; SSL* ssl; @@ -120,12 +133,14 @@ typedef struct { /* --- Library Initialization. ---*/ static gpr_once g_init_openssl_once = GPR_ONCE_INIT; -static gpr_mu* g_openssl_mutexes = nullptr; static int g_ssl_ctx_ex_factory_index = -1; +static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'}; + +#if OPENSSL_VERSION_NUMBER < 0x10100000 +static gpr_mu* g_openssl_mutexes = nullptr; static void openssl_locking_cb(int mode, int type, const char* file, int line) GRPC_UNUSED; static unsigned long openssl_thread_id_cb(void) GRPC_UNUSED; -static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'}; static void openssl_locking_cb(int mode, int type, const char* file, int line) { if (mode & CRYPTO_LOCK) { @@ -138,22 +153,31 @@ static void openssl_locking_cb(int mode, int type, const char* file, int line) { static unsigned long openssl_thread_id_cb(void) { return static_cast(gpr_thd_currentid()); } +#endif static void init_openssl(void) { - int i; - int num_locks; +#if OPENSSL_API_COMPAT >= 0x10100000L + OPENSSL_init_ssl(0, NULL); +#else SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); - num_locks = CRYPTO_num_locks(); - GPR_ASSERT(num_locks > 0); - g_openssl_mutexes = static_cast( - gpr_malloc(static_cast(num_locks) * sizeof(gpr_mu))); - for (i = 0; i < CRYPTO_num_locks(); i++) { - gpr_mu_init(&g_openssl_mutexes[i]); - } - CRYPTO_set_locking_callback(openssl_locking_cb); - CRYPTO_set_id_callback(openssl_thread_id_cb); +#endif +#if OPENSSL_VERSION_NUMBER < 0x10100000 + if (!CRYPTO_get_locking_callback()) { + int num_locks = CRYPTO_num_locks(); + GPR_ASSERT(num_locks > 0); + g_openssl_mutexes = static_cast( + gpr_malloc(static_cast(num_locks) * sizeof(gpr_mu))); + for (int i = 0; i < num_locks; i++) { + gpr_mu_init(&g_openssl_mutexes[i]); + } + CRYPTO_set_locking_callback(openssl_locking_cb); + CRYPTO_set_id_callback(openssl_thread_id_cb); + } else { + gpr_log(GPR_INFO, "OpenSSL callback has already been set."); + } +#endif g_ssl_ctx_ex_factory_index = SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); GPR_ASSERT(g_ssl_ctx_ex_factory_index != -1); @@ -198,7 +222,7 @@ static void ssl_log_where_info(const SSL* ssl, int where, int flag, /* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */ static void ssl_info_callback(const SSL* ssl, int where, int ret) { if (ret == 0) { - gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n"); + gpr_log(GPR_ERROR, "ssl_info_callback: error occurred.\n"); return; } @@ -242,14 +266,13 @@ static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8, X509_NAME* subject_name = X509_get_subject_name(cert); int utf8_returned_size = 0; if (subject_name == nullptr) { - gpr_log(GPR_ERROR, "Could not get subject name from certificate."); + gpr_log(GPR_INFO, "Could not get subject name from certificate."); return TSI_NOT_FOUND; } common_name_index = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1); if (common_name_index == -1) { - gpr_log(GPR_ERROR, - "Could not get common name of subject from certificate."); + gpr_log(GPR_INFO, "Could not get common name of subject from certificate."); return TSI_NOT_FOUND; } common_name_entry = X509_NAME_get_entry(subject_name, common_name_index); @@ -596,15 +619,19 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store, sk_X509_NAME_push(*root_names, root_name); root_name = nullptr; } + ERR_clear_error(); if (!X509_STORE_add_cert(cert_store, root)) { - gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); - result = TSI_INTERNAL_ERROR; - break; + unsigned long error = ERR_get_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); + result = TSI_INTERNAL_ERROR; + break; + } } X509_free(root); num_roots++; } - if (num_roots == 0) { gpr_log(GPR_ERROR, "Could not load any root certificate."); result = TSI_INVALID_ARGUMENT; @@ -628,6 +655,8 @@ static tsi_result ssl_ctx_load_verification_certs(SSL_CTX* context, STACK_OF(X509_NAME) * *root_name) { X509_STORE* cert_store = SSL_CTX_get_cert_store(context); + X509_STORE_set_flags(cert_store, + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_TRUSTED_FIRST); return x509_store_load_certs(cert_store, pem_roots, pem_roots_size, root_name); } @@ -987,94 +1016,15 @@ static void tsi_ssl_handshaker_factory_init( gpr_ref_init(&factory->refcount, 1); } -/* --- tsi_handshaker methods implementation. ---*/ - -static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self, - unsigned char* bytes, - size_t* bytes_size) { - tsi_ssl_handshaker* impl = reinterpret_cast(self); - int bytes_read_from_ssl = 0; - if (bytes == nullptr || bytes_size == nullptr || *bytes_size == 0 || - *bytes_size > INT_MAX) { - return TSI_INVALID_ARGUMENT; - } - GPR_ASSERT(*bytes_size <= INT_MAX); - bytes_read_from_ssl = - BIO_read(impl->network_io, bytes, static_cast(*bytes_size)); - if (bytes_read_from_ssl < 0) { - *bytes_size = 0; - if (!BIO_should_retry(impl->network_io)) { - impl->result = TSI_INTERNAL_ERROR; - return impl->result; - } else { - return TSI_OK; - } - } - *bytes_size = static_cast(bytes_read_from_ssl); - return BIO_pending(impl->network_io) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA; -} - -static tsi_result ssl_handshaker_get_result(tsi_handshaker* self) { - tsi_ssl_handshaker* impl = reinterpret_cast(self); - if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) && - SSL_is_init_finished(impl->ssl)) { - impl->result = TSI_OK; - } - return impl->result; -} +/* --- tsi_handshaker_result methods implementation. ---*/ -static tsi_result ssl_handshaker_process_bytes_from_peer( - tsi_handshaker* self, const unsigned char* bytes, size_t* bytes_size) { - tsi_ssl_handshaker* impl = reinterpret_cast(self); - int bytes_written_into_ssl_size = 0; - if (bytes == nullptr || bytes_size == nullptr || *bytes_size > INT_MAX) { - return TSI_INVALID_ARGUMENT; - } - GPR_ASSERT(*bytes_size <= INT_MAX); - bytes_written_into_ssl_size = - BIO_write(impl->network_io, bytes, static_cast(*bytes_size)); - if (bytes_written_into_ssl_size < 0) { - gpr_log(GPR_ERROR, "Could not write to memory BIO."); - impl->result = TSI_INTERNAL_ERROR; - return impl->result; - } - *bytes_size = static_cast(bytes_written_into_ssl_size); - - if (!tsi_handshaker_is_in_progress(self)) { - impl->result = TSI_OK; - return impl->result; - } else { - /* Get ready to get some bytes from SSL. */ - int ssl_result = SSL_do_handshake(impl->ssl); - ssl_result = SSL_get_error(impl->ssl, ssl_result); - switch (ssl_result) { - case SSL_ERROR_WANT_READ: - if (BIO_pending(impl->network_io) == 0) { - /* We need more data. */ - return TSI_INCOMPLETE_DATA; - } else { - return TSI_OK; - } - case SSL_ERROR_NONE: - return TSI_OK; - default: { - char err_str[256]; - ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str)); - gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.", - ssl_error_string(ssl_result), err_str); - impl->result = TSI_PROTOCOL_FAILURE; - return impl->result; - } - } - } -} - -static tsi_result ssl_handshaker_extract_peer(tsi_handshaker* self, - tsi_peer* peer) { +static tsi_result ssl_handshaker_result_extract_peer( + const tsi_handshaker_result* self, tsi_peer* peer) { tsi_result result = TSI_OK; const unsigned char* alpn_selected = nullptr; unsigned int alpn_selected_len; - tsi_ssl_handshaker* impl = reinterpret_cast(self); + const tsi_ssl_handshaker_result* impl = + reinterpret_cast(self); X509* peer_cert = SSL_get_peer_certificate(impl->ssl); if (peer_cert != nullptr) { result = peer_from_x509(peer_cert, 1, peer); @@ -1111,21 +1061,23 @@ static tsi_result ssl_handshaker_extract_peer(tsi_handshaker* self, } const char* session_reused = SSL_session_reused(impl->ssl) ? "true" : "false"; - result = tsi_construct_string_peer_property( + result = tsi_construct_string_peer_property_from_cstring( TSI_SSL_SESSION_REUSED_PEER_PROPERTY, session_reused, - strlen(session_reused) + 1, &peer->properties[peer->property_count]); + &peer->properties[peer->property_count]); if (result != TSI_OK) return result; peer->property_count++; return result; } -static tsi_result ssl_handshaker_create_frame_protector( - tsi_handshaker* self, size_t* max_output_protected_frame_size, +static tsi_result ssl_handshaker_result_create_frame_protector( + const tsi_handshaker_result* self, size_t* max_output_protected_frame_size, tsi_frame_protector** protector) { size_t actual_max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND; - tsi_ssl_handshaker* impl = reinterpret_cast(self); + tsi_ssl_handshaker_result* impl = + reinterpret_cast( + const_cast(self)); tsi_ssl_frame_protector* protector_impl = static_cast( gpr_zalloc(sizeof(*protector_impl))); @@ -1153,35 +1105,218 @@ static tsi_result ssl_handshaker_create_frame_protector( return TSI_INTERNAL_ERROR; } - /* Transfer ownership of ssl and network_io to the frame protector. It is OK - * as the caller cannot call anything else but destroy on the handshaker - * after this call. */ + /* Transfer ownership of ssl and network_io to the frame protector. */ protector_impl->ssl = impl->ssl; impl->ssl = nullptr; protector_impl->network_io = impl->network_io; impl->network_io = nullptr; - protector_impl->base.vtable = &frame_protector_vtable; *protector = &protector_impl->base; return TSI_OK; } +static tsi_result ssl_handshaker_result_get_unused_bytes( + const tsi_handshaker_result* self, const unsigned char** bytes, + size_t* bytes_size) { + const tsi_ssl_handshaker_result* impl = + reinterpret_cast(self); + *bytes_size = impl->unused_bytes_size; + *bytes = impl->unused_bytes; + return TSI_OK; +} + +static void ssl_handshaker_result_destroy(tsi_handshaker_result* self) { + tsi_ssl_handshaker_result* impl = + reinterpret_cast(self); + SSL_free(impl->ssl); + BIO_free(impl->network_io); + gpr_free(impl->unused_bytes); + gpr_free(impl); +} + +static const tsi_handshaker_result_vtable handshaker_result_vtable = { + ssl_handshaker_result_extract_peer, + nullptr, /* create_zero_copy_grpc_protector */ + ssl_handshaker_result_create_frame_protector, + ssl_handshaker_result_get_unused_bytes, + ssl_handshaker_result_destroy, +}; + +static tsi_result ssl_handshaker_result_create( + tsi_ssl_handshaker* handshaker, const unsigned char* unused_bytes, + size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) { + if (handshaker == nullptr || handshaker_result == nullptr || + (unused_bytes_size > 0 && unused_bytes == nullptr)) { + return TSI_INVALID_ARGUMENT; + } + tsi_ssl_handshaker_result* result = + static_cast(gpr_zalloc(sizeof(*result))); + result->base.vtable = &handshaker_result_vtable; + /* Transfer ownership of ssl and network_io to the handshaker result. */ + result->ssl = handshaker->ssl; + handshaker->ssl = nullptr; + result->network_io = handshaker->network_io; + handshaker->network_io = nullptr; + if (unused_bytes_size > 0) { + result->unused_bytes = + static_cast(gpr_malloc(unused_bytes_size)); + memcpy(result->unused_bytes, unused_bytes, unused_bytes_size); + } + result->unused_bytes_size = unused_bytes_size; + *handshaker_result = &result->base; + return TSI_OK; +} + +/* --- tsi_handshaker methods implementation. ---*/ + +static tsi_result ssl_handshaker_get_bytes_to_send_to_peer( + tsi_ssl_handshaker* impl, unsigned char* bytes, size_t* bytes_size) { + int bytes_read_from_ssl = 0; + if (bytes == nullptr || bytes_size == nullptr || *bytes_size == 0 || + *bytes_size > INT_MAX) { + return TSI_INVALID_ARGUMENT; + } + GPR_ASSERT(*bytes_size <= INT_MAX); + bytes_read_from_ssl = + BIO_read(impl->network_io, bytes, static_cast(*bytes_size)); + if (bytes_read_from_ssl < 0) { + *bytes_size = 0; + if (!BIO_should_retry(impl->network_io)) { + impl->result = TSI_INTERNAL_ERROR; + return impl->result; + } else { + return TSI_OK; + } + } + *bytes_size = static_cast(bytes_read_from_ssl); + return BIO_pending(impl->network_io) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA; +} + +static tsi_result ssl_handshaker_get_result(tsi_ssl_handshaker* impl) { + if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) && + SSL_is_init_finished(impl->ssl)) { + impl->result = TSI_OK; + } + return impl->result; +} + +static tsi_result ssl_handshaker_process_bytes_from_peer( + tsi_ssl_handshaker* impl, const unsigned char* bytes, size_t* bytes_size) { + int bytes_written_into_ssl_size = 0; + if (bytes == nullptr || bytes_size == nullptr || *bytes_size > INT_MAX) { + return TSI_INVALID_ARGUMENT; + } + GPR_ASSERT(*bytes_size <= INT_MAX); + bytes_written_into_ssl_size = + BIO_write(impl->network_io, bytes, static_cast(*bytes_size)); + if (bytes_written_into_ssl_size < 0) { + gpr_log(GPR_ERROR, "Could not write to memory BIO."); + impl->result = TSI_INTERNAL_ERROR; + return impl->result; + } + *bytes_size = static_cast(bytes_written_into_ssl_size); + + if (ssl_handshaker_get_result(impl) != TSI_HANDSHAKE_IN_PROGRESS) { + impl->result = TSI_OK; + return impl->result; + } else { + /* Get ready to get some bytes from SSL. */ + int ssl_result = SSL_do_handshake(impl->ssl); + ssl_result = SSL_get_error(impl->ssl, ssl_result); + switch (ssl_result) { + case SSL_ERROR_WANT_READ: + if (BIO_pending(impl->network_io) == 0) { + /* We need more data. */ + return TSI_INCOMPLETE_DATA; + } else { + return TSI_OK; + } + case SSL_ERROR_NONE: + return TSI_OK; + default: { + char err_str[256]; + ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str)); + gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.", + ssl_error_string(ssl_result), err_str); + impl->result = TSI_PROTOCOL_FAILURE; + return impl->result; + } + } + } +} + static void ssl_handshaker_destroy(tsi_handshaker* self) { tsi_ssl_handshaker* impl = reinterpret_cast(self); SSL_free(impl->ssl); BIO_free(impl->network_io); + gpr_free(impl->outgoing_bytes_buffer); tsi_ssl_handshaker_factory_unref(impl->factory_ref); gpr_free(impl); } +static tsi_result ssl_handshaker_next( + tsi_handshaker* self, const unsigned char* received_bytes, + size_t received_bytes_size, const unsigned char** bytes_to_send, + size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result, + tsi_handshaker_on_next_done_cb cb, void* user_data) { + /* Input sanity check. */ + if ((received_bytes_size > 0 && received_bytes == nullptr) || + bytes_to_send == nullptr || bytes_to_send_size == nullptr || + handshaker_result == nullptr) { + return TSI_INVALID_ARGUMENT; + } + /* If there are received bytes, process them first. */ + tsi_ssl_handshaker* impl = reinterpret_cast(self); + tsi_result status = TSI_OK; + size_t bytes_consumed = received_bytes_size; + if (received_bytes_size > 0) { + status = ssl_handshaker_process_bytes_from_peer(impl, received_bytes, + &bytes_consumed); + if (status != TSI_OK) return status; + } + /* Get bytes to send to the peer, if available. */ + size_t offset = 0; + do { + size_t to_send_size = impl->outgoing_bytes_buffer_size - offset; + status = ssl_handshaker_get_bytes_to_send_to_peer( + impl, impl->outgoing_bytes_buffer + offset, &to_send_size); + offset += to_send_size; + if (status == TSI_INCOMPLETE_DATA) { + impl->outgoing_bytes_buffer_size *= 2; + impl->outgoing_bytes_buffer = static_cast(gpr_realloc( + impl->outgoing_bytes_buffer, impl->outgoing_bytes_buffer_size)); + } + } while (status == TSI_INCOMPLETE_DATA); + if (status != TSI_OK) return status; + *bytes_to_send = impl->outgoing_bytes_buffer; + *bytes_to_send_size = offset; + /* If handshake completes, create tsi_handshaker_result. */ + if (ssl_handshaker_get_result(impl) == TSI_HANDSHAKE_IN_PROGRESS) { + *handshaker_result = nullptr; + } else { + size_t unused_bytes_size = received_bytes_size - bytes_consumed; + const unsigned char* unused_bytes = + unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed; + status = ssl_handshaker_result_create(impl, unused_bytes, unused_bytes_size, + handshaker_result); + if (status == TSI_OK) { + /* Indicates that the handshake has completed and that a handshaker_result + * has been created. */ + self->handshaker_result_created = true; + } + } + return status; +} + static const tsi_handshaker_vtable handshaker_vtable = { - ssl_handshaker_get_bytes_to_send_to_peer, - ssl_handshaker_process_bytes_from_peer, - ssl_handshaker_get_result, - ssl_handshaker_extract_peer, - ssl_handshaker_create_frame_protector, + nullptr, /* get_bytes_to_send_to_peer -- deprecated */ + nullptr, /* process_bytes_from_peer -- deprecated */ + nullptr, /* get_result -- deprecated */ + nullptr, /* extract_peer -- deprecated */ + nullptr, /* create_frame_protector -- deprecated */ ssl_handshaker_destroy, - nullptr, + ssl_handshaker_next, + nullptr, /* shutdown */ }; /* --- tsi_ssl_handshaker_factory common methods. --- */ @@ -1259,6 +1394,10 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client, impl->ssl = ssl; impl->network_io = network_io; impl->result = TSI_HANDSHAKE_IN_PROGRESS; + impl->outgoing_bytes_buffer_size = + TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE; + impl->outgoing_bytes_buffer = + static_cast(gpr_zalloc(impl->outgoing_bytes_buffer_size)); impl->base.vtable = &handshaker_vtable; impl->factory_ref = tsi_ssl_handshaker_factory_ref(factory); @@ -1520,7 +1659,11 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options( return TSI_INVALID_ARGUMENT; } +#if defined(OPENSSL_NO_TLS1_2_METHOD) || OPENSSL_API_COMPAT >= 0x10100000L + ssl_context = SSL_CTX_new(TLS_method()); +#else ssl_context = SSL_CTX_new(TLSv1_2_method()); +#endif if (ssl_context == nullptr) { gpr_log(GPR_ERROR, "Could not create ssl context."); return TSI_INVALID_ARGUMENT; @@ -1677,7 +1820,11 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options( for (i = 0; i < options->num_key_cert_pairs; i++) { do { +#if defined(OPENSSL_NO_TLS1_2_METHOD) || OPENSSL_API_COMPAT >= 0x10100000L + impl->ssl_contexts[i] = SSL_CTX_new(TLS_method()); +#else impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method()); +#endif if (impl->ssl_contexts[i] == nullptr) { gpr_log(GPR_ERROR, "Could not create ssl context."); result = TSI_OUT_OF_RESOURCES; @@ -1721,31 +1868,30 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options( break; } SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names); - switch (options->client_certificate_request) { - case TSI_DONT_REQUEST_CLIENT_CERTIFICATE: - SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, nullptr); - break; - case TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, - NullVerifyCallback); - break; - case TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: - SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, nullptr); - break; - case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - SSL_CTX_set_verify( - impl->ssl_contexts[i], - SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - NullVerifyCallback); - break; - case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: - SSL_CTX_set_verify( - impl->ssl_contexts[i], - SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); - break; - } - /* TODO(jboeuf): Add revocation verification. */ } + switch (options->client_certificate_request) { + case TSI_DONT_REQUEST_CLIENT_CERTIFICATE: + SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, nullptr); + break; + case TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, + NullVerifyCallback); + break; + case TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: + SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, nullptr); + break; + case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + SSL_CTX_set_verify(impl->ssl_contexts[i], + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + NullVerifyCallback); + break; + case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: + SSL_CTX_set_verify(impl->ssl_contexts[i], + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + nullptr); + break; + } + /* TODO(jboeuf): Add revocation verification. */ result = extract_x509_subject_names_from_pem_cert( options->pem_key_cert_pairs[i].cert_chain, diff --git a/Sources/CgRPC/src/core/tsi/ssl_types.h b/Sources/CgRPC/src/core/tsi/ssl_types.h index b15d02be3..0ce5e2ee6 100644 --- a/Sources/CgRPC/src/core/tsi/ssl_types.h +++ b/Sources/CgRPC/src/core/tsi/ssl_types.h @@ -29,6 +29,8 @@ #include +#include "src/core/tsi/grpc_shadow_boringssl.h" + #include #ifdef OPENSSL_IS_BORINGSSL diff --git a/Sources/CgRPC/src/core/tsi/transport_security.cc b/Sources/CgRPC/src/core/tsi/transport_security.cc index 129533f77..078a917bb 100644 --- a/Sources/CgRPC/src/core/tsi/transport_security.cc +++ b/Sources/CgRPC/src/core/tsi/transport_security.cc @@ -136,6 +136,7 @@ tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self, return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN; if (self->vtable->get_bytes_to_send_to_peer == nullptr) return TSI_UNIMPLEMENTED; return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size); @@ -149,6 +150,7 @@ tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker* self, return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN; if (self->vtable->process_bytes_from_peer == nullptr) return TSI_UNIMPLEMENTED; return self->vtable->process_bytes_from_peer(self, bytes, bytes_size); @@ -157,6 +159,7 @@ tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker* self, tsi_result tsi_handshaker_get_result(tsi_handshaker* self) { if (self == nullptr || self->vtable == nullptr) return TSI_INVALID_ARGUMENT; if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN; if (self->vtable->get_result == nullptr) return TSI_UNIMPLEMENTED; return self->vtable->get_result(self); } @@ -167,6 +170,7 @@ tsi_result tsi_handshaker_extract_peer(tsi_handshaker* self, tsi_peer* peer) { } memset(peer, 0, sizeof(tsi_peer)); if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN; if (tsi_handshaker_get_result(self) != TSI_OK) { return TSI_FAILED_PRECONDITION; } @@ -182,6 +186,7 @@ tsi_result tsi_handshaker_create_frame_protector( return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN; if (tsi_handshaker_get_result(self) != TSI_OK) return TSI_FAILED_PRECONDITION; if (self->vtable->create_frame_protector == nullptr) return TSI_UNIMPLEMENTED; result = self->vtable->create_frame_protector(self, max_protected_frame_size, @@ -199,12 +204,21 @@ tsi_result tsi_handshaker_next( tsi_handshaker_on_next_done_cb cb, void* user_data) { if (self == nullptr || self->vtable == nullptr) return TSI_INVALID_ARGUMENT; if (self->handshaker_result_created) return TSI_FAILED_PRECONDITION; + if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN; if (self->vtable->next == nullptr) return TSI_UNIMPLEMENTED; return self->vtable->next(self, received_bytes, received_bytes_size, bytes_to_send, bytes_to_send_size, handshaker_result, cb, user_data); } +void tsi_handshaker_shutdown(tsi_handshaker* self) { + if (self == nullptr || self->vtable == nullptr) return; + if (self->vtable->shutdown != nullptr) { + self->vtable->shutdown(self); + } + self->handshake_shutdown = true; +} + void tsi_handshaker_destroy(tsi_handshaker* self) { if (self == nullptr) return; self->vtable->destroy(self); @@ -324,3 +338,20 @@ tsi_result tsi_construct_peer(size_t property_count, tsi_peer* peer) { } return TSI_OK; } + +const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* peer, + const char* name) { + size_t i; + if (peer == nullptr) return nullptr; + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property* property = &peer->properties[i]; + if (name == nullptr && property->name == nullptr) { + return property; + } + if (name != nullptr && property->name != nullptr && + strcmp(property->name, name) == 0) { + return property; + } + } + return nullptr; +} diff --git a/Sources/CgRPC/src/core/tsi/transport_security.h b/Sources/CgRPC/src/core/tsi/transport_security.h index b1ec82d3f..482d300a0 100644 --- a/Sources/CgRPC/src/core/tsi/transport_security.h +++ b/Sources/CgRPC/src/core/tsi/transport_security.h @@ -73,12 +73,14 @@ typedef struct { size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result, tsi_handshaker_on_next_done_cb cb, void* user_data); + void (*shutdown)(tsi_handshaker* self); } tsi_handshaker_vtable; struct tsi_handshaker { const tsi_handshaker_vtable* vtable; bool frame_protector_created; bool handshaker_result_created; + bool handshake_shutdown; }; /* Base for tsi_handshaker_result implementations. @@ -120,7 +122,8 @@ tsi_result tsi_construct_allocated_string_peer_property( const char* name, size_t value_length, tsi_peer_property* property); tsi_result tsi_construct_string_peer_property_from_cstring( const char* name, const char* value, tsi_peer_property* property); - +const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* peer, + const char* name); /* Utils. */ char* tsi_strdup(const char* src); /* Sadly, no strdup in C89. */ diff --git a/Sources/CgRPC/src/core/tsi/transport_security_adapter.cc b/Sources/CgRPC/src/core/tsi/transport_security_adapter.cc deleted file mode 100644 index 25608f065..000000000 --- a/Sources/CgRPC/src/core/tsi/transport_security_adapter.cc +++ /dev/null @@ -1,235 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/tsi/transport_security_adapter.h" - -#include - -#include -#include -#include "src/core/tsi/transport_security.h" - -#define TSI_ADAPTER_INITIAL_BUFFER_SIZE 256 - -/* --- tsi_adapter_handshaker_result implementation ---*/ - -typedef struct { - tsi_handshaker_result base; - tsi_handshaker* wrapped; - unsigned char* unused_bytes; - size_t unused_bytes_size; -} tsi_adapter_handshaker_result; - -static tsi_result adapter_result_extract_peer(const tsi_handshaker_result* self, - tsi_peer* peer) { - tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self; - return tsi_handshaker_extract_peer(impl->wrapped, peer); -} - -static tsi_result adapter_result_create_frame_protector( - const tsi_handshaker_result* self, size_t* max_output_protected_frame_size, - tsi_frame_protector** protector) { - tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self; - return tsi_handshaker_create_frame_protector( - impl->wrapped, max_output_protected_frame_size, protector); -} - -static tsi_result adapter_result_get_unused_bytes( - const tsi_handshaker_result* self, const unsigned char** bytes, - size_t* byte_size) { - tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self; - *bytes = impl->unused_bytes; - *byte_size = impl->unused_bytes_size; - return TSI_OK; -} - -static void adapter_result_destroy(tsi_handshaker_result* self) { - tsi_adapter_handshaker_result* impl = - reinterpret_cast(self); - tsi_handshaker_destroy(impl->wrapped); - gpr_free(impl->unused_bytes); - gpr_free(self); -} - -static const tsi_handshaker_result_vtable result_vtable = { - adapter_result_extract_peer, - nullptr, /* create_zero_copy_grpc_protector */ - adapter_result_create_frame_protector, - adapter_result_get_unused_bytes, - adapter_result_destroy, -}; - -/* Ownership of wrapped tsi_handshaker is transferred to the result object. */ -static tsi_result tsi_adapter_create_handshaker_result( - tsi_handshaker* wrapped, const unsigned char* unused_bytes, - size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) { - if (wrapped == nullptr || - (unused_bytes_size > 0 && unused_bytes == nullptr)) { - return TSI_INVALID_ARGUMENT; - } - tsi_adapter_handshaker_result* impl = - static_cast(gpr_zalloc(sizeof(*impl))); - impl->base.vtable = &result_vtable; - impl->wrapped = wrapped; - impl->unused_bytes_size = unused_bytes_size; - if (unused_bytes_size > 0) { - impl->unused_bytes = - static_cast(gpr_malloc(unused_bytes_size)); - memcpy(impl->unused_bytes, unused_bytes, unused_bytes_size); - } else { - impl->unused_bytes = nullptr; - } - *handshaker_result = &impl->base; - return TSI_OK; -} - -/* --- tsi_adapter_handshaker implementation ---*/ - -typedef struct { - tsi_handshaker base; - tsi_handshaker* wrapped; - unsigned char* adapter_buffer; - size_t adapter_buffer_size; -} tsi_adapter_handshaker; - -static tsi_result adapter_get_bytes_to_send_to_peer(tsi_handshaker* self, - unsigned char* bytes, - size_t* bytes_size) { - return tsi_handshaker_get_bytes_to_send_to_peer( - tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size); -} - -static tsi_result adapter_process_bytes_from_peer(tsi_handshaker* self, - const unsigned char* bytes, - size_t* bytes_size) { - return tsi_handshaker_process_bytes_from_peer( - tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size); -} - -static tsi_result adapter_get_result(tsi_handshaker* self) { - return tsi_handshaker_get_result(tsi_adapter_handshaker_get_wrapped(self)); -} - -static tsi_result adapter_extract_peer(tsi_handshaker* self, tsi_peer* peer) { - return tsi_handshaker_extract_peer(tsi_adapter_handshaker_get_wrapped(self), - peer); -} - -static tsi_result adapter_create_frame_protector( - tsi_handshaker* self, size_t* max_protected_frame_size, - tsi_frame_protector** protector) { - return tsi_handshaker_create_frame_protector( - tsi_adapter_handshaker_get_wrapped(self), max_protected_frame_size, - protector); -} - -static void adapter_destroy(tsi_handshaker* self) { - tsi_adapter_handshaker* impl = - reinterpret_cast(self); - tsi_handshaker_destroy(impl->wrapped); - gpr_free(impl->adapter_buffer); - gpr_free(self); -} - -static tsi_result adapter_next( - tsi_handshaker* self, const unsigned char* received_bytes, - size_t received_bytes_size, const unsigned char** bytes_to_send, - size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result, - tsi_handshaker_on_next_done_cb cb, void* user_data) { - /* Input sanity check. */ - if ((received_bytes_size > 0 && received_bytes == nullptr) || - bytes_to_send == nullptr || bytes_to_send_size == nullptr || - handshaker_result == nullptr) { - return TSI_INVALID_ARGUMENT; - } - - /* If there are received bytes, process them first. */ - tsi_adapter_handshaker* impl = - reinterpret_cast(self); - tsi_result status = TSI_OK; - size_t bytes_consumed = received_bytes_size; - if (received_bytes_size > 0) { - status = tsi_handshaker_process_bytes_from_peer( - impl->wrapped, received_bytes, &bytes_consumed); - if (status != TSI_OK) return status; - } - - /* Get bytes to send to the peer, if available. */ - size_t offset = 0; - do { - size_t to_send_size = impl->adapter_buffer_size - offset; - status = tsi_handshaker_get_bytes_to_send_to_peer( - impl->wrapped, impl->adapter_buffer + offset, &to_send_size); - offset += to_send_size; - if (status == TSI_INCOMPLETE_DATA) { - impl->adapter_buffer_size *= 2; - impl->adapter_buffer = static_cast( - gpr_realloc(impl->adapter_buffer, impl->adapter_buffer_size)); - } - } while (status == TSI_INCOMPLETE_DATA); - if (status != TSI_OK) return status; - *bytes_to_send = impl->adapter_buffer; - *bytes_to_send_size = offset; - - /* If handshake completes, create tsi_handshaker_result. */ - if (tsi_handshaker_is_in_progress(impl->wrapped)) { - *handshaker_result = nullptr; - } else { - size_t unused_bytes_size = received_bytes_size - bytes_consumed; - const unsigned char* unused_bytes = - unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed; - status = tsi_adapter_create_handshaker_result( - impl->wrapped, unused_bytes, unused_bytes_size, handshaker_result); - if (status == TSI_OK) { - impl->base.handshaker_result_created = true; - impl->wrapped = nullptr; - } - } - return status; -} - -static const tsi_handshaker_vtable handshaker_vtable = { - adapter_get_bytes_to_send_to_peer, - adapter_process_bytes_from_peer, - adapter_get_result, - adapter_extract_peer, - adapter_create_frame_protector, - adapter_destroy, - adapter_next, -}; - -tsi_handshaker* tsi_create_adapter_handshaker(tsi_handshaker* wrapped) { - GPR_ASSERT(wrapped != nullptr); - tsi_adapter_handshaker* impl = - static_cast(gpr_zalloc(sizeof(*impl))); - impl->base.vtable = &handshaker_vtable; - impl->wrapped = wrapped; - impl->adapter_buffer_size = TSI_ADAPTER_INITIAL_BUFFER_SIZE; - impl->adapter_buffer = - static_cast(gpr_malloc(impl->adapter_buffer_size)); - return &impl->base; -} - -tsi_handshaker* tsi_adapter_handshaker_get_wrapped(tsi_handshaker* adapter) { - if (adapter == nullptr) return nullptr; - tsi_adapter_handshaker* impl = - reinterpret_cast(adapter); - return impl->wrapped; -} diff --git a/Sources/CgRPC/src/core/tsi/transport_security_adapter.h b/Sources/CgRPC/src/core/tsi/transport_security_adapter.h deleted file mode 100644 index f83ecc53e..000000000 --- a/Sources/CgRPC/src/core/tsi/transport_security_adapter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H -#define GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H - -#include - -#include "src/core/tsi/transport_security_interface.h" - -/* Create a tsi handshaker that takes an implementation of old interface and - converts into an implementation of new interface. In the old interface, - there are get_bytes_to_send_to_peer, process_bytes_from_peer, get_result, - extract_peer, and create_frame_protector. In the new interface, only next - method is needed. See transport_security_interface.h for details. Note that - this tsi adapter handshaker is temporary. It will be removed once TSI has - been fully migrated to the new interface. - Ownership of input tsi_handshaker is transferred to this new adapter. */ -tsi_handshaker* tsi_create_adapter_handshaker(tsi_handshaker* wrapped); - -/* Given a tsi adapter handshaker, return the original wrapped handshaker. The - adapter still owns the wrapped handshaker which should not be destroyed by - the caller. */ -tsi_handshaker* tsi_adapter_handshaker_get_wrapped(tsi_handshaker* adapter); - -#endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H */ diff --git a/Sources/CgRPC/src/core/tsi/transport_security_interface.h b/Sources/CgRPC/src/core/tsi/transport_security_interface.h index 8c1086693..7a0cdc345 100644 --- a/Sources/CgRPC/src/core/tsi/transport_security_interface.h +++ b/Sources/CgRPC/src/core/tsi/transport_security_interface.h @@ -42,7 +42,8 @@ typedef enum { TSI_PROTOCOL_FAILURE = 10, TSI_HANDSHAKE_IN_PROGRESS = 11, TSI_OUT_OF_RESOURCES = 12, - TSI_ASYNC = 13 + TSI_ASYNC = 13, + TSI_HANDSHAKE_SHUTDOWN = 14, } tsi_result; typedef enum { @@ -332,6 +333,8 @@ void tsi_handshaker_result_destroy(tsi_handshaker_result* self); ------------------------------------------------------------------------ */ typedef struct tsi_handshaker tsi_handshaker; +/* TODO(jiangtaoli2016): Cleans up deprecated methods when we are ready. */ + /* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead. Gets bytes that need to be sent to the peer. - bytes is the buffer that will be written with the data to be sent to the @@ -440,6 +443,13 @@ tsi_result tsi_handshaker_next( size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result, tsi_handshaker_on_next_done_cb cb, void* user_data); +/* This method shuts down a TSI handshake that is in progress. + * + * This method will be invoked when TSI handshake should be terminated before + * being finished in order to free any resources being used. + */ +void tsi_handshaker_shutdown(tsi_handshaker* self); + /* This method releases the tsi_handshaker object. After this method is called, no other method can be called on the object. */ void tsi_handshaker_destroy(tsi_handshaker* self); diff --git a/Sources/SwiftGRPC/Core/Roots.swift b/Sources/SwiftGRPC/Core/Roots.swift index fc26ed9b8..03664e618 100644 --- a/Sources/SwiftGRPC/Core/Roots.swift +++ b/Sources/SwiftGRPC/Core/Roots.swift @@ -368,36 +368,6 @@ OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- -# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association -# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association -# Label: "Visa eCommerce Root" -# Serial: 25952180776285836048024890241505565794 -# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 -# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 -# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- - # Issuer: CN=AAA Certificate Services O=Comodo CA Limited # Subject: CN=AAA Certificate Services O=Comodo CA Limited # Label: "Comodo AAA Services root" @@ -3773,169 +3743,6 @@ lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- -# Issuer: CN=Certplus Root CA G1 O=Certplus -# Subject: CN=Certplus Root CA G1 O=Certplus -# Label: "Certplus Root CA G1" -# Serial: 1491911565779898356709731176965615564637713 -# MD5 Fingerprint: 7f:09:9c:f7:d9:b9:5c:69:69:56:d5:37:3e:14:0d:42 -# SHA1 Fingerprint: 22:fd:d0:b7:fd:a2:4e:0d:ac:49:2c:a0:ac:a6:7b:6a:1f:e3:f7:66 -# SHA256 Fingerprint: 15:2a:40:2b:fc:df:2c:d5:48:05:4d:22:75:b3:9c:7f:ca:3e:c0:97:80:78:b0:f0:ea:76:e5:61:a6:c7:43:3e ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a -iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt -6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP -0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f -6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE -EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN -1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc -h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT -mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV -4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO -WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud -DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd -Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq -hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh -66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 -/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS -S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j -2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R -Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr -RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy -6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV -V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 -g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl -++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= ------END CERTIFICATE----- - -# Issuer: CN=Certplus Root CA G2 O=Certplus -# Subject: CN=Certplus Root CA G2 O=Certplus -# Label: "Certplus Root CA G2" -# Serial: 1492087096131536844209563509228951875861589 -# MD5 Fingerprint: a7:ee:c4:78:2d:1b:ee:2d:b9:29:ce:d6:a7:96:32:31 -# SHA1 Fingerprint: 4f:65:8e:1f:e9:06:d8:28:02:e9:54:47:41:c9:54:25:5d:69:cc:1a -# SHA256 Fingerprint: 6c:c0:50:41:e6:44:5e:74:69:6c:4c:fb:c9:f8:0f:54:3b:7e:ab:bb:44:b4:ce:6f:78:7c:6a:99:71:c4:2f:17 ------BEGIN CERTIFICATE----- -MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat -93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x -Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj -FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG -SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch -p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal -U5ORGpOucGpnutee5WEaXw== ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G1 O=OpenTrust -# Subject: CN=OpenTrust Root CA G1 O=OpenTrust -# Label: "OpenTrust Root CA G1" -# Serial: 1492036577811947013770400127034825178844775 -# MD5 Fingerprint: 76:00:cc:81:29:cd:55:5e:88:6a:7a:2e:f7:4d:39:da -# SHA1 Fingerprint: 79:91:e8:34:f7:e2:ee:dd:08:95:01:52:e9:55:2d:14:e9:58:d5:7e -# SHA256 Fingerprint: 56:c7:71:28:d9:8c:18:d9:1b:4c:fd:ff:bc:25:ee:91:03:d4:75:8e:a2:ab:ad:82:6a:90:f3:45:7d:46:0e:b4 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b -wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX -/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 -77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP -uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx -p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx -Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 -TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W -G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw -vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY -EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 -2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw -DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E -PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf -gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS -FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 -V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P -XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I -i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t -TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 -09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky -Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ -AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj -1oxx ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G2 O=OpenTrust -# Subject: CN=OpenTrust Root CA G2 O=OpenTrust -# Label: "OpenTrust Root CA G2" -# Serial: 1492012448042702096986875987676935573415441 -# MD5 Fingerprint: 57:24:b6:59:24:6b:ae:c8:fe:1c:0c:20:f2:c0:4e:eb -# SHA1 Fingerprint: 79:5f:88:60:c5:ab:7c:3d:92:e6:cb:f4:8d:e1:45:cd:11:ef:60:0b -# SHA256 Fingerprint: 27:99:58:29:fe:6a:75:15:c1:bf:e8:48:f9:c4:76:1d:b1:6c:22:59:29:25:7b:f4:0d:08:94:f2:9e:a8:ba:f2 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh -/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e -CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 -1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE -FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS -gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X -G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy -YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH -vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 -t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ -gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 -5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w -DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz -Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 -nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT -RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT -wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 -t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa -TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 -o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU -3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA -iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f -WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM -S1IK ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G3 O=OpenTrust -# Subject: CN=OpenTrust Root CA G3 O=OpenTrust -# Label: "OpenTrust Root CA G3" -# Serial: 1492104908271485653071219941864171170455615 -# MD5 Fingerprint: 21:37:b4:17:16:92:7b:67:46:70:a9:96:d7:a8:13:24 -# SHA1 Fingerprint: 6e:26:64:f3:56:bf:34:55:bf:d1:93:3f:7c:01:de:d8:13:da:8a:a6 -# SHA256 Fingerprint: b7:c3:62:31:70:6e:81:07:8c:36:7c:b8:96:19:8f:1e:32:08:dd:92:69:49:dd:8f:57:09:a4:10:f7:5b:62:92 ------BEGIN CERTIFICATE----- -MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx -CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U -cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow -QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl -blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm -3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d -oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 -DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK -BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q -j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx -4nxp5V2a+EEfOzmTk51V6s2N8fvB ------END CERTIFICATE----- - # Issuer: CN=ISRG Root X1 O=Internet Security Research Group # Subject: CN=ISRG Root X1 O=Internet Security Research Group # Label: "ISRG Root X1" @@ -4479,4 +4286,309 @@ MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== -----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Label: "GlobalSign Root CA - R6" +# Serial: 1417766617973444989252670301619537 +# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae +# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 +# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GC CA" +# Serial: 44084345621038548146064804565436152554 +# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 +# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 +# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R1 O=Google Trust Services LLC +# Subject: CN=GTS Root R1 O=Google Trust Services LLC +# Label: "GTS Root R1" +# Serial: 146587175971765017618439757810265552097 +# MD5 Fingerprint: 82:1a:ef:d4:d2:4a:f2:9f:e2:3d:97:06:14:70:72:85 +# SHA1 Fingerprint: e1:c9:50:e6:ef:22:f8:4c:56:45:72:8b:92:20:60:d7:d5:a7:a3:e8 +# SHA256 Fingerprint: 2a:57:54:71:e3:13:40:bc:21:58:1c:bd:2c:f1:3e:15:84:63:20:3e:ce:94:bc:f9:d3:cc:19:6b:f0:9a:54:72 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX +mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 +zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P +fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc +vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 +Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp +zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO +Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW +k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ +DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF +lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW +Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z +XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR +gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 +d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv +J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg +DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM ++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy +F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 +SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws +E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R2 O=Google Trust Services LLC +# Subject: CN=GTS Root R2 O=Google Trust Services LLC +# Label: "GTS Root R2" +# Serial: 146587176055767053814479386953112547951 +# MD5 Fingerprint: 44:ed:9a:0e:a4:09:3b:00:f2:ae:4c:a3:c6:61:b0:8b +# SHA1 Fingerprint: d2:73:96:2a:2a:5e:39:9f:73:3f:e1:c7:1e:64:3f:03:38:34:fc:4d +# SHA256 Fingerprint: c4:5d:7b:b0:8e:6d:67:e6:2e:42:35:11:0b:56:4e:5f:78:fd:92:ef:05:8c:84:0a:ea:4e:64:55:d7:58:5c:60 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg +GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu +XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd +re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu +PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 +mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K +8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj +x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR +nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 +kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok +twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp +8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT +z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA +pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb +pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB +R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R +RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk +0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC +5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF +izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn +yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R3 O=Google Trust Services LLC +# Subject: CN=GTS Root R3 O=Google Trust Services LLC +# Label: "GTS Root R3" +# Serial: 146587176140553309517047991083707763997 +# MD5 Fingerprint: 1a:79:5b:6b:04:52:9c:5d:c7:74:33:1b:25:9a:f9:25 +# SHA1 Fingerprint: 30:d4:24:6f:07:ff:db:91:89:8a:0b:e9:49:66:11:eb:8c:5e:46:e5 +# SHA256 Fingerprint: 15:d5:b8:77:46:19:ea:7d:54:ce:1c:a6:d0:b0:c4:03:e0:37:a9:17:f1:31:e8:a0:4e:1e:6b:7a:71:ba:bc:e5 +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A +DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk +fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA +njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R4 O=Google Trust Services LLC +# Subject: CN=GTS Root R4 O=Google Trust Services LLC +# Label: "GTS Root R4" +# Serial: 146587176229350439916519468929765261721 +# MD5 Fingerprint: 5d:b6:6a:c4:60:17:24:6a:1a:99:a8:4b:ee:5e:b4:26 +# SHA1 Fingerprint: 2a:1d:60:27:d9:4a:b1:0a:1c:4d:91:5c:cd:33:a0:cb:3e:2d:54:cb +# SHA256 Fingerprint: 71:cc:a5:39:1f:9e:79:4b:04:80:25:30:b3:63:e1:21:da:8a:30:43:bb:26:66:2f:ea:4d:ca:7f:c9:51:a4:bd +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l +xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 +CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx +sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Global G2 Root O=UniTrust +# Subject: CN=UCA Global G2 Root O=UniTrust +# Label: "UCA Global G2 Root" +# Serial: 124779693093741543919145257850076631279 +# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 +# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a +# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Extended Validation Root O=UniTrust +# Subject: CN=UCA Extended Validation Root O=UniTrust +# Label: "UCA Extended Validation Root" +# Serial: 106100277556486529736699587978573607008 +# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 +# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a +# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- + +# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Label: "Certigna Root CA" +# Serial: 269714418870597844693661054334862075617 +# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 +# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 +# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- """ diff --git a/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap b/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap index d627df21e..42244b29d 100644 --- a/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap +++ b/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap @@ -1,4 +1,4 @@ module CNIONghttp2 { - umbrella "/Users/mrebello/Development/grpc-swift/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include" + umbrella "/Users/timburks/Desktop/grpc-swift/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include" export * } diff --git a/SwiftGRPC-Carthage.xcodeproj/project.pbxproj b/SwiftGRPC-Carthage.xcodeproj/project.pbxproj index ddeba1f81..83c5fb674 100644 --- a/SwiftGRPC-Carthage.xcodeproj/project.pbxproj +++ b/SwiftGRPC-Carthage.xcodeproj/project.pbxproj @@ -7,2312 +7,2400 @@ objects = { /* Begin PBXBuildFile section */ - 15DDE0819E918F1958E0892B /* cgrpc.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_463 /* cgrpc.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1406 /* a_bitstr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_611 /* a_bitstr.c */; }; - OBJ_1407 /* a_bool.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_612 /* a_bool.c */; }; - OBJ_1408 /* a_d2i_fp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_613 /* a_d2i_fp.c */; }; - OBJ_1409 /* a_dup.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_614 /* a_dup.c */; }; - OBJ_1410 /* a_enum.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_615 /* a_enum.c */; }; - OBJ_1411 /* a_gentm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_616 /* a_gentm.c */; }; - OBJ_1412 /* a_i2d_fp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_617 /* a_i2d_fp.c */; }; - OBJ_1413 /* a_int.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_618 /* a_int.c */; }; - OBJ_1414 /* a_mbstr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_619 /* a_mbstr.c */; }; - OBJ_1415 /* a_object.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_620 /* a_object.c */; }; - OBJ_1416 /* a_octet.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_621 /* a_octet.c */; }; - OBJ_1417 /* a_print.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_622 /* a_print.c */; }; - OBJ_1418 /* a_strnid.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_623 /* a_strnid.c */; }; - OBJ_1419 /* a_time.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_624 /* a_time.c */; }; - OBJ_1420 /* a_type.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_625 /* a_type.c */; }; - OBJ_1421 /* a_utctm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_626 /* a_utctm.c */; }; - OBJ_1422 /* a_utf8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_627 /* a_utf8.c */; }; - OBJ_1423 /* asn1_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_628 /* asn1_lib.c */; }; - OBJ_1424 /* asn1_par.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_629 /* asn1_par.c */; }; - OBJ_1425 /* asn_pack.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_630 /* asn_pack.c */; }; - OBJ_1426 /* f_enum.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_631 /* f_enum.c */; }; - OBJ_1427 /* f_int.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_632 /* f_int.c */; }; - OBJ_1428 /* f_string.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_633 /* f_string.c */; }; - OBJ_1429 /* tasn_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_634 /* tasn_dec.c */; }; - OBJ_1430 /* tasn_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_635 /* tasn_enc.c */; }; - OBJ_1431 /* tasn_fre.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_636 /* tasn_fre.c */; }; - OBJ_1432 /* tasn_new.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_637 /* tasn_new.c */; }; - OBJ_1433 /* tasn_typ.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_638 /* tasn_typ.c */; }; - OBJ_1434 /* tasn_utl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_639 /* tasn_utl.c */; }; - OBJ_1435 /* time_support.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_640 /* time_support.c */; }; - OBJ_1436 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_642 /* base64.c */; }; - OBJ_1437 /* bio.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_644 /* bio.c */; }; - OBJ_1438 /* bio_mem.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_645 /* bio_mem.c */; }; - OBJ_1439 /* connect.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_646 /* connect.c */; }; - OBJ_1440 /* fd.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_647 /* fd.c */; }; - OBJ_1441 /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_648 /* file.c */; }; - OBJ_1442 /* hexdump.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_649 /* hexdump.c */; }; - OBJ_1443 /* pair.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_650 /* pair.c */; }; - OBJ_1444 /* printf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_651 /* printf.c */; }; - OBJ_1445 /* socket.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_652 /* socket.c */; }; - OBJ_1446 /* socket_helper.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_653 /* socket_helper.c */; }; - OBJ_1447 /* bn_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_655 /* bn_asn1.c */; }; - OBJ_1448 /* convert.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_656 /* convert.c */; }; - OBJ_1449 /* buf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_658 /* buf.c */; }; - OBJ_1450 /* asn1_compat.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_660 /* asn1_compat.c */; }; - OBJ_1451 /* ber.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_661 /* ber.c */; }; - OBJ_1452 /* cbb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_662 /* cbb.c */; }; - OBJ_1453 /* cbs.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_663 /* cbs.c */; }; - OBJ_1454 /* chacha.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_665 /* chacha.c */; }; - OBJ_1455 /* cipher_extra.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_667 /* cipher_extra.c */; }; - OBJ_1456 /* derive_key.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_668 /* derive_key.c */; }; - OBJ_1457 /* e_aesctrhmac.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_669 /* e_aesctrhmac.c */; }; - OBJ_1458 /* e_aesgcmsiv.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_670 /* e_aesgcmsiv.c */; }; - OBJ_1459 /* e_chacha20poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_671 /* e_chacha20poly1305.c */; }; - OBJ_1460 /* e_null.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_672 /* e_null.c */; }; - OBJ_1461 /* e_rc2.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_673 /* e_rc2.c */; }; - OBJ_1462 /* e_rc4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_674 /* e_rc4.c */; }; - OBJ_1463 /* e_ssl3.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_675 /* e_ssl3.c */; }; - OBJ_1464 /* e_tls.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_676 /* e_tls.c */; }; - OBJ_1465 /* tls_cbc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_677 /* tls_cbc.c */; }; - OBJ_1466 /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_679 /* cmac.c */; }; - OBJ_1467 /* conf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_681 /* conf.c */; }; - OBJ_1468 /* cpu-aarch64-linux.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_682 /* cpu-aarch64-linux.c */; }; - OBJ_1469 /* cpu-arm-linux.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_683 /* cpu-arm-linux.c */; }; - OBJ_1470 /* cpu-arm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_684 /* cpu-arm.c */; }; - OBJ_1471 /* cpu-intel.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_685 /* cpu-intel.c */; }; - OBJ_1472 /* cpu-ppc64le.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_686 /* cpu-ppc64le.c */; }; - OBJ_1473 /* crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_687 /* crypto.c */; }; - OBJ_1474 /* spake25519.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_689 /* spake25519.c */; }; - OBJ_1475 /* x25519-x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_690 /* x25519-x86_64.c */; }; - OBJ_1476 /* check.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_692 /* check.c */; }; - OBJ_1477 /* dh.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_693 /* dh.c */; }; - OBJ_1478 /* dh_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_694 /* dh_asn1.c */; }; - OBJ_1479 /* params.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_695 /* params.c */; }; - OBJ_1480 /* digest_extra.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_697 /* digest_extra.c */; }; - OBJ_1481 /* dsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_699 /* dsa.c */; }; - OBJ_1482 /* dsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_700 /* dsa_asn1.c */; }; - OBJ_1483 /* ec_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_702 /* ec_asn1.c */; }; - OBJ_1484 /* ecdh.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_704 /* ecdh.c */; }; - OBJ_1485 /* ecdsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_706 /* ecdsa_asn1.c */; }; - OBJ_1486 /* engine.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_708 /* engine.c */; }; - OBJ_1487 /* err.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_710 /* err.c */; }; - OBJ_1488 /* err_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_711 /* err_data.c */; }; - OBJ_1489 /* digestsign.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_713 /* digestsign.c */; }; - OBJ_1490 /* evp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_714 /* evp.c */; }; - OBJ_1491 /* evp_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_715 /* evp_asn1.c */; }; - OBJ_1492 /* evp_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_716 /* evp_ctx.c */; }; - OBJ_1493 /* p_dsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_717 /* p_dsa_asn1.c */; }; - OBJ_1494 /* p_ec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_718 /* p_ec.c */; }; - OBJ_1495 /* p_ec_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_719 /* p_ec_asn1.c */; }; - OBJ_1496 /* p_ed25519.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_720 /* p_ed25519.c */; }; - OBJ_1497 /* p_ed25519_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_721 /* p_ed25519_asn1.c */; }; - OBJ_1498 /* p_rsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_722 /* p_rsa.c */; }; - OBJ_1499 /* p_rsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_723 /* p_rsa_asn1.c */; }; - OBJ_1500 /* pbkdf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_724 /* pbkdf.c */; }; - OBJ_1501 /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_725 /* print.c */; }; - OBJ_1502 /* scrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_726 /* scrypt.c */; }; - OBJ_1503 /* sign.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_727 /* sign.c */; }; - OBJ_1504 /* ex_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_728 /* ex_data.c */; }; - OBJ_1505 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_731 /* aes.c */; }; - OBJ_1506 /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_732 /* key_wrap.c */; }; - OBJ_1507 /* mode_wrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_733 /* mode_wrappers.c */; }; - OBJ_1508 /* add.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_735 /* add.c */; }; - OBJ_1509 /* bn.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_736 /* bn.c */; }; - OBJ_1510 /* bytes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_737 /* bytes.c */; }; - OBJ_1511 /* cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_738 /* cmp.c */; }; - OBJ_1512 /* ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_739 /* ctx.c */; }; - OBJ_1513 /* div.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_740 /* div.c */; }; - OBJ_1514 /* exponentiation.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_741 /* exponentiation.c */; }; - OBJ_1515 /* gcd.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_742 /* gcd.c */; }; - OBJ_1516 /* generic.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_743 /* generic.c */; }; - OBJ_1517 /* jacobi.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_744 /* jacobi.c */; }; - OBJ_1518 /* montgomery.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_745 /* montgomery.c */; }; - OBJ_1519 /* montgomery_inv.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_746 /* montgomery_inv.c */; }; - OBJ_1520 /* mul.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_747 /* mul.c */; }; - OBJ_1521 /* prime.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_748 /* prime.c */; }; - OBJ_1522 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_749 /* random.c */; }; - OBJ_1523 /* rsaz_exp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_750 /* rsaz_exp.c */; }; - OBJ_1524 /* shift.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_751 /* shift.c */; }; - OBJ_1525 /* sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_752 /* sqrt.c */; }; - OBJ_1526 /* aead.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_754 /* aead.c */; }; - OBJ_1527 /* cipher.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_755 /* cipher.c */; }; - OBJ_1528 /* e_aes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_756 /* e_aes.c */; }; - OBJ_1529 /* e_des.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_757 /* e_des.c */; }; - OBJ_1530 /* des.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_759 /* des.c */; }; - OBJ_1531 /* digest.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_761 /* digest.c */; }; - OBJ_1532 /* digests.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_762 /* digests.c */; }; - OBJ_1533 /* ec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_764 /* ec.c */; }; - OBJ_1534 /* ec_key.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_765 /* ec_key.c */; }; - OBJ_1535 /* ec_montgomery.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_766 /* ec_montgomery.c */; }; - OBJ_1536 /* oct.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_767 /* oct.c */; }; - OBJ_1537 /* p224-64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_768 /* p224-64.c */; }; - OBJ_1538 /* p256-64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_769 /* p256-64.c */; }; - OBJ_1539 /* p256-x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_770 /* p256-x86_64.c */; }; - OBJ_1540 /* simple.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_771 /* simple.c */; }; - OBJ_1541 /* util-64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_772 /* util-64.c */; }; - OBJ_1542 /* wnaf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_773 /* wnaf.c */; }; - OBJ_1543 /* ecdsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_775 /* ecdsa.c */; }; - OBJ_1544 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_777 /* hmac.c */; }; - OBJ_1545 /* is_fips.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_778 /* is_fips.c */; }; - OBJ_1546 /* md4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_780 /* md4.c */; }; - OBJ_1547 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_782 /* md5.c */; }; - OBJ_1548 /* cbc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_784 /* cbc.c */; }; - OBJ_1549 /* cfb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_785 /* cfb.c */; }; - OBJ_1550 /* ctr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_786 /* ctr.c */; }; - OBJ_1551 /* gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_787 /* gcm.c */; }; - OBJ_1552 /* ofb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_788 /* ofb.c */; }; - OBJ_1553 /* polyval.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_789 /* polyval.c */; }; - OBJ_1554 /* ctrdrbg.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_791 /* ctrdrbg.c */; }; - OBJ_1555 /* rand.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_792 /* rand.c */; }; - OBJ_1556 /* urandom.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_793 /* urandom.c */; }; - OBJ_1557 /* blinding.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_795 /* blinding.c */; }; - OBJ_1558 /* padding.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_796 /* padding.c */; }; - OBJ_1559 /* rsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_797 /* rsa.c */; }; - OBJ_1560 /* rsa_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_798 /* rsa_impl.c */; }; - OBJ_1561 /* sha1-altivec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_800 /* sha1-altivec.c */; }; - OBJ_1562 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_801 /* sha1.c */; }; - OBJ_1563 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_802 /* sha256.c */; }; - OBJ_1564 /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_803 /* sha512.c */; }; - OBJ_1565 /* hkdf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_805 /* hkdf.c */; }; - OBJ_1566 /* lhash.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_807 /* lhash.c */; }; - OBJ_1567 /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_808 /* mem.c */; }; - OBJ_1568 /* obj.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_810 /* obj.c */; }; - OBJ_1569 /* obj_xref.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_811 /* obj_xref.c */; }; - OBJ_1570 /* pem_all.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_813 /* pem_all.c */; }; - OBJ_1571 /* pem_info.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_814 /* pem_info.c */; }; - OBJ_1572 /* pem_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_815 /* pem_lib.c */; }; - OBJ_1573 /* pem_oth.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_816 /* pem_oth.c */; }; - OBJ_1574 /* pem_pk8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_817 /* pem_pk8.c */; }; - OBJ_1575 /* pem_pkey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_818 /* pem_pkey.c */; }; - OBJ_1576 /* pem_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_819 /* pem_x509.c */; }; - OBJ_1577 /* pem_xaux.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_820 /* pem_xaux.c */; }; - OBJ_1578 /* pkcs7.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_822 /* pkcs7.c */; }; - OBJ_1579 /* pkcs7_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_823 /* pkcs7_x509.c */; }; - OBJ_1580 /* p5_pbev2.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_825 /* p5_pbev2.c */; }; - OBJ_1581 /* pkcs8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_826 /* pkcs8.c */; }; - OBJ_1582 /* pkcs8_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_827 /* pkcs8_x509.c */; }; - OBJ_1583 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_829 /* poly1305.c */; }; - OBJ_1584 /* poly1305_arm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_830 /* poly1305_arm.c */; }; - OBJ_1585 /* poly1305_vec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_831 /* poly1305_vec.c */; }; - OBJ_1586 /* pool.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_833 /* pool.c */; }; - OBJ_1587 /* deterministic.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_835 /* deterministic.c */; }; - OBJ_1588 /* forkunsafe.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_836 /* forkunsafe.c */; }; - OBJ_1589 /* fuchsia.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_837 /* fuchsia.c */; }; - OBJ_1590 /* rand_extra.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_838 /* rand_extra.c */; }; - OBJ_1591 /* windows.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_839 /* windows.c */; }; - OBJ_1592 /* rc4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_841 /* rc4.c */; }; - OBJ_1593 /* refcount_c11.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_842 /* refcount_c11.c */; }; - OBJ_1594 /* refcount_lock.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_843 /* refcount_lock.c */; }; - OBJ_1595 /* rsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_845 /* rsa_asn1.c */; }; - OBJ_1596 /* stack.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_847 /* stack.c */; }; - OBJ_1597 /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_848 /* thread.c */; }; - OBJ_1598 /* thread_none.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_849 /* thread_none.c */; }; - OBJ_1599 /* thread_pthread.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_850 /* thread_pthread.c */; }; - OBJ_1600 /* thread_win.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_851 /* thread_win.c */; }; - OBJ_1601 /* a_digest.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_853 /* a_digest.c */; }; - OBJ_1602 /* a_sign.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_854 /* a_sign.c */; }; - OBJ_1603 /* a_strex.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_855 /* a_strex.c */; }; - OBJ_1604 /* a_verify.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_856 /* a_verify.c */; }; - OBJ_1605 /* algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_857 /* algorithm.c */; }; - OBJ_1606 /* asn1_gen.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_858 /* asn1_gen.c */; }; - OBJ_1607 /* by_dir.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_859 /* by_dir.c */; }; - OBJ_1608 /* by_file.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_860 /* by_file.c */; }; - OBJ_1609 /* i2d_pr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_861 /* i2d_pr.c */; }; - OBJ_1610 /* rsa_pss.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_862 /* rsa_pss.c */; }; - OBJ_1611 /* t_crl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_863 /* t_crl.c */; }; - OBJ_1612 /* t_req.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_864 /* t_req.c */; }; - OBJ_1613 /* t_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_865 /* t_x509.c */; }; - OBJ_1614 /* t_x509a.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_866 /* t_x509a.c */; }; - OBJ_1615 /* x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_867 /* x509.c */; }; - OBJ_1616 /* x509_att.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_868 /* x509_att.c */; }; - OBJ_1617 /* x509_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_869 /* x509_cmp.c */; }; - OBJ_1618 /* x509_d2.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_870 /* x509_d2.c */; }; - OBJ_1619 /* x509_def.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_871 /* x509_def.c */; }; - OBJ_1620 /* x509_ext.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_872 /* x509_ext.c */; }; - OBJ_1621 /* x509_lu.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_873 /* x509_lu.c */; }; - OBJ_1622 /* x509_obj.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_874 /* x509_obj.c */; }; - OBJ_1623 /* x509_r2x.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_875 /* x509_r2x.c */; }; - OBJ_1624 /* x509_req.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_876 /* x509_req.c */; }; - OBJ_1625 /* x509_set.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_877 /* x509_set.c */; }; - OBJ_1626 /* x509_trs.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_878 /* x509_trs.c */; }; - OBJ_1627 /* x509_txt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_879 /* x509_txt.c */; }; - OBJ_1628 /* x509_v3.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_880 /* x509_v3.c */; }; - OBJ_1629 /* x509_vfy.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_881 /* x509_vfy.c */; }; - OBJ_1630 /* x509_vpm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_882 /* x509_vpm.c */; }; - OBJ_1631 /* x509cset.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_883 /* x509cset.c */; }; - OBJ_1632 /* x509name.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_884 /* x509name.c */; }; - OBJ_1633 /* x509rset.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_885 /* x509rset.c */; }; - OBJ_1634 /* x509spki.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_886 /* x509spki.c */; }; - OBJ_1635 /* x_algor.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_887 /* x_algor.c */; }; - OBJ_1636 /* x_all.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_888 /* x_all.c */; }; - OBJ_1637 /* x_attrib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_889 /* x_attrib.c */; }; - OBJ_1638 /* x_crl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_890 /* x_crl.c */; }; - OBJ_1639 /* x_exten.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_891 /* x_exten.c */; }; - OBJ_1640 /* x_info.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_892 /* x_info.c */; }; - OBJ_1641 /* x_name.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_893 /* x_name.c */; }; - OBJ_1642 /* x_pkey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_894 /* x_pkey.c */; }; - OBJ_1643 /* x_pubkey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_895 /* x_pubkey.c */; }; - OBJ_1644 /* x_req.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_896 /* x_req.c */; }; - OBJ_1645 /* x_sig.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_897 /* x_sig.c */; }; - OBJ_1646 /* x_spki.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_898 /* x_spki.c */; }; - OBJ_1647 /* x_val.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_899 /* x_val.c */; }; - OBJ_1648 /* x_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_900 /* x_x509.c */; }; - OBJ_1649 /* x_x509a.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_901 /* x_x509a.c */; }; - OBJ_1650 /* pcy_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_903 /* pcy_cache.c */; }; - OBJ_1651 /* pcy_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_904 /* pcy_data.c */; }; - OBJ_1652 /* pcy_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_905 /* pcy_lib.c */; }; - OBJ_1653 /* pcy_map.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_906 /* pcy_map.c */; }; - OBJ_1654 /* pcy_node.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_907 /* pcy_node.c */; }; - OBJ_1655 /* pcy_tree.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_908 /* pcy_tree.c */; }; - OBJ_1656 /* v3_akey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_909 /* v3_akey.c */; }; - OBJ_1657 /* v3_akeya.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_910 /* v3_akeya.c */; }; - OBJ_1658 /* v3_alt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_911 /* v3_alt.c */; }; - OBJ_1659 /* v3_bcons.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_912 /* v3_bcons.c */; }; - OBJ_1660 /* v3_bitst.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_913 /* v3_bitst.c */; }; - OBJ_1661 /* v3_conf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_914 /* v3_conf.c */; }; - OBJ_1662 /* v3_cpols.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_915 /* v3_cpols.c */; }; - OBJ_1663 /* v3_crld.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_916 /* v3_crld.c */; }; - OBJ_1664 /* v3_enum.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_917 /* v3_enum.c */; }; - OBJ_1665 /* v3_extku.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_918 /* v3_extku.c */; }; - OBJ_1666 /* v3_genn.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_919 /* v3_genn.c */; }; - OBJ_1667 /* v3_ia5.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_920 /* v3_ia5.c */; }; - OBJ_1668 /* v3_info.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_921 /* v3_info.c */; }; - OBJ_1669 /* v3_int.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_922 /* v3_int.c */; }; - OBJ_1670 /* v3_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_923 /* v3_lib.c */; }; - OBJ_1671 /* v3_ncons.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_924 /* v3_ncons.c */; }; - OBJ_1672 /* v3_pci.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_925 /* v3_pci.c */; }; - OBJ_1673 /* v3_pcia.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_926 /* v3_pcia.c */; }; - OBJ_1674 /* v3_pcons.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_927 /* v3_pcons.c */; }; - OBJ_1675 /* v3_pku.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_928 /* v3_pku.c */; }; - OBJ_1676 /* v3_pmaps.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_929 /* v3_pmaps.c */; }; - OBJ_1677 /* v3_prn.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_930 /* v3_prn.c */; }; - OBJ_1678 /* v3_purp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_931 /* v3_purp.c */; }; - OBJ_1679 /* v3_skey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_932 /* v3_skey.c */; }; - OBJ_1680 /* v3_sxnet.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_933 /* v3_sxnet.c */; }; - OBJ_1681 /* v3_utl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_934 /* v3_utl.c */; }; - OBJ_1682 /* err_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_935 /* err_data.c */; }; - OBJ_1683 /* bio_ssl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_937 /* bio_ssl.cc */; }; - OBJ_1684 /* custom_extensions.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_938 /* custom_extensions.cc */; }; - OBJ_1685 /* d1_both.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_939 /* d1_both.cc */; }; - OBJ_1686 /* d1_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_940 /* d1_lib.cc */; }; - OBJ_1687 /* d1_pkt.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_941 /* d1_pkt.cc */; }; - OBJ_1688 /* d1_srtp.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_942 /* d1_srtp.cc */; }; - OBJ_1689 /* dtls_method.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_943 /* dtls_method.cc */; }; - OBJ_1690 /* dtls_record.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_944 /* dtls_record.cc */; }; - OBJ_1691 /* handshake.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_945 /* handshake.cc */; }; - OBJ_1692 /* handshake_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_946 /* handshake_client.cc */; }; - OBJ_1693 /* handshake_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_947 /* handshake_server.cc */; }; - OBJ_1694 /* s3_both.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_948 /* s3_both.cc */; }; - OBJ_1695 /* s3_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_949 /* s3_lib.cc */; }; - OBJ_1696 /* s3_pkt.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_950 /* s3_pkt.cc */; }; - OBJ_1697 /* ssl_aead_ctx.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_951 /* ssl_aead_ctx.cc */; }; - OBJ_1698 /* ssl_asn1.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_952 /* ssl_asn1.cc */; }; - OBJ_1699 /* ssl_buffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_953 /* ssl_buffer.cc */; }; - OBJ_1700 /* ssl_cert.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_954 /* ssl_cert.cc */; }; - OBJ_1701 /* ssl_cipher.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_955 /* ssl_cipher.cc */; }; - OBJ_1702 /* ssl_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_956 /* ssl_file.cc */; }; - OBJ_1703 /* ssl_key_share.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_957 /* ssl_key_share.cc */; }; - OBJ_1704 /* ssl_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_958 /* ssl_lib.cc */; }; - OBJ_1705 /* ssl_privkey.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_959 /* ssl_privkey.cc */; }; - OBJ_1706 /* ssl_session.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_960 /* ssl_session.cc */; }; - OBJ_1707 /* ssl_stat.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_961 /* ssl_stat.cc */; }; - OBJ_1708 /* ssl_transcript.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_962 /* ssl_transcript.cc */; }; - OBJ_1709 /* ssl_versions.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_963 /* ssl_versions.cc */; }; - OBJ_1710 /* ssl_x509.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_964 /* ssl_x509.cc */; }; - OBJ_1711 /* t1_enc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_965 /* t1_enc.cc */; }; - OBJ_1712 /* t1_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_966 /* t1_lib.cc */; }; - OBJ_1713 /* tls13_both.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_967 /* tls13_both.cc */; }; - OBJ_1714 /* tls13_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_968 /* tls13_client.cc */; }; - OBJ_1715 /* tls13_enc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_969 /* tls13_enc.cc */; }; - OBJ_1716 /* tls13_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_970 /* tls13_server.cc */; }; - OBJ_1717 /* tls_method.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_971 /* tls_method.cc */; }; - OBJ_1718 /* tls_record.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_972 /* tls_record.cc */; }; - OBJ_1719 /* curve25519.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_975 /* curve25519.c */; }; - OBJ_1726 /* c-atomics.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1223 /* c-atomics.c */; }; - OBJ_1728 /* CNIOAtomics.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1225 /* CNIOAtomics.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1729 /* cpp_magic.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1226 /* cpp_magic.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1736 /* shim.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1128 /* shim.c */; }; - OBJ_1738 /* CNIODarwin.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1130 /* CNIODarwin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1745 /* c_nio_http_parser.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1196 /* c_nio_http_parser.c */; }; - OBJ_1747 /* c_nio_http_parser.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1198 /* c_nio_http_parser.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1748 /* CNIOHTTPParser.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1199 /* CNIOHTTPParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1755 /* ifaddrs-android.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1229 /* ifaddrs-android.c */; }; - OBJ_1756 /* shim.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1230 /* shim.c */; }; - OBJ_1758 /* CNIOLinux.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1232 /* CNIOLinux.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1759 /* ifaddrs-android.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1233 /* ifaddrs-android.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1766 /* shims.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1098 /* shims.c */; }; - OBJ_1773 /* c_nio_sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1206 /* c_nio_sha1.c */; }; - OBJ_1775 /* CNIOSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1208 /* CNIOSHA1.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1782 /* empty.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1132 /* empty.c */; }; - OBJ_1784 /* CNIOZlib.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1134 /* CNIOZlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; - OBJ_1791 /* byte_buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_27 /* byte_buffer.c */; }; - OBJ_1792 /* call.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* call.c */; }; - OBJ_1793 /* channel.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_29 /* channel.c */; }; - OBJ_1794 /* completion_queue.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_30 /* completion_queue.c */; }; - OBJ_1795 /* event.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_31 /* event.c */; }; - OBJ_1796 /* handler.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_32 /* handler.c */; }; - OBJ_1797 /* internal.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_33 /* internal.c */; }; - OBJ_1798 /* metadata.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_34 /* metadata.c */; }; - OBJ_1799 /* mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_35 /* mutex.c */; }; - OBJ_1800 /* observers.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_36 /* observers.c */; }; - OBJ_1801 /* operations.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_37 /* operations.c */; }; - OBJ_1802 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_38 /* server.c */; }; - OBJ_1803 /* grpc_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_43 /* grpc_context.cc */; }; - OBJ_1804 /* backup_poller.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_46 /* backup_poller.cc */; }; - OBJ_1805 /* channel_connectivity.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_47 /* channel_connectivity.cc */; }; - OBJ_1806 /* client_channel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_48 /* client_channel.cc */; }; - OBJ_1807 /* client_channel_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_49 /* client_channel_factory.cc */; }; - OBJ_1808 /* client_channel_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_50 /* client_channel_plugin.cc */; }; - OBJ_1809 /* connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_51 /* connector.cc */; }; - OBJ_1810 /* http_connect_handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_52 /* http_connect_handshaker.cc */; }; - OBJ_1811 /* http_proxy.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_53 /* http_proxy.cc */; }; - OBJ_1812 /* lb_policy.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_54 /* lb_policy.cc */; }; - OBJ_1813 /* client_load_reporting_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_57 /* client_load_reporting_filter.cc */; }; - OBJ_1814 /* grpclb.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_58 /* grpclb.cc */; }; - OBJ_1815 /* grpclb_channel_secure.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_59 /* grpclb_channel_secure.cc */; }; - OBJ_1816 /* grpclb_client_stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_60 /* grpclb_client_stats.cc */; }; - OBJ_1817 /* load_balancer_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_61 /* load_balancer_api.cc */; }; - OBJ_1818 /* load_balancer.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_66 /* load_balancer.pb.c */; }; - OBJ_1819 /* pick_first.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_68 /* pick_first.cc */; }; - OBJ_1820 /* round_robin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_70 /* round_robin.cc */; }; - OBJ_1821 /* lb_policy_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_71 /* lb_policy_factory.cc */; }; - OBJ_1822 /* lb_policy_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_72 /* lb_policy_registry.cc */; }; - OBJ_1823 /* method_params.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_73 /* method_params.cc */; }; - OBJ_1824 /* parse_address.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_74 /* parse_address.cc */; }; - OBJ_1825 /* proxy_mapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_75 /* proxy_mapper.cc */; }; - OBJ_1826 /* proxy_mapper_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_76 /* proxy_mapper_registry.cc */; }; - OBJ_1827 /* resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_77 /* resolver.cc */; }; - OBJ_1828 /* dns_resolver_ares.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_81 /* dns_resolver_ares.cc */; }; - OBJ_1829 /* grpc_ares_ev_driver_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_82 /* grpc_ares_ev_driver_posix.cc */; }; - OBJ_1830 /* grpc_ares_wrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_83 /* grpc_ares_wrapper.cc */; }; - OBJ_1831 /* grpc_ares_wrapper_fallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_84 /* grpc_ares_wrapper_fallback.cc */; }; - OBJ_1832 /* dns_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_86 /* dns_resolver.cc */; }; - OBJ_1833 /* fake_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_88 /* fake_resolver.cc */; }; - OBJ_1834 /* sockaddr_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_90 /* sockaddr_resolver.cc */; }; - OBJ_1835 /* resolver_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_91 /* resolver_registry.cc */; }; - OBJ_1836 /* retry_throttle.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_92 /* retry_throttle.cc */; }; - OBJ_1837 /* subchannel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_93 /* subchannel.cc */; }; - OBJ_1838 /* subchannel_index.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_94 /* subchannel_index.cc */; }; - OBJ_1839 /* uri_parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_95 /* uri_parser.cc */; }; - OBJ_1840 /* deadline_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_97 /* deadline_filter.cc */; }; - OBJ_1841 /* http_client_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_100 /* http_client_filter.cc */; }; - OBJ_1842 /* client_authority_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_101 /* client_authority_filter.cc */; }; - OBJ_1843 /* http_filters_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_102 /* http_filters_plugin.cc */; }; - OBJ_1844 /* message_compress_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_104 /* message_compress_filter.cc */; }; - OBJ_1845 /* http_server_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_106 /* http_server_filter.cc */; }; - OBJ_1846 /* server_load_reporting_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_108 /* server_load_reporting_filter.cc */; }; - OBJ_1847 /* server_load_reporting_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_109 /* server_load_reporting_plugin.cc */; }; - OBJ_1848 /* max_age_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_111 /* max_age_filter.cc */; }; - OBJ_1849 /* message_size_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_113 /* message_size_filter.cc */; }; - OBJ_1850 /* workaround_cronet_compression_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_115 /* workaround_cronet_compression_filter.cc */; }; - OBJ_1851 /* workaround_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_116 /* workaround_utils.cc */; }; - OBJ_1852 /* alpn.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_120 /* alpn.cc */; }; - OBJ_1853 /* authority.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_122 /* authority.cc */; }; - OBJ_1854 /* chttp2_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_123 /* chttp2_connector.cc */; }; - OBJ_1855 /* channel_create.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_125 /* channel_create.cc */; }; - OBJ_1856 /* channel_create_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_126 /* channel_create_posix.cc */; }; - OBJ_1857 /* secure_channel_create.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_128 /* secure_channel_create.cc */; }; - OBJ_1858 /* chttp2_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_130 /* chttp2_server.cc */; }; - OBJ_1859 /* server_chttp2.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_132 /* server_chttp2.cc */; }; - OBJ_1860 /* server_chttp2_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_133 /* server_chttp2_posix.cc */; }; - OBJ_1861 /* server_secure_chttp2.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_135 /* server_secure_chttp2.cc */; }; - OBJ_1862 /* bin_decoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_137 /* bin_decoder.cc */; }; - OBJ_1863 /* bin_encoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_138 /* bin_encoder.cc */; }; - OBJ_1864 /* chttp2_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_139 /* chttp2_plugin.cc */; }; - OBJ_1865 /* chttp2_transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_140 /* chttp2_transport.cc */; }; - OBJ_1866 /* flow_control.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_141 /* flow_control.cc */; }; - OBJ_1867 /* frame_data.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_142 /* frame_data.cc */; }; - OBJ_1868 /* frame_goaway.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_143 /* frame_goaway.cc */; }; - OBJ_1869 /* frame_ping.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_144 /* frame_ping.cc */; }; - OBJ_1870 /* frame_rst_stream.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_145 /* frame_rst_stream.cc */; }; - OBJ_1871 /* frame_settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_146 /* frame_settings.cc */; }; - OBJ_1872 /* frame_window_update.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_147 /* frame_window_update.cc */; }; - OBJ_1873 /* hpack_encoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_148 /* hpack_encoder.cc */; }; - OBJ_1874 /* hpack_parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_149 /* hpack_parser.cc */; }; - OBJ_1875 /* hpack_table.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_150 /* hpack_table.cc */; }; - OBJ_1876 /* http2_settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_151 /* http2_settings.cc */; }; - OBJ_1877 /* huffsyms.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_152 /* huffsyms.cc */; }; - OBJ_1878 /* incoming_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_153 /* incoming_metadata.cc */; }; - OBJ_1879 /* parsing.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_154 /* parsing.cc */; }; - OBJ_1880 /* stream_lists.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_155 /* stream_lists.cc */; }; - OBJ_1881 /* stream_map.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_156 /* stream_map.cc */; }; - OBJ_1882 /* varint.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_157 /* varint.cc */; }; - OBJ_1883 /* writing.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_158 /* writing.cc */; }; - OBJ_1884 /* inproc_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_160 /* inproc_plugin.cc */; }; - OBJ_1885 /* inproc_transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_161 /* inproc_transport.cc */; }; - OBJ_1886 /* avl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_164 /* avl.cc */; }; - OBJ_1887 /* backoff.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_166 /* backoff.cc */; }; - OBJ_1888 /* channel_args.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_168 /* channel_args.cc */; }; - OBJ_1889 /* channel_stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_169 /* channel_stack.cc */; }; - OBJ_1890 /* channel_stack_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_170 /* channel_stack_builder.cc */; }; - OBJ_1891 /* channel_trace.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_171 /* channel_trace.cc */; }; - OBJ_1892 /* channel_trace_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_172 /* channel_trace_registry.cc */; }; - OBJ_1893 /* connected_channel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_173 /* connected_channel.cc */; }; - OBJ_1894 /* handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_174 /* handshaker.cc */; }; - OBJ_1895 /* handshaker_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_175 /* handshaker_factory.cc */; }; - OBJ_1896 /* handshaker_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_176 /* handshaker_registry.cc */; }; - OBJ_1897 /* status_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_177 /* status_util.cc */; }; - OBJ_1898 /* compression.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_179 /* compression.cc */; }; - OBJ_1899 /* compression_internal.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_180 /* compression_internal.cc */; }; - OBJ_1900 /* message_compress.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_181 /* message_compress.cc */; }; - OBJ_1901 /* stream_compression.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_182 /* stream_compression.cc */; }; - OBJ_1902 /* stream_compression_gzip.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_183 /* stream_compression_gzip.cc */; }; - OBJ_1903 /* stream_compression_identity.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_184 /* stream_compression_identity.cc */; }; - OBJ_1904 /* stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_186 /* stats.cc */; }; - OBJ_1905 /* stats_data.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_187 /* stats_data.cc */; }; - OBJ_1906 /* trace.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_188 /* trace.cc */; }; - OBJ_1907 /* alloc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_190 /* alloc.cc */; }; - OBJ_1908 /* arena.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_191 /* arena.cc */; }; - OBJ_1909 /* atm.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_192 /* atm.cc */; }; - OBJ_1910 /* cpu_iphone.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_193 /* cpu_iphone.cc */; }; - OBJ_1911 /* cpu_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_194 /* cpu_linux.cc */; }; - OBJ_1912 /* cpu_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_195 /* cpu_posix.cc */; }; - OBJ_1913 /* cpu_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_196 /* cpu_windows.cc */; }; - OBJ_1914 /* env_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_197 /* env_linux.cc */; }; - OBJ_1915 /* env_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_198 /* env_posix.cc */; }; - OBJ_1916 /* env_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_199 /* env_windows.cc */; }; - OBJ_1917 /* fork.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_200 /* fork.cc */; }; - OBJ_1918 /* host_port.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_201 /* host_port.cc */; }; - OBJ_1919 /* log.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_202 /* log.cc */; }; - OBJ_1920 /* log_android.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_203 /* log_android.cc */; }; - OBJ_1921 /* log_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_204 /* log_linux.cc */; }; - OBJ_1922 /* log_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_205 /* log_posix.cc */; }; - OBJ_1923 /* log_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_206 /* log_windows.cc */; }; - OBJ_1924 /* mpscq.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_207 /* mpscq.cc */; }; - OBJ_1925 /* murmur_hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_208 /* murmur_hash.cc */; }; - OBJ_1926 /* string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_209 /* string.cc */; }; - OBJ_1927 /* string_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_210 /* string_posix.cc */; }; - OBJ_1928 /* string_util_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_211 /* string_util_windows.cc */; }; - OBJ_1929 /* string_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_212 /* string_windows.cc */; }; - OBJ_1930 /* sync.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_213 /* sync.cc */; }; - OBJ_1931 /* sync_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_214 /* sync_posix.cc */; }; - OBJ_1932 /* sync_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_215 /* sync_windows.cc */; }; - OBJ_1933 /* time.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_216 /* time.cc */; }; - OBJ_1934 /* time_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_217 /* time_posix.cc */; }; - OBJ_1935 /* time_precise.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_218 /* time_precise.cc */; }; - OBJ_1936 /* time_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_219 /* time_windows.cc */; }; - OBJ_1937 /* tls_pthread.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_220 /* tls_pthread.cc */; }; - OBJ_1938 /* tmpfile_msys.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_221 /* tmpfile_msys.cc */; }; - OBJ_1939 /* tmpfile_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_222 /* tmpfile_posix.cc */; }; - OBJ_1940 /* tmpfile_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_223 /* tmpfile_windows.cc */; }; - OBJ_1941 /* wrap_memcpy.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_224 /* wrap_memcpy.cc */; }; - OBJ_1942 /* thd_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_226 /* thd_posix.cc */; }; - OBJ_1943 /* thd_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_227 /* thd_windows.cc */; }; - OBJ_1944 /* format_request.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_229 /* format_request.cc */; }; - OBJ_1945 /* httpcli.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_230 /* httpcli.cc */; }; - OBJ_1946 /* httpcli_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_231 /* httpcli_security_connector.cc */; }; - OBJ_1947 /* parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_232 /* parser.cc */; }; - OBJ_1948 /* call_combiner.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_234 /* call_combiner.cc */; }; - OBJ_1949 /* combiner.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_235 /* combiner.cc */; }; - OBJ_1950 /* endpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_236 /* endpoint.cc */; }; - OBJ_1951 /* endpoint_pair_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_237 /* endpoint_pair_posix.cc */; }; - OBJ_1952 /* endpoint_pair_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_238 /* endpoint_pair_uv.cc */; }; - OBJ_1953 /* endpoint_pair_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_239 /* endpoint_pair_windows.cc */; }; - OBJ_1954 /* error.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_240 /* error.cc */; }; - OBJ_1955 /* ev_epoll1_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_241 /* ev_epoll1_linux.cc */; }; - OBJ_1956 /* ev_epollex_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_242 /* ev_epollex_linux.cc */; }; - OBJ_1957 /* ev_epollsig_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_243 /* ev_epollsig_linux.cc */; }; - OBJ_1958 /* ev_poll_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_244 /* ev_poll_posix.cc */; }; - OBJ_1959 /* ev_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_245 /* ev_posix.cc */; }; - OBJ_1960 /* ev_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_246 /* ev_windows.cc */; }; - OBJ_1961 /* exec_ctx.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_247 /* exec_ctx.cc */; }; - OBJ_1962 /* executor.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_248 /* executor.cc */; }; - OBJ_1963 /* fork_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_249 /* fork_posix.cc */; }; - OBJ_1964 /* fork_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_250 /* fork_windows.cc */; }; - OBJ_1965 /* gethostname_fallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_251 /* gethostname_fallback.cc */; }; - OBJ_1966 /* gethostname_host_name_max.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_252 /* gethostname_host_name_max.cc */; }; - OBJ_1967 /* gethostname_sysconf.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_253 /* gethostname_sysconf.cc */; }; - OBJ_1968 /* iocp_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_254 /* iocp_windows.cc */; }; - OBJ_1969 /* iomgr.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_255 /* iomgr.cc */; }; - OBJ_1970 /* iomgr_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_256 /* iomgr_custom.cc */; }; - OBJ_1971 /* iomgr_internal.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_257 /* iomgr_internal.cc */; }; - OBJ_1972 /* iomgr_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_258 /* iomgr_posix.cc */; }; - OBJ_1973 /* iomgr_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_259 /* iomgr_uv.cc */; }; - OBJ_1974 /* iomgr_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_260 /* iomgr_windows.cc */; }; - OBJ_1975 /* is_epollexclusive_available.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_261 /* is_epollexclusive_available.cc */; }; - OBJ_1976 /* load_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_262 /* load_file.cc */; }; - OBJ_1977 /* lockfree_event.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_263 /* lockfree_event.cc */; }; - OBJ_1978 /* network_status_tracker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_264 /* network_status_tracker.cc */; }; - OBJ_1979 /* polling_entity.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_265 /* polling_entity.cc */; }; - OBJ_1980 /* pollset.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_266 /* pollset.cc */; }; - OBJ_1981 /* pollset_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_267 /* pollset_custom.cc */; }; - OBJ_1982 /* pollset_set.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_268 /* pollset_set.cc */; }; - OBJ_1983 /* pollset_set_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_269 /* pollset_set_custom.cc */; }; - OBJ_1984 /* pollset_set_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_270 /* pollset_set_windows.cc */; }; - OBJ_1985 /* pollset_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_271 /* pollset_uv.cc */; }; - OBJ_1986 /* pollset_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_272 /* pollset_windows.cc */; }; - OBJ_1987 /* resolve_address.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_273 /* resolve_address.cc */; }; - OBJ_1988 /* resolve_address_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_274 /* resolve_address_custom.cc */; }; - OBJ_1989 /* resolve_address_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_275 /* resolve_address_posix.cc */; }; - OBJ_1990 /* resolve_address_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_276 /* resolve_address_windows.cc */; }; - OBJ_1991 /* resource_quota.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_277 /* resource_quota.cc */; }; - OBJ_1992 /* sockaddr_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_278 /* sockaddr_utils.cc */; }; - OBJ_1993 /* socket_factory_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_279 /* socket_factory_posix.cc */; }; - OBJ_1994 /* socket_mutator.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_280 /* socket_mutator.cc */; }; - OBJ_1995 /* socket_utils_common_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_281 /* socket_utils_common_posix.cc */; }; - OBJ_1996 /* socket_utils_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_282 /* socket_utils_linux.cc */; }; - OBJ_1997 /* socket_utils_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_283 /* socket_utils_posix.cc */; }; - OBJ_1998 /* socket_utils_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_284 /* socket_utils_uv.cc */; }; - OBJ_1999 /* socket_utils_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_285 /* socket_utils_windows.cc */; }; - OBJ_2000 /* socket_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_286 /* socket_windows.cc */; }; - OBJ_2001 /* tcp_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_287 /* tcp_client.cc */; }; - OBJ_2002 /* tcp_client_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_288 /* tcp_client_custom.cc */; }; - OBJ_2003 /* tcp_client_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_289 /* tcp_client_posix.cc */; }; - OBJ_2004 /* tcp_client_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_290 /* tcp_client_windows.cc */; }; - OBJ_2005 /* tcp_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_291 /* tcp_custom.cc */; }; - OBJ_2006 /* tcp_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_292 /* tcp_posix.cc */; }; - OBJ_2007 /* tcp_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_293 /* tcp_server.cc */; }; - OBJ_2008 /* tcp_server_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_294 /* tcp_server_custom.cc */; }; - OBJ_2009 /* tcp_server_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_295 /* tcp_server_posix.cc */; }; - OBJ_2010 /* tcp_server_utils_posix_common.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_296 /* tcp_server_utils_posix_common.cc */; }; - OBJ_2011 /* tcp_server_utils_posix_ifaddrs.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_297 /* tcp_server_utils_posix_ifaddrs.cc */; }; - OBJ_2012 /* tcp_server_utils_posix_noifaddrs.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_298 /* tcp_server_utils_posix_noifaddrs.cc */; }; - OBJ_2013 /* tcp_server_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_299 /* tcp_server_windows.cc */; }; - OBJ_2014 /* tcp_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_300 /* tcp_uv.cc */; }; - OBJ_2015 /* tcp_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_301 /* tcp_windows.cc */; }; - OBJ_2016 /* time_averaged_stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_302 /* time_averaged_stats.cc */; }; - OBJ_2017 /* timer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_303 /* timer.cc */; }; - OBJ_2018 /* timer_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_304 /* timer_custom.cc */; }; - OBJ_2019 /* timer_generic.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_305 /* timer_generic.cc */; }; - OBJ_2020 /* timer_heap.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_306 /* timer_heap.cc */; }; - OBJ_2021 /* timer_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_307 /* timer_manager.cc */; }; - OBJ_2022 /* timer_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_308 /* timer_uv.cc */; }; - OBJ_2023 /* udp_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_309 /* udp_server.cc */; }; - OBJ_2024 /* unix_sockets_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_310 /* unix_sockets_posix.cc */; }; - OBJ_2025 /* unix_sockets_posix_noop.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_311 /* unix_sockets_posix_noop.cc */; }; - OBJ_2026 /* wakeup_fd_cv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_312 /* wakeup_fd_cv.cc */; }; - OBJ_2027 /* wakeup_fd_eventfd.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_313 /* wakeup_fd_eventfd.cc */; }; - OBJ_2028 /* wakeup_fd_nospecial.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_314 /* wakeup_fd_nospecial.cc */; }; - OBJ_2029 /* wakeup_fd_pipe.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_315 /* wakeup_fd_pipe.cc */; }; - OBJ_2030 /* wakeup_fd_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_316 /* wakeup_fd_posix.cc */; }; - OBJ_2031 /* json.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_318 /* json.cc */; }; - OBJ_2032 /* json_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_319 /* json_reader.cc */; }; - OBJ_2033 /* json_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_320 /* json_string.cc */; }; - OBJ_2034 /* json_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_321 /* json_writer.cc */; }; - OBJ_2035 /* basic_timers.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_323 /* basic_timers.cc */; }; - OBJ_2036 /* stap_timers.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_324 /* stap_timers.cc */; }; - OBJ_2037 /* security_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_327 /* security_context.cc */; }; - OBJ_2038 /* alts_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_330 /* alts_credentials.cc */; }; - OBJ_2039 /* check_gcp_environment.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_331 /* check_gcp_environment.cc */; }; - OBJ_2040 /* check_gcp_environment_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_332 /* check_gcp_environment_linux.cc */; }; - OBJ_2041 /* check_gcp_environment_no_op.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_333 /* check_gcp_environment_no_op.cc */; }; - OBJ_2042 /* check_gcp_environment_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_334 /* check_gcp_environment_windows.cc */; }; - OBJ_2043 /* grpc_alts_credentials_client_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_335 /* grpc_alts_credentials_client_options.cc */; }; - OBJ_2044 /* grpc_alts_credentials_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_336 /* grpc_alts_credentials_options.cc */; }; - OBJ_2045 /* grpc_alts_credentials_server_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_337 /* grpc_alts_credentials_server_options.cc */; }; - OBJ_2046 /* composite_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_339 /* composite_credentials.cc */; }; - OBJ_2047 /* credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_340 /* credentials.cc */; }; - OBJ_2048 /* credentials_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_341 /* credentials_metadata.cc */; }; - OBJ_2049 /* fake_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_343 /* fake_credentials.cc */; }; - OBJ_2050 /* credentials_generic.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_345 /* credentials_generic.cc */; }; - OBJ_2051 /* google_default_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_346 /* google_default_credentials.cc */; }; - OBJ_2052 /* iam_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_348 /* iam_credentials.cc */; }; - OBJ_2053 /* json_token.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_350 /* json_token.cc */; }; - OBJ_2054 /* jwt_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_351 /* jwt_credentials.cc */; }; - OBJ_2055 /* jwt_verifier.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_352 /* jwt_verifier.cc */; }; - OBJ_2056 /* oauth2_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_354 /* oauth2_credentials.cc */; }; - OBJ_2057 /* plugin_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_356 /* plugin_credentials.cc */; }; - OBJ_2058 /* ssl_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_358 /* ssl_credentials.cc */; }; - OBJ_2059 /* alts_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_360 /* alts_security_connector.cc */; }; - OBJ_2060 /* security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_361 /* security_connector.cc */; }; - OBJ_2061 /* client_auth_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_363 /* client_auth_filter.cc */; }; - OBJ_2062 /* secure_endpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_364 /* secure_endpoint.cc */; }; - OBJ_2063 /* security_handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_365 /* security_handshaker.cc */; }; - OBJ_2064 /* server_auth_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_366 /* server_auth_filter.cc */; }; - OBJ_2065 /* target_authority_table.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_367 /* target_authority_table.cc */; }; - OBJ_2066 /* tsi_error.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_368 /* tsi_error.cc */; }; - OBJ_2067 /* json_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_370 /* json_util.cc */; }; - OBJ_2068 /* b64.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_372 /* b64.cc */; }; - OBJ_2069 /* percent_encoding.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_373 /* percent_encoding.cc */; }; - OBJ_2070 /* slice.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_374 /* slice.cc */; }; - OBJ_2071 /* slice_buffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_375 /* slice_buffer.cc */; }; - OBJ_2072 /* slice_intern.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_376 /* slice_intern.cc */; }; - OBJ_2073 /* slice_string_helpers.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_377 /* slice_string_helpers.cc */; }; - OBJ_2074 /* api_trace.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_379 /* api_trace.cc */; }; - OBJ_2075 /* byte_buffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_380 /* byte_buffer.cc */; }; - OBJ_2076 /* byte_buffer_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_381 /* byte_buffer_reader.cc */; }; - OBJ_2077 /* call.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_382 /* call.cc */; }; - OBJ_2078 /* call_details.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_383 /* call_details.cc */; }; - OBJ_2079 /* call_log_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_384 /* call_log_batch.cc */; }; - OBJ_2080 /* channel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_385 /* channel.cc */; }; - OBJ_2081 /* channel_init.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_386 /* channel_init.cc */; }; - OBJ_2082 /* channel_ping.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_387 /* channel_ping.cc */; }; - OBJ_2083 /* channel_stack_type.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_388 /* channel_stack_type.cc */; }; - OBJ_2084 /* completion_queue.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_389 /* completion_queue.cc */; }; - OBJ_2085 /* completion_queue_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_390 /* completion_queue_factory.cc */; }; - OBJ_2086 /* event_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_391 /* event_string.cc */; }; - OBJ_2087 /* init.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_392 /* init.cc */; }; - OBJ_2088 /* init_secure.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_393 /* init_secure.cc */; }; - OBJ_2089 /* lame_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_394 /* lame_client.cc */; }; - OBJ_2090 /* metadata_array.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_395 /* metadata_array.cc */; }; - OBJ_2091 /* server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_396 /* server.cc */; }; - OBJ_2092 /* validate_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_397 /* validate_metadata.cc */; }; - OBJ_2093 /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_398 /* version.cc */; }; - OBJ_2094 /* bdp_estimator.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_400 /* bdp_estimator.cc */; }; - OBJ_2095 /* byte_stream.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_401 /* byte_stream.cc */; }; - OBJ_2096 /* connectivity_state.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_402 /* connectivity_state.cc */; }; - OBJ_2097 /* error_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_403 /* error_utils.cc */; }; - OBJ_2098 /* metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_404 /* metadata.cc */; }; - OBJ_2099 /* metadata_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_405 /* metadata_batch.cc */; }; - OBJ_2100 /* pid_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_406 /* pid_controller.cc */; }; - OBJ_2101 /* service_config.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_407 /* service_config.cc */; }; - OBJ_2102 /* static_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_408 /* static_metadata.cc */; }; - OBJ_2103 /* status_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_409 /* status_conversion.cc */; }; - OBJ_2104 /* status_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_410 /* status_metadata.cc */; }; - OBJ_2105 /* timeout_encoding.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_411 /* timeout_encoding.cc */; }; - OBJ_2106 /* transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_412 /* transport.cc */; }; - OBJ_2107 /* transport_op_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_413 /* transport_op_string.cc */; }; - OBJ_2108 /* grpc_plugin_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_415 /* grpc_plugin_registry.cc */; }; - OBJ_2109 /* aes_gcm.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_419 /* aes_gcm.cc */; }; - OBJ_2110 /* gsec.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_420 /* gsec.cc */; }; - OBJ_2111 /* alts_counter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_422 /* alts_counter.cc */; }; - OBJ_2112 /* alts_crypter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_423 /* alts_crypter.cc */; }; - OBJ_2113 /* alts_frame_protector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_424 /* alts_frame_protector.cc */; }; - OBJ_2114 /* alts_record_protocol_crypter_common.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_425 /* alts_record_protocol_crypter_common.cc */; }; - OBJ_2115 /* alts_seal_privacy_integrity_crypter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_426 /* alts_seal_privacy_integrity_crypter.cc */; }; - OBJ_2116 /* alts_unseal_privacy_integrity_crypter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_427 /* alts_unseal_privacy_integrity_crypter.cc */; }; - OBJ_2117 /* frame_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_428 /* frame_handler.cc */; }; - OBJ_2118 /* alts_handshaker_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_430 /* alts_handshaker_client.cc */; }; - OBJ_2119 /* alts_handshaker_service_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_431 /* alts_handshaker_service_api.cc */; }; - OBJ_2120 /* alts_handshaker_service_api_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_432 /* alts_handshaker_service_api_util.cc */; }; - OBJ_2121 /* alts_tsi_event.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_433 /* alts_tsi_event.cc */; }; - OBJ_2122 /* alts_tsi_handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_434 /* alts_tsi_handshaker.cc */; }; - OBJ_2123 /* alts_tsi_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_435 /* alts_tsi_utils.cc */; }; - OBJ_2124 /* altscontext.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_436 /* altscontext.pb.c */; }; - OBJ_2125 /* handshaker.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_437 /* handshaker.pb.c */; }; - OBJ_2126 /* transport_security_common.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_438 /* transport_security_common.pb.c */; }; - OBJ_2127 /* transport_security_common_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_439 /* transport_security_common_api.cc */; }; - OBJ_2128 /* alts_grpc_integrity_only_record_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_441 /* alts_grpc_integrity_only_record_protocol.cc */; }; - OBJ_2129 /* alts_grpc_privacy_integrity_record_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_442 /* alts_grpc_privacy_integrity_record_protocol.cc */; }; - OBJ_2130 /* alts_grpc_record_protocol_common.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_443 /* alts_grpc_record_protocol_common.cc */; }; - OBJ_2131 /* alts_iovec_record_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_444 /* alts_iovec_record_protocol.cc */; }; - OBJ_2132 /* alts_zero_copy_grpc_protector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_445 /* alts_zero_copy_grpc_protector.cc */; }; - OBJ_2133 /* alts_transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_446 /* alts_transport_security.cc */; }; - OBJ_2134 /* fake_transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_447 /* fake_transport_security.cc */; }; - OBJ_2135 /* ssl_session_boringssl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_450 /* ssl_session_boringssl.cc */; }; - OBJ_2136 /* ssl_session_cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_451 /* ssl_session_cache.cc */; }; - OBJ_2137 /* ssl_session_openssl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_452 /* ssl_session_openssl.cc */; }; - OBJ_2138 /* ssl_transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_453 /* ssl_transport_security.cc */; }; - OBJ_2139 /* transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_454 /* transport_security.cc */; }; - OBJ_2140 /* transport_security_adapter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_455 /* transport_security_adapter.cc */; }; - OBJ_2141 /* transport_security_grpc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_456 /* transport_security_grpc.cc */; }; - OBJ_2142 /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_459 /* pb_common.c */; }; - OBJ_2143 /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_460 /* pb_decode.c */; }; - OBJ_2144 /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_461 /* pb_encode.c */; }; - OBJ_2146 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; - OBJ_2153 /* ArgumentConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1242 /* ArgumentConvertible.swift */; }; - OBJ_2154 /* ArgumentDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1243 /* ArgumentDescription.swift */; }; - OBJ_2155 /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1244 /* ArgumentParser.swift */; }; - OBJ_2156 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1245 /* Command.swift */; }; - OBJ_2157 /* CommandRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1246 /* CommandRunner.swift */; }; - OBJ_2158 /* CommandType.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1247 /* CommandType.swift */; }; - OBJ_2159 /* Commands.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1248 /* Commands.swift */; }; - OBJ_2160 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1249 /* Error.swift */; }; - OBJ_2161 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1250 /* Group.swift */; }; - OBJ_2168 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1251 /* Package.swift */; }; - OBJ_2174 /* EchoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_564 /* EchoProvider.swift */; }; - OBJ_2175 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_566 /* echo.grpc.swift */; }; - OBJ_2176 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_567 /* echo.pb.swift */; }; - OBJ_2177 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_568 /* main.swift */; }; - OBJ_2179 /* Commander.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = Commander::Commander::Product /* Commander.framework */; }; - OBJ_2180 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; - OBJ_2181 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2182 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; - OBJ_2183 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; - OBJ_2196 /* EchoProviderNIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* EchoProviderNIO.swift */; }; - OBJ_2197 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* echo.grpc.swift */; }; - OBJ_2198 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* echo.pb.swift */; }; - OBJ_2199 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_22 /* main.swift */; }; - OBJ_2201 /* Commander.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = Commander::Commander::Product /* Commander.framework */; }; - OBJ_2202 /* SwiftGRPCNIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPCNIO::Product /* SwiftGRPCNIO.framework */; }; - OBJ_2203 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2204 /* NIOHTTP2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */; }; - OBJ_2205 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; - OBJ_2206 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; - OBJ_2207 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; - OBJ_2208 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; - OBJ_2209 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; - OBJ_2210 /* NIOFoundationCompat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */; }; - OBJ_2211 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2212 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2213 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2214 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2215 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2216 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2217 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2247 /* AddressedEnvelope.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1139 /* AddressedEnvelope.swift */; }; - OBJ_2248 /* BaseSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1140 /* BaseSocket.swift */; }; - OBJ_2249 /* BaseSocketChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1141 /* BaseSocketChannel.swift */; }; - OBJ_2250 /* BlockingIOThreadPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1142 /* BlockingIOThreadPool.swift */; }; - OBJ_2251 /* Bootstrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1143 /* Bootstrap.swift */; }; - OBJ_2252 /* ByteBuffer-aux.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1144 /* ByteBuffer-aux.swift */; }; - OBJ_2253 /* ByteBuffer-core.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1145 /* ByteBuffer-core.swift */; }; - OBJ_2254 /* ByteBuffer-int.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1146 /* ByteBuffer-int.swift */; }; - OBJ_2255 /* ByteBuffer-views.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1147 /* ByteBuffer-views.swift */; }; - OBJ_2256 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1148 /* Channel.swift */; }; - OBJ_2257 /* ChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1149 /* ChannelHandler.swift */; }; - OBJ_2258 /* ChannelHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1150 /* ChannelHandlers.swift */; }; - OBJ_2259 /* ChannelInvoker.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1151 /* ChannelInvoker.swift */; }; - OBJ_2260 /* ChannelOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1152 /* ChannelOption.swift */; }; - OBJ_2261 /* ChannelPipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1153 /* ChannelPipeline.swift */; }; - OBJ_2262 /* CircularBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1154 /* CircularBuffer.swift */; }; - OBJ_2263 /* Codec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1155 /* Codec.swift */; }; - OBJ_2264 /* CompositeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1156 /* CompositeError.swift */; }; - OBJ_2265 /* ContiguousCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1157 /* ContiguousCollection.swift */; }; - OBJ_2266 /* DeadChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1158 /* DeadChannel.swift */; }; - OBJ_2267 /* Embedded.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1159 /* Embedded.swift */; }; - OBJ_2268 /* EventLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1160 /* EventLoop.swift */; }; - OBJ_2269 /* EventLoopFuture.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1161 /* EventLoopFuture.swift */; }; - OBJ_2270 /* FileDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1162 /* FileDescriptor.swift */; }; - OBJ_2271 /* FileHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1163 /* FileHandle.swift */; }; - OBJ_2272 /* FileRegion.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1164 /* FileRegion.swift */; }; - OBJ_2273 /* GetaddrinfoResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1165 /* GetaddrinfoResolver.swift */; }; - OBJ_2274 /* HappyEyeballs.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1166 /* HappyEyeballs.swift */; }; - OBJ_2275 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1167 /* Heap.swift */; }; - OBJ_2276 /* IO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1168 /* IO.swift */; }; - OBJ_2277 /* IOData.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1169 /* IOData.swift */; }; - OBJ_2278 /* IntegerTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1170 /* IntegerTypes.swift */; }; - OBJ_2279 /* Interfaces.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1171 /* Interfaces.swift */; }; - OBJ_2280 /* Linux.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1172 /* Linux.swift */; }; - OBJ_2281 /* LinuxCPUSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1173 /* LinuxCPUSet.swift */; }; - OBJ_2282 /* MarkedCircularBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1174 /* MarkedCircularBuffer.swift */; }; - OBJ_2283 /* MulticastChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1175 /* MulticastChannel.swift */; }; - OBJ_2284 /* NIOAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1176 /* NIOAny.swift */; }; - OBJ_2285 /* NonBlockingFileIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1177 /* NonBlockingFileIO.swift */; }; - OBJ_2286 /* PendingDatagramWritesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1178 /* PendingDatagramWritesManager.swift */; }; - OBJ_2287 /* PendingWritesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1179 /* PendingWritesManager.swift */; }; - OBJ_2288 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1180 /* PriorityQueue.swift */; }; - OBJ_2289 /* RecvByteBufferAllocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1181 /* RecvByteBufferAllocator.swift */; }; - OBJ_2290 /* Resolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1182 /* Resolver.swift */; }; - OBJ_2291 /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1183 /* Selectable.swift */; }; - OBJ_2292 /* Selector.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1184 /* Selector.swift */; }; - OBJ_2293 /* ServerSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1185 /* ServerSocket.swift */; }; - OBJ_2294 /* Socket.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1186 /* Socket.swift */; }; - OBJ_2295 /* SocketAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1187 /* SocketAddresses.swift */; }; - OBJ_2296 /* SocketChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1188 /* SocketChannel.swift */; }; - OBJ_2297 /* SocketOptionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1189 /* SocketOptionProvider.swift */; }; - OBJ_2298 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1190 /* System.swift */; }; - OBJ_2299 /* Thread.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1191 /* Thread.swift */; }; - OBJ_2300 /* TypeAssistedChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1192 /* TypeAssistedChannelHandler.swift */; }; - OBJ_2301 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1193 /* Utilities.swift */; }; - OBJ_2303 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2304 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2305 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2306 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2307 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2308 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2319 /* atomics.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1201 /* atomics.swift */; }; - OBJ_2320 /* lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1202 /* lock.swift */; }; - OBJ_2322 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2328 /* ByteBuffer-foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1204 /* ByteBuffer-foundation.swift */; }; - OBJ_2330 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2331 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2332 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2333 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2334 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2335 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2336 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2348 /* ByteCollectionUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1212 /* ByteCollectionUtils.swift */; }; - OBJ_2349 /* HTTPDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1213 /* HTTPDecoder.swift */; }; - OBJ_2350 /* HTTPEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1214 /* HTTPEncoder.swift */; }; - OBJ_2351 /* HTTPPipelineSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1215 /* HTTPPipelineSetup.swift */; }; - OBJ_2352 /* HTTPResponseCompressor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1216 /* HTTPResponseCompressor.swift */; }; - OBJ_2353 /* HTTPServerPipelineHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1217 /* HTTPServerPipelineHandler.swift */; }; - OBJ_2354 /* HTTPServerProtocolErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1218 /* HTTPServerProtocolErrorHandler.swift */; }; - OBJ_2355 /* HTTPTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1219 /* HTTPTypes.swift */; }; - OBJ_2356 /* HTTPUpgradeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1220 /* HTTPUpgradeHandler.swift */; }; - OBJ_2358 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; - OBJ_2359 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; - OBJ_2360 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2361 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2362 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2363 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2364 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2365 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2366 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2380 /* HTTP2DataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1104 /* HTTP2DataProvider.swift */; }; - OBJ_2381 /* HTTP2Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1105 /* HTTP2Error.swift */; }; - OBJ_2382 /* HTTP2ErrorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1106 /* HTTP2ErrorCode.swift */; }; - OBJ_2383 /* HTTP2Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1107 /* HTTP2Frame.swift */; }; - OBJ_2384 /* HTTP2HeaderBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1108 /* HTTP2HeaderBlock.swift */; }; - OBJ_2385 /* HTTP2Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1109 /* HTTP2Parser.swift */; }; - OBJ_2386 /* HTTP2PingData.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1110 /* HTTP2PingData.swift */; }; - OBJ_2387 /* HTTP2PipelineHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1111 /* HTTP2PipelineHelpers.swift */; }; - OBJ_2388 /* HTTP2Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1112 /* HTTP2Settings.swift */; }; - OBJ_2389 /* HTTP2Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1113 /* HTTP2Stream.swift */; }; - OBJ_2390 /* HTTP2StreamChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1114 /* HTTP2StreamChannel.swift */; }; - OBJ_2391 /* HTTP2StreamID.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1115 /* HTTP2StreamID.swift */; }; - OBJ_2392 /* HTTP2StreamMultiplexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1116 /* HTTP2StreamMultiplexer.swift */; }; - OBJ_2393 /* HTTP2ToHTTP1Codec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1117 /* HTTP2ToHTTP1Codec.swift */; }; - OBJ_2394 /* HTTP2UserEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1118 /* HTTP2UserEvents.swift */; }; - OBJ_2395 /* NGHTTP2Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1119 /* NGHTTP2Session.swift */; }; - OBJ_2397 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; - OBJ_2398 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; - OBJ_2399 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; - OBJ_2400 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; - OBJ_2401 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2402 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2403 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2404 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2405 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2406 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2407 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2408 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; - OBJ_2425 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1236 /* Heap.swift */; }; - OBJ_2426 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1237 /* PriorityQueue.swift */; }; - OBJ_2432 /* ApplicationProtocolNegotiationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1124 /* ApplicationProtocolNegotiationHandler.swift */; }; - OBJ_2433 /* SNIHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1125 /* SNIHandler.swift */; }; - OBJ_2434 /* TLSEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1126 /* TLSEvents.swift */; }; - OBJ_2436 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2437 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2438 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2439 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2440 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2441 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2442 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2455 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_24 /* main.swift */; }; - OBJ_2462 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_522 /* main.swift */; }; - OBJ_2464 /* Commander.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = Commander::Commander::Product /* Commander.framework */; }; - OBJ_2465 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; - OBJ_2466 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2467 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; - OBJ_2468 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; - OBJ_2478 /* ByteBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_571 /* ByteBuffer.swift */; }; - OBJ_2479 /* Call.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_572 /* Call.swift */; }; - OBJ_2480 /* CallError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_573 /* CallError.swift */; }; - OBJ_2481 /* CallResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_574 /* CallResult.swift */; }; - OBJ_2482 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_575 /* Channel.swift */; }; - OBJ_2483 /* ChannelArgument.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_576 /* ChannelArgument.swift */; }; - OBJ_2484 /* ChannelConnectivityObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_577 /* ChannelConnectivityObserver.swift */; }; - OBJ_2485 /* ChannelConnectivityState.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_578 /* ChannelConnectivityState.swift */; }; - OBJ_2486 /* ClientNetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_579 /* ClientNetworkMonitor.swift */; }; - OBJ_2487 /* CompletionQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_580 /* CompletionQueue.swift */; }; - OBJ_2488 /* Handler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_581 /* Handler.swift */; }; - OBJ_2489 /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_582 /* Metadata.swift */; }; - OBJ_2490 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_583 /* Mutex.swift */; }; - OBJ_2491 /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_584 /* Operation.swift */; }; - OBJ_2492 /* OperationGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_585 /* OperationGroup.swift */; }; - OBJ_2493 /* Roots.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_586 /* Roots.swift */; }; - OBJ_2494 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_587 /* Server.swift */; }; - OBJ_2495 /* ServerStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_588 /* ServerStatus.swift */; }; - OBJ_2496 /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_589 /* StatusCode.swift */; }; - OBJ_2497 /* gRPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_590 /* gRPC.swift */; }; - OBJ_2498 /* ClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_592 /* ClientCall.swift */; }; - OBJ_2499 /* ClientCallBidirectionalStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_593 /* ClientCallBidirectionalStreaming.swift */; }; - OBJ_2500 /* ClientCallClientStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_594 /* ClientCallClientStreaming.swift */; }; - OBJ_2501 /* ClientCallServerStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_595 /* ClientCallServerStreaming.swift */; }; - OBJ_2502 /* ClientCallUnary.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_596 /* ClientCallUnary.swift */; }; - OBJ_2503 /* RPCError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_597 /* RPCError.swift */; }; - OBJ_2504 /* ServerSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_598 /* ServerSession.swift */; }; - OBJ_2505 /* ServerSessionBidirectionalStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_599 /* ServerSessionBidirectionalStreaming.swift */; }; - OBJ_2506 /* ServerSessionClientStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_600 /* ServerSessionClientStreaming.swift */; }; - OBJ_2507 /* ServerSessionServerStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_601 /* ServerSessionServerStreaming.swift */; }; - OBJ_2508 /* ServerSessionUnary.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_602 /* ServerSessionUnary.swift */; }; - OBJ_2509 /* ServiceClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_603 /* ServiceClient.swift */; }; - OBJ_2510 /* ServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_604 /* ServiceProvider.swift */; }; - OBJ_2511 /* ServiceServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_605 /* ServiceServer.swift */; }; - OBJ_2512 /* StreamReceiving.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_606 /* StreamReceiving.swift */; }; - OBJ_2513 /* StreamSending.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_607 /* StreamSending.swift */; }; - OBJ_2515 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2516 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; - OBJ_2517 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; - OBJ_2525 /* BaseCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_525 /* BaseCallHandler.swift */; }; - OBJ_2526 /* BidirectionalStreamingCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_526 /* BidirectionalStreamingCallHandler.swift */; }; - OBJ_2527 /* ClientStreamingCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_527 /* ClientStreamingCallHandler.swift */; }; - OBJ_2528 /* ServerStreamingCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_528 /* ServerStreamingCallHandler.swift */; }; - OBJ_2529 /* UnaryCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_529 /* UnaryCallHandler.swift */; }; - OBJ_2530 /* BaseClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_531 /* BaseClientCall.swift */; }; - OBJ_2531 /* BidirectionalStreamingClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_532 /* BidirectionalStreamingClientCall.swift */; }; - OBJ_2532 /* ClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_533 /* ClientCall.swift */; }; - OBJ_2533 /* ClientStreamingClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_534 /* ClientStreamingClientCall.swift */; }; - OBJ_2534 /* ResponseObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_535 /* ResponseObserver.swift */; }; - OBJ_2535 /* ServerStreamingClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_536 /* ServerStreamingClientCall.swift */; }; - OBJ_2536 /* UnaryClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_537 /* UnaryClientCall.swift */; }; - OBJ_2537 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_538 /* ClientOptions.swift */; }; - OBJ_2538 /* CompressionMechanism.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_539 /* CompressionMechanism.swift */; }; - OBJ_2539 /* GRPCChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_540 /* GRPCChannelHandler.swift */; }; - OBJ_2540 /* GRPCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_541 /* GRPCClient.swift */; }; - OBJ_2541 /* GRPCClientChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_542 /* GRPCClientChannelHandler.swift */; }; - OBJ_2542 /* GRPCClientCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_543 /* GRPCClientCodec.swift */; }; - OBJ_2543 /* GRPCError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_544 /* GRPCError.swift */; }; - OBJ_2544 /* GRPCServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_545 /* GRPCServer.swift */; }; - OBJ_2545 /* GRPCServerCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_546 /* GRPCServerCodec.swift */; }; - OBJ_2546 /* GRPCStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_547 /* GRPCStatus.swift */; }; - OBJ_2547 /* GRPCTimeout.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_548 /* GRPCTimeout.swift */; }; - OBJ_2548 /* HTTP1ToRawGRPCClientCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_549 /* HTTP1ToRawGRPCClientCodec.swift */; }; - OBJ_2549 /* HTTP1ToRawGRPCServerCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_550 /* HTTP1ToRawGRPCServerCodec.swift */; }; - OBJ_2550 /* HTTPProtocolSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_551 /* HTTPProtocolSwitcher.swift */; }; - OBJ_2551 /* LengthPrefixedMessageReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_552 /* LengthPrefixedMessageReader.swift */; }; - OBJ_2552 /* LengthPrefixedMessageWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_553 /* LengthPrefixedMessageWriter.swift */; }; - OBJ_2553 /* LoggingServerErrorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_554 /* LoggingServerErrorDelegate.swift */; }; - OBJ_2554 /* ServerCallContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_556 /* ServerCallContext.swift */; }; - OBJ_2555 /* StreamingResponseCallContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_557 /* StreamingResponseCallContext.swift */; }; - OBJ_2556 /* UnaryResponseCallContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_558 /* UnaryResponseCallContext.swift */; }; - OBJ_2557 /* ServerErrorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_559 /* ServerErrorDelegate.swift */; }; - OBJ_2558 /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_560 /* StatusCode.swift */; }; - OBJ_2559 /* StreamEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_561 /* StreamEvent.swift */; }; - OBJ_2560 /* WebCORSHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_562 /* WebCORSHandler.swift */; }; - OBJ_2562 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2563 /* NIOHTTP2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */; }; - OBJ_2564 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; - OBJ_2565 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; - OBJ_2566 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; - OBJ_2567 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; - OBJ_2568 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; - OBJ_2569 /* NIOFoundationCompat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */; }; - OBJ_2570 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2571 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2572 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2573 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2574 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2575 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2576 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2597 /* EchoProviderNIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1054 /* EchoProviderNIO.swift */; }; - OBJ_2598 /* GRPCChannelHandlerResponseCapturingTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1055 /* GRPCChannelHandlerResponseCapturingTestCase.swift */; }; - OBJ_2599 /* GRPCChannelHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1056 /* GRPCChannelHandlerTests.swift */; }; - OBJ_2600 /* HTTP1ToRawGRPCServerCodecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1057 /* HTTP1ToRawGRPCServerCodecTests.swift */; }; - OBJ_2601 /* LengthPrefixedMessageReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1058 /* LengthPrefixedMessageReaderTests.swift */; }; - OBJ_2602 /* NIOBasicEchoTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1059 /* NIOBasicEchoTestCase.swift */; }; - OBJ_2603 /* NIOClientCancellingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1060 /* NIOClientCancellingTests.swift */; }; - OBJ_2604 /* NIOClientTimeoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1061 /* NIOClientTimeoutTests.swift */; }; - OBJ_2605 /* NIOServerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1062 /* NIOServerTests.swift */; }; - OBJ_2606 /* NIOServerWebTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1063 /* NIOServerWebTests.swift */; }; - OBJ_2607 /* ServerThrowingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1064 /* ServerThrowingTests.swift */; }; - OBJ_2608 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1065 /* TestHelpers.swift */; }; - OBJ_2609 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1066 /* echo.grpc.swift */; }; - OBJ_2610 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1067 /* echo.pb.swift */; }; - OBJ_2612 /* SwiftGRPCNIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPCNIO::Product /* SwiftGRPCNIO.framework */; }; - OBJ_2613 /* NIOHTTP2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */; }; - OBJ_2614 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; - OBJ_2615 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; - OBJ_2616 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; - OBJ_2617 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; - OBJ_2618 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; - OBJ_2619 /* NIOFoundationCompat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */; }; - OBJ_2620 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; - OBJ_2621 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; - OBJ_2622 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; - OBJ_2623 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; - OBJ_2624 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; - OBJ_2625 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; - OBJ_2626 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; - OBJ_2627 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; - OBJ_2628 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2629 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; - OBJ_2630 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; - OBJ_2655 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; - OBJ_2667 /* BasicEchoTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1069 /* BasicEchoTestCase.swift */; }; - OBJ_2668 /* ChannelArgumentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1070 /* ChannelArgumentTests.swift */; }; - OBJ_2669 /* ChannelConnectivityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1071 /* ChannelConnectivityTests.swift */; }; - OBJ_2670 /* ChannelShutdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1072 /* ChannelShutdownTests.swift */; }; - OBJ_2671 /* ClientCancellingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1073 /* ClientCancellingTests.swift */; }; - OBJ_2672 /* ClientTestExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1074 /* ClientTestExample.swift */; }; - OBJ_2673 /* ClientTimeoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1075 /* ClientTimeoutTests.swift */; }; - OBJ_2674 /* CompletionQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1076 /* CompletionQueueTests.swift */; }; - OBJ_2675 /* ConnectionFailureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1077 /* ConnectionFailureTests.swift */; }; - OBJ_2676 /* EchoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1078 /* EchoProvider.swift */; }; - OBJ_2677 /* EchoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1079 /* EchoTests.swift */; }; - OBJ_2678 /* GRPCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1080 /* GRPCTests.swift */; }; - OBJ_2679 /* MetadataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1081 /* MetadataTests.swift */; }; - OBJ_2680 /* ServerCancellingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1082 /* ServerCancellingTests.swift */; }; - OBJ_2681 /* ServerTestExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1083 /* ServerTestExample.swift */; }; - OBJ_2682 /* ServerThrowingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1084 /* ServerThrowingTests.swift */; }; - OBJ_2683 /* ServerTimeoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1085 /* ServerTimeoutTests.swift */; }; - OBJ_2684 /* ServiceClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1086 /* ServiceClientTests.swift */; }; - OBJ_2685 /* TestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1087 /* TestKeys.swift */; }; - OBJ_2686 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1088 /* echo.grpc.swift */; }; - OBJ_2687 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1089 /* echo.pb.swift */; }; - OBJ_2689 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; - OBJ_2690 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2691 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; - OBJ_2692 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; - OBJ_2701 /* AnyMessageStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1254 /* AnyMessageStorage.swift */; }; - OBJ_2702 /* AnyUnpackError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1255 /* AnyUnpackError.swift */; }; - OBJ_2703 /* BinaryDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1256 /* BinaryDecoder.swift */; }; - OBJ_2704 /* BinaryDecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1257 /* BinaryDecodingError.swift */; }; - OBJ_2705 /* BinaryDecodingOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1258 /* BinaryDecodingOptions.swift */; }; - OBJ_2706 /* BinaryDelimited.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1259 /* BinaryDelimited.swift */; }; - OBJ_2707 /* BinaryEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1260 /* BinaryEncoder.swift */; }; - OBJ_2708 /* BinaryEncodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1261 /* BinaryEncodingError.swift */; }; - OBJ_2709 /* BinaryEncodingSizeVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1262 /* BinaryEncodingSizeVisitor.swift */; }; - OBJ_2710 /* BinaryEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1263 /* BinaryEncodingVisitor.swift */; }; - OBJ_2711 /* CustomJSONCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1264 /* CustomJSONCodable.swift */; }; - OBJ_2712 /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1265 /* Decoder.swift */; }; - OBJ_2713 /* DoubleFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1266 /* DoubleFormatter.swift */; }; - OBJ_2714 /* Enum.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1267 /* Enum.swift */; }; - OBJ_2715 /* ExtensibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1268 /* ExtensibleMessage.swift */; }; - OBJ_2716 /* ExtensionFieldValueSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1269 /* ExtensionFieldValueSet.swift */; }; - OBJ_2717 /* ExtensionFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1270 /* ExtensionFields.swift */; }; - OBJ_2718 /* ExtensionMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1271 /* ExtensionMap.swift */; }; - OBJ_2719 /* FieldTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1272 /* FieldTag.swift */; }; - OBJ_2720 /* FieldTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1273 /* FieldTypes.swift */; }; - OBJ_2721 /* Google_Protobuf_Any+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1274 /* Google_Protobuf_Any+Extensions.swift */; }; - OBJ_2722 /* Google_Protobuf_Any+Registry.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1275 /* Google_Protobuf_Any+Registry.swift */; }; - OBJ_2723 /* Google_Protobuf_Duration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1276 /* Google_Protobuf_Duration+Extensions.swift */; }; - OBJ_2724 /* Google_Protobuf_FieldMask+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1277 /* Google_Protobuf_FieldMask+Extensions.swift */; }; - OBJ_2725 /* Google_Protobuf_ListValue+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1278 /* Google_Protobuf_ListValue+Extensions.swift */; }; - OBJ_2726 /* Google_Protobuf_Struct+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1279 /* Google_Protobuf_Struct+Extensions.swift */; }; - OBJ_2727 /* Google_Protobuf_Timestamp+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1280 /* Google_Protobuf_Timestamp+Extensions.swift */; }; - OBJ_2728 /* Google_Protobuf_Value+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1281 /* Google_Protobuf_Value+Extensions.swift */; }; - OBJ_2729 /* Google_Protobuf_Wrappers+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1282 /* Google_Protobuf_Wrappers+Extensions.swift */; }; - OBJ_2730 /* HashVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1283 /* HashVisitor.swift */; }; - OBJ_2731 /* Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1284 /* Internal.swift */; }; - OBJ_2732 /* JSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1285 /* JSONDecoder.swift */; }; - OBJ_2733 /* JSONDecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1286 /* JSONDecodingError.swift */; }; - OBJ_2734 /* JSONDecodingOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1287 /* JSONDecodingOptions.swift */; }; - OBJ_2735 /* JSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1288 /* JSONEncoder.swift */; }; - OBJ_2736 /* JSONEncodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1289 /* JSONEncodingError.swift */; }; - OBJ_2737 /* JSONEncodingOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1290 /* JSONEncodingOptions.swift */; }; - OBJ_2738 /* JSONEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1291 /* JSONEncodingVisitor.swift */; }; - OBJ_2739 /* JSONMapEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1292 /* JSONMapEncodingVisitor.swift */; }; - OBJ_2740 /* JSONScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1293 /* JSONScanner.swift */; }; - OBJ_2741 /* MathUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1294 /* MathUtils.swift */; }; - OBJ_2742 /* Message+AnyAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1295 /* Message+AnyAdditions.swift */; }; - OBJ_2743 /* Message+BinaryAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1296 /* Message+BinaryAdditions.swift */; }; - OBJ_2744 /* Message+JSONAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1297 /* Message+JSONAdditions.swift */; }; - OBJ_2745 /* Message+JSONArrayAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1298 /* Message+JSONArrayAdditions.swift */; }; - OBJ_2746 /* Message+TextFormatAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1299 /* Message+TextFormatAdditions.swift */; }; - OBJ_2747 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1300 /* Message.swift */; }; - OBJ_2748 /* MessageExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1301 /* MessageExtension.swift */; }; - OBJ_2749 /* NameMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1302 /* NameMap.swift */; }; - OBJ_2750 /* ProtoNameProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1303 /* ProtoNameProviding.swift */; }; - OBJ_2751 /* ProtobufAPIVersionCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1304 /* ProtobufAPIVersionCheck.swift */; }; - OBJ_2752 /* ProtobufMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1305 /* ProtobufMap.swift */; }; - OBJ_2753 /* SelectiveVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1306 /* SelectiveVisitor.swift */; }; - OBJ_2754 /* SimpleExtensionMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1307 /* SimpleExtensionMap.swift */; }; - OBJ_2755 /* StringUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1308 /* StringUtils.swift */; }; - OBJ_2756 /* TextFormatDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1309 /* TextFormatDecoder.swift */; }; - OBJ_2757 /* TextFormatDecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1310 /* TextFormatDecodingError.swift */; }; - OBJ_2758 /* TextFormatEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1311 /* TextFormatEncoder.swift */; }; - OBJ_2759 /* TextFormatEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1312 /* TextFormatEncodingVisitor.swift */; }; - OBJ_2760 /* TextFormatScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1313 /* TextFormatScanner.swift */; }; - OBJ_2761 /* TimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1314 /* TimeUtils.swift */; }; - OBJ_2762 /* UnknownStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1315 /* UnknownStorage.swift */; }; - OBJ_2763 /* Varint.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1316 /* Varint.swift */; }; - OBJ_2764 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1317 /* Version.swift */; }; - OBJ_2765 /* Visitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1318 /* Visitor.swift */; }; - OBJ_2766 /* WireFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1319 /* WireFormat.swift */; }; - OBJ_2767 /* ZigZag.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1320 /* ZigZag.swift */; }; - OBJ_2768 /* any.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1321 /* any.pb.swift */; }; - OBJ_2769 /* api.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1322 /* api.pb.swift */; }; - OBJ_2770 /* duration.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1323 /* duration.pb.swift */; }; - OBJ_2771 /* empty.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1324 /* empty.pb.swift */; }; - OBJ_2772 /* field_mask.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1325 /* field_mask.pb.swift */; }; - OBJ_2773 /* source_context.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1326 /* source_context.pb.swift */; }; - OBJ_2774 /* struct.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1327 /* struct.pb.swift */; }; - OBJ_2775 /* timestamp.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1328 /* timestamp.pb.swift */; }; - OBJ_2776 /* type.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1329 /* type.pb.swift */; }; - OBJ_2777 /* wrappers.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1330 /* wrappers.pb.swift */; }; - OBJ_2784 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1370 /* Package.swift */; }; - OBJ_2790 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1352 /* Array+Extensions.swift */; }; - OBJ_2791 /* CodePrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1353 /* CodePrinter.swift */; }; - OBJ_2792 /* Descriptor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1354 /* Descriptor+Extensions.swift */; }; - OBJ_2793 /* Descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1355 /* Descriptor.swift */; }; - OBJ_2794 /* FieldNumbers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1356 /* FieldNumbers.swift */; }; - OBJ_2795 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1357 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift */; }; - OBJ_2796 /* Google_Protobuf_SourceCodeInfo+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1358 /* Google_Protobuf_SourceCodeInfo+Extensions.swift */; }; - OBJ_2797 /* NamingUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1359 /* NamingUtils.swift */; }; - OBJ_2798 /* ProtoFileToModuleMappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1360 /* ProtoFileToModuleMappings.swift */; }; - OBJ_2799 /* ProvidesLocationPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1361 /* ProvidesLocationPath.swift */; }; - OBJ_2800 /* ProvidesSourceCodeLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1362 /* ProvidesSourceCodeLocation.swift */; }; - OBJ_2801 /* SwiftLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1363 /* SwiftLanguage.swift */; }; - OBJ_2802 /* SwiftProtobufInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1364 /* SwiftProtobufInfo.swift */; }; - OBJ_2803 /* SwiftProtobufNamer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1365 /* SwiftProtobufNamer.swift */; }; - OBJ_2804 /* UnicodeScalar+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1366 /* UnicodeScalar+Extensions.swift */; }; - OBJ_2805 /* descriptor.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1367 /* descriptor.pb.swift */; }; - OBJ_2806 /* plugin.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1368 /* plugin.pb.swift */; }; - OBJ_2807 /* swift_protobuf_module_mappings.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1369 /* swift_protobuf_module_mappings.pb.swift */; }; - OBJ_2809 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2816 /* CommandLine+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1332 /* CommandLine+Extensions.swift */; }; - OBJ_2817 /* Descriptor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1333 /* Descriptor+Extensions.swift */; }; - OBJ_2818 /* EnumGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1334 /* EnumGenerator.swift */; }; - OBJ_2819 /* ExtensionSetGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1335 /* ExtensionSetGenerator.swift */; }; - OBJ_2820 /* FieldGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1336 /* FieldGenerator.swift */; }; - OBJ_2821 /* FileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1337 /* FileGenerator.swift */; }; - OBJ_2822 /* FileIo.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1338 /* FileIo.swift */; }; - OBJ_2823 /* GenerationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1339 /* GenerationError.swift */; }; - OBJ_2824 /* GeneratorOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1340 /* GeneratorOptions.swift */; }; - OBJ_2825 /* Google_Protobuf_DescriptorProto+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1341 /* Google_Protobuf_DescriptorProto+Extensions.swift */; }; - OBJ_2826 /* Google_Protobuf_FileDescriptorProto+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1342 /* Google_Protobuf_FileDescriptorProto+Extensions.swift */; }; - OBJ_2827 /* MessageFieldGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1343 /* MessageFieldGenerator.swift */; }; - OBJ_2828 /* MessageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1344 /* MessageGenerator.swift */; }; - OBJ_2829 /* MessageStorageClassGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1345 /* MessageStorageClassGenerator.swift */; }; - OBJ_2830 /* OneofGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1346 /* OneofGenerator.swift */; }; - OBJ_2831 /* StringUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1347 /* StringUtils.swift */; }; - OBJ_2832 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1348 /* Version.swift */; }; - OBJ_2833 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1349 /* main.swift */; }; - OBJ_2835 /* SwiftProtobufPluginLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobufPluginLibrary::Product /* SwiftProtobufPluginLibrary.framework */; }; - OBJ_2836 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2844 /* Generator-Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* Generator-Client.swift */; }; - OBJ_2845 /* Generator-Methods.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* Generator-Methods.swift */; }; - OBJ_2846 /* Generator-Names.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* Generator-Names.swift */; }; - OBJ_2847 /* Generator-Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* Generator-Server.swift */; }; - OBJ_2848 /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* Generator.swift */; }; - OBJ_2849 /* StreamingType.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* StreamingType.swift */; }; - OBJ_2850 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* main.swift */; }; - OBJ_2851 /* options.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* options.swift */; }; - OBJ_2853 /* SwiftProtobufPluginLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobufPluginLibrary::Product /* SwiftProtobufPluginLibrary.framework */; }; - OBJ_2854 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; - OBJ_2863 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1121 /* Package.swift */; }; - OBJ_2869 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1239 /* Package.swift */; }; + 8C62FEC438C40E6C5D10918B /* cgrpc.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_933 /* cgrpc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1478 /* a_bitstr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* a_bitstr.c */; }; + OBJ_1479 /* a_bool.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* a_bool.c */; }; + OBJ_1480 /* a_d2i_fp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* a_d2i_fp.c */; }; + OBJ_1481 /* a_dup.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* a_dup.c */; }; + OBJ_1482 /* a_enum.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* a_enum.c */; }; + OBJ_1483 /* a_gentm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* a_gentm.c */; }; + OBJ_1484 /* a_i2d_fp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* a_i2d_fp.c */; }; + OBJ_1485 /* a_int.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* a_int.c */; }; + OBJ_1486 /* a_mbstr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* a_mbstr.c */; }; + OBJ_1487 /* a_object.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* a_object.c */; }; + OBJ_1488 /* a_octet.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_22 /* a_octet.c */; }; + OBJ_1489 /* a_print.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_23 /* a_print.c */; }; + OBJ_1490 /* a_strnid.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_24 /* a_strnid.c */; }; + OBJ_1491 /* a_time.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_25 /* a_time.c */; }; + OBJ_1492 /* a_type.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_26 /* a_type.c */; }; + OBJ_1493 /* a_utctm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_27 /* a_utctm.c */; }; + OBJ_1494 /* a_utf8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* a_utf8.c */; }; + OBJ_1495 /* asn1_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_29 /* asn1_lib.c */; }; + OBJ_1496 /* asn1_par.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_30 /* asn1_par.c */; }; + OBJ_1497 /* asn_pack.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_31 /* asn_pack.c */; }; + OBJ_1498 /* f_enum.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_32 /* f_enum.c */; }; + OBJ_1499 /* f_int.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_33 /* f_int.c */; }; + OBJ_1500 /* f_string.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_34 /* f_string.c */; }; + OBJ_1501 /* tasn_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_35 /* tasn_dec.c */; }; + OBJ_1502 /* tasn_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_36 /* tasn_enc.c */; }; + OBJ_1503 /* tasn_fre.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_37 /* tasn_fre.c */; }; + OBJ_1504 /* tasn_new.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_38 /* tasn_new.c */; }; + OBJ_1505 /* tasn_typ.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_39 /* tasn_typ.c */; }; + OBJ_1506 /* tasn_utl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_40 /* tasn_utl.c */; }; + OBJ_1507 /* time_support.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_41 /* time_support.c */; }; + OBJ_1508 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_43 /* base64.c */; }; + OBJ_1509 /* bio.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_45 /* bio.c */; }; + OBJ_1510 /* bio_mem.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_46 /* bio_mem.c */; }; + OBJ_1511 /* connect.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_47 /* connect.c */; }; + OBJ_1512 /* fd.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_48 /* fd.c */; }; + OBJ_1513 /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_49 /* file.c */; }; + OBJ_1514 /* hexdump.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_50 /* hexdump.c */; }; + OBJ_1515 /* pair.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_51 /* pair.c */; }; + OBJ_1516 /* printf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_52 /* printf.c */; }; + OBJ_1517 /* socket.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_53 /* socket.c */; }; + OBJ_1518 /* socket_helper.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_54 /* socket_helper.c */; }; + OBJ_1519 /* bn_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_56 /* bn_asn1.c */; }; + OBJ_1520 /* convert.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_57 /* convert.c */; }; + OBJ_1521 /* buf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_59 /* buf.c */; }; + OBJ_1522 /* asn1_compat.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_61 /* asn1_compat.c */; }; + OBJ_1523 /* ber.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_62 /* ber.c */; }; + OBJ_1524 /* cbb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_63 /* cbb.c */; }; + OBJ_1525 /* cbs.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_64 /* cbs.c */; }; + OBJ_1526 /* chacha.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_66 /* chacha.c */; }; + OBJ_1527 /* cipher_extra.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_68 /* cipher_extra.c */; }; + OBJ_1528 /* derive_key.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_69 /* derive_key.c */; }; + OBJ_1529 /* e_aesccm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_70 /* e_aesccm.c */; }; + OBJ_1530 /* e_aesctrhmac.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_71 /* e_aesctrhmac.c */; }; + OBJ_1531 /* e_aesgcmsiv.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_72 /* e_aesgcmsiv.c */; }; + OBJ_1532 /* e_chacha20poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_73 /* e_chacha20poly1305.c */; }; + OBJ_1533 /* e_null.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_74 /* e_null.c */; }; + OBJ_1534 /* e_rc2.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_75 /* e_rc2.c */; }; + OBJ_1535 /* e_rc4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_76 /* e_rc4.c */; }; + OBJ_1536 /* e_ssl3.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_77 /* e_ssl3.c */; }; + OBJ_1537 /* e_tls.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_78 /* e_tls.c */; }; + OBJ_1538 /* tls_cbc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_79 /* tls_cbc.c */; }; + OBJ_1539 /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_81 /* cmac.c */; }; + OBJ_1540 /* conf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_83 /* conf.c */; }; + OBJ_1541 /* cpu-aarch64-fuchsia.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_84 /* cpu-aarch64-fuchsia.c */; }; + OBJ_1542 /* cpu-aarch64-linux.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_85 /* cpu-aarch64-linux.c */; }; + OBJ_1543 /* cpu-arm-linux.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_86 /* cpu-arm-linux.c */; }; + OBJ_1544 /* cpu-arm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_87 /* cpu-arm.c */; }; + OBJ_1545 /* cpu-intel.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_88 /* cpu-intel.c */; }; + OBJ_1546 /* cpu-ppc64le.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_89 /* cpu-ppc64le.c */; }; + OBJ_1547 /* crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_90 /* crypto.c */; }; + OBJ_1548 /* spake25519.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_92 /* spake25519.c */; }; + OBJ_1549 /* check.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_94 /* check.c */; }; + OBJ_1550 /* dh.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_95 /* dh.c */; }; + OBJ_1551 /* dh_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_96 /* dh_asn1.c */; }; + OBJ_1552 /* params.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_97 /* params.c */; }; + OBJ_1553 /* digest_extra.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_99 /* digest_extra.c */; }; + OBJ_1554 /* dsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_101 /* dsa.c */; }; + OBJ_1555 /* dsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_102 /* dsa_asn1.c */; }; + OBJ_1556 /* ec_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_104 /* ec_asn1.c */; }; + OBJ_1557 /* ecdh.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_106 /* ecdh.c */; }; + OBJ_1558 /* ecdsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_108 /* ecdsa_asn1.c */; }; + OBJ_1559 /* engine.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_110 /* engine.c */; }; + OBJ_1560 /* err.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_112 /* err.c */; }; + OBJ_1561 /* err_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_113 /* err_data.c */; }; + OBJ_1562 /* digestsign.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_115 /* digestsign.c */; }; + OBJ_1563 /* evp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_116 /* evp.c */; }; + OBJ_1564 /* evp_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_117 /* evp_asn1.c */; }; + OBJ_1565 /* evp_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_118 /* evp_ctx.c */; }; + OBJ_1566 /* p_dsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_119 /* p_dsa_asn1.c */; }; + OBJ_1567 /* p_ec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_120 /* p_ec.c */; }; + OBJ_1568 /* p_ec_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_121 /* p_ec_asn1.c */; }; + OBJ_1569 /* p_ed25519.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_122 /* p_ed25519.c */; }; + OBJ_1570 /* p_ed25519_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_123 /* p_ed25519_asn1.c */; }; + OBJ_1571 /* p_rsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_124 /* p_rsa.c */; }; + OBJ_1572 /* p_rsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_125 /* p_rsa_asn1.c */; }; + OBJ_1573 /* pbkdf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_126 /* pbkdf.c */; }; + OBJ_1574 /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_127 /* print.c */; }; + OBJ_1575 /* scrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_128 /* scrypt.c */; }; + OBJ_1576 /* sign.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_129 /* sign.c */; }; + OBJ_1577 /* ex_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_130 /* ex_data.c */; }; + OBJ_1578 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_133 /* aes.c */; }; + OBJ_1579 /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_134 /* key_wrap.c */; }; + OBJ_1580 /* mode_wrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_135 /* mode_wrappers.c */; }; + OBJ_1581 /* add.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_137 /* add.c */; }; + OBJ_1582 /* bn.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_138 /* bn.c */; }; + OBJ_1583 /* bytes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_139 /* bytes.c */; }; + OBJ_1584 /* cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_140 /* cmp.c */; }; + OBJ_1585 /* ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_141 /* ctx.c */; }; + OBJ_1586 /* div.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_142 /* div.c */; }; + OBJ_1587 /* exponentiation.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_143 /* exponentiation.c */; }; + OBJ_1588 /* gcd.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_144 /* gcd.c */; }; + OBJ_1589 /* generic.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_145 /* generic.c */; }; + OBJ_1590 /* jacobi.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_146 /* jacobi.c */; }; + OBJ_1591 /* montgomery.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_147 /* montgomery.c */; }; + OBJ_1592 /* montgomery_inv.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_148 /* montgomery_inv.c */; }; + OBJ_1593 /* mul.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_149 /* mul.c */; }; + OBJ_1594 /* prime.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_150 /* prime.c */; }; + OBJ_1595 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_151 /* random.c */; }; + OBJ_1596 /* rsaz_exp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_152 /* rsaz_exp.c */; }; + OBJ_1597 /* shift.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_153 /* shift.c */; }; + OBJ_1598 /* sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_154 /* sqrt.c */; }; + OBJ_1599 /* aead.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_156 /* aead.c */; }; + OBJ_1600 /* cipher.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_157 /* cipher.c */; }; + OBJ_1601 /* e_aes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_158 /* e_aes.c */; }; + OBJ_1602 /* e_des.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_159 /* e_des.c */; }; + OBJ_1603 /* des.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_161 /* des.c */; }; + OBJ_1604 /* digest.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_163 /* digest.c */; }; + OBJ_1605 /* digests.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_164 /* digests.c */; }; + OBJ_1606 /* ec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_166 /* ec.c */; }; + OBJ_1607 /* ec_key.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_167 /* ec_key.c */; }; + OBJ_1608 /* ec_montgomery.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_168 /* ec_montgomery.c */; }; + OBJ_1609 /* oct.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_169 /* oct.c */; }; + OBJ_1610 /* p224-64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_170 /* p224-64.c */; }; + OBJ_1611 /* p256-x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_171 /* p256-x86_64.c */; }; + OBJ_1612 /* simple.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_172 /* simple.c */; }; + OBJ_1613 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_173 /* util.c */; }; + OBJ_1614 /* wnaf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_174 /* wnaf.c */; }; + OBJ_1615 /* ecdsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_176 /* ecdsa.c */; }; + OBJ_1616 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_178 /* hmac.c */; }; + OBJ_1617 /* is_fips.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_179 /* is_fips.c */; }; + OBJ_1618 /* md4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_181 /* md4.c */; }; + OBJ_1619 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_183 /* md5.c */; }; + OBJ_1620 /* cbc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_185 /* cbc.c */; }; + OBJ_1621 /* ccm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_186 /* ccm.c */; }; + OBJ_1622 /* cfb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_187 /* cfb.c */; }; + OBJ_1623 /* ctr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_188 /* ctr.c */; }; + OBJ_1624 /* gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_189 /* gcm.c */; }; + OBJ_1625 /* ofb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_190 /* ofb.c */; }; + OBJ_1626 /* polyval.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_191 /* polyval.c */; }; + OBJ_1627 /* ctrdrbg.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_193 /* ctrdrbg.c */; }; + OBJ_1628 /* rand.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_194 /* rand.c */; }; + OBJ_1629 /* urandom.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_195 /* urandom.c */; }; + OBJ_1630 /* blinding.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_197 /* blinding.c */; }; + OBJ_1631 /* padding.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_198 /* padding.c */; }; + OBJ_1632 /* rsa.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_199 /* rsa.c */; }; + OBJ_1633 /* rsa_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_200 /* rsa_impl.c */; }; + OBJ_1634 /* self_check.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_202 /* self_check.c */; }; + OBJ_1635 /* sha1-altivec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_204 /* sha1-altivec.c */; }; + OBJ_1636 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_205 /* sha1.c */; }; + OBJ_1637 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_206 /* sha256.c */; }; + OBJ_1638 /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_207 /* sha512.c */; }; + OBJ_1639 /* kdf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_209 /* kdf.c */; }; + OBJ_1640 /* hkdf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_211 /* hkdf.c */; }; + OBJ_1641 /* lhash.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_213 /* lhash.c */; }; + OBJ_1642 /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_214 /* mem.c */; }; + OBJ_1643 /* obj.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_216 /* obj.c */; }; + OBJ_1644 /* obj_xref.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_217 /* obj_xref.c */; }; + OBJ_1645 /* pem_all.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_219 /* pem_all.c */; }; + OBJ_1646 /* pem_info.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_220 /* pem_info.c */; }; + OBJ_1647 /* pem_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_221 /* pem_lib.c */; }; + OBJ_1648 /* pem_oth.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_222 /* pem_oth.c */; }; + OBJ_1649 /* pem_pk8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_223 /* pem_pk8.c */; }; + OBJ_1650 /* pem_pkey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_224 /* pem_pkey.c */; }; + OBJ_1651 /* pem_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_225 /* pem_x509.c */; }; + OBJ_1652 /* pem_xaux.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_226 /* pem_xaux.c */; }; + OBJ_1653 /* pkcs7.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_228 /* pkcs7.c */; }; + OBJ_1654 /* pkcs7_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_229 /* pkcs7_x509.c */; }; + OBJ_1655 /* p5_pbev2.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_231 /* p5_pbev2.c */; }; + OBJ_1656 /* pkcs8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_232 /* pkcs8.c */; }; + OBJ_1657 /* pkcs8_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_233 /* pkcs8_x509.c */; }; + OBJ_1658 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_235 /* poly1305.c */; }; + OBJ_1659 /* poly1305_arm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_236 /* poly1305_arm.c */; }; + OBJ_1660 /* poly1305_vec.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_237 /* poly1305_vec.c */; }; + OBJ_1661 /* pool.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_239 /* pool.c */; }; + OBJ_1662 /* deterministic.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_241 /* deterministic.c */; }; + OBJ_1663 /* forkunsafe.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_242 /* forkunsafe.c */; }; + OBJ_1664 /* fuchsia.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_243 /* fuchsia.c */; }; + OBJ_1665 /* rand_extra.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_244 /* rand_extra.c */; }; + OBJ_1666 /* windows.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_245 /* windows.c */; }; + OBJ_1667 /* rc4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_247 /* rc4.c */; }; + OBJ_1668 /* refcount_c11.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_248 /* refcount_c11.c */; }; + OBJ_1669 /* refcount_lock.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_249 /* refcount_lock.c */; }; + OBJ_1670 /* rsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_251 /* rsa_asn1.c */; }; + OBJ_1671 /* stack.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_253 /* stack.c */; }; + OBJ_1672 /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_254 /* thread.c */; }; + OBJ_1673 /* thread_none.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_255 /* thread_none.c */; }; + OBJ_1674 /* thread_pthread.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_256 /* thread_pthread.c */; }; + OBJ_1675 /* thread_win.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_257 /* thread_win.c */; }; + OBJ_1676 /* a_digest.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_259 /* a_digest.c */; }; + OBJ_1677 /* a_sign.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_260 /* a_sign.c */; }; + OBJ_1678 /* a_strex.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_261 /* a_strex.c */; }; + OBJ_1679 /* a_verify.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_262 /* a_verify.c */; }; + OBJ_1680 /* algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_263 /* algorithm.c */; }; + OBJ_1681 /* asn1_gen.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_264 /* asn1_gen.c */; }; + OBJ_1682 /* by_dir.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_265 /* by_dir.c */; }; + OBJ_1683 /* by_file.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_266 /* by_file.c */; }; + OBJ_1684 /* i2d_pr.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_267 /* i2d_pr.c */; }; + OBJ_1685 /* rsa_pss.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_268 /* rsa_pss.c */; }; + OBJ_1686 /* t_crl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_269 /* t_crl.c */; }; + OBJ_1687 /* t_req.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_270 /* t_req.c */; }; + OBJ_1688 /* t_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_271 /* t_x509.c */; }; + OBJ_1689 /* t_x509a.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_272 /* t_x509a.c */; }; + OBJ_1690 /* x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_273 /* x509.c */; }; + OBJ_1691 /* x509_att.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_274 /* x509_att.c */; }; + OBJ_1692 /* x509_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_275 /* x509_cmp.c */; }; + OBJ_1693 /* x509_d2.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_276 /* x509_d2.c */; }; + OBJ_1694 /* x509_def.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_277 /* x509_def.c */; }; + OBJ_1695 /* x509_ext.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_278 /* x509_ext.c */; }; + OBJ_1696 /* x509_lu.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_279 /* x509_lu.c */; }; + OBJ_1697 /* x509_obj.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_280 /* x509_obj.c */; }; + OBJ_1698 /* x509_r2x.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_281 /* x509_r2x.c */; }; + OBJ_1699 /* x509_req.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_282 /* x509_req.c */; }; + OBJ_1700 /* x509_set.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_283 /* x509_set.c */; }; + OBJ_1701 /* x509_trs.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_284 /* x509_trs.c */; }; + OBJ_1702 /* x509_txt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_285 /* x509_txt.c */; }; + OBJ_1703 /* x509_v3.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_286 /* x509_v3.c */; }; + OBJ_1704 /* x509_vfy.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_287 /* x509_vfy.c */; }; + OBJ_1705 /* x509_vpm.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_288 /* x509_vpm.c */; }; + OBJ_1706 /* x509cset.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_289 /* x509cset.c */; }; + OBJ_1707 /* x509name.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_290 /* x509name.c */; }; + OBJ_1708 /* x509rset.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_291 /* x509rset.c */; }; + OBJ_1709 /* x509spki.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_292 /* x509spki.c */; }; + OBJ_1710 /* x_algor.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_293 /* x_algor.c */; }; + OBJ_1711 /* x_all.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_294 /* x_all.c */; }; + OBJ_1712 /* x_attrib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_295 /* x_attrib.c */; }; + OBJ_1713 /* x_crl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_296 /* x_crl.c */; }; + OBJ_1714 /* x_exten.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_297 /* x_exten.c */; }; + OBJ_1715 /* x_info.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_298 /* x_info.c */; }; + OBJ_1716 /* x_name.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_299 /* x_name.c */; }; + OBJ_1717 /* x_pkey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_300 /* x_pkey.c */; }; + OBJ_1718 /* x_pubkey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_301 /* x_pubkey.c */; }; + OBJ_1719 /* x_req.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_302 /* x_req.c */; }; + OBJ_1720 /* x_sig.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_303 /* x_sig.c */; }; + OBJ_1721 /* x_spki.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_304 /* x_spki.c */; }; + OBJ_1722 /* x_val.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_305 /* x_val.c */; }; + OBJ_1723 /* x_x509.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_306 /* x_x509.c */; }; + OBJ_1724 /* x_x509a.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_307 /* x_x509a.c */; }; + OBJ_1725 /* pcy_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_309 /* pcy_cache.c */; }; + OBJ_1726 /* pcy_data.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_310 /* pcy_data.c */; }; + OBJ_1727 /* pcy_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_311 /* pcy_lib.c */; }; + OBJ_1728 /* pcy_map.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_312 /* pcy_map.c */; }; + OBJ_1729 /* pcy_node.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_313 /* pcy_node.c */; }; + OBJ_1730 /* pcy_tree.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_314 /* pcy_tree.c */; }; + OBJ_1731 /* v3_akey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_315 /* v3_akey.c */; }; + OBJ_1732 /* v3_akeya.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_316 /* v3_akeya.c */; }; + OBJ_1733 /* v3_alt.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_317 /* v3_alt.c */; }; + OBJ_1734 /* v3_bcons.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_318 /* v3_bcons.c */; }; + OBJ_1735 /* v3_bitst.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_319 /* v3_bitst.c */; }; + OBJ_1736 /* v3_conf.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_320 /* v3_conf.c */; }; + OBJ_1737 /* v3_cpols.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_321 /* v3_cpols.c */; }; + OBJ_1738 /* v3_crld.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_322 /* v3_crld.c */; }; + OBJ_1739 /* v3_enum.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_323 /* v3_enum.c */; }; + OBJ_1740 /* v3_extku.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_324 /* v3_extku.c */; }; + OBJ_1741 /* v3_genn.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_325 /* v3_genn.c */; }; + OBJ_1742 /* v3_ia5.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_326 /* v3_ia5.c */; }; + OBJ_1743 /* v3_info.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_327 /* v3_info.c */; }; + OBJ_1744 /* v3_int.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_328 /* v3_int.c */; }; + OBJ_1745 /* v3_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_329 /* v3_lib.c */; }; + OBJ_1746 /* v3_ncons.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_330 /* v3_ncons.c */; }; + OBJ_1747 /* v3_pci.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_331 /* v3_pci.c */; }; + OBJ_1748 /* v3_pcia.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_332 /* v3_pcia.c */; }; + OBJ_1749 /* v3_pcons.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_333 /* v3_pcons.c */; }; + OBJ_1750 /* v3_pku.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_334 /* v3_pku.c */; }; + OBJ_1751 /* v3_pmaps.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_335 /* v3_pmaps.c */; }; + OBJ_1752 /* v3_prn.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_336 /* v3_prn.c */; }; + OBJ_1753 /* v3_purp.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_337 /* v3_purp.c */; }; + OBJ_1754 /* v3_skey.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_338 /* v3_skey.c */; }; + OBJ_1755 /* v3_sxnet.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_339 /* v3_sxnet.c */; }; + OBJ_1756 /* v3_utl.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_340 /* v3_utl.c */; }; + OBJ_1757 /* bio_ssl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_342 /* bio_ssl.cc */; }; + OBJ_1758 /* custom_extensions.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_343 /* custom_extensions.cc */; }; + OBJ_1759 /* d1_both.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_344 /* d1_both.cc */; }; + OBJ_1760 /* d1_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_345 /* d1_lib.cc */; }; + OBJ_1761 /* d1_pkt.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_346 /* d1_pkt.cc */; }; + OBJ_1762 /* d1_srtp.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_347 /* d1_srtp.cc */; }; + OBJ_1763 /* dtls_method.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_348 /* dtls_method.cc */; }; + OBJ_1764 /* dtls_record.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_349 /* dtls_record.cc */; }; + OBJ_1765 /* handoff.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_350 /* handoff.cc */; }; + OBJ_1766 /* handshake.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_351 /* handshake.cc */; }; + OBJ_1767 /* handshake_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_352 /* handshake_client.cc */; }; + OBJ_1768 /* handshake_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_353 /* handshake_server.cc */; }; + OBJ_1769 /* s3_both.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_354 /* s3_both.cc */; }; + OBJ_1770 /* s3_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_355 /* s3_lib.cc */; }; + OBJ_1771 /* s3_pkt.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_356 /* s3_pkt.cc */; }; + OBJ_1772 /* ssl_aead_ctx.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_357 /* ssl_aead_ctx.cc */; }; + OBJ_1773 /* ssl_asn1.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_358 /* ssl_asn1.cc */; }; + OBJ_1774 /* ssl_buffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_359 /* ssl_buffer.cc */; }; + OBJ_1775 /* ssl_cert.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_360 /* ssl_cert.cc */; }; + OBJ_1776 /* ssl_cipher.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_361 /* ssl_cipher.cc */; }; + OBJ_1777 /* ssl_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_362 /* ssl_file.cc */; }; + OBJ_1778 /* ssl_key_share.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_363 /* ssl_key_share.cc */; }; + OBJ_1779 /* ssl_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_364 /* ssl_lib.cc */; }; + OBJ_1780 /* ssl_privkey.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_365 /* ssl_privkey.cc */; }; + OBJ_1781 /* ssl_session.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_366 /* ssl_session.cc */; }; + OBJ_1782 /* ssl_stat.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_367 /* ssl_stat.cc */; }; + OBJ_1783 /* ssl_transcript.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_368 /* ssl_transcript.cc */; }; + OBJ_1784 /* ssl_versions.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_369 /* ssl_versions.cc */; }; + OBJ_1785 /* ssl_x509.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_370 /* ssl_x509.cc */; }; + OBJ_1786 /* t1_enc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_371 /* t1_enc.cc */; }; + OBJ_1787 /* t1_lib.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_372 /* t1_lib.cc */; }; + OBJ_1788 /* tls13_both.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_373 /* tls13_both.cc */; }; + OBJ_1789 /* tls13_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_374 /* tls13_client.cc */; }; + OBJ_1790 /* tls13_enc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_375 /* tls13_enc.cc */; }; + OBJ_1791 /* tls13_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_376 /* tls13_server.cc */; }; + OBJ_1792 /* tls_method.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_377 /* tls_method.cc */; }; + OBJ_1793 /* tls_record.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_378 /* tls_record.cc */; }; + OBJ_1794 /* curve25519.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_381 /* curve25519.c */; }; + OBJ_1795 /* p256.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_382 /* p256.c */; }; + OBJ_1802 /* c-atomics.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1180 /* c-atomics.c */; }; + OBJ_1804 /* CNIOAtomics.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1182 /* CNIOAtomics.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1805 /* cpp_magic.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1183 /* cpp_magic.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1812 /* shim.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1185 /* shim.c */; }; + OBJ_1814 /* CNIODarwin.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1187 /* CNIODarwin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1821 /* c_nio_http_parser.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1189 /* c_nio_http_parser.c */; }; + OBJ_1823 /* c_nio_http_parser.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1191 /* c_nio_http_parser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1824 /* CNIOHTTPParser.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1192 /* CNIOHTTPParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1831 /* ifaddrs-android.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1194 /* ifaddrs-android.c */; }; + OBJ_1832 /* shim.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1195 /* shim.c */; }; + OBJ_1834 /* CNIOLinux.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1197 /* CNIOLinux.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1835 /* ifaddrs-android.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1198 /* ifaddrs-android.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1842 /* shims.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1153 /* shims.c */; }; + OBJ_1849 /* c_nio_sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1200 /* c_nio_sha1.c */; }; + OBJ_1851 /* CNIOSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1202 /* CNIOSHA1.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1858 /* empty.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1204 /* empty.c */; }; + OBJ_1860 /* CNIOZlib.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_1206 /* CNIOZlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + OBJ_1867 /* byte_buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_462 /* byte_buffer.c */; }; + OBJ_1868 /* call.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_463 /* call.c */; }; + OBJ_1869 /* channel.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_464 /* channel.c */; }; + OBJ_1870 /* completion_queue.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_465 /* completion_queue.c */; }; + OBJ_1871 /* event.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_466 /* event.c */; }; + OBJ_1872 /* handler.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_467 /* handler.c */; }; + OBJ_1873 /* internal.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_468 /* internal.c */; }; + OBJ_1874 /* metadata.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_469 /* metadata.c */; }; + OBJ_1875 /* mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_470 /* mutex.c */; }; + OBJ_1876 /* observers.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_471 /* observers.c */; }; + OBJ_1877 /* operations.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_472 /* operations.c */; }; + OBJ_1878 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_473 /* server.c */; }; + OBJ_1879 /* grpc_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_479 /* grpc_context.cc */; }; + OBJ_1880 /* backup_poller.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_481 /* backup_poller.cc */; }; + OBJ_1881 /* channel_connectivity.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_482 /* channel_connectivity.cc */; }; + OBJ_1882 /* client_channel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_483 /* client_channel.cc */; }; + OBJ_1883 /* client_channel_channelz.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_484 /* client_channel_channelz.cc */; }; + OBJ_1884 /* client_channel_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_485 /* client_channel_factory.cc */; }; + OBJ_1885 /* client_channel_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_486 /* client_channel_plugin.cc */; }; + OBJ_1886 /* connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_487 /* connector.cc */; }; + OBJ_1887 /* global_subchannel_pool.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_488 /* global_subchannel_pool.cc */; }; + OBJ_1888 /* health.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_490 /* health.pb.c */; }; + OBJ_1889 /* health_check_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_491 /* health_check_client.cc */; }; + OBJ_1890 /* http_connect_handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_492 /* http_connect_handshaker.cc */; }; + OBJ_1891 /* http_proxy.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_493 /* http_proxy.cc */; }; + OBJ_1892 /* lb_policy.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_494 /* lb_policy.cc */; }; + OBJ_1893 /* client_load_reporting_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_497 /* client_load_reporting_filter.cc */; }; + OBJ_1894 /* grpclb.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_498 /* grpclb.cc */; }; + OBJ_1895 /* grpclb_channel_secure.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_499 /* grpclb_channel_secure.cc */; }; + OBJ_1896 /* grpclb_client_stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_500 /* grpclb_client_stats.cc */; }; + OBJ_1897 /* load_balancer_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_501 /* load_balancer_api.cc */; }; + OBJ_1898 /* duration.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_508 /* duration.pb.c */; }; + OBJ_1899 /* timestamp.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_509 /* timestamp.pb.c */; }; + OBJ_1900 /* load_balancer.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_510 /* load_balancer.pb.c */; }; + OBJ_1901 /* pick_first.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_512 /* pick_first.cc */; }; + OBJ_1902 /* round_robin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_514 /* round_robin.cc */; }; + OBJ_1903 /* xds.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_516 /* xds.cc */; }; + OBJ_1904 /* xds_channel_secure.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_517 /* xds_channel_secure.cc */; }; + OBJ_1905 /* xds_client_stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_518 /* xds_client_stats.cc */; }; + OBJ_1906 /* xds_load_balancer_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_519 /* xds_load_balancer_api.cc */; }; + OBJ_1907 /* lb_policy_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_520 /* lb_policy_registry.cc */; }; + OBJ_1908 /* local_subchannel_pool.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_521 /* local_subchannel_pool.cc */; }; + OBJ_1909 /* parse_address.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_522 /* parse_address.cc */; }; + OBJ_1910 /* proxy_mapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_523 /* proxy_mapper.cc */; }; + OBJ_1911 /* proxy_mapper_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_524 /* proxy_mapper_registry.cc */; }; + OBJ_1912 /* request_routing.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_525 /* request_routing.cc */; }; + OBJ_1913 /* resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_526 /* resolver.cc */; }; + OBJ_1914 /* dns_resolver_ares.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_530 /* dns_resolver_ares.cc */; }; + OBJ_1915 /* grpc_ares_ev_driver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_531 /* grpc_ares_ev_driver.cc */; }; + OBJ_1916 /* grpc_ares_ev_driver_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_532 /* grpc_ares_ev_driver_posix.cc */; }; + OBJ_1917 /* grpc_ares_ev_driver_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_533 /* grpc_ares_ev_driver_windows.cc */; }; + OBJ_1918 /* grpc_ares_wrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_534 /* grpc_ares_wrapper.cc */; }; + OBJ_1919 /* grpc_ares_wrapper_fallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_535 /* grpc_ares_wrapper_fallback.cc */; }; + OBJ_1920 /* grpc_ares_wrapper_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_536 /* grpc_ares_wrapper_posix.cc */; }; + OBJ_1921 /* grpc_ares_wrapper_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_537 /* grpc_ares_wrapper_windows.cc */; }; + OBJ_1922 /* dns_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_539 /* dns_resolver.cc */; }; + OBJ_1923 /* fake_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_541 /* fake_resolver.cc */; }; + OBJ_1924 /* sockaddr_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_543 /* sockaddr_resolver.cc */; }; + OBJ_1925 /* resolver_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_544 /* resolver_registry.cc */; }; + OBJ_1926 /* resolver_result_parsing.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_545 /* resolver_result_parsing.cc */; }; + OBJ_1927 /* retry_throttle.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_546 /* retry_throttle.cc */; }; + OBJ_1928 /* server_address.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_547 /* server_address.cc */; }; + OBJ_1929 /* subchannel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_548 /* subchannel.cc */; }; + OBJ_1930 /* subchannel_pool_interface.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_549 /* subchannel_pool_interface.cc */; }; + OBJ_1931 /* deadline_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_551 /* deadline_filter.cc */; }; + OBJ_1932 /* http_client_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_554 /* http_client_filter.cc */; }; + OBJ_1933 /* client_authority_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_555 /* client_authority_filter.cc */; }; + OBJ_1934 /* http_filters_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_556 /* http_filters_plugin.cc */; }; + OBJ_1935 /* message_compress_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_558 /* message_compress_filter.cc */; }; + OBJ_1936 /* http_server_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_560 /* http_server_filter.cc */; }; + OBJ_1937 /* max_age_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_562 /* max_age_filter.cc */; }; + OBJ_1938 /* message_size_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_564 /* message_size_filter.cc */; }; + OBJ_1939 /* workaround_cronet_compression_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_566 /* workaround_cronet_compression_filter.cc */; }; + OBJ_1940 /* workaround_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_567 /* workaround_utils.cc */; }; + OBJ_1941 /* alpn.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_571 /* alpn.cc */; }; + OBJ_1942 /* authority.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_573 /* authority.cc */; }; + OBJ_1943 /* chttp2_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_574 /* chttp2_connector.cc */; }; + OBJ_1944 /* channel_create.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_576 /* channel_create.cc */; }; + OBJ_1945 /* channel_create_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_577 /* channel_create_posix.cc */; }; + OBJ_1946 /* secure_channel_create.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_579 /* secure_channel_create.cc */; }; + OBJ_1947 /* chttp2_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_581 /* chttp2_server.cc */; }; + OBJ_1948 /* server_chttp2.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_583 /* server_chttp2.cc */; }; + OBJ_1949 /* server_chttp2_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_584 /* server_chttp2_posix.cc */; }; + OBJ_1950 /* server_secure_chttp2.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_586 /* server_secure_chttp2.cc */; }; + OBJ_1951 /* bin_decoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_588 /* bin_decoder.cc */; }; + OBJ_1952 /* bin_encoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_589 /* bin_encoder.cc */; }; + OBJ_1953 /* chttp2_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_590 /* chttp2_plugin.cc */; }; + OBJ_1954 /* chttp2_transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_591 /* chttp2_transport.cc */; }; + OBJ_1955 /* context_list.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_592 /* context_list.cc */; }; + OBJ_1956 /* flow_control.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_593 /* flow_control.cc */; }; + OBJ_1957 /* frame_data.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_594 /* frame_data.cc */; }; + OBJ_1958 /* frame_goaway.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_595 /* frame_goaway.cc */; }; + OBJ_1959 /* frame_ping.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_596 /* frame_ping.cc */; }; + OBJ_1960 /* frame_rst_stream.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_597 /* frame_rst_stream.cc */; }; + OBJ_1961 /* frame_settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_598 /* frame_settings.cc */; }; + OBJ_1962 /* frame_window_update.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_599 /* frame_window_update.cc */; }; + OBJ_1963 /* hpack_encoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_600 /* hpack_encoder.cc */; }; + OBJ_1964 /* hpack_parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_601 /* hpack_parser.cc */; }; + OBJ_1965 /* hpack_table.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_602 /* hpack_table.cc */; }; + OBJ_1966 /* http2_settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_603 /* http2_settings.cc */; }; + OBJ_1967 /* huffsyms.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_604 /* huffsyms.cc */; }; + OBJ_1968 /* incoming_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_605 /* incoming_metadata.cc */; }; + OBJ_1969 /* parsing.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_606 /* parsing.cc */; }; + OBJ_1970 /* stream_lists.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_607 /* stream_lists.cc */; }; + OBJ_1971 /* stream_map.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_608 /* stream_map.cc */; }; + OBJ_1972 /* varint.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_609 /* varint.cc */; }; + OBJ_1973 /* writing.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_610 /* writing.cc */; }; + OBJ_1974 /* inproc_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_612 /* inproc_plugin.cc */; }; + OBJ_1975 /* inproc_transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_613 /* inproc_transport.cc */; }; + OBJ_1976 /* avl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_616 /* avl.cc */; }; + OBJ_1977 /* backoff.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_618 /* backoff.cc */; }; + OBJ_1978 /* channel_args.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_620 /* channel_args.cc */; }; + OBJ_1979 /* channel_stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_621 /* channel_stack.cc */; }; + OBJ_1980 /* channel_stack_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_622 /* channel_stack_builder.cc */; }; + OBJ_1981 /* channel_trace.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_623 /* channel_trace.cc */; }; + OBJ_1982 /* channelz.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_624 /* channelz.cc */; }; + OBJ_1983 /* channelz_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_625 /* channelz_registry.cc */; }; + OBJ_1984 /* connected_channel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_626 /* connected_channel.cc */; }; + OBJ_1985 /* handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_627 /* handshaker.cc */; }; + OBJ_1986 /* handshaker_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_628 /* handshaker_registry.cc */; }; + OBJ_1987 /* status_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_629 /* status_util.cc */; }; + OBJ_1988 /* compression.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_631 /* compression.cc */; }; + OBJ_1989 /* compression_internal.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_632 /* compression_internal.cc */; }; + OBJ_1990 /* message_compress.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_633 /* message_compress.cc */; }; + OBJ_1991 /* stream_compression.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_634 /* stream_compression.cc */; }; + OBJ_1992 /* stream_compression_gzip.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_635 /* stream_compression_gzip.cc */; }; + OBJ_1993 /* stream_compression_identity.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_636 /* stream_compression_identity.cc */; }; + OBJ_1994 /* stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_638 /* stats.cc */; }; + OBJ_1995 /* stats_data.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_639 /* stats_data.cc */; }; + OBJ_1996 /* trace.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_640 /* trace.cc */; }; + OBJ_1997 /* alloc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_642 /* alloc.cc */; }; + OBJ_1998 /* arena.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_643 /* arena.cc */; }; + OBJ_1999 /* atm.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_644 /* atm.cc */; }; + OBJ_2000 /* cpu_iphone.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_645 /* cpu_iphone.cc */; }; + OBJ_2001 /* cpu_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_646 /* cpu_linux.cc */; }; + OBJ_2002 /* cpu_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_647 /* cpu_posix.cc */; }; + OBJ_2003 /* cpu_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_648 /* cpu_windows.cc */; }; + OBJ_2004 /* env_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_649 /* env_linux.cc */; }; + OBJ_2005 /* env_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_650 /* env_posix.cc */; }; + OBJ_2006 /* env_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_651 /* env_windows.cc */; }; + OBJ_2007 /* host_port.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_652 /* host_port.cc */; }; + OBJ_2008 /* log.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_653 /* log.cc */; }; + OBJ_2009 /* log_android.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_654 /* log_android.cc */; }; + OBJ_2010 /* log_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_655 /* log_linux.cc */; }; + OBJ_2011 /* log_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_656 /* log_posix.cc */; }; + OBJ_2012 /* log_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_657 /* log_windows.cc */; }; + OBJ_2013 /* mpscq.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_658 /* mpscq.cc */; }; + OBJ_2014 /* murmur_hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_659 /* murmur_hash.cc */; }; + OBJ_2015 /* string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_660 /* string.cc */; }; + OBJ_2016 /* string_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_661 /* string_posix.cc */; }; + OBJ_2017 /* string_util_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_662 /* string_util_windows.cc */; }; + OBJ_2018 /* string_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_663 /* string_windows.cc */; }; + OBJ_2019 /* sync.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_664 /* sync.cc */; }; + OBJ_2020 /* sync_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_665 /* sync_posix.cc */; }; + OBJ_2021 /* sync_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_666 /* sync_windows.cc */; }; + OBJ_2022 /* time.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_667 /* time.cc */; }; + OBJ_2023 /* time_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_668 /* time_posix.cc */; }; + OBJ_2024 /* time_precise.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_669 /* time_precise.cc */; }; + OBJ_2025 /* time_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_670 /* time_windows.cc */; }; + OBJ_2026 /* tls_pthread.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_671 /* tls_pthread.cc */; }; + OBJ_2027 /* tmpfile_msys.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_672 /* tmpfile_msys.cc */; }; + OBJ_2028 /* tmpfile_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_673 /* tmpfile_posix.cc */; }; + OBJ_2029 /* tmpfile_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_674 /* tmpfile_windows.cc */; }; + OBJ_2030 /* wrap_memcpy.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_675 /* wrap_memcpy.cc */; }; + OBJ_2031 /* fork.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_677 /* fork.cc */; }; + OBJ_2032 /* thd_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_678 /* thd_posix.cc */; }; + OBJ_2033 /* thd_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_679 /* thd_windows.cc */; }; + OBJ_2034 /* format_request.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_681 /* format_request.cc */; }; + OBJ_2035 /* httpcli.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_682 /* httpcli.cc */; }; + OBJ_2036 /* httpcli_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_683 /* httpcli_security_connector.cc */; }; + OBJ_2037 /* parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_684 /* parser.cc */; }; + OBJ_2038 /* buffer_list.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_686 /* buffer_list.cc */; }; + OBJ_2039 /* call_combiner.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_687 /* call_combiner.cc */; }; + OBJ_2040 /* combiner.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_688 /* combiner.cc */; }; + OBJ_2041 /* endpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_689 /* endpoint.cc */; }; + OBJ_2042 /* endpoint_pair_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_690 /* endpoint_pair_posix.cc */; }; + OBJ_2043 /* endpoint_pair_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_691 /* endpoint_pair_uv.cc */; }; + OBJ_2044 /* endpoint_pair_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_692 /* endpoint_pair_windows.cc */; }; + OBJ_2045 /* error.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_693 /* error.cc */; }; + OBJ_2046 /* ev_epoll1_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_694 /* ev_epoll1_linux.cc */; }; + OBJ_2047 /* ev_epollex_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_695 /* ev_epollex_linux.cc */; }; + OBJ_2048 /* ev_poll_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_696 /* ev_poll_posix.cc */; }; + OBJ_2049 /* ev_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_697 /* ev_posix.cc */; }; + OBJ_2050 /* ev_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_698 /* ev_windows.cc */; }; + OBJ_2051 /* exec_ctx.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_699 /* exec_ctx.cc */; }; + OBJ_2052 /* executor.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_700 /* executor.cc */; }; + OBJ_2053 /* fork_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_701 /* fork_posix.cc */; }; + OBJ_2054 /* fork_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_702 /* fork_windows.cc */; }; + OBJ_2055 /* gethostname_fallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_703 /* gethostname_fallback.cc */; }; + OBJ_2056 /* gethostname_host_name_max.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_704 /* gethostname_host_name_max.cc */; }; + OBJ_2057 /* gethostname_sysconf.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_705 /* gethostname_sysconf.cc */; }; + OBJ_2058 /* grpc_if_nametoindex_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_706 /* grpc_if_nametoindex_posix.cc */; }; + OBJ_2059 /* grpc_if_nametoindex_unsupported.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_707 /* grpc_if_nametoindex_unsupported.cc */; }; + OBJ_2060 /* internal_errqueue.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_708 /* internal_errqueue.cc */; }; + OBJ_2061 /* iocp_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_709 /* iocp_windows.cc */; }; + OBJ_2062 /* iomgr.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_710 /* iomgr.cc */; }; + OBJ_2063 /* iomgr_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_711 /* iomgr_custom.cc */; }; + OBJ_2064 /* iomgr_internal.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_712 /* iomgr_internal.cc */; }; + OBJ_2065 /* iomgr_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_713 /* iomgr_posix.cc */; }; + OBJ_2066 /* iomgr_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_714 /* iomgr_uv.cc */; }; + OBJ_2067 /* iomgr_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_715 /* iomgr_windows.cc */; }; + OBJ_2068 /* is_epollexclusive_available.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_716 /* is_epollexclusive_available.cc */; }; + OBJ_2069 /* load_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_717 /* load_file.cc */; }; + OBJ_2070 /* lockfree_event.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_718 /* lockfree_event.cc */; }; + OBJ_2071 /* polling_entity.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_719 /* polling_entity.cc */; }; + OBJ_2072 /* pollset.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_720 /* pollset.cc */; }; + OBJ_2073 /* pollset_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_721 /* pollset_custom.cc */; }; + OBJ_2074 /* pollset_set.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_722 /* pollset_set.cc */; }; + OBJ_2075 /* pollset_set_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_723 /* pollset_set_custom.cc */; }; + OBJ_2076 /* pollset_set_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_724 /* pollset_set_windows.cc */; }; + OBJ_2077 /* pollset_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_725 /* pollset_uv.cc */; }; + OBJ_2078 /* pollset_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_726 /* pollset_windows.cc */; }; + OBJ_2079 /* resolve_address.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_727 /* resolve_address.cc */; }; + OBJ_2080 /* resolve_address_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_728 /* resolve_address_custom.cc */; }; + OBJ_2081 /* resolve_address_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_729 /* resolve_address_posix.cc */; }; + OBJ_2082 /* resolve_address_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_730 /* resolve_address_windows.cc */; }; + OBJ_2083 /* resource_quota.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_731 /* resource_quota.cc */; }; + OBJ_2084 /* sockaddr_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_732 /* sockaddr_utils.cc */; }; + OBJ_2085 /* socket_factory_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_733 /* socket_factory_posix.cc */; }; + OBJ_2086 /* socket_mutator.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_734 /* socket_mutator.cc */; }; + OBJ_2087 /* socket_utils_common_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_735 /* socket_utils_common_posix.cc */; }; + OBJ_2088 /* socket_utils_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_736 /* socket_utils_linux.cc */; }; + OBJ_2089 /* socket_utils_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_737 /* socket_utils_posix.cc */; }; + OBJ_2090 /* socket_utils_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_738 /* socket_utils_uv.cc */; }; + OBJ_2091 /* socket_utils_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_739 /* socket_utils_windows.cc */; }; + OBJ_2092 /* socket_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_740 /* socket_windows.cc */; }; + OBJ_2093 /* tcp_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_741 /* tcp_client.cc */; }; + OBJ_2094 /* tcp_client_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_742 /* tcp_client_custom.cc */; }; + OBJ_2095 /* tcp_client_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_743 /* tcp_client_posix.cc */; }; + OBJ_2096 /* tcp_client_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_744 /* tcp_client_windows.cc */; }; + OBJ_2097 /* tcp_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_745 /* tcp_custom.cc */; }; + OBJ_2098 /* tcp_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_746 /* tcp_posix.cc */; }; + OBJ_2099 /* tcp_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_747 /* tcp_server.cc */; }; + OBJ_2100 /* tcp_server_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_748 /* tcp_server_custom.cc */; }; + OBJ_2101 /* tcp_server_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_749 /* tcp_server_posix.cc */; }; + OBJ_2102 /* tcp_server_utils_posix_common.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_750 /* tcp_server_utils_posix_common.cc */; }; + OBJ_2103 /* tcp_server_utils_posix_ifaddrs.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_751 /* tcp_server_utils_posix_ifaddrs.cc */; }; + OBJ_2104 /* tcp_server_utils_posix_noifaddrs.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_752 /* tcp_server_utils_posix_noifaddrs.cc */; }; + OBJ_2105 /* tcp_server_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_753 /* tcp_server_windows.cc */; }; + OBJ_2106 /* tcp_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_754 /* tcp_uv.cc */; }; + OBJ_2107 /* tcp_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_755 /* tcp_windows.cc */; }; + OBJ_2108 /* time_averaged_stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_756 /* time_averaged_stats.cc */; }; + OBJ_2109 /* timer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_757 /* timer.cc */; }; + OBJ_2110 /* timer_custom.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_758 /* timer_custom.cc */; }; + OBJ_2111 /* timer_generic.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_759 /* timer_generic.cc */; }; + OBJ_2112 /* timer_heap.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_760 /* timer_heap.cc */; }; + OBJ_2113 /* timer_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_761 /* timer_manager.cc */; }; + OBJ_2114 /* timer_uv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_762 /* timer_uv.cc */; }; + OBJ_2115 /* udp_server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_763 /* udp_server.cc */; }; + OBJ_2116 /* unix_sockets_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_764 /* unix_sockets_posix.cc */; }; + OBJ_2117 /* unix_sockets_posix_noop.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_765 /* unix_sockets_posix_noop.cc */; }; + OBJ_2118 /* wakeup_fd_cv.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_766 /* wakeup_fd_cv.cc */; }; + OBJ_2119 /* wakeup_fd_eventfd.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_767 /* wakeup_fd_eventfd.cc */; }; + OBJ_2120 /* wakeup_fd_nospecial.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_768 /* wakeup_fd_nospecial.cc */; }; + OBJ_2121 /* wakeup_fd_pipe.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_769 /* wakeup_fd_pipe.cc */; }; + OBJ_2122 /* wakeup_fd_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_770 /* wakeup_fd_posix.cc */; }; + OBJ_2123 /* json.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_772 /* json.cc */; }; + OBJ_2124 /* json_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_773 /* json_reader.cc */; }; + OBJ_2125 /* json_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_774 /* json_string.cc */; }; + OBJ_2126 /* json_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_775 /* json_writer.cc */; }; + OBJ_2127 /* basic_timers.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_777 /* basic_timers.cc */; }; + OBJ_2128 /* stap_timers.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_778 /* stap_timers.cc */; }; + OBJ_2129 /* security_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_781 /* security_context.cc */; }; + OBJ_2130 /* alts_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_784 /* alts_credentials.cc */; }; + OBJ_2131 /* check_gcp_environment.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_785 /* check_gcp_environment.cc */; }; + OBJ_2132 /* check_gcp_environment_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_786 /* check_gcp_environment_linux.cc */; }; + OBJ_2133 /* check_gcp_environment_no_op.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_787 /* check_gcp_environment_no_op.cc */; }; + OBJ_2134 /* check_gcp_environment_windows.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_788 /* check_gcp_environment_windows.cc */; }; + OBJ_2135 /* grpc_alts_credentials_client_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_789 /* grpc_alts_credentials_client_options.cc */; }; + OBJ_2136 /* grpc_alts_credentials_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_790 /* grpc_alts_credentials_options.cc */; }; + OBJ_2137 /* grpc_alts_credentials_server_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_791 /* grpc_alts_credentials_server_options.cc */; }; + OBJ_2138 /* composite_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_793 /* composite_credentials.cc */; }; + OBJ_2139 /* credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_794 /* credentials.cc */; }; + OBJ_2140 /* credentials_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_795 /* credentials_metadata.cc */; }; + OBJ_2141 /* fake_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_797 /* fake_credentials.cc */; }; + OBJ_2142 /* credentials_generic.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_799 /* credentials_generic.cc */; }; + OBJ_2143 /* google_default_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_800 /* google_default_credentials.cc */; }; + OBJ_2144 /* iam_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_802 /* iam_credentials.cc */; }; + OBJ_2145 /* json_token.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_804 /* json_token.cc */; }; + OBJ_2146 /* jwt_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_805 /* jwt_credentials.cc */; }; + OBJ_2147 /* jwt_verifier.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_806 /* jwt_verifier.cc */; }; + OBJ_2148 /* local_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_808 /* local_credentials.cc */; }; + OBJ_2149 /* oauth2_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_810 /* oauth2_credentials.cc */; }; + OBJ_2150 /* plugin_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_812 /* plugin_credentials.cc */; }; + OBJ_2151 /* ssl_credentials.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_814 /* ssl_credentials.cc */; }; + OBJ_2152 /* grpc_tls_credentials_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_816 /* grpc_tls_credentials_options.cc */; }; + OBJ_2153 /* alts_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_819 /* alts_security_connector.cc */; }; + OBJ_2154 /* fake_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_821 /* fake_security_connector.cc */; }; + OBJ_2155 /* load_system_roots_fallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_822 /* load_system_roots_fallback.cc */; }; + OBJ_2156 /* load_system_roots_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_823 /* load_system_roots_linux.cc */; }; + OBJ_2157 /* local_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_825 /* local_security_connector.cc */; }; + OBJ_2158 /* security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_826 /* security_connector.cc */; }; + OBJ_2159 /* ssl_security_connector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_828 /* ssl_security_connector.cc */; }; + OBJ_2160 /* ssl_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_829 /* ssl_utils.cc */; }; + OBJ_2161 /* client_auth_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_831 /* client_auth_filter.cc */; }; + OBJ_2162 /* secure_endpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_832 /* secure_endpoint.cc */; }; + OBJ_2163 /* security_handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_833 /* security_handshaker.cc */; }; + OBJ_2164 /* server_auth_filter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_834 /* server_auth_filter.cc */; }; + OBJ_2165 /* target_authority_table.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_835 /* target_authority_table.cc */; }; + OBJ_2166 /* tsi_error.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_836 /* tsi_error.cc */; }; + OBJ_2167 /* json_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_838 /* json_util.cc */; }; + OBJ_2168 /* b64.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_840 /* b64.cc */; }; + OBJ_2169 /* percent_encoding.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_841 /* percent_encoding.cc */; }; + OBJ_2170 /* slice.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_842 /* slice.cc */; }; + OBJ_2171 /* slice_buffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_843 /* slice_buffer.cc */; }; + OBJ_2172 /* slice_intern.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_844 /* slice_intern.cc */; }; + OBJ_2173 /* slice_string_helpers.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_845 /* slice_string_helpers.cc */; }; + OBJ_2174 /* api_trace.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_847 /* api_trace.cc */; }; + OBJ_2175 /* byte_buffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_848 /* byte_buffer.cc */; }; + OBJ_2176 /* byte_buffer_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_849 /* byte_buffer_reader.cc */; }; + OBJ_2177 /* call.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_850 /* call.cc */; }; + OBJ_2178 /* call_details.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_851 /* call_details.cc */; }; + OBJ_2179 /* call_log_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_852 /* call_log_batch.cc */; }; + OBJ_2180 /* channel.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_853 /* channel.cc */; }; + OBJ_2181 /* channel_init.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_854 /* channel_init.cc */; }; + OBJ_2182 /* channel_ping.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_855 /* channel_ping.cc */; }; + OBJ_2183 /* channel_stack_type.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_856 /* channel_stack_type.cc */; }; + OBJ_2184 /* completion_queue.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_857 /* completion_queue.cc */; }; + OBJ_2185 /* completion_queue_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_858 /* completion_queue_factory.cc */; }; + OBJ_2186 /* event_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_859 /* event_string.cc */; }; + OBJ_2187 /* init.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_860 /* init.cc */; }; + OBJ_2188 /* init_secure.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_861 /* init_secure.cc */; }; + OBJ_2189 /* lame_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_862 /* lame_client.cc */; }; + OBJ_2190 /* metadata_array.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_863 /* metadata_array.cc */; }; + OBJ_2191 /* server.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_864 /* server.cc */; }; + OBJ_2192 /* validate_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_865 /* validate_metadata.cc */; }; + OBJ_2193 /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_866 /* version.cc */; }; + OBJ_2194 /* bdp_estimator.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_868 /* bdp_estimator.cc */; }; + OBJ_2195 /* byte_stream.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_869 /* byte_stream.cc */; }; + OBJ_2196 /* connectivity_state.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_870 /* connectivity_state.cc */; }; + OBJ_2197 /* error_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_871 /* error_utils.cc */; }; + OBJ_2198 /* metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_872 /* metadata.cc */; }; + OBJ_2199 /* metadata_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_873 /* metadata_batch.cc */; }; + OBJ_2200 /* pid_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_874 /* pid_controller.cc */; }; + OBJ_2201 /* service_config.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_875 /* service_config.cc */; }; + OBJ_2202 /* static_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_876 /* static_metadata.cc */; }; + OBJ_2203 /* status_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_877 /* status_conversion.cc */; }; + OBJ_2204 /* status_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_878 /* status_metadata.cc */; }; + OBJ_2205 /* timeout_encoding.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_879 /* timeout_encoding.cc */; }; + OBJ_2206 /* transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_880 /* transport.cc */; }; + OBJ_2207 /* transport_op_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_881 /* transport_op_string.cc */; }; + OBJ_2208 /* uri_parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_883 /* uri_parser.cc */; }; + OBJ_2209 /* grpc_plugin_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_885 /* grpc_plugin_registry.cc */; }; + OBJ_2210 /* aes_gcm.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_889 /* aes_gcm.cc */; }; + OBJ_2211 /* gsec.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_890 /* gsec.cc */; }; + OBJ_2212 /* alts_counter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_892 /* alts_counter.cc */; }; + OBJ_2213 /* alts_crypter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_893 /* alts_crypter.cc */; }; + OBJ_2214 /* alts_frame_protector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_894 /* alts_frame_protector.cc */; }; + OBJ_2215 /* alts_record_protocol_crypter_common.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_895 /* alts_record_protocol_crypter_common.cc */; }; + OBJ_2216 /* alts_seal_privacy_integrity_crypter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_896 /* alts_seal_privacy_integrity_crypter.cc */; }; + OBJ_2217 /* alts_unseal_privacy_integrity_crypter.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_897 /* alts_unseal_privacy_integrity_crypter.cc */; }; + OBJ_2218 /* frame_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_898 /* frame_handler.cc */; }; + OBJ_2219 /* alts_handshaker_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_900 /* alts_handshaker_client.cc */; }; + OBJ_2220 /* alts_handshaker_service_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_901 /* alts_handshaker_service_api.cc */; }; + OBJ_2221 /* alts_handshaker_service_api_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_902 /* alts_handshaker_service_api_util.cc */; }; + OBJ_2222 /* alts_shared_resource.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_903 /* alts_shared_resource.cc */; }; + OBJ_2223 /* alts_tsi_handshaker.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_904 /* alts_tsi_handshaker.cc */; }; + OBJ_2224 /* alts_tsi_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_905 /* alts_tsi_utils.cc */; }; + OBJ_2225 /* altscontext.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_906 /* altscontext.pb.c */; }; + OBJ_2226 /* handshaker.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_907 /* handshaker.pb.c */; }; + OBJ_2227 /* transport_security_common.pb.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_908 /* transport_security_common.pb.c */; }; + OBJ_2228 /* transport_security_common_api.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_909 /* transport_security_common_api.cc */; }; + OBJ_2229 /* alts_grpc_integrity_only_record_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_911 /* alts_grpc_integrity_only_record_protocol.cc */; }; + OBJ_2230 /* alts_grpc_privacy_integrity_record_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_912 /* alts_grpc_privacy_integrity_record_protocol.cc */; }; + OBJ_2231 /* alts_grpc_record_protocol_common.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_913 /* alts_grpc_record_protocol_common.cc */; }; + OBJ_2232 /* alts_iovec_record_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_914 /* alts_iovec_record_protocol.cc */; }; + OBJ_2233 /* alts_zero_copy_grpc_protector.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_915 /* alts_zero_copy_grpc_protector.cc */; }; + OBJ_2234 /* fake_transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_916 /* fake_transport_security.cc */; }; + OBJ_2235 /* local_transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_917 /* local_transport_security.cc */; }; + OBJ_2236 /* ssl_session_boringssl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_920 /* ssl_session_boringssl.cc */; }; + OBJ_2237 /* ssl_session_cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_921 /* ssl_session_cache.cc */; }; + OBJ_2238 /* ssl_session_openssl.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_922 /* ssl_session_openssl.cc */; }; + OBJ_2239 /* ssl_transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_923 /* ssl_transport_security.cc */; }; + OBJ_2240 /* transport_security.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_924 /* transport_security.cc */; }; + OBJ_2241 /* transport_security_grpc.cc in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_925 /* transport_security_grpc.cc */; }; + OBJ_2242 /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_928 /* pb_common.c */; }; + OBJ_2243 /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_929 /* pb_decode.c */; }; + OBJ_2244 /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_930 /* pb_encode.c */; }; + OBJ_2246 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; + OBJ_2253 /* ArgumentConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1297 /* ArgumentConvertible.swift */; }; + OBJ_2254 /* ArgumentDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1298 /* ArgumentDescription.swift */; }; + OBJ_2255 /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1299 /* ArgumentParser.swift */; }; + OBJ_2256 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1300 /* Command.swift */; }; + OBJ_2257 /* CommandRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1301 /* CommandRunner.swift */; }; + OBJ_2258 /* CommandType.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1302 /* CommandType.swift */; }; + OBJ_2259 /* Commands.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1303 /* Commands.swift */; }; + OBJ_2260 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1304 /* Error.swift */; }; + OBJ_2261 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1305 /* Group.swift */; }; + OBJ_2268 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1306 /* Package.swift */; }; + OBJ_2274 /* EchoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1003 /* EchoProvider.swift */; }; + OBJ_2275 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1005 /* echo.grpc.swift */; }; + OBJ_2276 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1006 /* echo.pb.swift */; }; + OBJ_2277 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1007 /* main.swift */; }; + OBJ_2279 /* Commander.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = Commander::Commander::Product /* Commander.framework */; }; + OBJ_2280 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; + OBJ_2281 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2282 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; + OBJ_2283 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; + OBJ_2296 /* EchoProviderNIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1013 /* EchoProviderNIO.swift */; }; + OBJ_2297 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1015 /* echo.grpc.swift */; }; + OBJ_2298 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1016 /* echo.pb.swift */; }; + OBJ_2299 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1017 /* main.swift */; }; + OBJ_2301 /* Commander.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = Commander::Commander::Product /* Commander.framework */; }; + OBJ_2302 /* SwiftGRPCNIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPCNIO::Product /* SwiftGRPCNIO.framework */; }; + OBJ_2303 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2304 /* NIOHTTP2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */; }; + OBJ_2305 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; + OBJ_2306 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; + OBJ_2307 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; + OBJ_2308 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; + OBJ_2309 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; + OBJ_2310 /* NIOFoundationCompat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */; }; + OBJ_2311 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2312 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2313 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2314 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2315 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2316 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2317 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2347 /* AddressedEnvelope.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1208 /* AddressedEnvelope.swift */; }; + OBJ_2348 /* BaseSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1209 /* BaseSocket.swift */; }; + OBJ_2349 /* BaseSocketChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1210 /* BaseSocketChannel.swift */; }; + OBJ_2350 /* BlockingIOThreadPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1211 /* BlockingIOThreadPool.swift */; }; + OBJ_2351 /* Bootstrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1212 /* Bootstrap.swift */; }; + OBJ_2352 /* ByteBuffer-aux.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1213 /* ByteBuffer-aux.swift */; }; + OBJ_2353 /* ByteBuffer-core.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1214 /* ByteBuffer-core.swift */; }; + OBJ_2354 /* ByteBuffer-int.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1215 /* ByteBuffer-int.swift */; }; + OBJ_2355 /* ByteBuffer-views.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1216 /* ByteBuffer-views.swift */; }; + OBJ_2356 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1217 /* Channel.swift */; }; + OBJ_2357 /* ChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1218 /* ChannelHandler.swift */; }; + OBJ_2358 /* ChannelHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1219 /* ChannelHandlers.swift */; }; + OBJ_2359 /* ChannelInvoker.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1220 /* ChannelInvoker.swift */; }; + OBJ_2360 /* ChannelOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1221 /* ChannelOption.swift */; }; + OBJ_2361 /* ChannelPipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1222 /* ChannelPipeline.swift */; }; + OBJ_2362 /* CircularBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1223 /* CircularBuffer.swift */; }; + OBJ_2363 /* Codec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1224 /* Codec.swift */; }; + OBJ_2364 /* CompositeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1225 /* CompositeError.swift */; }; + OBJ_2365 /* ContiguousCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1226 /* ContiguousCollection.swift */; }; + OBJ_2366 /* DeadChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1227 /* DeadChannel.swift */; }; + OBJ_2367 /* Embedded.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1228 /* Embedded.swift */; }; + OBJ_2368 /* EventLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1229 /* EventLoop.swift */; }; + OBJ_2369 /* EventLoopFuture.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1230 /* EventLoopFuture.swift */; }; + OBJ_2370 /* FileDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1231 /* FileDescriptor.swift */; }; + OBJ_2371 /* FileHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1232 /* FileHandle.swift */; }; + OBJ_2372 /* FileRegion.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1233 /* FileRegion.swift */; }; + OBJ_2373 /* GetaddrinfoResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1234 /* GetaddrinfoResolver.swift */; }; + OBJ_2374 /* HappyEyeballs.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1235 /* HappyEyeballs.swift */; }; + OBJ_2375 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1236 /* Heap.swift */; }; + OBJ_2376 /* IO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1237 /* IO.swift */; }; + OBJ_2377 /* IOData.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1238 /* IOData.swift */; }; + OBJ_2378 /* IntegerTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1239 /* IntegerTypes.swift */; }; + OBJ_2379 /* Interfaces.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1240 /* Interfaces.swift */; }; + OBJ_2380 /* Linux.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1241 /* Linux.swift */; }; + OBJ_2381 /* LinuxCPUSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1242 /* LinuxCPUSet.swift */; }; + OBJ_2382 /* MarkedCircularBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1243 /* MarkedCircularBuffer.swift */; }; + OBJ_2383 /* MulticastChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1244 /* MulticastChannel.swift */; }; + OBJ_2384 /* NIOAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1245 /* NIOAny.swift */; }; + OBJ_2385 /* NonBlockingFileIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1246 /* NonBlockingFileIO.swift */; }; + OBJ_2386 /* PendingDatagramWritesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1247 /* PendingDatagramWritesManager.swift */; }; + OBJ_2387 /* PendingWritesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1248 /* PendingWritesManager.swift */; }; + OBJ_2388 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1249 /* PriorityQueue.swift */; }; + OBJ_2389 /* RecvByteBufferAllocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1250 /* RecvByteBufferAllocator.swift */; }; + OBJ_2390 /* Resolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1251 /* Resolver.swift */; }; + OBJ_2391 /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1252 /* Selectable.swift */; }; + OBJ_2392 /* Selector.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1253 /* Selector.swift */; }; + OBJ_2393 /* ServerSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1254 /* ServerSocket.swift */; }; + OBJ_2394 /* Socket.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1255 /* Socket.swift */; }; + OBJ_2395 /* SocketAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1256 /* SocketAddresses.swift */; }; + OBJ_2396 /* SocketChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1257 /* SocketChannel.swift */; }; + OBJ_2397 /* SocketOptionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1258 /* SocketOptionProvider.swift */; }; + OBJ_2398 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1259 /* System.swift */; }; + OBJ_2399 /* Thread.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1260 /* Thread.swift */; }; + OBJ_2400 /* TypeAssistedChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1261 /* TypeAssistedChannelHandler.swift */; }; + OBJ_2401 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1262 /* Utilities.swift */; }; + OBJ_2403 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2404 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2405 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2406 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2407 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2408 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2419 /* atomics.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1266 /* atomics.swift */; }; + OBJ_2420 /* lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1267 /* lock.swift */; }; + OBJ_2422 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2428 /* ByteBuffer-foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1271 /* ByteBuffer-foundation.swift */; }; + OBJ_2430 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2431 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2432 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2433 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2434 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2435 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2436 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2448 /* ByteCollectionUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1273 /* ByteCollectionUtils.swift */; }; + OBJ_2449 /* HTTPDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1274 /* HTTPDecoder.swift */; }; + OBJ_2450 /* HTTPEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1275 /* HTTPEncoder.swift */; }; + OBJ_2451 /* HTTPPipelineSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1276 /* HTTPPipelineSetup.swift */; }; + OBJ_2452 /* HTTPResponseCompressor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1277 /* HTTPResponseCompressor.swift */; }; + OBJ_2453 /* HTTPServerPipelineHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1278 /* HTTPServerPipelineHandler.swift */; }; + OBJ_2454 /* HTTPServerProtocolErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1279 /* HTTPServerProtocolErrorHandler.swift */; }; + OBJ_2455 /* HTTPTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1280 /* HTTPTypes.swift */; }; + OBJ_2456 /* HTTPUpgradeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1281 /* HTTPUpgradeHandler.swift */; }; + OBJ_2458 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; + OBJ_2459 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; + OBJ_2460 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2461 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2462 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2463 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2464 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2465 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2466 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2480 /* HTTP2DataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1159 /* HTTP2DataProvider.swift */; }; + OBJ_2481 /* HTTP2Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1160 /* HTTP2Error.swift */; }; + OBJ_2482 /* HTTP2ErrorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1161 /* HTTP2ErrorCode.swift */; }; + OBJ_2483 /* HTTP2Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1162 /* HTTP2Frame.swift */; }; + OBJ_2484 /* HTTP2HeaderBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1163 /* HTTP2HeaderBlock.swift */; }; + OBJ_2485 /* HTTP2Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1164 /* HTTP2Parser.swift */; }; + OBJ_2486 /* HTTP2PingData.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1165 /* HTTP2PingData.swift */; }; + OBJ_2487 /* HTTP2PipelineHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1166 /* HTTP2PipelineHelpers.swift */; }; + OBJ_2488 /* HTTP2Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1167 /* HTTP2Settings.swift */; }; + OBJ_2489 /* HTTP2Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1168 /* HTTP2Stream.swift */; }; + OBJ_2490 /* HTTP2StreamChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1169 /* HTTP2StreamChannel.swift */; }; + OBJ_2491 /* HTTP2StreamID.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1170 /* HTTP2StreamID.swift */; }; + OBJ_2492 /* HTTP2StreamMultiplexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1171 /* HTTP2StreamMultiplexer.swift */; }; + OBJ_2493 /* HTTP2ToHTTP1Codec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1172 /* HTTP2ToHTTP1Codec.swift */; }; + OBJ_2494 /* HTTP2UserEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1173 /* HTTP2UserEvents.swift */; }; + OBJ_2495 /* NGHTTP2Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1174 /* NGHTTP2Session.swift */; }; + OBJ_2497 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; + OBJ_2498 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; + OBJ_2499 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; + OBJ_2500 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; + OBJ_2501 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2502 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2503 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2504 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2505 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2506 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2507 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2508 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; + OBJ_2525 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1286 /* Heap.swift */; }; + OBJ_2526 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1287 /* PriorityQueue.swift */; }; + OBJ_2532 /* ApplicationProtocolNegotiationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1289 /* ApplicationProtocolNegotiationHandler.swift */; }; + OBJ_2533 /* SNIHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1290 /* SNIHandler.swift */; }; + OBJ_2534 /* TLSEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1291 /* TLSEvents.swift */; }; + OBJ_2536 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2537 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2538 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2539 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2540 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2541 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2542 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2555 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1019 /* main.swift */; }; + OBJ_2562 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1022 /* main.swift */; }; + OBJ_2564 /* Commander.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = Commander::Commander::Product /* Commander.framework */; }; + OBJ_2565 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; + OBJ_2566 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2567 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; + OBJ_2568 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; + OBJ_2578 /* ByteBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1025 /* ByteBuffer.swift */; }; + OBJ_2579 /* Call.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1026 /* Call.swift */; }; + OBJ_2580 /* CallError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1027 /* CallError.swift */; }; + OBJ_2581 /* CallResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1028 /* CallResult.swift */; }; + OBJ_2582 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1029 /* Channel.swift */; }; + OBJ_2583 /* ChannelArgument.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1030 /* ChannelArgument.swift */; }; + OBJ_2584 /* ChannelConnectivityObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1031 /* ChannelConnectivityObserver.swift */; }; + OBJ_2585 /* ChannelConnectivityState.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1032 /* ChannelConnectivityState.swift */; }; + OBJ_2586 /* ClientNetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1033 /* ClientNetworkMonitor.swift */; }; + OBJ_2587 /* CompletionQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1034 /* CompletionQueue.swift */; }; + OBJ_2588 /* Handler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1035 /* Handler.swift */; }; + OBJ_2589 /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1036 /* Metadata.swift */; }; + OBJ_2590 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1037 /* Mutex.swift */; }; + OBJ_2591 /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1038 /* Operation.swift */; }; + OBJ_2592 /* OperationGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1039 /* OperationGroup.swift */; }; + OBJ_2593 /* Roots.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1040 /* Roots.swift */; }; + OBJ_2594 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1041 /* Server.swift */; }; + OBJ_2595 /* ServerStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1042 /* ServerStatus.swift */; }; + OBJ_2596 /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1043 /* StatusCode.swift */; }; + OBJ_2597 /* gRPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1044 /* gRPC.swift */; }; + OBJ_2598 /* ClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1046 /* ClientCall.swift */; }; + OBJ_2599 /* ClientCallBidirectionalStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1047 /* ClientCallBidirectionalStreaming.swift */; }; + OBJ_2600 /* ClientCallClientStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1048 /* ClientCallClientStreaming.swift */; }; + OBJ_2601 /* ClientCallServerStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1049 /* ClientCallServerStreaming.swift */; }; + OBJ_2602 /* ClientCallUnary.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1050 /* ClientCallUnary.swift */; }; + OBJ_2603 /* RPCError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1051 /* RPCError.swift */; }; + OBJ_2604 /* ServerSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1052 /* ServerSession.swift */; }; + OBJ_2605 /* ServerSessionBidirectionalStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1053 /* ServerSessionBidirectionalStreaming.swift */; }; + OBJ_2606 /* ServerSessionClientStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1054 /* ServerSessionClientStreaming.swift */; }; + OBJ_2607 /* ServerSessionServerStreaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1055 /* ServerSessionServerStreaming.swift */; }; + OBJ_2608 /* ServerSessionUnary.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1056 /* ServerSessionUnary.swift */; }; + OBJ_2609 /* ServiceClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1057 /* ServiceClient.swift */; }; + OBJ_2610 /* ServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1058 /* ServiceProvider.swift */; }; + OBJ_2611 /* ServiceServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1059 /* ServiceServer.swift */; }; + OBJ_2612 /* StreamReceiving.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1060 /* StreamReceiving.swift */; }; + OBJ_2613 /* StreamSending.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1061 /* StreamSending.swift */; }; + OBJ_2615 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2616 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; + OBJ_2617 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; + OBJ_2625 /* BaseCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1064 /* BaseCallHandler.swift */; }; + OBJ_2626 /* BidirectionalStreamingCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1065 /* BidirectionalStreamingCallHandler.swift */; }; + OBJ_2627 /* ClientStreamingCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1066 /* ClientStreamingCallHandler.swift */; }; + OBJ_2628 /* ServerStreamingCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1067 /* ServerStreamingCallHandler.swift */; }; + OBJ_2629 /* UnaryCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1068 /* UnaryCallHandler.swift */; }; + OBJ_2630 /* BaseClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1070 /* BaseClientCall.swift */; }; + OBJ_2631 /* BidirectionalStreamingClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1071 /* BidirectionalStreamingClientCall.swift */; }; + OBJ_2632 /* ClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1072 /* ClientCall.swift */; }; + OBJ_2633 /* ClientStreamingClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1073 /* ClientStreamingClientCall.swift */; }; + OBJ_2634 /* ResponseObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1074 /* ResponseObserver.swift */; }; + OBJ_2635 /* ServerStreamingClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1075 /* ServerStreamingClientCall.swift */; }; + OBJ_2636 /* UnaryClientCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1076 /* UnaryClientCall.swift */; }; + OBJ_2637 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1077 /* ClientOptions.swift */; }; + OBJ_2638 /* CompressionMechanism.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1078 /* CompressionMechanism.swift */; }; + OBJ_2639 /* GRPCChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1079 /* GRPCChannelHandler.swift */; }; + OBJ_2640 /* GRPCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1080 /* GRPCClient.swift */; }; + OBJ_2641 /* GRPCClientChannelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1081 /* GRPCClientChannelHandler.swift */; }; + OBJ_2642 /* GRPCClientCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1082 /* GRPCClientCodec.swift */; }; + OBJ_2643 /* GRPCError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1083 /* GRPCError.swift */; }; + OBJ_2644 /* GRPCServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1084 /* GRPCServer.swift */; }; + OBJ_2645 /* GRPCServerCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1085 /* GRPCServerCodec.swift */; }; + OBJ_2646 /* GRPCStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1086 /* GRPCStatus.swift */; }; + OBJ_2647 /* GRPCTimeout.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1087 /* GRPCTimeout.swift */; }; + OBJ_2648 /* HTTP1ToRawGRPCClientCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1088 /* HTTP1ToRawGRPCClientCodec.swift */; }; + OBJ_2649 /* HTTP1ToRawGRPCServerCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1089 /* HTTP1ToRawGRPCServerCodec.swift */; }; + OBJ_2650 /* HTTPProtocolSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1090 /* HTTPProtocolSwitcher.swift */; }; + OBJ_2651 /* LengthPrefixedMessageReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1091 /* LengthPrefixedMessageReader.swift */; }; + OBJ_2652 /* LengthPrefixedMessageWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1092 /* LengthPrefixedMessageWriter.swift */; }; + OBJ_2653 /* LoggingServerErrorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1093 /* LoggingServerErrorDelegate.swift */; }; + OBJ_2654 /* ServerCallContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1095 /* ServerCallContext.swift */; }; + OBJ_2655 /* StreamingResponseCallContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1096 /* StreamingResponseCallContext.swift */; }; + OBJ_2656 /* UnaryResponseCallContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1097 /* UnaryResponseCallContext.swift */; }; + OBJ_2657 /* ServerErrorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1098 /* ServerErrorDelegate.swift */; }; + OBJ_2658 /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1099 /* StatusCode.swift */; }; + OBJ_2659 /* StreamEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1100 /* StreamEvent.swift */; }; + OBJ_2660 /* WebCORSHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1101 /* WebCORSHandler.swift */; }; + OBJ_2662 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2663 /* NIOHTTP2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */; }; + OBJ_2664 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; + OBJ_2665 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; + OBJ_2666 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; + OBJ_2667 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; + OBJ_2668 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; + OBJ_2669 /* NIOFoundationCompat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */; }; + OBJ_2670 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2671 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2672 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2673 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2674 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2675 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2676 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2697 /* EchoProviderNIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1114 /* EchoProviderNIO.swift */; }; + OBJ_2698 /* GRPCChannelHandlerResponseCapturingTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1115 /* GRPCChannelHandlerResponseCapturingTestCase.swift */; }; + OBJ_2699 /* GRPCChannelHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1116 /* GRPCChannelHandlerTests.swift */; }; + OBJ_2700 /* HTTP1ToRawGRPCServerCodecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1117 /* HTTP1ToRawGRPCServerCodecTests.swift */; }; + OBJ_2701 /* LengthPrefixedMessageReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1118 /* LengthPrefixedMessageReaderTests.swift */; }; + OBJ_2702 /* NIOBasicEchoTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1119 /* NIOBasicEchoTestCase.swift */; }; + OBJ_2703 /* NIOClientCancellingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1120 /* NIOClientCancellingTests.swift */; }; + OBJ_2704 /* NIOClientTimeoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1121 /* NIOClientTimeoutTests.swift */; }; + OBJ_2705 /* NIOServerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1122 /* NIOServerTests.swift */; }; + OBJ_2706 /* NIOServerWebTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1123 /* NIOServerWebTests.swift */; }; + OBJ_2707 /* ServerThrowingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1124 /* ServerThrowingTests.swift */; }; + OBJ_2708 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1125 /* TestHelpers.swift */; }; + OBJ_2709 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1126 /* echo.grpc.swift */; }; + OBJ_2710 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1127 /* echo.pb.swift */; }; + OBJ_2712 /* SwiftGRPCNIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPCNIO::Product /* SwiftGRPCNIO.framework */; }; + OBJ_2713 /* NIOHTTP2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */; }; + OBJ_2714 /* NIOTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOTLS::Product /* NIOTLS.framework */; }; + OBJ_2715 /* CNIONghttp2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */; }; + OBJ_2716 /* NIOHTTP1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */; }; + OBJ_2717 /* CNIOZlib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOZlib::Product /* CNIOZlib.framework */; }; + OBJ_2718 /* CNIOHTTPParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */; }; + OBJ_2719 /* NIOFoundationCompat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */; }; + OBJ_2720 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIO::Product /* NIO.framework */; }; + OBJ_2721 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */; }; + OBJ_2722 /* NIOPriorityQueue.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */; }; + OBJ_2723 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */; }; + OBJ_2724 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */; }; + OBJ_2725 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIODarwin::Product /* CNIODarwin.framework */; }; + OBJ_2726 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = swift-nio::CNIOLinux::Product /* CNIOLinux.framework */; }; + OBJ_2727 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; + OBJ_2728 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2729 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; + OBJ_2730 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; + OBJ_2755 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; + OBJ_2767 /* BasicEchoTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1129 /* BasicEchoTestCase.swift */; }; + OBJ_2768 /* ChannelArgumentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1130 /* ChannelArgumentTests.swift */; }; + OBJ_2769 /* ChannelConnectivityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1131 /* ChannelConnectivityTests.swift */; }; + OBJ_2770 /* ChannelShutdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1132 /* ChannelShutdownTests.swift */; }; + OBJ_2771 /* ClientCancellingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1133 /* ClientCancellingTests.swift */; }; + OBJ_2772 /* ClientTestExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1134 /* ClientTestExample.swift */; }; + OBJ_2773 /* ClientTimeoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1135 /* ClientTimeoutTests.swift */; }; + OBJ_2774 /* CompletionQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1136 /* CompletionQueueTests.swift */; }; + OBJ_2775 /* ConnectionFailureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1137 /* ConnectionFailureTests.swift */; }; + OBJ_2776 /* EchoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1138 /* EchoProvider.swift */; }; + OBJ_2777 /* EchoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1139 /* EchoTests.swift */; }; + OBJ_2778 /* GRPCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1140 /* GRPCTests.swift */; }; + OBJ_2779 /* MetadataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1141 /* MetadataTests.swift */; }; + OBJ_2780 /* ServerCancellingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1142 /* ServerCancellingTests.swift */; }; + OBJ_2781 /* ServerTestExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1143 /* ServerTestExample.swift */; }; + OBJ_2782 /* ServerThrowingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1144 /* ServerThrowingTests.swift */; }; + OBJ_2783 /* ServerTimeoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1145 /* ServerTimeoutTests.swift */; }; + OBJ_2784 /* ServiceClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1146 /* ServiceClientTests.swift */; }; + OBJ_2785 /* TestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1147 /* TestKeys.swift */; }; + OBJ_2786 /* echo.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1148 /* echo.grpc.swift */; }; + OBJ_2787 /* echo.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1149 /* echo.pb.swift */; }; + OBJ_2789 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */; }; + OBJ_2790 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2791 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::CgRPC::Product /* CgRPC.framework */; }; + OBJ_2792 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */; }; + OBJ_2801 /* AnyMessageStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1310 /* AnyMessageStorage.swift */; }; + OBJ_2802 /* AnyUnpackError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1311 /* AnyUnpackError.swift */; }; + OBJ_2803 /* BinaryDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1312 /* BinaryDecoder.swift */; }; + OBJ_2804 /* BinaryDecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1313 /* BinaryDecodingError.swift */; }; + OBJ_2805 /* BinaryDecodingOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1314 /* BinaryDecodingOptions.swift */; }; + OBJ_2806 /* BinaryDelimited.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1315 /* BinaryDelimited.swift */; }; + OBJ_2807 /* BinaryEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1316 /* BinaryEncoder.swift */; }; + OBJ_2808 /* BinaryEncodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1317 /* BinaryEncodingError.swift */; }; + OBJ_2809 /* BinaryEncodingSizeVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1318 /* BinaryEncodingSizeVisitor.swift */; }; + OBJ_2810 /* BinaryEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1319 /* BinaryEncodingVisitor.swift */; }; + OBJ_2811 /* CustomJSONCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1320 /* CustomJSONCodable.swift */; }; + OBJ_2812 /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1321 /* Decoder.swift */; }; + OBJ_2813 /* DoubleFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1322 /* DoubleFormatter.swift */; }; + OBJ_2814 /* Enum.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1323 /* Enum.swift */; }; + OBJ_2815 /* ExtensibleMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1324 /* ExtensibleMessage.swift */; }; + OBJ_2816 /* ExtensionFieldValueSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1325 /* ExtensionFieldValueSet.swift */; }; + OBJ_2817 /* ExtensionFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1326 /* ExtensionFields.swift */; }; + OBJ_2818 /* ExtensionMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1327 /* ExtensionMap.swift */; }; + OBJ_2819 /* FieldTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1328 /* FieldTag.swift */; }; + OBJ_2820 /* FieldTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1329 /* FieldTypes.swift */; }; + OBJ_2821 /* Google_Protobuf_Any+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1330 /* Google_Protobuf_Any+Extensions.swift */; }; + OBJ_2822 /* Google_Protobuf_Any+Registry.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1331 /* Google_Protobuf_Any+Registry.swift */; }; + OBJ_2823 /* Google_Protobuf_Duration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1332 /* Google_Protobuf_Duration+Extensions.swift */; }; + OBJ_2824 /* Google_Protobuf_FieldMask+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1333 /* Google_Protobuf_FieldMask+Extensions.swift */; }; + OBJ_2825 /* Google_Protobuf_ListValue+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1334 /* Google_Protobuf_ListValue+Extensions.swift */; }; + OBJ_2826 /* Google_Protobuf_Struct+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1335 /* Google_Protobuf_Struct+Extensions.swift */; }; + OBJ_2827 /* Google_Protobuf_Timestamp+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1336 /* Google_Protobuf_Timestamp+Extensions.swift */; }; + OBJ_2828 /* Google_Protobuf_Value+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1337 /* Google_Protobuf_Value+Extensions.swift */; }; + OBJ_2829 /* Google_Protobuf_Wrappers+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1338 /* Google_Protobuf_Wrappers+Extensions.swift */; }; + OBJ_2830 /* HashVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1339 /* HashVisitor.swift */; }; + OBJ_2831 /* Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1340 /* Internal.swift */; }; + OBJ_2832 /* JSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1341 /* JSONDecoder.swift */; }; + OBJ_2833 /* JSONDecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1342 /* JSONDecodingError.swift */; }; + OBJ_2834 /* JSONDecodingOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1343 /* JSONDecodingOptions.swift */; }; + OBJ_2835 /* JSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1344 /* JSONEncoder.swift */; }; + OBJ_2836 /* JSONEncodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1345 /* JSONEncodingError.swift */; }; + OBJ_2837 /* JSONEncodingOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1346 /* JSONEncodingOptions.swift */; }; + OBJ_2838 /* JSONEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1347 /* JSONEncodingVisitor.swift */; }; + OBJ_2839 /* JSONMapEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1348 /* JSONMapEncodingVisitor.swift */; }; + OBJ_2840 /* JSONScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1349 /* JSONScanner.swift */; }; + OBJ_2841 /* MathUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1350 /* MathUtils.swift */; }; + OBJ_2842 /* Message+AnyAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1351 /* Message+AnyAdditions.swift */; }; + OBJ_2843 /* Message+BinaryAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1352 /* Message+BinaryAdditions.swift */; }; + OBJ_2844 /* Message+JSONAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1353 /* Message+JSONAdditions.swift */; }; + OBJ_2845 /* Message+JSONArrayAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1354 /* Message+JSONArrayAdditions.swift */; }; + OBJ_2846 /* Message+TextFormatAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1355 /* Message+TextFormatAdditions.swift */; }; + OBJ_2847 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1356 /* Message.swift */; }; + OBJ_2848 /* MessageExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1357 /* MessageExtension.swift */; }; + OBJ_2849 /* NameMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1358 /* NameMap.swift */; }; + OBJ_2850 /* ProtoNameProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1359 /* ProtoNameProviding.swift */; }; + OBJ_2851 /* ProtobufAPIVersionCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1360 /* ProtobufAPIVersionCheck.swift */; }; + OBJ_2852 /* ProtobufMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1361 /* ProtobufMap.swift */; }; + OBJ_2853 /* SelectiveVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1362 /* SelectiveVisitor.swift */; }; + OBJ_2854 /* SimpleExtensionMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1363 /* SimpleExtensionMap.swift */; }; + OBJ_2855 /* StringUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1364 /* StringUtils.swift */; }; + OBJ_2856 /* TextFormatDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1365 /* TextFormatDecoder.swift */; }; + OBJ_2857 /* TextFormatDecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1366 /* TextFormatDecodingError.swift */; }; + OBJ_2858 /* TextFormatEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1367 /* TextFormatEncoder.swift */; }; + OBJ_2859 /* TextFormatEncodingVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1368 /* TextFormatEncodingVisitor.swift */; }; + OBJ_2860 /* TextFormatScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1369 /* TextFormatScanner.swift */; }; + OBJ_2861 /* TimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1370 /* TimeUtils.swift */; }; + OBJ_2862 /* UnknownStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1371 /* UnknownStorage.swift */; }; + OBJ_2863 /* Varint.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1372 /* Varint.swift */; }; + OBJ_2864 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1373 /* Version.swift */; }; + OBJ_2865 /* Visitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1374 /* Visitor.swift */; }; + OBJ_2866 /* WireFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1375 /* WireFormat.swift */; }; + OBJ_2867 /* ZigZag.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1376 /* ZigZag.swift */; }; + OBJ_2868 /* any.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1377 /* any.pb.swift */; }; + OBJ_2869 /* api.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1378 /* api.pb.swift */; }; + OBJ_2870 /* duration.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1379 /* duration.pb.swift */; }; + OBJ_2871 /* empty.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1380 /* empty.pb.swift */; }; + OBJ_2872 /* field_mask.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1381 /* field_mask.pb.swift */; }; + OBJ_2873 /* source_context.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1382 /* source_context.pb.swift */; }; + OBJ_2874 /* struct.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1383 /* struct.pb.swift */; }; + OBJ_2875 /* timestamp.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1384 /* timestamp.pb.swift */; }; + OBJ_2876 /* type.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1385 /* type.pb.swift */; }; + OBJ_2877 /* wrappers.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1386 /* wrappers.pb.swift */; }; + OBJ_2884 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1425 /* Package.swift */; }; + OBJ_2890 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1388 /* Array+Extensions.swift */; }; + OBJ_2891 /* CodePrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1389 /* CodePrinter.swift */; }; + OBJ_2892 /* Descriptor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1390 /* Descriptor+Extensions.swift */; }; + OBJ_2893 /* Descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1391 /* Descriptor.swift */; }; + OBJ_2894 /* FieldNumbers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1392 /* FieldNumbers.swift */; }; + OBJ_2895 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1393 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift */; }; + OBJ_2896 /* Google_Protobuf_SourceCodeInfo+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1394 /* Google_Protobuf_SourceCodeInfo+Extensions.swift */; }; + OBJ_2897 /* NamingUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1395 /* NamingUtils.swift */; }; + OBJ_2898 /* ProtoFileToModuleMappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1396 /* ProtoFileToModuleMappings.swift */; }; + OBJ_2899 /* ProvidesLocationPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1397 /* ProvidesLocationPath.swift */; }; + OBJ_2900 /* ProvidesSourceCodeLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1398 /* ProvidesSourceCodeLocation.swift */; }; + OBJ_2901 /* SwiftLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1399 /* SwiftLanguage.swift */; }; + OBJ_2902 /* SwiftProtobufInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1400 /* SwiftProtobufInfo.swift */; }; + OBJ_2903 /* SwiftProtobufNamer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1401 /* SwiftProtobufNamer.swift */; }; + OBJ_2904 /* UnicodeScalar+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1402 /* UnicodeScalar+Extensions.swift */; }; + OBJ_2905 /* descriptor.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1403 /* descriptor.pb.swift */; }; + OBJ_2906 /* plugin.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1404 /* plugin.pb.swift */; }; + OBJ_2907 /* swift_protobuf_module_mappings.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1405 /* swift_protobuf_module_mappings.pb.swift */; }; + OBJ_2909 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2916 /* CommandLine+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1407 /* CommandLine+Extensions.swift */; }; + OBJ_2917 /* Descriptor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1408 /* Descriptor+Extensions.swift */; }; + OBJ_2918 /* EnumGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1409 /* EnumGenerator.swift */; }; + OBJ_2919 /* ExtensionSetGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1410 /* ExtensionSetGenerator.swift */; }; + OBJ_2920 /* FieldGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1411 /* FieldGenerator.swift */; }; + OBJ_2921 /* FileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1412 /* FileGenerator.swift */; }; + OBJ_2922 /* FileIo.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1413 /* FileIo.swift */; }; + OBJ_2923 /* GenerationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1414 /* GenerationError.swift */; }; + OBJ_2924 /* GeneratorOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1415 /* GeneratorOptions.swift */; }; + OBJ_2925 /* Google_Protobuf_DescriptorProto+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1416 /* Google_Protobuf_DescriptorProto+Extensions.swift */; }; + OBJ_2926 /* Google_Protobuf_FileDescriptorProto+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1417 /* Google_Protobuf_FileDescriptorProto+Extensions.swift */; }; + OBJ_2927 /* MessageFieldGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1418 /* MessageFieldGenerator.swift */; }; + OBJ_2928 /* MessageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1419 /* MessageGenerator.swift */; }; + OBJ_2929 /* MessageStorageClassGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1420 /* MessageStorageClassGenerator.swift */; }; + OBJ_2930 /* OneofGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1421 /* OneofGenerator.swift */; }; + OBJ_2931 /* StringUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1422 /* StringUtils.swift */; }; + OBJ_2932 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1423 /* Version.swift */; }; + OBJ_2933 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1424 /* main.swift */; }; + OBJ_2935 /* SwiftProtobufPluginLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobufPluginLibrary::Product /* SwiftProtobufPluginLibrary.framework */; }; + OBJ_2936 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2944 /* Generator-Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1104 /* Generator-Client.swift */; }; + OBJ_2945 /* Generator-Methods.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1105 /* Generator-Methods.swift */; }; + OBJ_2946 /* Generator-Names.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1106 /* Generator-Names.swift */; }; + OBJ_2947 /* Generator-Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1107 /* Generator-Server.swift */; }; + OBJ_2948 /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1108 /* Generator.swift */; }; + OBJ_2949 /* StreamingType.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1109 /* StreamingType.swift */; }; + OBJ_2950 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1110 /* main.swift */; }; + OBJ_2951 /* options.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1111 /* options.swift */; }; + OBJ_2953 /* SwiftProtobufPluginLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobufPluginLibrary::Product /* SwiftProtobufPluginLibrary.framework */; }; + OBJ_2954 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */; }; + OBJ_2963 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1176 /* Package.swift */; }; + OBJ_2969 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_1294 /* Package.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ Commander::Commander::Product /* Commander.framework */ = {isa = PBXFileReference; path = Commander.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - OBJ_10 /* Generator-Methods.swift */ = {isa = PBXFileReference; path = "Generator-Methods.swift"; sourceTree = ""; }; - OBJ_100 /* http_client_filter.cc */ = {isa = PBXFileReference; path = http_client_filter.cc; sourceTree = ""; }; - OBJ_1000 /* dh.h */ = {isa = PBXFileReference; path = dh.h; sourceTree = ""; }; - OBJ_1001 /* digest.h */ = {isa = PBXFileReference; path = digest.h; sourceTree = ""; }; - OBJ_1002 /* x509v3.h */ = {isa = PBXFileReference; path = x509v3.h; sourceTree = ""; }; - OBJ_1003 /* conf.h */ = {isa = PBXFileReference; path = conf.h; sourceTree = ""; }; - OBJ_1004 /* poly1305.h */ = {isa = PBXFileReference; path = poly1305.h; sourceTree = ""; }; - OBJ_1005 /* hkdf.h */ = {isa = PBXFileReference; path = hkdf.h; sourceTree = ""; }; - OBJ_1006 /* type_check.h */ = {isa = PBXFileReference; path = type_check.h; sourceTree = ""; }; - OBJ_1007 /* md5.h */ = {isa = PBXFileReference; path = md5.h; sourceTree = ""; }; - OBJ_1008 /* x509_vfy.h */ = {isa = PBXFileReference; path = x509_vfy.h; sourceTree = ""; }; - OBJ_1009 /* pkcs8.h */ = {isa = PBXFileReference; path = pkcs8.h; sourceTree = ""; }; - OBJ_101 /* client_authority_filter.cc */ = {isa = PBXFileReference; path = client_authority_filter.cc; sourceTree = ""; }; - OBJ_1010 /* safestack.h */ = {isa = PBXFileReference; path = safestack.h; sourceTree = ""; }; - OBJ_1011 /* buf.h */ = {isa = PBXFileReference; path = buf.h; sourceTree = ""; }; - OBJ_1012 /* obj.h */ = {isa = PBXFileReference; path = obj.h; sourceTree = ""; }; - OBJ_1013 /* ecdsa.h */ = {isa = PBXFileReference; path = ecdsa.h; sourceTree = ""; }; - OBJ_1014 /* cipher.h */ = {isa = PBXFileReference; path = cipher.h; sourceTree = ""; }; - OBJ_1015 /* objects.h */ = {isa = PBXFileReference; path = objects.h; sourceTree = ""; }; - OBJ_1016 /* pkcs12.h */ = {isa = PBXFileReference; path = pkcs12.h; sourceTree = ""; }; - OBJ_1017 /* crypto.h */ = {isa = PBXFileReference; path = crypto.h; sourceTree = ""; }; - OBJ_1018 /* opensslv.h */ = {isa = PBXFileReference; path = opensslv.h; sourceTree = ""; }; - OBJ_1019 /* pkcs7.h */ = {isa = PBXFileReference; path = pkcs7.h; sourceTree = ""; }; - OBJ_102 /* http_filters_plugin.cc */ = {isa = PBXFileReference; path = http_filters_plugin.cc; sourceTree = ""; }; - OBJ_1020 /* obj_mac.h */ = {isa = PBXFileReference; path = obj_mac.h; sourceTree = ""; }; - OBJ_1021 /* buffer.h */ = {isa = PBXFileReference; path = buffer.h; sourceTree = ""; }; - OBJ_1022 /* ssl.h */ = {isa = PBXFileReference; path = ssl.h; sourceTree = ""; }; - OBJ_1023 /* thread.h */ = {isa = PBXFileReference; path = thread.h; sourceTree = ""; }; - OBJ_1024 /* evp.h */ = {isa = PBXFileReference; path = evp.h; sourceTree = ""; }; - OBJ_1025 /* md4.h */ = {isa = PBXFileReference; path = md4.h; sourceTree = ""; }; - OBJ_1026 /* hmac.h */ = {isa = PBXFileReference; path = hmac.h; sourceTree = ""; }; - OBJ_1027 /* aes.h */ = {isa = PBXFileReference; path = aes.h; sourceTree = ""; }; - OBJ_1028 /* cast.h */ = {isa = PBXFileReference; path = cast.h; sourceTree = ""; }; - OBJ_1029 /* rc4.h */ = {isa = PBXFileReference; path = rc4.h; sourceTree = ""; }; - OBJ_1030 /* cpu.h */ = {isa = PBXFileReference; path = cpu.h; sourceTree = ""; }; - OBJ_1031 /* stack.h */ = {isa = PBXFileReference; path = stack.h; sourceTree = ""; }; - OBJ_1032 /* des.h */ = {isa = PBXFileReference; path = des.h; sourceTree = ""; }; - OBJ_1033 /* ec.h */ = {isa = PBXFileReference; path = ec.h; sourceTree = ""; }; - OBJ_1034 /* ecdh.h */ = {isa = PBXFileReference; path = ecdh.h; sourceTree = ""; }; - OBJ_1035 /* rand.h */ = {isa = PBXFileReference; path = rand.h; sourceTree = ""; }; - OBJ_1036 /* aead.h */ = {isa = PBXFileReference; path = aead.h; sourceTree = ""; }; - OBJ_1037 /* lhash_macros.h */ = {isa = PBXFileReference; path = lhash_macros.h; sourceTree = ""; }; - OBJ_1038 /* span.h */ = {isa = PBXFileReference; path = span.h; sourceTree = ""; }; - OBJ_1039 /* rsa.h */ = {isa = PBXFileReference; path = rsa.h; sourceTree = ""; }; - OBJ_104 /* message_compress_filter.cc */ = {isa = PBXFileReference; path = message_compress_filter.cc; sourceTree = ""; }; - OBJ_1040 /* mem.h */ = {isa = PBXFileReference; path = mem.h; sourceTree = ""; }; - OBJ_1041 /* ripemd.h */ = {isa = PBXFileReference; path = ripemd.h; sourceTree = ""; }; - OBJ_1042 /* curve25519.h */ = {isa = PBXFileReference; path = curve25519.h; sourceTree = ""; }; - OBJ_1043 /* tls1.h */ = {isa = PBXFileReference; path = tls1.h; sourceTree = ""; }; - OBJ_1044 /* dsa.h */ = {isa = PBXFileReference; path = dsa.h; sourceTree = ""; }; - OBJ_1045 /* srtp.h */ = {isa = PBXFileReference; path = srtp.h; sourceTree = ""; }; - OBJ_1046 /* asn1t.h */ = {isa = PBXFileReference; path = asn1t.h; sourceTree = ""; }; - OBJ_1047 /* cmac.h */ = {isa = PBXFileReference; path = cmac.h; sourceTree = ""; }; - OBJ_1048 /* lhash.h */ = {isa = PBXFileReference; path = lhash.h; sourceTree = ""; }; - OBJ_1049 /* ex_data.h */ = {isa = PBXFileReference; path = ex_data.h; sourceTree = ""; }; - OBJ_1050 /* base.h */ = {isa = PBXFileReference; path = base.h; sourceTree = ""; }; - OBJ_1051 /* module.modulemap */ = {isa = PBXFileReference; name = module.modulemap; path = "../SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; sourceTree = ""; }; - OBJ_1054 /* EchoProviderNIO.swift */ = {isa = PBXFileReference; path = EchoProviderNIO.swift; sourceTree = ""; }; - OBJ_1055 /* GRPCChannelHandlerResponseCapturingTestCase.swift */ = {isa = PBXFileReference; path = GRPCChannelHandlerResponseCapturingTestCase.swift; sourceTree = ""; }; - OBJ_1056 /* GRPCChannelHandlerTests.swift */ = {isa = PBXFileReference; path = GRPCChannelHandlerTests.swift; sourceTree = ""; }; - OBJ_1057 /* HTTP1ToRawGRPCServerCodecTests.swift */ = {isa = PBXFileReference; path = HTTP1ToRawGRPCServerCodecTests.swift; sourceTree = ""; }; - OBJ_1058 /* LengthPrefixedMessageReaderTests.swift */ = {isa = PBXFileReference; path = LengthPrefixedMessageReaderTests.swift; sourceTree = ""; }; - OBJ_1059 /* NIOBasicEchoTestCase.swift */ = {isa = PBXFileReference; path = NIOBasicEchoTestCase.swift; sourceTree = ""; }; - OBJ_106 /* http_server_filter.cc */ = {isa = PBXFileReference; path = http_server_filter.cc; sourceTree = ""; }; - OBJ_1060 /* NIOClientCancellingTests.swift */ = {isa = PBXFileReference; path = NIOClientCancellingTests.swift; sourceTree = ""; }; - OBJ_1061 /* NIOClientTimeoutTests.swift */ = {isa = PBXFileReference; path = NIOClientTimeoutTests.swift; sourceTree = ""; }; - OBJ_1062 /* NIOServerTests.swift */ = {isa = PBXFileReference; path = NIOServerTests.swift; sourceTree = ""; }; - OBJ_1063 /* NIOServerWebTests.swift */ = {isa = PBXFileReference; path = NIOServerWebTests.swift; sourceTree = ""; }; - OBJ_1064 /* ServerThrowingTests.swift */ = {isa = PBXFileReference; path = ServerThrowingTests.swift; sourceTree = ""; }; - OBJ_1065 /* TestHelpers.swift */ = {isa = PBXFileReference; path = TestHelpers.swift; sourceTree = ""; }; - OBJ_1066 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; - OBJ_1067 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; - OBJ_1069 /* BasicEchoTestCase.swift */ = {isa = PBXFileReference; path = BasicEchoTestCase.swift; sourceTree = ""; }; - OBJ_1070 /* ChannelArgumentTests.swift */ = {isa = PBXFileReference; path = ChannelArgumentTests.swift; sourceTree = ""; }; - OBJ_1071 /* ChannelConnectivityTests.swift */ = {isa = PBXFileReference; path = ChannelConnectivityTests.swift; sourceTree = ""; }; - OBJ_1072 /* ChannelShutdownTests.swift */ = {isa = PBXFileReference; path = ChannelShutdownTests.swift; sourceTree = ""; }; - OBJ_1073 /* ClientCancellingTests.swift */ = {isa = PBXFileReference; path = ClientCancellingTests.swift; sourceTree = ""; }; - OBJ_1074 /* ClientTestExample.swift */ = {isa = PBXFileReference; path = ClientTestExample.swift; sourceTree = ""; }; - OBJ_1075 /* ClientTimeoutTests.swift */ = {isa = PBXFileReference; path = ClientTimeoutTests.swift; sourceTree = ""; }; - OBJ_1076 /* CompletionQueueTests.swift */ = {isa = PBXFileReference; path = CompletionQueueTests.swift; sourceTree = ""; }; - OBJ_1077 /* ConnectionFailureTests.swift */ = {isa = PBXFileReference; path = ConnectionFailureTests.swift; sourceTree = ""; }; - OBJ_1078 /* EchoProvider.swift */ = {isa = PBXFileReference; path = EchoProvider.swift; sourceTree = ""; }; - OBJ_1079 /* EchoTests.swift */ = {isa = PBXFileReference; path = EchoTests.swift; sourceTree = ""; }; - OBJ_108 /* server_load_reporting_filter.cc */ = {isa = PBXFileReference; path = server_load_reporting_filter.cc; sourceTree = ""; }; - OBJ_1080 /* GRPCTests.swift */ = {isa = PBXFileReference; path = GRPCTests.swift; sourceTree = ""; }; - OBJ_1081 /* MetadataTests.swift */ = {isa = PBXFileReference; path = MetadataTests.swift; sourceTree = ""; }; - OBJ_1082 /* ServerCancellingTests.swift */ = {isa = PBXFileReference; path = ServerCancellingTests.swift; sourceTree = ""; }; - OBJ_1083 /* ServerTestExample.swift */ = {isa = PBXFileReference; path = ServerTestExample.swift; sourceTree = ""; }; - OBJ_1084 /* ServerThrowingTests.swift */ = {isa = PBXFileReference; path = ServerThrowingTests.swift; sourceTree = ""; }; - OBJ_1085 /* ServerTimeoutTests.swift */ = {isa = PBXFileReference; path = ServerTimeoutTests.swift; sourceTree = ""; }; - OBJ_1086 /* ServiceClientTests.swift */ = {isa = PBXFileReference; path = ServiceClientTests.swift; sourceTree = ""; }; - OBJ_1087 /* TestKeys.swift */ = {isa = PBXFileReference; path = TestKeys.swift; sourceTree = ""; }; - OBJ_1088 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; - OBJ_1089 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; - OBJ_109 /* server_load_reporting_plugin.cc */ = {isa = PBXFileReference; path = server_load_reporting_plugin.cc; sourceTree = ""; }; - OBJ_1090 /* Docker */ = {isa = PBXFileReference; path = Docker; sourceTree = SOURCE_ROOT; }; - OBJ_1091 /* Examples */ = {isa = PBXFileReference; path = Examples; sourceTree = SOURCE_ROOT; }; - OBJ_1092 /* scripts */ = {isa = PBXFileReference; path = scripts; sourceTree = SOURCE_ROOT; }; - OBJ_1093 /* Assets */ = {isa = PBXFileReference; path = Assets; sourceTree = SOURCE_ROOT; }; - OBJ_1094 /* DerivedData */ = {isa = PBXFileReference; path = DerivedData; sourceTree = SOURCE_ROOT; }; - OBJ_1098 /* shims.c */ = {isa = PBXFileReference; path = shims.c; sourceTree = ""; }; - OBJ_11 /* Generator-Names.swift */ = {isa = PBXFileReference; path = "Generator-Names.swift"; sourceTree = ""; }; - OBJ_1100 /* c_nio_nghttp2.h */ = {isa = PBXFileReference; path = c_nio_nghttp2.h; sourceTree = ""; }; - OBJ_1101 /* module.modulemap */ = {isa = PBXFileReference; name = module.modulemap; path = "../SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; sourceTree = ""; }; - OBJ_1104 /* HTTP2DataProvider.swift */ = {isa = PBXFileReference; path = HTTP2DataProvider.swift; sourceTree = ""; }; - OBJ_1105 /* HTTP2Error.swift */ = {isa = PBXFileReference; path = HTTP2Error.swift; sourceTree = ""; }; - OBJ_1106 /* HTTP2ErrorCode.swift */ = {isa = PBXFileReference; path = HTTP2ErrorCode.swift; sourceTree = ""; }; - OBJ_1107 /* HTTP2Frame.swift */ = {isa = PBXFileReference; path = HTTP2Frame.swift; sourceTree = ""; }; - OBJ_1108 /* HTTP2HeaderBlock.swift */ = {isa = PBXFileReference; path = HTTP2HeaderBlock.swift; sourceTree = ""; }; - OBJ_1109 /* HTTP2Parser.swift */ = {isa = PBXFileReference; path = HTTP2Parser.swift; sourceTree = ""; }; - OBJ_111 /* max_age_filter.cc */ = {isa = PBXFileReference; path = max_age_filter.cc; sourceTree = ""; }; - OBJ_1110 /* HTTP2PingData.swift */ = {isa = PBXFileReference; path = HTTP2PingData.swift; sourceTree = ""; }; - OBJ_1111 /* HTTP2PipelineHelpers.swift */ = {isa = PBXFileReference; path = HTTP2PipelineHelpers.swift; sourceTree = ""; }; - OBJ_1112 /* HTTP2Settings.swift */ = {isa = PBXFileReference; path = HTTP2Settings.swift; sourceTree = ""; }; - OBJ_1113 /* HTTP2Stream.swift */ = {isa = PBXFileReference; path = HTTP2Stream.swift; sourceTree = ""; }; - OBJ_1114 /* HTTP2StreamChannel.swift */ = {isa = PBXFileReference; path = HTTP2StreamChannel.swift; sourceTree = ""; }; - OBJ_1115 /* HTTP2StreamID.swift */ = {isa = PBXFileReference; path = HTTP2StreamID.swift; sourceTree = ""; }; - OBJ_1116 /* HTTP2StreamMultiplexer.swift */ = {isa = PBXFileReference; path = HTTP2StreamMultiplexer.swift; sourceTree = ""; }; - OBJ_1117 /* HTTP2ToHTTP1Codec.swift */ = {isa = PBXFileReference; path = HTTP2ToHTTP1Codec.swift; sourceTree = ""; }; - OBJ_1118 /* HTTP2UserEvents.swift */ = {isa = PBXFileReference; path = HTTP2UserEvents.swift; sourceTree = ""; }; - OBJ_1119 /* NGHTTP2Session.swift */ = {isa = PBXFileReference; path = NGHTTP2Session.swift; sourceTree = ""; }; - OBJ_1121 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/swift-nio-http2.git-1684232237084789971/Package.swift"; sourceTree = ""; }; - OBJ_1124 /* ApplicationProtocolNegotiationHandler.swift */ = {isa = PBXFileReference; path = ApplicationProtocolNegotiationHandler.swift; sourceTree = ""; }; - OBJ_1125 /* SNIHandler.swift */ = {isa = PBXFileReference; path = SNIHandler.swift; sourceTree = ""; }; - OBJ_1126 /* TLSEvents.swift */ = {isa = PBXFileReference; path = TLSEvents.swift; sourceTree = ""; }; - OBJ_1128 /* shim.c */ = {isa = PBXFileReference; path = shim.c; sourceTree = ""; }; - OBJ_113 /* message_size_filter.cc */ = {isa = PBXFileReference; path = message_size_filter.cc; sourceTree = ""; }; - OBJ_1130 /* CNIODarwin.h */ = {isa = PBXFileReference; path = CNIODarwin.h; sourceTree = ""; }; - OBJ_1132 /* empty.c */ = {isa = PBXFileReference; path = empty.c; sourceTree = ""; }; - OBJ_1134 /* CNIOZlib.h */ = {isa = PBXFileReference; path = CNIOZlib.h; sourceTree = ""; }; - OBJ_1139 /* AddressedEnvelope.swift */ = {isa = PBXFileReference; path = AddressedEnvelope.swift; sourceTree = ""; }; - OBJ_1140 /* BaseSocket.swift */ = {isa = PBXFileReference; path = BaseSocket.swift; sourceTree = ""; }; - OBJ_1141 /* BaseSocketChannel.swift */ = {isa = PBXFileReference; path = BaseSocketChannel.swift; sourceTree = ""; }; - OBJ_1142 /* BlockingIOThreadPool.swift */ = {isa = PBXFileReference; path = BlockingIOThreadPool.swift; sourceTree = ""; }; - OBJ_1143 /* Bootstrap.swift */ = {isa = PBXFileReference; path = Bootstrap.swift; sourceTree = ""; }; - OBJ_1144 /* ByteBuffer-aux.swift */ = {isa = PBXFileReference; path = "ByteBuffer-aux.swift"; sourceTree = ""; }; - OBJ_1145 /* ByteBuffer-core.swift */ = {isa = PBXFileReference; path = "ByteBuffer-core.swift"; sourceTree = ""; }; - OBJ_1146 /* ByteBuffer-int.swift */ = {isa = PBXFileReference; path = "ByteBuffer-int.swift"; sourceTree = ""; }; - OBJ_1147 /* ByteBuffer-views.swift */ = {isa = PBXFileReference; path = "ByteBuffer-views.swift"; sourceTree = ""; }; - OBJ_1148 /* Channel.swift */ = {isa = PBXFileReference; path = Channel.swift; sourceTree = ""; }; - OBJ_1149 /* ChannelHandler.swift */ = {isa = PBXFileReference; path = ChannelHandler.swift; sourceTree = ""; }; - OBJ_115 /* workaround_cronet_compression_filter.cc */ = {isa = PBXFileReference; path = workaround_cronet_compression_filter.cc; sourceTree = ""; }; - OBJ_1150 /* ChannelHandlers.swift */ = {isa = PBXFileReference; path = ChannelHandlers.swift; sourceTree = ""; }; - OBJ_1151 /* ChannelInvoker.swift */ = {isa = PBXFileReference; path = ChannelInvoker.swift; sourceTree = ""; }; - OBJ_1152 /* ChannelOption.swift */ = {isa = PBXFileReference; path = ChannelOption.swift; sourceTree = ""; }; - OBJ_1153 /* ChannelPipeline.swift */ = {isa = PBXFileReference; path = ChannelPipeline.swift; sourceTree = ""; }; - OBJ_1154 /* CircularBuffer.swift */ = {isa = PBXFileReference; path = CircularBuffer.swift; sourceTree = ""; }; - OBJ_1155 /* Codec.swift */ = {isa = PBXFileReference; path = Codec.swift; sourceTree = ""; }; - OBJ_1156 /* CompositeError.swift */ = {isa = PBXFileReference; path = CompositeError.swift; sourceTree = ""; }; - OBJ_1157 /* ContiguousCollection.swift */ = {isa = PBXFileReference; path = ContiguousCollection.swift; sourceTree = ""; }; - OBJ_1158 /* DeadChannel.swift */ = {isa = PBXFileReference; path = DeadChannel.swift; sourceTree = ""; }; - OBJ_1159 /* Embedded.swift */ = {isa = PBXFileReference; path = Embedded.swift; sourceTree = ""; }; - OBJ_116 /* workaround_utils.cc */ = {isa = PBXFileReference; path = workaround_utils.cc; sourceTree = ""; }; - OBJ_1160 /* EventLoop.swift */ = {isa = PBXFileReference; path = EventLoop.swift; sourceTree = ""; }; - OBJ_1161 /* EventLoopFuture.swift */ = {isa = PBXFileReference; path = EventLoopFuture.swift; sourceTree = ""; }; - OBJ_1162 /* FileDescriptor.swift */ = {isa = PBXFileReference; path = FileDescriptor.swift; sourceTree = ""; }; - OBJ_1163 /* FileHandle.swift */ = {isa = PBXFileReference; path = FileHandle.swift; sourceTree = ""; }; - OBJ_1164 /* FileRegion.swift */ = {isa = PBXFileReference; path = FileRegion.swift; sourceTree = ""; }; - OBJ_1165 /* GetaddrinfoResolver.swift */ = {isa = PBXFileReference; path = GetaddrinfoResolver.swift; sourceTree = ""; }; - OBJ_1166 /* HappyEyeballs.swift */ = {isa = PBXFileReference; path = HappyEyeballs.swift; sourceTree = ""; }; - OBJ_1167 /* Heap.swift */ = {isa = PBXFileReference; path = Heap.swift; sourceTree = ""; }; - OBJ_1168 /* IO.swift */ = {isa = PBXFileReference; path = IO.swift; sourceTree = ""; }; - OBJ_1169 /* IOData.swift */ = {isa = PBXFileReference; path = IOData.swift; sourceTree = ""; }; - OBJ_1170 /* IntegerTypes.swift */ = {isa = PBXFileReference; path = IntegerTypes.swift; sourceTree = ""; }; - OBJ_1171 /* Interfaces.swift */ = {isa = PBXFileReference; path = Interfaces.swift; sourceTree = ""; }; - OBJ_1172 /* Linux.swift */ = {isa = PBXFileReference; path = Linux.swift; sourceTree = ""; }; - OBJ_1173 /* LinuxCPUSet.swift */ = {isa = PBXFileReference; path = LinuxCPUSet.swift; sourceTree = ""; }; - OBJ_1174 /* MarkedCircularBuffer.swift */ = {isa = PBXFileReference; path = MarkedCircularBuffer.swift; sourceTree = ""; }; - OBJ_1175 /* MulticastChannel.swift */ = {isa = PBXFileReference; path = MulticastChannel.swift; sourceTree = ""; }; - OBJ_1176 /* NIOAny.swift */ = {isa = PBXFileReference; path = NIOAny.swift; sourceTree = ""; }; - OBJ_1177 /* NonBlockingFileIO.swift */ = {isa = PBXFileReference; path = NonBlockingFileIO.swift; sourceTree = ""; }; - OBJ_1178 /* PendingDatagramWritesManager.swift */ = {isa = PBXFileReference; path = PendingDatagramWritesManager.swift; sourceTree = ""; }; - OBJ_1179 /* PendingWritesManager.swift */ = {isa = PBXFileReference; path = PendingWritesManager.swift; sourceTree = ""; }; - OBJ_1180 /* PriorityQueue.swift */ = {isa = PBXFileReference; path = PriorityQueue.swift; sourceTree = ""; }; - OBJ_1181 /* RecvByteBufferAllocator.swift */ = {isa = PBXFileReference; path = RecvByteBufferAllocator.swift; sourceTree = ""; }; - OBJ_1182 /* Resolver.swift */ = {isa = PBXFileReference; path = Resolver.swift; sourceTree = ""; }; - OBJ_1183 /* Selectable.swift */ = {isa = PBXFileReference; path = Selectable.swift; sourceTree = ""; }; - OBJ_1184 /* Selector.swift */ = {isa = PBXFileReference; path = Selector.swift; sourceTree = ""; }; - OBJ_1185 /* ServerSocket.swift */ = {isa = PBXFileReference; path = ServerSocket.swift; sourceTree = ""; }; - OBJ_1186 /* Socket.swift */ = {isa = PBXFileReference; path = Socket.swift; sourceTree = ""; }; - OBJ_1187 /* SocketAddresses.swift */ = {isa = PBXFileReference; path = SocketAddresses.swift; sourceTree = ""; }; - OBJ_1188 /* SocketChannel.swift */ = {isa = PBXFileReference; path = SocketChannel.swift; sourceTree = ""; }; - OBJ_1189 /* SocketOptionProvider.swift */ = {isa = PBXFileReference; path = SocketOptionProvider.swift; sourceTree = ""; }; - OBJ_1190 /* System.swift */ = {isa = PBXFileReference; path = System.swift; sourceTree = ""; }; - OBJ_1191 /* Thread.swift */ = {isa = PBXFileReference; path = Thread.swift; sourceTree = ""; }; - OBJ_1192 /* TypeAssistedChannelHandler.swift */ = {isa = PBXFileReference; path = TypeAssistedChannelHandler.swift; sourceTree = ""; }; - OBJ_1193 /* Utilities.swift */ = {isa = PBXFileReference; path = Utilities.swift; sourceTree = ""; }; - OBJ_1196 /* c_nio_http_parser.c */ = {isa = PBXFileReference; path = c_nio_http_parser.c; sourceTree = ""; }; - OBJ_1198 /* c_nio_http_parser.h */ = {isa = PBXFileReference; path = c_nio_http_parser.h; sourceTree = ""; }; - OBJ_1199 /* CNIOHTTPParser.h */ = {isa = PBXFileReference; path = CNIOHTTPParser.h; sourceTree = ""; }; - OBJ_12 /* Generator-Server.swift */ = {isa = PBXFileReference; path = "Generator-Server.swift"; sourceTree = ""; }; - OBJ_120 /* alpn.cc */ = {isa = PBXFileReference; path = alpn.cc; sourceTree = ""; }; - OBJ_1201 /* atomics.swift */ = {isa = PBXFileReference; path = atomics.swift; sourceTree = ""; }; - OBJ_1202 /* lock.swift */ = {isa = PBXFileReference; path = lock.swift; sourceTree = ""; }; - OBJ_1204 /* ByteBuffer-foundation.swift */ = {isa = PBXFileReference; path = "ByteBuffer-foundation.swift"; sourceTree = ""; }; - OBJ_1206 /* c_nio_sha1.c */ = {isa = PBXFileReference; path = c_nio_sha1.c; sourceTree = ""; }; - OBJ_1208 /* CNIOSHA1.h */ = {isa = PBXFileReference; path = CNIOSHA1.h; sourceTree = ""; }; - OBJ_1212 /* ByteCollectionUtils.swift */ = {isa = PBXFileReference; path = ByteCollectionUtils.swift; sourceTree = ""; }; - OBJ_1213 /* HTTPDecoder.swift */ = {isa = PBXFileReference; path = HTTPDecoder.swift; sourceTree = ""; }; - OBJ_1214 /* HTTPEncoder.swift */ = {isa = PBXFileReference; path = HTTPEncoder.swift; sourceTree = ""; }; - OBJ_1215 /* HTTPPipelineSetup.swift */ = {isa = PBXFileReference; path = HTTPPipelineSetup.swift; sourceTree = ""; }; - OBJ_1216 /* HTTPResponseCompressor.swift */ = {isa = PBXFileReference; path = HTTPResponseCompressor.swift; sourceTree = ""; }; - OBJ_1217 /* HTTPServerPipelineHandler.swift */ = {isa = PBXFileReference; path = HTTPServerPipelineHandler.swift; sourceTree = ""; }; - OBJ_1218 /* HTTPServerProtocolErrorHandler.swift */ = {isa = PBXFileReference; path = HTTPServerProtocolErrorHandler.swift; sourceTree = ""; }; - OBJ_1219 /* HTTPTypes.swift */ = {isa = PBXFileReference; path = HTTPTypes.swift; sourceTree = ""; }; - OBJ_122 /* authority.cc */ = {isa = PBXFileReference; path = authority.cc; sourceTree = ""; }; - OBJ_1220 /* HTTPUpgradeHandler.swift */ = {isa = PBXFileReference; path = HTTPUpgradeHandler.swift; sourceTree = ""; }; - OBJ_1223 /* c-atomics.c */ = {isa = PBXFileReference; path = "c-atomics.c"; sourceTree = ""; }; - OBJ_1225 /* CNIOAtomics.h */ = {isa = PBXFileReference; path = CNIOAtomics.h; sourceTree = ""; }; - OBJ_1226 /* cpp_magic.h */ = {isa = PBXFileReference; path = cpp_magic.h; sourceTree = ""; }; - OBJ_1229 /* ifaddrs-android.c */ = {isa = PBXFileReference; path = "ifaddrs-android.c"; sourceTree = ""; }; - OBJ_123 /* chttp2_connector.cc */ = {isa = PBXFileReference; path = chttp2_connector.cc; sourceTree = ""; }; - OBJ_1230 /* shim.c */ = {isa = PBXFileReference; path = shim.c; sourceTree = ""; }; - OBJ_1232 /* CNIOLinux.h */ = {isa = PBXFileReference; path = CNIOLinux.h; sourceTree = ""; }; - OBJ_1233 /* ifaddrs-android.h */ = {isa = PBXFileReference; path = "ifaddrs-android.h"; sourceTree = ""; }; + OBJ_1000 /* test.gold */ = {isa = PBXFileReference; path = test.gold; sourceTree = ""; }; + OBJ_1001 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_1002 /* ssl.key */ = {isa = PBXFileReference; path = ssl.key; sourceTree = ""; }; + OBJ_1003 /* EchoProvider.swift */ = {isa = PBXFileReference; path = EchoProvider.swift; sourceTree = ""; }; + OBJ_1005 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; + OBJ_1006 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; + OBJ_1007 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; + OBJ_1009 /* echo.proto */ = {isa = PBXFileReference; path = echo.proto; sourceTree = ""; }; + OBJ_101 /* dsa.c */ = {isa = PBXFileReference; path = dsa.c; sourceTree = ""; }; + OBJ_1010 /* Makefile */ = {isa = PBXFileReference; path = Makefile; sourceTree = ""; }; + OBJ_1011 /* RUNME */ = {isa = PBXFileReference; path = RUNME; sourceTree = ""; }; + OBJ_1012 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_1013 /* EchoProviderNIO.swift */ = {isa = PBXFileReference; path = EchoProviderNIO.swift; sourceTree = ""; }; + OBJ_1015 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; + OBJ_1016 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; + OBJ_1017 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; + OBJ_1019 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; + OBJ_102 /* dsa_asn1.c */ = {isa = PBXFileReference; path = dsa_asn1.c; sourceTree = ""; }; + OBJ_1021 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_1022 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; + OBJ_1025 /* ByteBuffer.swift */ = {isa = PBXFileReference; path = ByteBuffer.swift; sourceTree = ""; }; + OBJ_1026 /* Call.swift */ = {isa = PBXFileReference; path = Call.swift; sourceTree = ""; }; + OBJ_1027 /* CallError.swift */ = {isa = PBXFileReference; path = CallError.swift; sourceTree = ""; }; + OBJ_1028 /* CallResult.swift */ = {isa = PBXFileReference; path = CallResult.swift; sourceTree = ""; }; + OBJ_1029 /* Channel.swift */ = {isa = PBXFileReference; path = Channel.swift; sourceTree = ""; }; + OBJ_1030 /* ChannelArgument.swift */ = {isa = PBXFileReference; path = ChannelArgument.swift; sourceTree = ""; }; + OBJ_1031 /* ChannelConnectivityObserver.swift */ = {isa = PBXFileReference; path = ChannelConnectivityObserver.swift; sourceTree = ""; }; + OBJ_1032 /* ChannelConnectivityState.swift */ = {isa = PBXFileReference; path = ChannelConnectivityState.swift; sourceTree = ""; }; + OBJ_1033 /* ClientNetworkMonitor.swift */ = {isa = PBXFileReference; path = ClientNetworkMonitor.swift; sourceTree = ""; }; + OBJ_1034 /* CompletionQueue.swift */ = {isa = PBXFileReference; path = CompletionQueue.swift; sourceTree = ""; }; + OBJ_1035 /* Handler.swift */ = {isa = PBXFileReference; path = Handler.swift; sourceTree = ""; }; + OBJ_1036 /* Metadata.swift */ = {isa = PBXFileReference; path = Metadata.swift; sourceTree = ""; }; + OBJ_1037 /* Mutex.swift */ = {isa = PBXFileReference; path = Mutex.swift; sourceTree = ""; }; + OBJ_1038 /* Operation.swift */ = {isa = PBXFileReference; path = Operation.swift; sourceTree = ""; }; + OBJ_1039 /* OperationGroup.swift */ = {isa = PBXFileReference; path = OperationGroup.swift; sourceTree = ""; }; + OBJ_104 /* ec_asn1.c */ = {isa = PBXFileReference; path = ec_asn1.c; sourceTree = ""; }; + OBJ_1040 /* Roots.swift */ = {isa = PBXFileReference; path = Roots.swift; sourceTree = ""; }; + OBJ_1041 /* Server.swift */ = {isa = PBXFileReference; path = Server.swift; sourceTree = ""; }; + OBJ_1042 /* ServerStatus.swift */ = {isa = PBXFileReference; path = ServerStatus.swift; sourceTree = ""; }; + OBJ_1043 /* StatusCode.swift */ = {isa = PBXFileReference; path = StatusCode.swift; sourceTree = ""; }; + OBJ_1044 /* gRPC.swift */ = {isa = PBXFileReference; path = gRPC.swift; sourceTree = ""; }; + OBJ_1046 /* ClientCall.swift */ = {isa = PBXFileReference; path = ClientCall.swift; sourceTree = ""; }; + OBJ_1047 /* ClientCallBidirectionalStreaming.swift */ = {isa = PBXFileReference; path = ClientCallBidirectionalStreaming.swift; sourceTree = ""; }; + OBJ_1048 /* ClientCallClientStreaming.swift */ = {isa = PBXFileReference; path = ClientCallClientStreaming.swift; sourceTree = ""; }; + OBJ_1049 /* ClientCallServerStreaming.swift */ = {isa = PBXFileReference; path = ClientCallServerStreaming.swift; sourceTree = ""; }; + OBJ_1050 /* ClientCallUnary.swift */ = {isa = PBXFileReference; path = ClientCallUnary.swift; sourceTree = ""; }; + OBJ_1051 /* RPCError.swift */ = {isa = PBXFileReference; path = RPCError.swift; sourceTree = ""; }; + OBJ_1052 /* ServerSession.swift */ = {isa = PBXFileReference; path = ServerSession.swift; sourceTree = ""; }; + OBJ_1053 /* ServerSessionBidirectionalStreaming.swift */ = {isa = PBXFileReference; path = ServerSessionBidirectionalStreaming.swift; sourceTree = ""; }; + OBJ_1054 /* ServerSessionClientStreaming.swift */ = {isa = PBXFileReference; path = ServerSessionClientStreaming.swift; sourceTree = ""; }; + OBJ_1055 /* ServerSessionServerStreaming.swift */ = {isa = PBXFileReference; path = ServerSessionServerStreaming.swift; sourceTree = ""; }; + OBJ_1056 /* ServerSessionUnary.swift */ = {isa = PBXFileReference; path = ServerSessionUnary.swift; sourceTree = ""; }; + OBJ_1057 /* ServiceClient.swift */ = {isa = PBXFileReference; path = ServiceClient.swift; sourceTree = ""; }; + OBJ_1058 /* ServiceProvider.swift */ = {isa = PBXFileReference; path = ServiceProvider.swift; sourceTree = ""; }; + OBJ_1059 /* ServiceServer.swift */ = {isa = PBXFileReference; path = ServiceServer.swift; sourceTree = ""; }; + OBJ_106 /* ecdh.c */ = {isa = PBXFileReference; path = ecdh.c; sourceTree = ""; }; + OBJ_1060 /* StreamReceiving.swift */ = {isa = PBXFileReference; path = StreamReceiving.swift; sourceTree = ""; }; + OBJ_1061 /* StreamSending.swift */ = {isa = PBXFileReference; path = StreamSending.swift; sourceTree = ""; }; + OBJ_1064 /* BaseCallHandler.swift */ = {isa = PBXFileReference; path = BaseCallHandler.swift; sourceTree = ""; }; + OBJ_1065 /* BidirectionalStreamingCallHandler.swift */ = {isa = PBXFileReference; path = BidirectionalStreamingCallHandler.swift; sourceTree = ""; }; + OBJ_1066 /* ClientStreamingCallHandler.swift */ = {isa = PBXFileReference; path = ClientStreamingCallHandler.swift; sourceTree = ""; }; + OBJ_1067 /* ServerStreamingCallHandler.swift */ = {isa = PBXFileReference; path = ServerStreamingCallHandler.swift; sourceTree = ""; }; + OBJ_1068 /* UnaryCallHandler.swift */ = {isa = PBXFileReference; path = UnaryCallHandler.swift; sourceTree = ""; }; + OBJ_1070 /* BaseClientCall.swift */ = {isa = PBXFileReference; path = BaseClientCall.swift; sourceTree = ""; }; + OBJ_1071 /* BidirectionalStreamingClientCall.swift */ = {isa = PBXFileReference; path = BidirectionalStreamingClientCall.swift; sourceTree = ""; }; + OBJ_1072 /* ClientCall.swift */ = {isa = PBXFileReference; path = ClientCall.swift; sourceTree = ""; }; + OBJ_1073 /* ClientStreamingClientCall.swift */ = {isa = PBXFileReference; path = ClientStreamingClientCall.swift; sourceTree = ""; }; + OBJ_1074 /* ResponseObserver.swift */ = {isa = PBXFileReference; path = ResponseObserver.swift; sourceTree = ""; }; + OBJ_1075 /* ServerStreamingClientCall.swift */ = {isa = PBXFileReference; path = ServerStreamingClientCall.swift; sourceTree = ""; }; + OBJ_1076 /* UnaryClientCall.swift */ = {isa = PBXFileReference; path = UnaryClientCall.swift; sourceTree = ""; }; + OBJ_1077 /* ClientOptions.swift */ = {isa = PBXFileReference; path = ClientOptions.swift; sourceTree = ""; }; + OBJ_1078 /* CompressionMechanism.swift */ = {isa = PBXFileReference; path = CompressionMechanism.swift; sourceTree = ""; }; + OBJ_1079 /* GRPCChannelHandler.swift */ = {isa = PBXFileReference; path = GRPCChannelHandler.swift; sourceTree = ""; }; + OBJ_108 /* ecdsa_asn1.c */ = {isa = PBXFileReference; path = ecdsa_asn1.c; sourceTree = ""; }; + OBJ_1080 /* GRPCClient.swift */ = {isa = PBXFileReference; path = GRPCClient.swift; sourceTree = ""; }; + OBJ_1081 /* GRPCClientChannelHandler.swift */ = {isa = PBXFileReference; path = GRPCClientChannelHandler.swift; sourceTree = ""; }; + OBJ_1082 /* GRPCClientCodec.swift */ = {isa = PBXFileReference; path = GRPCClientCodec.swift; sourceTree = ""; }; + OBJ_1083 /* GRPCError.swift */ = {isa = PBXFileReference; path = GRPCError.swift; sourceTree = ""; }; + OBJ_1084 /* GRPCServer.swift */ = {isa = PBXFileReference; path = GRPCServer.swift; sourceTree = ""; }; + OBJ_1085 /* GRPCServerCodec.swift */ = {isa = PBXFileReference; path = GRPCServerCodec.swift; sourceTree = ""; }; + OBJ_1086 /* GRPCStatus.swift */ = {isa = PBXFileReference; path = GRPCStatus.swift; sourceTree = ""; }; + OBJ_1087 /* GRPCTimeout.swift */ = {isa = PBXFileReference; path = GRPCTimeout.swift; sourceTree = ""; }; + OBJ_1088 /* HTTP1ToRawGRPCClientCodec.swift */ = {isa = PBXFileReference; path = HTTP1ToRawGRPCClientCodec.swift; sourceTree = ""; }; + OBJ_1089 /* HTTP1ToRawGRPCServerCodec.swift */ = {isa = PBXFileReference; path = HTTP1ToRawGRPCServerCodec.swift; sourceTree = ""; }; + OBJ_1090 /* HTTPProtocolSwitcher.swift */ = {isa = PBXFileReference; path = HTTPProtocolSwitcher.swift; sourceTree = ""; }; + OBJ_1091 /* LengthPrefixedMessageReader.swift */ = {isa = PBXFileReference; path = LengthPrefixedMessageReader.swift; sourceTree = ""; }; + OBJ_1092 /* LengthPrefixedMessageWriter.swift */ = {isa = PBXFileReference; path = LengthPrefixedMessageWriter.swift; sourceTree = ""; }; + OBJ_1093 /* LoggingServerErrorDelegate.swift */ = {isa = PBXFileReference; path = LoggingServerErrorDelegate.swift; sourceTree = ""; }; + OBJ_1095 /* ServerCallContext.swift */ = {isa = PBXFileReference; path = ServerCallContext.swift; sourceTree = ""; }; + OBJ_1096 /* StreamingResponseCallContext.swift */ = {isa = PBXFileReference; path = StreamingResponseCallContext.swift; sourceTree = ""; }; + OBJ_1097 /* UnaryResponseCallContext.swift */ = {isa = PBXFileReference; path = UnaryResponseCallContext.swift; sourceTree = ""; }; + OBJ_1098 /* ServerErrorDelegate.swift */ = {isa = PBXFileReference; path = ServerErrorDelegate.swift; sourceTree = ""; }; + OBJ_1099 /* StatusCode.swift */ = {isa = PBXFileReference; path = StatusCode.swift; sourceTree = ""; }; + OBJ_110 /* engine.c */ = {isa = PBXFileReference; path = engine.c; sourceTree = ""; }; + OBJ_1100 /* StreamEvent.swift */ = {isa = PBXFileReference; path = StreamEvent.swift; sourceTree = ""; }; + OBJ_1101 /* WebCORSHandler.swift */ = {isa = PBXFileReference; path = WebCORSHandler.swift; sourceTree = ""; }; + OBJ_1103 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_1104 /* Generator-Client.swift */ = {isa = PBXFileReference; path = "Generator-Client.swift"; sourceTree = ""; }; + OBJ_1105 /* Generator-Methods.swift */ = {isa = PBXFileReference; path = "Generator-Methods.swift"; sourceTree = ""; }; + OBJ_1106 /* Generator-Names.swift */ = {isa = PBXFileReference; path = "Generator-Names.swift"; sourceTree = ""; }; + OBJ_1107 /* Generator-Server.swift */ = {isa = PBXFileReference; path = "Generator-Server.swift"; sourceTree = ""; }; + OBJ_1108 /* Generator.swift */ = {isa = PBXFileReference; path = Generator.swift; sourceTree = ""; }; + OBJ_1109 /* StreamingType.swift */ = {isa = PBXFileReference; path = StreamingType.swift; sourceTree = ""; }; + OBJ_1110 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; + OBJ_1111 /* options.swift */ = {isa = PBXFileReference; path = options.swift; sourceTree = ""; }; + OBJ_1114 /* EchoProviderNIO.swift */ = {isa = PBXFileReference; path = EchoProviderNIO.swift; sourceTree = ""; }; + OBJ_1115 /* GRPCChannelHandlerResponseCapturingTestCase.swift */ = {isa = PBXFileReference; path = GRPCChannelHandlerResponseCapturingTestCase.swift; sourceTree = ""; }; + OBJ_1116 /* GRPCChannelHandlerTests.swift */ = {isa = PBXFileReference; path = GRPCChannelHandlerTests.swift; sourceTree = ""; }; + OBJ_1117 /* HTTP1ToRawGRPCServerCodecTests.swift */ = {isa = PBXFileReference; path = HTTP1ToRawGRPCServerCodecTests.swift; sourceTree = ""; }; + OBJ_1118 /* LengthPrefixedMessageReaderTests.swift */ = {isa = PBXFileReference; path = LengthPrefixedMessageReaderTests.swift; sourceTree = ""; }; + OBJ_1119 /* NIOBasicEchoTestCase.swift */ = {isa = PBXFileReference; path = NIOBasicEchoTestCase.swift; sourceTree = ""; }; + OBJ_112 /* err.c */ = {isa = PBXFileReference; path = err.c; sourceTree = ""; }; + OBJ_1120 /* NIOClientCancellingTests.swift */ = {isa = PBXFileReference; path = NIOClientCancellingTests.swift; sourceTree = ""; }; + OBJ_1121 /* NIOClientTimeoutTests.swift */ = {isa = PBXFileReference; path = NIOClientTimeoutTests.swift; sourceTree = ""; }; + OBJ_1122 /* NIOServerTests.swift */ = {isa = PBXFileReference; path = NIOServerTests.swift; sourceTree = ""; }; + OBJ_1123 /* NIOServerWebTests.swift */ = {isa = PBXFileReference; path = NIOServerWebTests.swift; sourceTree = ""; }; + OBJ_1124 /* ServerThrowingTests.swift */ = {isa = PBXFileReference; path = ServerThrowingTests.swift; sourceTree = ""; }; + OBJ_1125 /* TestHelpers.swift */ = {isa = PBXFileReference; path = TestHelpers.swift; sourceTree = ""; }; + OBJ_1126 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; + OBJ_1127 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; + OBJ_1129 /* BasicEchoTestCase.swift */ = {isa = PBXFileReference; path = BasicEchoTestCase.swift; sourceTree = ""; }; + OBJ_113 /* err_data.c */ = {isa = PBXFileReference; path = err_data.c; sourceTree = ""; }; + OBJ_1130 /* ChannelArgumentTests.swift */ = {isa = PBXFileReference; path = ChannelArgumentTests.swift; sourceTree = ""; }; + OBJ_1131 /* ChannelConnectivityTests.swift */ = {isa = PBXFileReference; path = ChannelConnectivityTests.swift; sourceTree = ""; }; + OBJ_1132 /* ChannelShutdownTests.swift */ = {isa = PBXFileReference; path = ChannelShutdownTests.swift; sourceTree = ""; }; + OBJ_1133 /* ClientCancellingTests.swift */ = {isa = PBXFileReference; path = ClientCancellingTests.swift; sourceTree = ""; }; + OBJ_1134 /* ClientTestExample.swift */ = {isa = PBXFileReference; path = ClientTestExample.swift; sourceTree = ""; }; + OBJ_1135 /* ClientTimeoutTests.swift */ = {isa = PBXFileReference; path = ClientTimeoutTests.swift; sourceTree = ""; }; + OBJ_1136 /* CompletionQueueTests.swift */ = {isa = PBXFileReference; path = CompletionQueueTests.swift; sourceTree = ""; }; + OBJ_1137 /* ConnectionFailureTests.swift */ = {isa = PBXFileReference; path = ConnectionFailureTests.swift; sourceTree = ""; }; + OBJ_1138 /* EchoProvider.swift */ = {isa = PBXFileReference; path = EchoProvider.swift; sourceTree = ""; }; + OBJ_1139 /* EchoTests.swift */ = {isa = PBXFileReference; path = EchoTests.swift; sourceTree = ""; }; + OBJ_1140 /* GRPCTests.swift */ = {isa = PBXFileReference; path = GRPCTests.swift; sourceTree = ""; }; + OBJ_1141 /* MetadataTests.swift */ = {isa = PBXFileReference; path = MetadataTests.swift; sourceTree = ""; }; + OBJ_1142 /* ServerCancellingTests.swift */ = {isa = PBXFileReference; path = ServerCancellingTests.swift; sourceTree = ""; }; + OBJ_1143 /* ServerTestExample.swift */ = {isa = PBXFileReference; path = ServerTestExample.swift; sourceTree = ""; }; + OBJ_1144 /* ServerThrowingTests.swift */ = {isa = PBXFileReference; path = ServerThrowingTests.swift; sourceTree = ""; }; + OBJ_1145 /* ServerTimeoutTests.swift */ = {isa = PBXFileReference; path = ServerTimeoutTests.swift; sourceTree = ""; }; + OBJ_1146 /* ServiceClientTests.swift */ = {isa = PBXFileReference; path = ServiceClientTests.swift; sourceTree = ""; }; + OBJ_1147 /* TestKeys.swift */ = {isa = PBXFileReference; path = TestKeys.swift; sourceTree = ""; }; + OBJ_1148 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; + OBJ_1149 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; + OBJ_115 /* digestsign.c */ = {isa = PBXFileReference; path = digestsign.c; sourceTree = ""; }; + OBJ_1153 /* shims.c */ = {isa = PBXFileReference; path = shims.c; sourceTree = ""; }; + OBJ_1155 /* c_nio_nghttp2.h */ = {isa = PBXFileReference; path = c_nio_nghttp2.h; sourceTree = ""; }; + OBJ_1156 /* module.modulemap */ = {isa = PBXFileReference; name = module.modulemap; path = "../SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; sourceTree = ""; }; + OBJ_1159 /* HTTP2DataProvider.swift */ = {isa = PBXFileReference; path = HTTP2DataProvider.swift; sourceTree = ""; }; + OBJ_116 /* evp.c */ = {isa = PBXFileReference; path = evp.c; sourceTree = ""; }; + OBJ_1160 /* HTTP2Error.swift */ = {isa = PBXFileReference; path = HTTP2Error.swift; sourceTree = ""; }; + OBJ_1161 /* HTTP2ErrorCode.swift */ = {isa = PBXFileReference; path = HTTP2ErrorCode.swift; sourceTree = ""; }; + OBJ_1162 /* HTTP2Frame.swift */ = {isa = PBXFileReference; path = HTTP2Frame.swift; sourceTree = ""; }; + OBJ_1163 /* HTTP2HeaderBlock.swift */ = {isa = PBXFileReference; path = HTTP2HeaderBlock.swift; sourceTree = ""; }; + OBJ_1164 /* HTTP2Parser.swift */ = {isa = PBXFileReference; path = HTTP2Parser.swift; sourceTree = ""; }; + OBJ_1165 /* HTTP2PingData.swift */ = {isa = PBXFileReference; path = HTTP2PingData.swift; sourceTree = ""; }; + OBJ_1166 /* HTTP2PipelineHelpers.swift */ = {isa = PBXFileReference; path = HTTP2PipelineHelpers.swift; sourceTree = ""; }; + OBJ_1167 /* HTTP2Settings.swift */ = {isa = PBXFileReference; path = HTTP2Settings.swift; sourceTree = ""; }; + OBJ_1168 /* HTTP2Stream.swift */ = {isa = PBXFileReference; path = HTTP2Stream.swift; sourceTree = ""; }; + OBJ_1169 /* HTTP2StreamChannel.swift */ = {isa = PBXFileReference; path = HTTP2StreamChannel.swift; sourceTree = ""; }; + OBJ_117 /* evp_asn1.c */ = {isa = PBXFileReference; path = evp_asn1.c; sourceTree = ""; }; + OBJ_1170 /* HTTP2StreamID.swift */ = {isa = PBXFileReference; path = HTTP2StreamID.swift; sourceTree = ""; }; + OBJ_1171 /* HTTP2StreamMultiplexer.swift */ = {isa = PBXFileReference; path = HTTP2StreamMultiplexer.swift; sourceTree = ""; }; + OBJ_1172 /* HTTP2ToHTTP1Codec.swift */ = {isa = PBXFileReference; path = HTTP2ToHTTP1Codec.swift; sourceTree = ""; }; + OBJ_1173 /* HTTP2UserEvents.swift */ = {isa = PBXFileReference; path = HTTP2UserEvents.swift; sourceTree = ""; }; + OBJ_1174 /* NGHTTP2Session.swift */ = {isa = PBXFileReference; path = NGHTTP2Session.swift; sourceTree = ""; }; + OBJ_1176 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/swift-nio-http2/Package.swift"; sourceTree = ""; }; + OBJ_118 /* evp_ctx.c */ = {isa = PBXFileReference; path = evp_ctx.c; sourceTree = ""; }; + OBJ_1180 /* c-atomics.c */ = {isa = PBXFileReference; path = "c-atomics.c"; sourceTree = ""; }; + OBJ_1182 /* CNIOAtomics.h */ = {isa = PBXFileReference; path = CNIOAtomics.h; sourceTree = ""; }; + OBJ_1183 /* cpp_magic.h */ = {isa = PBXFileReference; path = cpp_magic.h; sourceTree = ""; }; + OBJ_1185 /* shim.c */ = {isa = PBXFileReference; path = shim.c; sourceTree = ""; }; + OBJ_1187 /* CNIODarwin.h */ = {isa = PBXFileReference; path = CNIODarwin.h; sourceTree = ""; }; + OBJ_1189 /* c_nio_http_parser.c */ = {isa = PBXFileReference; path = c_nio_http_parser.c; sourceTree = ""; }; + OBJ_119 /* p_dsa_asn1.c */ = {isa = PBXFileReference; path = p_dsa_asn1.c; sourceTree = ""; }; + OBJ_1191 /* c_nio_http_parser.h */ = {isa = PBXFileReference; path = c_nio_http_parser.h; sourceTree = ""; }; + OBJ_1192 /* CNIOHTTPParser.h */ = {isa = PBXFileReference; path = CNIOHTTPParser.h; sourceTree = ""; }; + OBJ_1194 /* ifaddrs-android.c */ = {isa = PBXFileReference; path = "ifaddrs-android.c"; sourceTree = ""; }; + OBJ_1195 /* shim.c */ = {isa = PBXFileReference; path = shim.c; sourceTree = ""; }; + OBJ_1197 /* CNIOLinux.h */ = {isa = PBXFileReference; path = CNIOLinux.h; sourceTree = ""; }; + OBJ_1198 /* ifaddrs-android.h */ = {isa = PBXFileReference; path = "ifaddrs-android.h"; sourceTree = ""; }; + OBJ_12 /* a_bitstr.c */ = {isa = PBXFileReference; path = a_bitstr.c; sourceTree = ""; }; + OBJ_120 /* p_ec.c */ = {isa = PBXFileReference; path = p_ec.c; sourceTree = ""; }; + OBJ_1200 /* c_nio_sha1.c */ = {isa = PBXFileReference; path = c_nio_sha1.c; sourceTree = ""; }; + OBJ_1202 /* CNIOSHA1.h */ = {isa = PBXFileReference; path = CNIOSHA1.h; sourceTree = ""; }; + OBJ_1204 /* empty.c */ = {isa = PBXFileReference; path = empty.c; sourceTree = ""; }; + OBJ_1206 /* CNIOZlib.h */ = {isa = PBXFileReference; path = CNIOZlib.h; sourceTree = ""; }; + OBJ_1208 /* AddressedEnvelope.swift */ = {isa = PBXFileReference; path = AddressedEnvelope.swift; sourceTree = ""; }; + OBJ_1209 /* BaseSocket.swift */ = {isa = PBXFileReference; path = BaseSocket.swift; sourceTree = ""; }; + OBJ_121 /* p_ec_asn1.c */ = {isa = PBXFileReference; path = p_ec_asn1.c; sourceTree = ""; }; + OBJ_1210 /* BaseSocketChannel.swift */ = {isa = PBXFileReference; path = BaseSocketChannel.swift; sourceTree = ""; }; + OBJ_1211 /* BlockingIOThreadPool.swift */ = {isa = PBXFileReference; path = BlockingIOThreadPool.swift; sourceTree = ""; }; + OBJ_1212 /* Bootstrap.swift */ = {isa = PBXFileReference; path = Bootstrap.swift; sourceTree = ""; }; + OBJ_1213 /* ByteBuffer-aux.swift */ = {isa = PBXFileReference; path = "ByteBuffer-aux.swift"; sourceTree = ""; }; + OBJ_1214 /* ByteBuffer-core.swift */ = {isa = PBXFileReference; path = "ByteBuffer-core.swift"; sourceTree = ""; }; + OBJ_1215 /* ByteBuffer-int.swift */ = {isa = PBXFileReference; path = "ByteBuffer-int.swift"; sourceTree = ""; }; + OBJ_1216 /* ByteBuffer-views.swift */ = {isa = PBXFileReference; path = "ByteBuffer-views.swift"; sourceTree = ""; }; + OBJ_1217 /* Channel.swift */ = {isa = PBXFileReference; path = Channel.swift; sourceTree = ""; }; + OBJ_1218 /* ChannelHandler.swift */ = {isa = PBXFileReference; path = ChannelHandler.swift; sourceTree = ""; }; + OBJ_1219 /* ChannelHandlers.swift */ = {isa = PBXFileReference; path = ChannelHandlers.swift; sourceTree = ""; }; + OBJ_122 /* p_ed25519.c */ = {isa = PBXFileReference; path = p_ed25519.c; sourceTree = ""; }; + OBJ_1220 /* ChannelInvoker.swift */ = {isa = PBXFileReference; path = ChannelInvoker.swift; sourceTree = ""; }; + OBJ_1221 /* ChannelOption.swift */ = {isa = PBXFileReference; path = ChannelOption.swift; sourceTree = ""; }; + OBJ_1222 /* ChannelPipeline.swift */ = {isa = PBXFileReference; path = ChannelPipeline.swift; sourceTree = ""; }; + OBJ_1223 /* CircularBuffer.swift */ = {isa = PBXFileReference; path = CircularBuffer.swift; sourceTree = ""; }; + OBJ_1224 /* Codec.swift */ = {isa = PBXFileReference; path = Codec.swift; sourceTree = ""; }; + OBJ_1225 /* CompositeError.swift */ = {isa = PBXFileReference; path = CompositeError.swift; sourceTree = ""; }; + OBJ_1226 /* ContiguousCollection.swift */ = {isa = PBXFileReference; path = ContiguousCollection.swift; sourceTree = ""; }; + OBJ_1227 /* DeadChannel.swift */ = {isa = PBXFileReference; path = DeadChannel.swift; sourceTree = ""; }; + OBJ_1228 /* Embedded.swift */ = {isa = PBXFileReference; path = Embedded.swift; sourceTree = ""; }; + OBJ_1229 /* EventLoop.swift */ = {isa = PBXFileReference; path = EventLoop.swift; sourceTree = ""; }; + OBJ_123 /* p_ed25519_asn1.c */ = {isa = PBXFileReference; path = p_ed25519_asn1.c; sourceTree = ""; }; + OBJ_1230 /* EventLoopFuture.swift */ = {isa = PBXFileReference; path = EventLoopFuture.swift; sourceTree = ""; }; + OBJ_1231 /* FileDescriptor.swift */ = {isa = PBXFileReference; path = FileDescriptor.swift; sourceTree = ""; }; + OBJ_1232 /* FileHandle.swift */ = {isa = PBXFileReference; path = FileHandle.swift; sourceTree = ""; }; + OBJ_1233 /* FileRegion.swift */ = {isa = PBXFileReference; path = FileRegion.swift; sourceTree = ""; }; + OBJ_1234 /* GetaddrinfoResolver.swift */ = {isa = PBXFileReference; path = GetaddrinfoResolver.swift; sourceTree = ""; }; + OBJ_1235 /* HappyEyeballs.swift */ = {isa = PBXFileReference; path = HappyEyeballs.swift; sourceTree = ""; }; OBJ_1236 /* Heap.swift */ = {isa = PBXFileReference; path = Heap.swift; sourceTree = ""; }; - OBJ_1237 /* PriorityQueue.swift */ = {isa = PBXFileReference; path = PriorityQueue.swift; sourceTree = ""; }; - OBJ_1239 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/swift-nio.git--5531377063216196022/Package.swift"; sourceTree = ""; }; - OBJ_1242 /* ArgumentConvertible.swift */ = {isa = PBXFileReference; path = ArgumentConvertible.swift; sourceTree = ""; }; - OBJ_1243 /* ArgumentDescription.swift */ = {isa = PBXFileReference; path = ArgumentDescription.swift; sourceTree = ""; }; - OBJ_1244 /* ArgumentParser.swift */ = {isa = PBXFileReference; path = ArgumentParser.swift; sourceTree = ""; }; - OBJ_1245 /* Command.swift */ = {isa = PBXFileReference; path = Command.swift; sourceTree = ""; }; - OBJ_1246 /* CommandRunner.swift */ = {isa = PBXFileReference; path = CommandRunner.swift; sourceTree = ""; }; - OBJ_1247 /* CommandType.swift */ = {isa = PBXFileReference; path = CommandType.swift; sourceTree = ""; }; - OBJ_1248 /* Commands.swift */ = {isa = PBXFileReference; path = Commands.swift; sourceTree = ""; }; - OBJ_1249 /* Error.swift */ = {isa = PBXFileReference; path = Error.swift; sourceTree = ""; }; - OBJ_125 /* channel_create.cc */ = {isa = PBXFileReference; path = channel_create.cc; sourceTree = ""; }; - OBJ_1250 /* Group.swift */ = {isa = PBXFileReference; path = Group.swift; sourceTree = ""; }; - OBJ_1251 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/Commander.git--4520459584696957767/Package.swift"; sourceTree = ""; }; - OBJ_1254 /* AnyMessageStorage.swift */ = {isa = PBXFileReference; path = AnyMessageStorage.swift; sourceTree = ""; }; - OBJ_1255 /* AnyUnpackError.swift */ = {isa = PBXFileReference; path = AnyUnpackError.swift; sourceTree = ""; }; - OBJ_1256 /* BinaryDecoder.swift */ = {isa = PBXFileReference; path = BinaryDecoder.swift; sourceTree = ""; }; - OBJ_1257 /* BinaryDecodingError.swift */ = {isa = PBXFileReference; path = BinaryDecodingError.swift; sourceTree = ""; }; - OBJ_1258 /* BinaryDecodingOptions.swift */ = {isa = PBXFileReference; path = BinaryDecodingOptions.swift; sourceTree = ""; }; - OBJ_1259 /* BinaryDelimited.swift */ = {isa = PBXFileReference; path = BinaryDelimited.swift; sourceTree = ""; }; - OBJ_126 /* channel_create_posix.cc */ = {isa = PBXFileReference; path = channel_create_posix.cc; sourceTree = ""; }; - OBJ_1260 /* BinaryEncoder.swift */ = {isa = PBXFileReference; path = BinaryEncoder.swift; sourceTree = ""; }; - OBJ_1261 /* BinaryEncodingError.swift */ = {isa = PBXFileReference; path = BinaryEncodingError.swift; sourceTree = ""; }; - OBJ_1262 /* BinaryEncodingSizeVisitor.swift */ = {isa = PBXFileReference; path = BinaryEncodingSizeVisitor.swift; sourceTree = ""; }; - OBJ_1263 /* BinaryEncodingVisitor.swift */ = {isa = PBXFileReference; path = BinaryEncodingVisitor.swift; sourceTree = ""; }; - OBJ_1264 /* CustomJSONCodable.swift */ = {isa = PBXFileReference; path = CustomJSONCodable.swift; sourceTree = ""; }; - OBJ_1265 /* Decoder.swift */ = {isa = PBXFileReference; path = Decoder.swift; sourceTree = ""; }; - OBJ_1266 /* DoubleFormatter.swift */ = {isa = PBXFileReference; path = DoubleFormatter.swift; sourceTree = ""; }; - OBJ_1267 /* Enum.swift */ = {isa = PBXFileReference; path = Enum.swift; sourceTree = ""; }; - OBJ_1268 /* ExtensibleMessage.swift */ = {isa = PBXFileReference; path = ExtensibleMessage.swift; sourceTree = ""; }; - OBJ_1269 /* ExtensionFieldValueSet.swift */ = {isa = PBXFileReference; path = ExtensionFieldValueSet.swift; sourceTree = ""; }; - OBJ_1270 /* ExtensionFields.swift */ = {isa = PBXFileReference; path = ExtensionFields.swift; sourceTree = ""; }; - OBJ_1271 /* ExtensionMap.swift */ = {isa = PBXFileReference; path = ExtensionMap.swift; sourceTree = ""; }; - OBJ_1272 /* FieldTag.swift */ = {isa = PBXFileReference; path = FieldTag.swift; sourceTree = ""; }; - OBJ_1273 /* FieldTypes.swift */ = {isa = PBXFileReference; path = FieldTypes.swift; sourceTree = ""; }; - OBJ_1274 /* Google_Protobuf_Any+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Any+Extensions.swift"; sourceTree = ""; }; - OBJ_1275 /* Google_Protobuf_Any+Registry.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Any+Registry.swift"; sourceTree = ""; }; - OBJ_1276 /* Google_Protobuf_Duration+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Duration+Extensions.swift"; sourceTree = ""; }; - OBJ_1277 /* Google_Protobuf_FieldMask+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_FieldMask+Extensions.swift"; sourceTree = ""; }; - OBJ_1278 /* Google_Protobuf_ListValue+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_ListValue+Extensions.swift"; sourceTree = ""; }; - OBJ_1279 /* Google_Protobuf_Struct+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Struct+Extensions.swift"; sourceTree = ""; }; - OBJ_128 /* secure_channel_create.cc */ = {isa = PBXFileReference; path = secure_channel_create.cc; sourceTree = ""; }; - OBJ_1280 /* Google_Protobuf_Timestamp+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Timestamp+Extensions.swift"; sourceTree = ""; }; - OBJ_1281 /* Google_Protobuf_Value+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Value+Extensions.swift"; sourceTree = ""; }; - OBJ_1282 /* Google_Protobuf_Wrappers+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Wrappers+Extensions.swift"; sourceTree = ""; }; - OBJ_1283 /* HashVisitor.swift */ = {isa = PBXFileReference; path = HashVisitor.swift; sourceTree = ""; }; - OBJ_1284 /* Internal.swift */ = {isa = PBXFileReference; path = Internal.swift; sourceTree = ""; }; - OBJ_1285 /* JSONDecoder.swift */ = {isa = PBXFileReference; path = JSONDecoder.swift; sourceTree = ""; }; - OBJ_1286 /* JSONDecodingError.swift */ = {isa = PBXFileReference; path = JSONDecodingError.swift; sourceTree = ""; }; - OBJ_1287 /* JSONDecodingOptions.swift */ = {isa = PBXFileReference; path = JSONDecodingOptions.swift; sourceTree = ""; }; - OBJ_1288 /* JSONEncoder.swift */ = {isa = PBXFileReference; path = JSONEncoder.swift; sourceTree = ""; }; - OBJ_1289 /* JSONEncodingError.swift */ = {isa = PBXFileReference; path = JSONEncodingError.swift; sourceTree = ""; }; - OBJ_1290 /* JSONEncodingOptions.swift */ = {isa = PBXFileReference; path = JSONEncodingOptions.swift; sourceTree = ""; }; - OBJ_1291 /* JSONEncodingVisitor.swift */ = {isa = PBXFileReference; path = JSONEncodingVisitor.swift; sourceTree = ""; }; - OBJ_1292 /* JSONMapEncodingVisitor.swift */ = {isa = PBXFileReference; path = JSONMapEncodingVisitor.swift; sourceTree = ""; }; - OBJ_1293 /* JSONScanner.swift */ = {isa = PBXFileReference; path = JSONScanner.swift; sourceTree = ""; }; - OBJ_1294 /* MathUtils.swift */ = {isa = PBXFileReference; path = MathUtils.swift; sourceTree = ""; }; - OBJ_1295 /* Message+AnyAdditions.swift */ = {isa = PBXFileReference; path = "Message+AnyAdditions.swift"; sourceTree = ""; }; - OBJ_1296 /* Message+BinaryAdditions.swift */ = {isa = PBXFileReference; path = "Message+BinaryAdditions.swift"; sourceTree = ""; }; - OBJ_1297 /* Message+JSONAdditions.swift */ = {isa = PBXFileReference; path = "Message+JSONAdditions.swift"; sourceTree = ""; }; - OBJ_1298 /* Message+JSONArrayAdditions.swift */ = {isa = PBXFileReference; path = "Message+JSONArrayAdditions.swift"; sourceTree = ""; }; - OBJ_1299 /* Message+TextFormatAdditions.swift */ = {isa = PBXFileReference; path = "Message+TextFormatAdditions.swift"; sourceTree = ""; }; - OBJ_13 /* Generator.swift */ = {isa = PBXFileReference; path = Generator.swift; sourceTree = ""; }; - OBJ_130 /* chttp2_server.cc */ = {isa = PBXFileReference; path = chttp2_server.cc; sourceTree = ""; }; - OBJ_1300 /* Message.swift */ = {isa = PBXFileReference; path = Message.swift; sourceTree = ""; }; - OBJ_1301 /* MessageExtension.swift */ = {isa = PBXFileReference; path = MessageExtension.swift; sourceTree = ""; }; - OBJ_1302 /* NameMap.swift */ = {isa = PBXFileReference; path = NameMap.swift; sourceTree = ""; }; - OBJ_1303 /* ProtoNameProviding.swift */ = {isa = PBXFileReference; path = ProtoNameProviding.swift; sourceTree = ""; }; - OBJ_1304 /* ProtobufAPIVersionCheck.swift */ = {isa = PBXFileReference; path = ProtobufAPIVersionCheck.swift; sourceTree = ""; }; - OBJ_1305 /* ProtobufMap.swift */ = {isa = PBXFileReference; path = ProtobufMap.swift; sourceTree = ""; }; - OBJ_1306 /* SelectiveVisitor.swift */ = {isa = PBXFileReference; path = SelectiveVisitor.swift; sourceTree = ""; }; - OBJ_1307 /* SimpleExtensionMap.swift */ = {isa = PBXFileReference; path = SimpleExtensionMap.swift; sourceTree = ""; }; - OBJ_1308 /* StringUtils.swift */ = {isa = PBXFileReference; path = StringUtils.swift; sourceTree = ""; }; - OBJ_1309 /* TextFormatDecoder.swift */ = {isa = PBXFileReference; path = TextFormatDecoder.swift; sourceTree = ""; }; - OBJ_1310 /* TextFormatDecodingError.swift */ = {isa = PBXFileReference; path = TextFormatDecodingError.swift; sourceTree = ""; }; - OBJ_1311 /* TextFormatEncoder.swift */ = {isa = PBXFileReference; path = TextFormatEncoder.swift; sourceTree = ""; }; - OBJ_1312 /* TextFormatEncodingVisitor.swift */ = {isa = PBXFileReference; path = TextFormatEncodingVisitor.swift; sourceTree = ""; }; - OBJ_1313 /* TextFormatScanner.swift */ = {isa = PBXFileReference; path = TextFormatScanner.swift; sourceTree = ""; }; - OBJ_1314 /* TimeUtils.swift */ = {isa = PBXFileReference; path = TimeUtils.swift; sourceTree = ""; }; - OBJ_1315 /* UnknownStorage.swift */ = {isa = PBXFileReference; path = UnknownStorage.swift; sourceTree = ""; }; - OBJ_1316 /* Varint.swift */ = {isa = PBXFileReference; path = Varint.swift; sourceTree = ""; }; - OBJ_1317 /* Version.swift */ = {isa = PBXFileReference; path = Version.swift; sourceTree = ""; }; - OBJ_1318 /* Visitor.swift */ = {isa = PBXFileReference; path = Visitor.swift; sourceTree = ""; }; - OBJ_1319 /* WireFormat.swift */ = {isa = PBXFileReference; path = WireFormat.swift; sourceTree = ""; }; - OBJ_132 /* server_chttp2.cc */ = {isa = PBXFileReference; path = server_chttp2.cc; sourceTree = ""; }; - OBJ_1320 /* ZigZag.swift */ = {isa = PBXFileReference; path = ZigZag.swift; sourceTree = ""; }; - OBJ_1321 /* any.pb.swift */ = {isa = PBXFileReference; path = any.pb.swift; sourceTree = ""; }; - OBJ_1322 /* api.pb.swift */ = {isa = PBXFileReference; path = api.pb.swift; sourceTree = ""; }; - OBJ_1323 /* duration.pb.swift */ = {isa = PBXFileReference; path = duration.pb.swift; sourceTree = ""; }; - OBJ_1324 /* empty.pb.swift */ = {isa = PBXFileReference; path = empty.pb.swift; sourceTree = ""; }; - OBJ_1325 /* field_mask.pb.swift */ = {isa = PBXFileReference; path = field_mask.pb.swift; sourceTree = ""; }; - OBJ_1326 /* source_context.pb.swift */ = {isa = PBXFileReference; path = source_context.pb.swift; sourceTree = ""; }; - OBJ_1327 /* struct.pb.swift */ = {isa = PBXFileReference; path = struct.pb.swift; sourceTree = ""; }; - OBJ_1328 /* timestamp.pb.swift */ = {isa = PBXFileReference; path = timestamp.pb.swift; sourceTree = ""; }; - OBJ_1329 /* type.pb.swift */ = {isa = PBXFileReference; path = type.pb.swift; sourceTree = ""; }; - OBJ_133 /* server_chttp2_posix.cc */ = {isa = PBXFileReference; path = server_chttp2_posix.cc; sourceTree = ""; }; - OBJ_1330 /* wrappers.pb.swift */ = {isa = PBXFileReference; path = wrappers.pb.swift; sourceTree = ""; }; - OBJ_1332 /* CommandLine+Extensions.swift */ = {isa = PBXFileReference; path = "CommandLine+Extensions.swift"; sourceTree = ""; }; - OBJ_1333 /* Descriptor+Extensions.swift */ = {isa = PBXFileReference; path = "Descriptor+Extensions.swift"; sourceTree = ""; }; - OBJ_1334 /* EnumGenerator.swift */ = {isa = PBXFileReference; path = EnumGenerator.swift; sourceTree = ""; }; - OBJ_1335 /* ExtensionSetGenerator.swift */ = {isa = PBXFileReference; path = ExtensionSetGenerator.swift; sourceTree = ""; }; - OBJ_1336 /* FieldGenerator.swift */ = {isa = PBXFileReference; path = FieldGenerator.swift; sourceTree = ""; }; - OBJ_1337 /* FileGenerator.swift */ = {isa = PBXFileReference; path = FileGenerator.swift; sourceTree = ""; }; - OBJ_1338 /* FileIo.swift */ = {isa = PBXFileReference; path = FileIo.swift; sourceTree = ""; }; - OBJ_1339 /* GenerationError.swift */ = {isa = PBXFileReference; path = GenerationError.swift; sourceTree = ""; }; - OBJ_1340 /* GeneratorOptions.swift */ = {isa = PBXFileReference; path = GeneratorOptions.swift; sourceTree = ""; }; - OBJ_1341 /* Google_Protobuf_DescriptorProto+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_DescriptorProto+Extensions.swift"; sourceTree = ""; }; - OBJ_1342 /* Google_Protobuf_FileDescriptorProto+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_FileDescriptorProto+Extensions.swift"; sourceTree = ""; }; - OBJ_1343 /* MessageFieldGenerator.swift */ = {isa = PBXFileReference; path = MessageFieldGenerator.swift; sourceTree = ""; }; - OBJ_1344 /* MessageGenerator.swift */ = {isa = PBXFileReference; path = MessageGenerator.swift; sourceTree = ""; }; - OBJ_1345 /* MessageStorageClassGenerator.swift */ = {isa = PBXFileReference; path = MessageStorageClassGenerator.swift; sourceTree = ""; }; - OBJ_1346 /* OneofGenerator.swift */ = {isa = PBXFileReference; path = OneofGenerator.swift; sourceTree = ""; }; - OBJ_1347 /* StringUtils.swift */ = {isa = PBXFileReference; path = StringUtils.swift; sourceTree = ""; }; - OBJ_1348 /* Version.swift */ = {isa = PBXFileReference; path = Version.swift; sourceTree = ""; }; - OBJ_1349 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; - OBJ_135 /* server_secure_chttp2.cc */ = {isa = PBXFileReference; path = server_secure_chttp2.cc; sourceTree = ""; }; - OBJ_1352 /* Array+Extensions.swift */ = {isa = PBXFileReference; path = "Array+Extensions.swift"; sourceTree = ""; }; - OBJ_1353 /* CodePrinter.swift */ = {isa = PBXFileReference; path = CodePrinter.swift; sourceTree = ""; }; - OBJ_1354 /* Descriptor+Extensions.swift */ = {isa = PBXFileReference; path = "Descriptor+Extensions.swift"; sourceTree = ""; }; - OBJ_1355 /* Descriptor.swift */ = {isa = PBXFileReference; path = Descriptor.swift; sourceTree = ""; }; - OBJ_1356 /* FieldNumbers.swift */ = {isa = PBXFileReference; path = FieldNumbers.swift; sourceTree = ""; }; - OBJ_1357 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift"; sourceTree = ""; }; - OBJ_1358 /* Google_Protobuf_SourceCodeInfo+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_SourceCodeInfo+Extensions.swift"; sourceTree = ""; }; - OBJ_1359 /* NamingUtils.swift */ = {isa = PBXFileReference; path = NamingUtils.swift; sourceTree = ""; }; - OBJ_1360 /* ProtoFileToModuleMappings.swift */ = {isa = PBXFileReference; path = ProtoFileToModuleMappings.swift; sourceTree = ""; }; - OBJ_1361 /* ProvidesLocationPath.swift */ = {isa = PBXFileReference; path = ProvidesLocationPath.swift; sourceTree = ""; }; - OBJ_1362 /* ProvidesSourceCodeLocation.swift */ = {isa = PBXFileReference; path = ProvidesSourceCodeLocation.swift; sourceTree = ""; }; - OBJ_1363 /* SwiftLanguage.swift */ = {isa = PBXFileReference; path = SwiftLanguage.swift; sourceTree = ""; }; - OBJ_1364 /* SwiftProtobufInfo.swift */ = {isa = PBXFileReference; path = SwiftProtobufInfo.swift; sourceTree = ""; }; - OBJ_1365 /* SwiftProtobufNamer.swift */ = {isa = PBXFileReference; path = SwiftProtobufNamer.swift; sourceTree = ""; }; - OBJ_1366 /* UnicodeScalar+Extensions.swift */ = {isa = PBXFileReference; path = "UnicodeScalar+Extensions.swift"; sourceTree = ""; }; - OBJ_1367 /* descriptor.pb.swift */ = {isa = PBXFileReference; path = descriptor.pb.swift; sourceTree = ""; }; - OBJ_1368 /* plugin.pb.swift */ = {isa = PBXFileReference; path = plugin.pb.swift; sourceTree = ""; }; - OBJ_1369 /* swift_protobuf_module_mappings.pb.swift */ = {isa = PBXFileReference; path = swift_protobuf_module_mappings.pb.swift; sourceTree = ""; }; - OBJ_137 /* bin_decoder.cc */ = {isa = PBXFileReference; path = bin_decoder.cc; sourceTree = ""; }; - OBJ_1370 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/swift-protobuf.git-2901371442460970160/Package.swift"; sourceTree = ""; }; - OBJ_138 /* bin_encoder.cc */ = {isa = PBXFileReference; path = bin_encoder.cc; sourceTree = ""; }; - OBJ_139 /* chttp2_plugin.cc */ = {isa = PBXFileReference; path = chttp2_plugin.cc; sourceTree = ""; }; - OBJ_14 /* StreamingType.swift */ = {isa = PBXFileReference; path = StreamingType.swift; sourceTree = ""; }; - OBJ_140 /* chttp2_transport.cc */ = {isa = PBXFileReference; path = chttp2_transport.cc; sourceTree = ""; }; - OBJ_141 /* flow_control.cc */ = {isa = PBXFileReference; path = flow_control.cc; sourceTree = ""; }; - OBJ_142 /* frame_data.cc */ = {isa = PBXFileReference; path = frame_data.cc; sourceTree = ""; }; - OBJ_143 /* frame_goaway.cc */ = {isa = PBXFileReference; path = frame_goaway.cc; sourceTree = ""; }; - OBJ_144 /* frame_ping.cc */ = {isa = PBXFileReference; path = frame_ping.cc; sourceTree = ""; }; - OBJ_145 /* frame_rst_stream.cc */ = {isa = PBXFileReference; path = frame_rst_stream.cc; sourceTree = ""; }; - OBJ_146 /* frame_settings.cc */ = {isa = PBXFileReference; path = frame_settings.cc; sourceTree = ""; }; - OBJ_147 /* frame_window_update.cc */ = {isa = PBXFileReference; path = frame_window_update.cc; sourceTree = ""; }; - OBJ_148 /* hpack_encoder.cc */ = {isa = PBXFileReference; path = hpack_encoder.cc; sourceTree = ""; }; - OBJ_149 /* hpack_parser.cc */ = {isa = PBXFileReference; path = hpack_parser.cc; sourceTree = ""; }; - OBJ_15 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; - OBJ_150 /* hpack_table.cc */ = {isa = PBXFileReference; path = hpack_table.cc; sourceTree = ""; }; - OBJ_151 /* http2_settings.cc */ = {isa = PBXFileReference; path = http2_settings.cc; sourceTree = ""; }; - OBJ_152 /* huffsyms.cc */ = {isa = PBXFileReference; path = huffsyms.cc; sourceTree = ""; }; - OBJ_153 /* incoming_metadata.cc */ = {isa = PBXFileReference; path = incoming_metadata.cc; sourceTree = ""; }; - OBJ_154 /* parsing.cc */ = {isa = PBXFileReference; path = parsing.cc; sourceTree = ""; }; - OBJ_155 /* stream_lists.cc */ = {isa = PBXFileReference; path = stream_lists.cc; sourceTree = ""; }; - OBJ_156 /* stream_map.cc */ = {isa = PBXFileReference; path = stream_map.cc; sourceTree = ""; }; - OBJ_157 /* varint.cc */ = {isa = PBXFileReference; path = varint.cc; sourceTree = ""; }; - OBJ_158 /* writing.cc */ = {isa = PBXFileReference; path = writing.cc; sourceTree = ""; }; - OBJ_16 /* options.swift */ = {isa = PBXFileReference; path = options.swift; sourceTree = ""; }; - OBJ_160 /* inproc_plugin.cc */ = {isa = PBXFileReference; path = inproc_plugin.cc; sourceTree = ""; }; - OBJ_161 /* inproc_transport.cc */ = {isa = PBXFileReference; path = inproc_transport.cc; sourceTree = ""; }; - OBJ_164 /* avl.cc */ = {isa = PBXFileReference; path = avl.cc; sourceTree = ""; }; - OBJ_166 /* backoff.cc */ = {isa = PBXFileReference; path = backoff.cc; sourceTree = ""; }; - OBJ_168 /* channel_args.cc */ = {isa = PBXFileReference; path = channel_args.cc; sourceTree = ""; }; - OBJ_169 /* channel_stack.cc */ = {isa = PBXFileReference; path = channel_stack.cc; sourceTree = ""; }; - OBJ_170 /* channel_stack_builder.cc */ = {isa = PBXFileReference; path = channel_stack_builder.cc; sourceTree = ""; }; - OBJ_171 /* channel_trace.cc */ = {isa = PBXFileReference; path = channel_trace.cc; sourceTree = ""; }; - OBJ_172 /* channel_trace_registry.cc */ = {isa = PBXFileReference; path = channel_trace_registry.cc; sourceTree = ""; }; - OBJ_173 /* connected_channel.cc */ = {isa = PBXFileReference; path = connected_channel.cc; sourceTree = ""; }; - OBJ_174 /* handshaker.cc */ = {isa = PBXFileReference; path = handshaker.cc; sourceTree = ""; }; - OBJ_175 /* handshaker_factory.cc */ = {isa = PBXFileReference; path = handshaker_factory.cc; sourceTree = ""; }; - OBJ_176 /* handshaker_registry.cc */ = {isa = PBXFileReference; path = handshaker_registry.cc; sourceTree = ""; }; - OBJ_177 /* status_util.cc */ = {isa = PBXFileReference; path = status_util.cc; sourceTree = ""; }; - OBJ_179 /* compression.cc */ = {isa = PBXFileReference; path = compression.cc; sourceTree = ""; }; - OBJ_18 /* EchoProviderNIO.swift */ = {isa = PBXFileReference; path = EchoProviderNIO.swift; sourceTree = ""; }; - OBJ_180 /* compression_internal.cc */ = {isa = PBXFileReference; path = compression_internal.cc; sourceTree = ""; }; - OBJ_181 /* message_compress.cc */ = {isa = PBXFileReference; path = message_compress.cc; sourceTree = ""; }; - OBJ_182 /* stream_compression.cc */ = {isa = PBXFileReference; path = stream_compression.cc; sourceTree = ""; }; - OBJ_183 /* stream_compression_gzip.cc */ = {isa = PBXFileReference; path = stream_compression_gzip.cc; sourceTree = ""; }; - OBJ_184 /* stream_compression_identity.cc */ = {isa = PBXFileReference; path = stream_compression_identity.cc; sourceTree = ""; }; - OBJ_186 /* stats.cc */ = {isa = PBXFileReference; path = stats.cc; sourceTree = ""; }; - OBJ_187 /* stats_data.cc */ = {isa = PBXFileReference; path = stats_data.cc; sourceTree = ""; }; - OBJ_188 /* trace.cc */ = {isa = PBXFileReference; path = trace.cc; sourceTree = ""; }; - OBJ_190 /* alloc.cc */ = {isa = PBXFileReference; path = alloc.cc; sourceTree = ""; }; - OBJ_191 /* arena.cc */ = {isa = PBXFileReference; path = arena.cc; sourceTree = ""; }; - OBJ_192 /* atm.cc */ = {isa = PBXFileReference; path = atm.cc; sourceTree = ""; }; - OBJ_193 /* cpu_iphone.cc */ = {isa = PBXFileReference; path = cpu_iphone.cc; sourceTree = ""; }; - OBJ_194 /* cpu_linux.cc */ = {isa = PBXFileReference; path = cpu_linux.cc; sourceTree = ""; }; - OBJ_195 /* cpu_posix.cc */ = {isa = PBXFileReference; path = cpu_posix.cc; sourceTree = ""; }; - OBJ_196 /* cpu_windows.cc */ = {isa = PBXFileReference; path = cpu_windows.cc; sourceTree = ""; }; - OBJ_197 /* env_linux.cc */ = {isa = PBXFileReference; path = env_linux.cc; sourceTree = ""; }; - OBJ_198 /* env_posix.cc */ = {isa = PBXFileReference; path = env_posix.cc; sourceTree = ""; }; - OBJ_199 /* env_windows.cc */ = {isa = PBXFileReference; path = env_windows.cc; sourceTree = ""; }; - OBJ_20 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; - OBJ_200 /* fork.cc */ = {isa = PBXFileReference; path = fork.cc; sourceTree = ""; }; - OBJ_201 /* host_port.cc */ = {isa = PBXFileReference; path = host_port.cc; sourceTree = ""; }; - OBJ_202 /* log.cc */ = {isa = PBXFileReference; path = log.cc; sourceTree = ""; }; - OBJ_203 /* log_android.cc */ = {isa = PBXFileReference; path = log_android.cc; sourceTree = ""; }; - OBJ_204 /* log_linux.cc */ = {isa = PBXFileReference; path = log_linux.cc; sourceTree = ""; }; - OBJ_205 /* log_posix.cc */ = {isa = PBXFileReference; path = log_posix.cc; sourceTree = ""; }; - OBJ_206 /* log_windows.cc */ = {isa = PBXFileReference; path = log_windows.cc; sourceTree = ""; }; - OBJ_207 /* mpscq.cc */ = {isa = PBXFileReference; path = mpscq.cc; sourceTree = ""; }; - OBJ_208 /* murmur_hash.cc */ = {isa = PBXFileReference; path = murmur_hash.cc; sourceTree = ""; }; - OBJ_209 /* string.cc */ = {isa = PBXFileReference; path = string.cc; sourceTree = ""; }; - OBJ_21 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; - OBJ_210 /* string_posix.cc */ = {isa = PBXFileReference; path = string_posix.cc; sourceTree = ""; }; - OBJ_211 /* string_util_windows.cc */ = {isa = PBXFileReference; path = string_util_windows.cc; sourceTree = ""; }; - OBJ_212 /* string_windows.cc */ = {isa = PBXFileReference; path = string_windows.cc; sourceTree = ""; }; - OBJ_213 /* sync.cc */ = {isa = PBXFileReference; path = sync.cc; sourceTree = ""; }; - OBJ_214 /* sync_posix.cc */ = {isa = PBXFileReference; path = sync_posix.cc; sourceTree = ""; }; - OBJ_215 /* sync_windows.cc */ = {isa = PBXFileReference; path = sync_windows.cc; sourceTree = ""; }; - OBJ_216 /* time.cc */ = {isa = PBXFileReference; path = time.cc; sourceTree = ""; }; - OBJ_217 /* time_posix.cc */ = {isa = PBXFileReference; path = time_posix.cc; sourceTree = ""; }; - OBJ_218 /* time_precise.cc */ = {isa = PBXFileReference; path = time_precise.cc; sourceTree = ""; }; - OBJ_219 /* time_windows.cc */ = {isa = PBXFileReference; path = time_windows.cc; sourceTree = ""; }; - OBJ_22 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; - OBJ_220 /* tls_pthread.cc */ = {isa = PBXFileReference; path = tls_pthread.cc; sourceTree = ""; }; - OBJ_221 /* tmpfile_msys.cc */ = {isa = PBXFileReference; path = tmpfile_msys.cc; sourceTree = ""; }; - OBJ_222 /* tmpfile_posix.cc */ = {isa = PBXFileReference; path = tmpfile_posix.cc; sourceTree = ""; }; - OBJ_223 /* tmpfile_windows.cc */ = {isa = PBXFileReference; path = tmpfile_windows.cc; sourceTree = ""; }; - OBJ_224 /* wrap_memcpy.cc */ = {isa = PBXFileReference; path = wrap_memcpy.cc; sourceTree = ""; }; - OBJ_226 /* thd_posix.cc */ = {isa = PBXFileReference; path = thd_posix.cc; sourceTree = ""; }; - OBJ_227 /* thd_windows.cc */ = {isa = PBXFileReference; path = thd_windows.cc; sourceTree = ""; }; - OBJ_229 /* format_request.cc */ = {isa = PBXFileReference; path = format_request.cc; sourceTree = ""; }; - OBJ_230 /* httpcli.cc */ = {isa = PBXFileReference; path = httpcli.cc; sourceTree = ""; }; - OBJ_231 /* httpcli_security_connector.cc */ = {isa = PBXFileReference; path = httpcli_security_connector.cc; sourceTree = ""; }; - OBJ_232 /* parser.cc */ = {isa = PBXFileReference; path = parser.cc; sourceTree = ""; }; - OBJ_234 /* call_combiner.cc */ = {isa = PBXFileReference; path = call_combiner.cc; sourceTree = ""; }; - OBJ_235 /* combiner.cc */ = {isa = PBXFileReference; path = combiner.cc; sourceTree = ""; }; - OBJ_236 /* endpoint.cc */ = {isa = PBXFileReference; path = endpoint.cc; sourceTree = ""; }; - OBJ_237 /* endpoint_pair_posix.cc */ = {isa = PBXFileReference; path = endpoint_pair_posix.cc; sourceTree = ""; }; - OBJ_238 /* endpoint_pair_uv.cc */ = {isa = PBXFileReference; path = endpoint_pair_uv.cc; sourceTree = ""; }; - OBJ_239 /* endpoint_pair_windows.cc */ = {isa = PBXFileReference; path = endpoint_pair_windows.cc; sourceTree = ""; }; - OBJ_24 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; - OBJ_240 /* error.cc */ = {isa = PBXFileReference; path = error.cc; sourceTree = ""; }; - OBJ_241 /* ev_epoll1_linux.cc */ = {isa = PBXFileReference; path = ev_epoll1_linux.cc; sourceTree = ""; }; - OBJ_242 /* ev_epollex_linux.cc */ = {isa = PBXFileReference; path = ev_epollex_linux.cc; sourceTree = ""; }; - OBJ_243 /* ev_epollsig_linux.cc */ = {isa = PBXFileReference; path = ev_epollsig_linux.cc; sourceTree = ""; }; - OBJ_244 /* ev_poll_posix.cc */ = {isa = PBXFileReference; path = ev_poll_posix.cc; sourceTree = ""; }; - OBJ_245 /* ev_posix.cc */ = {isa = PBXFileReference; path = ev_posix.cc; sourceTree = ""; }; - OBJ_246 /* ev_windows.cc */ = {isa = PBXFileReference; path = ev_windows.cc; sourceTree = ""; }; - OBJ_247 /* exec_ctx.cc */ = {isa = PBXFileReference; path = exec_ctx.cc; sourceTree = ""; }; - OBJ_248 /* executor.cc */ = {isa = PBXFileReference; path = executor.cc; sourceTree = ""; }; - OBJ_249 /* fork_posix.cc */ = {isa = PBXFileReference; path = fork_posix.cc; sourceTree = ""; }; - OBJ_250 /* fork_windows.cc */ = {isa = PBXFileReference; path = fork_windows.cc; sourceTree = ""; }; - OBJ_251 /* gethostname_fallback.cc */ = {isa = PBXFileReference; path = gethostname_fallback.cc; sourceTree = ""; }; - OBJ_252 /* gethostname_host_name_max.cc */ = {isa = PBXFileReference; path = gethostname_host_name_max.cc; sourceTree = ""; }; - OBJ_253 /* gethostname_sysconf.cc */ = {isa = PBXFileReference; path = gethostname_sysconf.cc; sourceTree = ""; }; - OBJ_254 /* iocp_windows.cc */ = {isa = PBXFileReference; path = iocp_windows.cc; sourceTree = ""; }; - OBJ_255 /* iomgr.cc */ = {isa = PBXFileReference; path = iomgr.cc; sourceTree = ""; }; - OBJ_256 /* iomgr_custom.cc */ = {isa = PBXFileReference; path = iomgr_custom.cc; sourceTree = ""; }; - OBJ_257 /* iomgr_internal.cc */ = {isa = PBXFileReference; path = iomgr_internal.cc; sourceTree = ""; }; - OBJ_258 /* iomgr_posix.cc */ = {isa = PBXFileReference; path = iomgr_posix.cc; sourceTree = ""; }; - OBJ_259 /* iomgr_uv.cc */ = {isa = PBXFileReference; path = iomgr_uv.cc; sourceTree = ""; }; - OBJ_260 /* iomgr_windows.cc */ = {isa = PBXFileReference; path = iomgr_windows.cc; sourceTree = ""; }; - OBJ_261 /* is_epollexclusive_available.cc */ = {isa = PBXFileReference; path = is_epollexclusive_available.cc; sourceTree = ""; }; - OBJ_262 /* load_file.cc */ = {isa = PBXFileReference; path = load_file.cc; sourceTree = ""; }; - OBJ_263 /* lockfree_event.cc */ = {isa = PBXFileReference; path = lockfree_event.cc; sourceTree = ""; }; - OBJ_264 /* network_status_tracker.cc */ = {isa = PBXFileReference; path = network_status_tracker.cc; sourceTree = ""; }; - OBJ_265 /* polling_entity.cc */ = {isa = PBXFileReference; path = polling_entity.cc; sourceTree = ""; }; - OBJ_266 /* pollset.cc */ = {isa = PBXFileReference; path = pollset.cc; sourceTree = ""; }; - OBJ_267 /* pollset_custom.cc */ = {isa = PBXFileReference; path = pollset_custom.cc; sourceTree = ""; }; - OBJ_268 /* pollset_set.cc */ = {isa = PBXFileReference; path = pollset_set.cc; sourceTree = ""; }; - OBJ_269 /* pollset_set_custom.cc */ = {isa = PBXFileReference; path = pollset_set_custom.cc; sourceTree = ""; }; - OBJ_27 /* byte_buffer.c */ = {isa = PBXFileReference; path = byte_buffer.c; sourceTree = ""; }; - OBJ_270 /* pollset_set_windows.cc */ = {isa = PBXFileReference; path = pollset_set_windows.cc; sourceTree = ""; }; - OBJ_271 /* pollset_uv.cc */ = {isa = PBXFileReference; path = pollset_uv.cc; sourceTree = ""; }; - OBJ_272 /* pollset_windows.cc */ = {isa = PBXFileReference; path = pollset_windows.cc; sourceTree = ""; }; - OBJ_273 /* resolve_address.cc */ = {isa = PBXFileReference; path = resolve_address.cc; sourceTree = ""; }; - OBJ_274 /* resolve_address_custom.cc */ = {isa = PBXFileReference; path = resolve_address_custom.cc; sourceTree = ""; }; - OBJ_275 /* resolve_address_posix.cc */ = {isa = PBXFileReference; path = resolve_address_posix.cc; sourceTree = ""; }; - OBJ_276 /* resolve_address_windows.cc */ = {isa = PBXFileReference; path = resolve_address_windows.cc; sourceTree = ""; }; - OBJ_277 /* resource_quota.cc */ = {isa = PBXFileReference; path = resource_quota.cc; sourceTree = ""; }; - OBJ_278 /* sockaddr_utils.cc */ = {isa = PBXFileReference; path = sockaddr_utils.cc; sourceTree = ""; }; - OBJ_279 /* socket_factory_posix.cc */ = {isa = PBXFileReference; path = socket_factory_posix.cc; sourceTree = ""; }; - OBJ_28 /* call.c */ = {isa = PBXFileReference; path = call.c; sourceTree = ""; }; - OBJ_280 /* socket_mutator.cc */ = {isa = PBXFileReference; path = socket_mutator.cc; sourceTree = ""; }; - OBJ_281 /* socket_utils_common_posix.cc */ = {isa = PBXFileReference; path = socket_utils_common_posix.cc; sourceTree = ""; }; - OBJ_282 /* socket_utils_linux.cc */ = {isa = PBXFileReference; path = socket_utils_linux.cc; sourceTree = ""; }; - OBJ_283 /* socket_utils_posix.cc */ = {isa = PBXFileReference; path = socket_utils_posix.cc; sourceTree = ""; }; - OBJ_284 /* socket_utils_uv.cc */ = {isa = PBXFileReference; path = socket_utils_uv.cc; sourceTree = ""; }; - OBJ_285 /* socket_utils_windows.cc */ = {isa = PBXFileReference; path = socket_utils_windows.cc; sourceTree = ""; }; - OBJ_286 /* socket_windows.cc */ = {isa = PBXFileReference; path = socket_windows.cc; sourceTree = ""; }; - OBJ_287 /* tcp_client.cc */ = {isa = PBXFileReference; path = tcp_client.cc; sourceTree = ""; }; - OBJ_288 /* tcp_client_custom.cc */ = {isa = PBXFileReference; path = tcp_client_custom.cc; sourceTree = ""; }; - OBJ_289 /* tcp_client_posix.cc */ = {isa = PBXFileReference; path = tcp_client_posix.cc; sourceTree = ""; }; - OBJ_29 /* channel.c */ = {isa = PBXFileReference; path = channel.c; sourceTree = ""; }; - OBJ_290 /* tcp_client_windows.cc */ = {isa = PBXFileReference; path = tcp_client_windows.cc; sourceTree = ""; }; - OBJ_291 /* tcp_custom.cc */ = {isa = PBXFileReference; path = tcp_custom.cc; sourceTree = ""; }; - OBJ_292 /* tcp_posix.cc */ = {isa = PBXFileReference; path = tcp_posix.cc; sourceTree = ""; }; - OBJ_293 /* tcp_server.cc */ = {isa = PBXFileReference; path = tcp_server.cc; sourceTree = ""; }; - OBJ_294 /* tcp_server_custom.cc */ = {isa = PBXFileReference; path = tcp_server_custom.cc; sourceTree = ""; }; - OBJ_295 /* tcp_server_posix.cc */ = {isa = PBXFileReference; path = tcp_server_posix.cc; sourceTree = ""; }; - OBJ_296 /* tcp_server_utils_posix_common.cc */ = {isa = PBXFileReference; path = tcp_server_utils_posix_common.cc; sourceTree = ""; }; - OBJ_297 /* tcp_server_utils_posix_ifaddrs.cc */ = {isa = PBXFileReference; path = tcp_server_utils_posix_ifaddrs.cc; sourceTree = ""; }; - OBJ_298 /* tcp_server_utils_posix_noifaddrs.cc */ = {isa = PBXFileReference; path = tcp_server_utils_posix_noifaddrs.cc; sourceTree = ""; }; - OBJ_299 /* tcp_server_windows.cc */ = {isa = PBXFileReference; path = tcp_server_windows.cc; sourceTree = ""; }; - OBJ_30 /* completion_queue.c */ = {isa = PBXFileReference; path = completion_queue.c; sourceTree = ""; }; - OBJ_300 /* tcp_uv.cc */ = {isa = PBXFileReference; path = tcp_uv.cc; sourceTree = ""; }; - OBJ_301 /* tcp_windows.cc */ = {isa = PBXFileReference; path = tcp_windows.cc; sourceTree = ""; }; - OBJ_302 /* time_averaged_stats.cc */ = {isa = PBXFileReference; path = time_averaged_stats.cc; sourceTree = ""; }; - OBJ_303 /* timer.cc */ = {isa = PBXFileReference; path = timer.cc; sourceTree = ""; }; - OBJ_304 /* timer_custom.cc */ = {isa = PBXFileReference; path = timer_custom.cc; sourceTree = ""; }; - OBJ_305 /* timer_generic.cc */ = {isa = PBXFileReference; path = timer_generic.cc; sourceTree = ""; }; - OBJ_306 /* timer_heap.cc */ = {isa = PBXFileReference; path = timer_heap.cc; sourceTree = ""; }; - OBJ_307 /* timer_manager.cc */ = {isa = PBXFileReference; path = timer_manager.cc; sourceTree = ""; }; - OBJ_308 /* timer_uv.cc */ = {isa = PBXFileReference; path = timer_uv.cc; sourceTree = ""; }; - OBJ_309 /* udp_server.cc */ = {isa = PBXFileReference; path = udp_server.cc; sourceTree = ""; }; - OBJ_31 /* event.c */ = {isa = PBXFileReference; path = event.c; sourceTree = ""; }; - OBJ_310 /* unix_sockets_posix.cc */ = {isa = PBXFileReference; path = unix_sockets_posix.cc; sourceTree = ""; }; - OBJ_311 /* unix_sockets_posix_noop.cc */ = {isa = PBXFileReference; path = unix_sockets_posix_noop.cc; sourceTree = ""; }; - OBJ_312 /* wakeup_fd_cv.cc */ = {isa = PBXFileReference; path = wakeup_fd_cv.cc; sourceTree = ""; }; - OBJ_313 /* wakeup_fd_eventfd.cc */ = {isa = PBXFileReference; path = wakeup_fd_eventfd.cc; sourceTree = ""; }; - OBJ_314 /* wakeup_fd_nospecial.cc */ = {isa = PBXFileReference; path = wakeup_fd_nospecial.cc; sourceTree = ""; }; - OBJ_315 /* wakeup_fd_pipe.cc */ = {isa = PBXFileReference; path = wakeup_fd_pipe.cc; sourceTree = ""; }; - OBJ_316 /* wakeup_fd_posix.cc */ = {isa = PBXFileReference; path = wakeup_fd_posix.cc; sourceTree = ""; }; - OBJ_318 /* json.cc */ = {isa = PBXFileReference; path = json.cc; sourceTree = ""; }; - OBJ_319 /* json_reader.cc */ = {isa = PBXFileReference; path = json_reader.cc; sourceTree = ""; }; - OBJ_32 /* handler.c */ = {isa = PBXFileReference; path = handler.c; sourceTree = ""; }; - OBJ_320 /* json_string.cc */ = {isa = PBXFileReference; path = json_string.cc; sourceTree = ""; }; - OBJ_321 /* json_writer.cc */ = {isa = PBXFileReference; path = json_writer.cc; sourceTree = ""; }; - OBJ_323 /* basic_timers.cc */ = {isa = PBXFileReference; path = basic_timers.cc; sourceTree = ""; }; - OBJ_324 /* stap_timers.cc */ = {isa = PBXFileReference; path = stap_timers.cc; sourceTree = ""; }; - OBJ_327 /* security_context.cc */ = {isa = PBXFileReference; path = security_context.cc; sourceTree = ""; }; - OBJ_33 /* internal.c */ = {isa = PBXFileReference; path = internal.c; sourceTree = ""; }; - OBJ_330 /* alts_credentials.cc */ = {isa = PBXFileReference; path = alts_credentials.cc; sourceTree = ""; }; - OBJ_331 /* check_gcp_environment.cc */ = {isa = PBXFileReference; path = check_gcp_environment.cc; sourceTree = ""; }; - OBJ_332 /* check_gcp_environment_linux.cc */ = {isa = PBXFileReference; path = check_gcp_environment_linux.cc; sourceTree = ""; }; - OBJ_333 /* check_gcp_environment_no_op.cc */ = {isa = PBXFileReference; path = check_gcp_environment_no_op.cc; sourceTree = ""; }; - OBJ_334 /* check_gcp_environment_windows.cc */ = {isa = PBXFileReference; path = check_gcp_environment_windows.cc; sourceTree = ""; }; - OBJ_335 /* grpc_alts_credentials_client_options.cc */ = {isa = PBXFileReference; path = grpc_alts_credentials_client_options.cc; sourceTree = ""; }; - OBJ_336 /* grpc_alts_credentials_options.cc */ = {isa = PBXFileReference; path = grpc_alts_credentials_options.cc; sourceTree = ""; }; - OBJ_337 /* grpc_alts_credentials_server_options.cc */ = {isa = PBXFileReference; path = grpc_alts_credentials_server_options.cc; sourceTree = ""; }; - OBJ_339 /* composite_credentials.cc */ = {isa = PBXFileReference; path = composite_credentials.cc; sourceTree = ""; }; - OBJ_34 /* metadata.c */ = {isa = PBXFileReference; path = metadata.c; sourceTree = ""; }; - OBJ_340 /* credentials.cc */ = {isa = PBXFileReference; path = credentials.cc; sourceTree = ""; }; - OBJ_341 /* credentials_metadata.cc */ = {isa = PBXFileReference; path = credentials_metadata.cc; sourceTree = ""; }; - OBJ_343 /* fake_credentials.cc */ = {isa = PBXFileReference; path = fake_credentials.cc; sourceTree = ""; }; - OBJ_345 /* credentials_generic.cc */ = {isa = PBXFileReference; path = credentials_generic.cc; sourceTree = ""; }; - OBJ_346 /* google_default_credentials.cc */ = {isa = PBXFileReference; path = google_default_credentials.cc; sourceTree = ""; }; - OBJ_348 /* iam_credentials.cc */ = {isa = PBXFileReference; path = iam_credentials.cc; sourceTree = ""; }; - OBJ_35 /* mutex.c */ = {isa = PBXFileReference; path = mutex.c; sourceTree = ""; }; - OBJ_350 /* json_token.cc */ = {isa = PBXFileReference; path = json_token.cc; sourceTree = ""; }; - OBJ_351 /* jwt_credentials.cc */ = {isa = PBXFileReference; path = jwt_credentials.cc; sourceTree = ""; }; - OBJ_352 /* jwt_verifier.cc */ = {isa = PBXFileReference; path = jwt_verifier.cc; sourceTree = ""; }; - OBJ_354 /* oauth2_credentials.cc */ = {isa = PBXFileReference; path = oauth2_credentials.cc; sourceTree = ""; }; - OBJ_356 /* plugin_credentials.cc */ = {isa = PBXFileReference; path = plugin_credentials.cc; sourceTree = ""; }; - OBJ_358 /* ssl_credentials.cc */ = {isa = PBXFileReference; path = ssl_credentials.cc; sourceTree = ""; }; - OBJ_36 /* observers.c */ = {isa = PBXFileReference; path = observers.c; sourceTree = ""; }; - OBJ_360 /* alts_security_connector.cc */ = {isa = PBXFileReference; path = alts_security_connector.cc; sourceTree = ""; }; - OBJ_361 /* security_connector.cc */ = {isa = PBXFileReference; path = security_connector.cc; sourceTree = ""; }; - OBJ_363 /* client_auth_filter.cc */ = {isa = PBXFileReference; path = client_auth_filter.cc; sourceTree = ""; }; - OBJ_364 /* secure_endpoint.cc */ = {isa = PBXFileReference; path = secure_endpoint.cc; sourceTree = ""; }; - OBJ_365 /* security_handshaker.cc */ = {isa = PBXFileReference; path = security_handshaker.cc; sourceTree = ""; }; - OBJ_366 /* server_auth_filter.cc */ = {isa = PBXFileReference; path = server_auth_filter.cc; sourceTree = ""; }; - OBJ_367 /* target_authority_table.cc */ = {isa = PBXFileReference; path = target_authority_table.cc; sourceTree = ""; }; - OBJ_368 /* tsi_error.cc */ = {isa = PBXFileReference; path = tsi_error.cc; sourceTree = ""; }; - OBJ_37 /* operations.c */ = {isa = PBXFileReference; path = operations.c; sourceTree = ""; }; - OBJ_370 /* json_util.cc */ = {isa = PBXFileReference; path = json_util.cc; sourceTree = ""; }; - OBJ_372 /* b64.cc */ = {isa = PBXFileReference; path = b64.cc; sourceTree = ""; }; - OBJ_373 /* percent_encoding.cc */ = {isa = PBXFileReference; path = percent_encoding.cc; sourceTree = ""; }; - OBJ_374 /* slice.cc */ = {isa = PBXFileReference; path = slice.cc; sourceTree = ""; }; - OBJ_375 /* slice_buffer.cc */ = {isa = PBXFileReference; path = slice_buffer.cc; sourceTree = ""; }; - OBJ_376 /* slice_intern.cc */ = {isa = PBXFileReference; path = slice_intern.cc; sourceTree = ""; }; - OBJ_377 /* slice_string_helpers.cc */ = {isa = PBXFileReference; path = slice_string_helpers.cc; sourceTree = ""; }; - OBJ_379 /* api_trace.cc */ = {isa = PBXFileReference; path = api_trace.cc; sourceTree = ""; }; - OBJ_38 /* server.c */ = {isa = PBXFileReference; path = server.c; sourceTree = ""; }; - OBJ_380 /* byte_buffer.cc */ = {isa = PBXFileReference; path = byte_buffer.cc; sourceTree = ""; }; - OBJ_381 /* byte_buffer_reader.cc */ = {isa = PBXFileReference; path = byte_buffer_reader.cc; sourceTree = ""; }; - OBJ_382 /* call.cc */ = {isa = PBXFileReference; path = call.cc; sourceTree = ""; }; - OBJ_383 /* call_details.cc */ = {isa = PBXFileReference; path = call_details.cc; sourceTree = ""; }; - OBJ_384 /* call_log_batch.cc */ = {isa = PBXFileReference; path = call_log_batch.cc; sourceTree = ""; }; - OBJ_385 /* channel.cc */ = {isa = PBXFileReference; path = channel.cc; sourceTree = ""; }; - OBJ_386 /* channel_init.cc */ = {isa = PBXFileReference; path = channel_init.cc; sourceTree = ""; }; - OBJ_387 /* channel_ping.cc */ = {isa = PBXFileReference; path = channel_ping.cc; sourceTree = ""; }; - OBJ_388 /* channel_stack_type.cc */ = {isa = PBXFileReference; path = channel_stack_type.cc; sourceTree = ""; }; - OBJ_389 /* completion_queue.cc */ = {isa = PBXFileReference; path = completion_queue.cc; sourceTree = ""; }; - OBJ_390 /* completion_queue_factory.cc */ = {isa = PBXFileReference; path = completion_queue_factory.cc; sourceTree = ""; }; - OBJ_391 /* event_string.cc */ = {isa = PBXFileReference; path = event_string.cc; sourceTree = ""; }; - OBJ_392 /* init.cc */ = {isa = PBXFileReference; path = init.cc; sourceTree = ""; }; - OBJ_393 /* init_secure.cc */ = {isa = PBXFileReference; path = init_secure.cc; sourceTree = ""; }; - OBJ_394 /* lame_client.cc */ = {isa = PBXFileReference; path = lame_client.cc; sourceTree = ""; }; - OBJ_395 /* metadata_array.cc */ = {isa = PBXFileReference; path = metadata_array.cc; sourceTree = ""; }; - OBJ_396 /* server.cc */ = {isa = PBXFileReference; path = server.cc; sourceTree = ""; }; - OBJ_397 /* validate_metadata.cc */ = {isa = PBXFileReference; path = validate_metadata.cc; sourceTree = ""; }; - OBJ_398 /* version.cc */ = {isa = PBXFileReference; path = version.cc; sourceTree = ""; }; - OBJ_400 /* bdp_estimator.cc */ = {isa = PBXFileReference; path = bdp_estimator.cc; sourceTree = ""; }; - OBJ_401 /* byte_stream.cc */ = {isa = PBXFileReference; path = byte_stream.cc; sourceTree = ""; }; - OBJ_402 /* connectivity_state.cc */ = {isa = PBXFileReference; path = connectivity_state.cc; sourceTree = ""; }; - OBJ_403 /* error_utils.cc */ = {isa = PBXFileReference; path = error_utils.cc; sourceTree = ""; }; - OBJ_404 /* metadata.cc */ = {isa = PBXFileReference; path = metadata.cc; sourceTree = ""; }; - OBJ_405 /* metadata_batch.cc */ = {isa = PBXFileReference; path = metadata_batch.cc; sourceTree = ""; }; - OBJ_406 /* pid_controller.cc */ = {isa = PBXFileReference; path = pid_controller.cc; sourceTree = ""; }; - OBJ_407 /* service_config.cc */ = {isa = PBXFileReference; path = service_config.cc; sourceTree = ""; }; - OBJ_408 /* static_metadata.cc */ = {isa = PBXFileReference; path = static_metadata.cc; sourceTree = ""; }; - OBJ_409 /* status_conversion.cc */ = {isa = PBXFileReference; path = status_conversion.cc; sourceTree = ""; }; - OBJ_410 /* status_metadata.cc */ = {isa = PBXFileReference; path = status_metadata.cc; sourceTree = ""; }; - OBJ_411 /* timeout_encoding.cc */ = {isa = PBXFileReference; path = timeout_encoding.cc; sourceTree = ""; }; - OBJ_412 /* transport.cc */ = {isa = PBXFileReference; path = transport.cc; sourceTree = ""; }; - OBJ_413 /* transport_op_string.cc */ = {isa = PBXFileReference; path = transport_op_string.cc; sourceTree = ""; }; - OBJ_415 /* grpc_plugin_registry.cc */ = {isa = PBXFileReference; path = grpc_plugin_registry.cc; sourceTree = ""; }; - OBJ_419 /* aes_gcm.cc */ = {isa = PBXFileReference; path = aes_gcm.cc; sourceTree = ""; }; - OBJ_420 /* gsec.cc */ = {isa = PBXFileReference; path = gsec.cc; sourceTree = ""; }; - OBJ_422 /* alts_counter.cc */ = {isa = PBXFileReference; path = alts_counter.cc; sourceTree = ""; }; - OBJ_423 /* alts_crypter.cc */ = {isa = PBXFileReference; path = alts_crypter.cc; sourceTree = ""; }; - OBJ_424 /* alts_frame_protector.cc */ = {isa = PBXFileReference; path = alts_frame_protector.cc; sourceTree = ""; }; - OBJ_425 /* alts_record_protocol_crypter_common.cc */ = {isa = PBXFileReference; path = alts_record_protocol_crypter_common.cc; sourceTree = ""; }; - OBJ_426 /* alts_seal_privacy_integrity_crypter.cc */ = {isa = PBXFileReference; path = alts_seal_privacy_integrity_crypter.cc; sourceTree = ""; }; - OBJ_427 /* alts_unseal_privacy_integrity_crypter.cc */ = {isa = PBXFileReference; path = alts_unseal_privacy_integrity_crypter.cc; sourceTree = ""; }; - OBJ_428 /* frame_handler.cc */ = {isa = PBXFileReference; path = frame_handler.cc; sourceTree = ""; }; - OBJ_43 /* grpc_context.cc */ = {isa = PBXFileReference; path = grpc_context.cc; sourceTree = ""; }; - OBJ_430 /* alts_handshaker_client.cc */ = {isa = PBXFileReference; path = alts_handshaker_client.cc; sourceTree = ""; }; - OBJ_431 /* alts_handshaker_service_api.cc */ = {isa = PBXFileReference; path = alts_handshaker_service_api.cc; sourceTree = ""; }; - OBJ_432 /* alts_handshaker_service_api_util.cc */ = {isa = PBXFileReference; path = alts_handshaker_service_api_util.cc; sourceTree = ""; }; - OBJ_433 /* alts_tsi_event.cc */ = {isa = PBXFileReference; path = alts_tsi_event.cc; sourceTree = ""; }; - OBJ_434 /* alts_tsi_handshaker.cc */ = {isa = PBXFileReference; path = alts_tsi_handshaker.cc; sourceTree = ""; }; - OBJ_435 /* alts_tsi_utils.cc */ = {isa = PBXFileReference; path = alts_tsi_utils.cc; sourceTree = ""; }; - OBJ_436 /* altscontext.pb.c */ = {isa = PBXFileReference; path = altscontext.pb.c; sourceTree = ""; }; - OBJ_437 /* handshaker.pb.c */ = {isa = PBXFileReference; path = handshaker.pb.c; sourceTree = ""; }; - OBJ_438 /* transport_security_common.pb.c */ = {isa = PBXFileReference; path = transport_security_common.pb.c; sourceTree = ""; }; - OBJ_439 /* transport_security_common_api.cc */ = {isa = PBXFileReference; path = transport_security_common_api.cc; sourceTree = ""; }; - OBJ_441 /* alts_grpc_integrity_only_record_protocol.cc */ = {isa = PBXFileReference; path = alts_grpc_integrity_only_record_protocol.cc; sourceTree = ""; }; - OBJ_442 /* alts_grpc_privacy_integrity_record_protocol.cc */ = {isa = PBXFileReference; path = alts_grpc_privacy_integrity_record_protocol.cc; sourceTree = ""; }; - OBJ_443 /* alts_grpc_record_protocol_common.cc */ = {isa = PBXFileReference; path = alts_grpc_record_protocol_common.cc; sourceTree = ""; }; - OBJ_444 /* alts_iovec_record_protocol.cc */ = {isa = PBXFileReference; path = alts_iovec_record_protocol.cc; sourceTree = ""; }; - OBJ_445 /* alts_zero_copy_grpc_protector.cc */ = {isa = PBXFileReference; path = alts_zero_copy_grpc_protector.cc; sourceTree = ""; }; - OBJ_446 /* alts_transport_security.cc */ = {isa = PBXFileReference; path = alts_transport_security.cc; sourceTree = ""; }; - OBJ_447 /* fake_transport_security.cc */ = {isa = PBXFileReference; path = fake_transport_security.cc; sourceTree = ""; }; - OBJ_450 /* ssl_session_boringssl.cc */ = {isa = PBXFileReference; path = ssl_session_boringssl.cc; sourceTree = ""; }; - OBJ_451 /* ssl_session_cache.cc */ = {isa = PBXFileReference; path = ssl_session_cache.cc; sourceTree = ""; }; - OBJ_452 /* ssl_session_openssl.cc */ = {isa = PBXFileReference; path = ssl_session_openssl.cc; sourceTree = ""; }; - OBJ_453 /* ssl_transport_security.cc */ = {isa = PBXFileReference; path = ssl_transport_security.cc; sourceTree = ""; }; - OBJ_454 /* transport_security.cc */ = {isa = PBXFileReference; path = transport_security.cc; sourceTree = ""; }; - OBJ_455 /* transport_security_adapter.cc */ = {isa = PBXFileReference; path = transport_security_adapter.cc; sourceTree = ""; }; - OBJ_456 /* transport_security_grpc.cc */ = {isa = PBXFileReference; path = transport_security_grpc.cc; sourceTree = ""; }; - OBJ_459 /* pb_common.c */ = {isa = PBXFileReference; path = pb_common.c; sourceTree = ""; }; - OBJ_46 /* backup_poller.cc */ = {isa = PBXFileReference; path = backup_poller.cc; sourceTree = ""; }; - OBJ_460 /* pb_decode.c */ = {isa = PBXFileReference; path = pb_decode.c; sourceTree = ""; }; - OBJ_461 /* pb_encode.c */ = {isa = PBXFileReference; path = pb_encode.c; sourceTree = ""; }; - OBJ_463 /* cgrpc.h */ = {isa = PBXFileReference; path = cgrpc.h; sourceTree = ""; }; - OBJ_465 /* grpc.h */ = {isa = PBXFileReference; path = grpc.h; sourceTree = ""; }; - OBJ_466 /* status.h */ = {isa = PBXFileReference; path = status.h; sourceTree = ""; }; - OBJ_467 /* census.h */ = {isa = PBXFileReference; path = census.h; sourceTree = ""; }; - OBJ_468 /* slice.h */ = {isa = PBXFileReference; path = slice.h; sourceTree = ""; }; - OBJ_469 /* compression.h */ = {isa = PBXFileReference; path = compression.h; sourceTree = ""; }; - OBJ_47 /* channel_connectivity.cc */ = {isa = PBXFileReference; path = channel_connectivity.cc; sourceTree = ""; }; - OBJ_470 /* fork.h */ = {isa = PBXFileReference; path = fork.h; sourceTree = ""; }; - OBJ_471 /* byte_buffer_reader.h */ = {isa = PBXFileReference; path = byte_buffer_reader.h; sourceTree = ""; }; - OBJ_472 /* grpc_security_constants.h */ = {isa = PBXFileReference; path = grpc_security_constants.h; sourceTree = ""; }; - OBJ_473 /* byte_buffer.h */ = {isa = PBXFileReference; path = byte_buffer.h; sourceTree = ""; }; - OBJ_474 /* slice_buffer.h */ = {isa = PBXFileReference; path = slice_buffer.h; sourceTree = ""; }; - OBJ_475 /* grpc_posix.h */ = {isa = PBXFileReference; path = grpc_posix.h; sourceTree = ""; }; - OBJ_476 /* grpc_security.h */ = {isa = PBXFileReference; path = grpc_security.h; sourceTree = ""; }; - OBJ_477 /* load_reporting.h */ = {isa = PBXFileReference; path = load_reporting.h; sourceTree = ""; }; - OBJ_479 /* time.h */ = {isa = PBXFileReference; path = time.h; sourceTree = ""; }; - OBJ_48 /* client_channel.cc */ = {isa = PBXFileReference; path = client_channel.cc; sourceTree = ""; }; - OBJ_480 /* port_platform.h */ = {isa = PBXFileReference; path = port_platform.h; sourceTree = ""; }; - OBJ_481 /* log_windows.h */ = {isa = PBXFileReference; path = log_windows.h; sourceTree = ""; }; - OBJ_482 /* sync.h */ = {isa = PBXFileReference; path = sync.h; sourceTree = ""; }; - OBJ_483 /* string_util.h */ = {isa = PBXFileReference; path = string_util.h; sourceTree = ""; }; - OBJ_484 /* sync_custom.h */ = {isa = PBXFileReference; path = sync_custom.h; sourceTree = ""; }; - OBJ_485 /* thd_id.h */ = {isa = PBXFileReference; path = thd_id.h; sourceTree = ""; }; - OBJ_486 /* workaround_list.h */ = {isa = PBXFileReference; path = workaround_list.h; sourceTree = ""; }; - OBJ_487 /* atm_gcc_sync.h */ = {isa = PBXFileReference; path = atm_gcc_sync.h; sourceTree = ""; }; - OBJ_488 /* atm_gcc_atomic.h */ = {isa = PBXFileReference; path = atm_gcc_atomic.h; sourceTree = ""; }; - OBJ_489 /* atm.h */ = {isa = PBXFileReference; path = atm.h; sourceTree = ""; }; - OBJ_49 /* client_channel_factory.cc */ = {isa = PBXFileReference; path = client_channel_factory.cc; sourceTree = ""; }; - OBJ_490 /* sync_generic.h */ = {isa = PBXFileReference; path = sync_generic.h; sourceTree = ""; }; - OBJ_491 /* log.h */ = {isa = PBXFileReference; path = log.h; sourceTree = ""; }; - OBJ_492 /* cpu.h */ = {isa = PBXFileReference; path = cpu.h; sourceTree = ""; }; - OBJ_493 /* sync_posix.h */ = {isa = PBXFileReference; path = sync_posix.h; sourceTree = ""; }; - OBJ_494 /* atm_windows.h */ = {isa = PBXFileReference; path = atm_windows.h; sourceTree = ""; }; - OBJ_495 /* sync_windows.h */ = {isa = PBXFileReference; path = sync_windows.h; sourceTree = ""; }; - OBJ_496 /* alloc.h */ = {isa = PBXFileReference; path = alloc.h; sourceTree = ""; }; - OBJ_499 /* port_platform.h */ = {isa = PBXFileReference; path = port_platform.h; sourceTree = ""; }; - OBJ_50 /* client_channel_plugin.cc */ = {isa = PBXFileReference; path = client_channel_plugin.cc; sourceTree = ""; }; - OBJ_500 /* status.h */ = {isa = PBXFileReference; path = status.h; sourceTree = ""; }; - OBJ_501 /* gpr_types.h */ = {isa = PBXFileReference; path = gpr_types.h; sourceTree = ""; }; - OBJ_502 /* sync.h */ = {isa = PBXFileReference; path = sync.h; sourceTree = ""; }; - OBJ_503 /* grpc_types.h */ = {isa = PBXFileReference; path = grpc_types.h; sourceTree = ""; }; - OBJ_504 /* sync_custom.h */ = {isa = PBXFileReference; path = sync_custom.h; sourceTree = ""; }; - OBJ_505 /* gpr_slice.h */ = {isa = PBXFileReference; path = gpr_slice.h; sourceTree = ""; }; - OBJ_506 /* slice.h */ = {isa = PBXFileReference; path = slice.h; sourceTree = ""; }; - OBJ_507 /* compression_types.h */ = {isa = PBXFileReference; path = compression_types.h; sourceTree = ""; }; - OBJ_508 /* atm_gcc_sync.h */ = {isa = PBXFileReference; path = atm_gcc_sync.h; sourceTree = ""; }; - OBJ_509 /* atm_gcc_atomic.h */ = {isa = PBXFileReference; path = atm_gcc_atomic.h; sourceTree = ""; }; - OBJ_51 /* connector.cc */ = {isa = PBXFileReference; path = connector.cc; sourceTree = ""; }; - OBJ_510 /* atm.h */ = {isa = PBXFileReference; path = atm.h; sourceTree = ""; }; - OBJ_511 /* sync_generic.h */ = {isa = PBXFileReference; path = sync_generic.h; sourceTree = ""; }; - OBJ_512 /* fork.h */ = {isa = PBXFileReference; path = fork.h; sourceTree = ""; }; - OBJ_513 /* byte_buffer_reader.h */ = {isa = PBXFileReference; path = byte_buffer_reader.h; sourceTree = ""; }; - OBJ_514 /* sync_posix.h */ = {isa = PBXFileReference; path = sync_posix.h; sourceTree = ""; }; - OBJ_515 /* atm_windows.h */ = {isa = PBXFileReference; path = atm_windows.h; sourceTree = ""; }; - OBJ_516 /* propagation_bits.h */ = {isa = PBXFileReference; path = propagation_bits.h; sourceTree = ""; }; - OBJ_517 /* byte_buffer.h */ = {isa = PBXFileReference; path = byte_buffer.h; sourceTree = ""; }; - OBJ_518 /* connectivity_state.h */ = {isa = PBXFileReference; path = connectivity_state.h; sourceTree = ""; }; - OBJ_519 /* sync_windows.h */ = {isa = PBXFileReference; path = sync_windows.h; sourceTree = ""; }; - OBJ_52 /* http_connect_handshaker.cc */ = {isa = PBXFileReference; path = http_connect_handshaker.cc; sourceTree = ""; }; - OBJ_520 /* module.modulemap */ = {isa = PBXFileReference; name = module.modulemap; path = ../Sources/CgRPC/include/module.modulemap; sourceTree = ""; }; - OBJ_522 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; - OBJ_525 /* BaseCallHandler.swift */ = {isa = PBXFileReference; path = BaseCallHandler.swift; sourceTree = ""; }; - OBJ_526 /* BidirectionalStreamingCallHandler.swift */ = {isa = PBXFileReference; path = BidirectionalStreamingCallHandler.swift; sourceTree = ""; }; - OBJ_527 /* ClientStreamingCallHandler.swift */ = {isa = PBXFileReference; path = ClientStreamingCallHandler.swift; sourceTree = ""; }; - OBJ_528 /* ServerStreamingCallHandler.swift */ = {isa = PBXFileReference; path = ServerStreamingCallHandler.swift; sourceTree = ""; }; - OBJ_529 /* UnaryCallHandler.swift */ = {isa = PBXFileReference; path = UnaryCallHandler.swift; sourceTree = ""; }; - OBJ_53 /* http_proxy.cc */ = {isa = PBXFileReference; path = http_proxy.cc; sourceTree = ""; }; - OBJ_531 /* BaseClientCall.swift */ = {isa = PBXFileReference; path = BaseClientCall.swift; sourceTree = ""; }; - OBJ_532 /* BidirectionalStreamingClientCall.swift */ = {isa = PBXFileReference; path = BidirectionalStreamingClientCall.swift; sourceTree = ""; }; - OBJ_533 /* ClientCall.swift */ = {isa = PBXFileReference; path = ClientCall.swift; sourceTree = ""; }; - OBJ_534 /* ClientStreamingClientCall.swift */ = {isa = PBXFileReference; path = ClientStreamingClientCall.swift; sourceTree = ""; }; - OBJ_535 /* ResponseObserver.swift */ = {isa = PBXFileReference; path = ResponseObserver.swift; sourceTree = ""; }; - OBJ_536 /* ServerStreamingClientCall.swift */ = {isa = PBXFileReference; path = ServerStreamingClientCall.swift; sourceTree = ""; }; - OBJ_537 /* UnaryClientCall.swift */ = {isa = PBXFileReference; path = UnaryClientCall.swift; sourceTree = ""; }; - OBJ_538 /* ClientOptions.swift */ = {isa = PBXFileReference; path = ClientOptions.swift; sourceTree = ""; }; - OBJ_539 /* CompressionMechanism.swift */ = {isa = PBXFileReference; path = CompressionMechanism.swift; sourceTree = ""; }; - OBJ_54 /* lb_policy.cc */ = {isa = PBXFileReference; path = lb_policy.cc; sourceTree = ""; }; - OBJ_540 /* GRPCChannelHandler.swift */ = {isa = PBXFileReference; path = GRPCChannelHandler.swift; sourceTree = ""; }; - OBJ_541 /* GRPCClient.swift */ = {isa = PBXFileReference; path = GRPCClient.swift; sourceTree = ""; }; - OBJ_542 /* GRPCClientChannelHandler.swift */ = {isa = PBXFileReference; path = GRPCClientChannelHandler.swift; sourceTree = ""; }; - OBJ_543 /* GRPCClientCodec.swift */ = {isa = PBXFileReference; path = GRPCClientCodec.swift; sourceTree = ""; }; - OBJ_544 /* GRPCError.swift */ = {isa = PBXFileReference; path = GRPCError.swift; sourceTree = ""; }; - OBJ_545 /* GRPCServer.swift */ = {isa = PBXFileReference; path = GRPCServer.swift; sourceTree = ""; }; - OBJ_546 /* GRPCServerCodec.swift */ = {isa = PBXFileReference; path = GRPCServerCodec.swift; sourceTree = ""; }; - OBJ_547 /* GRPCStatus.swift */ = {isa = PBXFileReference; path = GRPCStatus.swift; sourceTree = ""; }; - OBJ_548 /* GRPCTimeout.swift */ = {isa = PBXFileReference; path = GRPCTimeout.swift; sourceTree = ""; }; - OBJ_549 /* HTTP1ToRawGRPCClientCodec.swift */ = {isa = PBXFileReference; path = HTTP1ToRawGRPCClientCodec.swift; sourceTree = ""; }; - OBJ_550 /* HTTP1ToRawGRPCServerCodec.swift */ = {isa = PBXFileReference; path = HTTP1ToRawGRPCServerCodec.swift; sourceTree = ""; }; - OBJ_551 /* HTTPProtocolSwitcher.swift */ = {isa = PBXFileReference; path = HTTPProtocolSwitcher.swift; sourceTree = ""; }; - OBJ_552 /* LengthPrefixedMessageReader.swift */ = {isa = PBXFileReference; path = LengthPrefixedMessageReader.swift; sourceTree = ""; }; - OBJ_553 /* LengthPrefixedMessageWriter.swift */ = {isa = PBXFileReference; path = LengthPrefixedMessageWriter.swift; sourceTree = ""; }; - OBJ_554 /* LoggingServerErrorDelegate.swift */ = {isa = PBXFileReference; path = LoggingServerErrorDelegate.swift; sourceTree = ""; }; - OBJ_556 /* ServerCallContext.swift */ = {isa = PBXFileReference; path = ServerCallContext.swift; sourceTree = ""; }; - OBJ_557 /* StreamingResponseCallContext.swift */ = {isa = PBXFileReference; path = StreamingResponseCallContext.swift; sourceTree = ""; }; - OBJ_558 /* UnaryResponseCallContext.swift */ = {isa = PBXFileReference; path = UnaryResponseCallContext.swift; sourceTree = ""; }; - OBJ_559 /* ServerErrorDelegate.swift */ = {isa = PBXFileReference; path = ServerErrorDelegate.swift; sourceTree = ""; }; - OBJ_560 /* StatusCode.swift */ = {isa = PBXFileReference; path = StatusCode.swift; sourceTree = ""; }; - OBJ_561 /* StreamEvent.swift */ = {isa = PBXFileReference; path = StreamEvent.swift; sourceTree = ""; }; - OBJ_562 /* WebCORSHandler.swift */ = {isa = PBXFileReference; path = WebCORSHandler.swift; sourceTree = ""; }; - OBJ_564 /* EchoProvider.swift */ = {isa = PBXFileReference; path = EchoProvider.swift; sourceTree = ""; }; - OBJ_566 /* echo.grpc.swift */ = {isa = PBXFileReference; path = echo.grpc.swift; sourceTree = ""; }; - OBJ_567 /* echo.pb.swift */ = {isa = PBXFileReference; path = echo.pb.swift; sourceTree = ""; }; - OBJ_568 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; - OBJ_57 /* client_load_reporting_filter.cc */ = {isa = PBXFileReference; path = client_load_reporting_filter.cc; sourceTree = ""; }; - OBJ_571 /* ByteBuffer.swift */ = {isa = PBXFileReference; path = ByteBuffer.swift; sourceTree = ""; }; - OBJ_572 /* Call.swift */ = {isa = PBXFileReference; path = Call.swift; sourceTree = ""; }; - OBJ_573 /* CallError.swift */ = {isa = PBXFileReference; path = CallError.swift; sourceTree = ""; }; - OBJ_574 /* CallResult.swift */ = {isa = PBXFileReference; path = CallResult.swift; sourceTree = ""; }; - OBJ_575 /* Channel.swift */ = {isa = PBXFileReference; path = Channel.swift; sourceTree = ""; }; - OBJ_576 /* ChannelArgument.swift */ = {isa = PBXFileReference; path = ChannelArgument.swift; sourceTree = ""; }; - OBJ_577 /* ChannelConnectivityObserver.swift */ = {isa = PBXFileReference; path = ChannelConnectivityObserver.swift; sourceTree = ""; }; - OBJ_578 /* ChannelConnectivityState.swift */ = {isa = PBXFileReference; path = ChannelConnectivityState.swift; sourceTree = ""; }; - OBJ_579 /* ClientNetworkMonitor.swift */ = {isa = PBXFileReference; path = ClientNetworkMonitor.swift; sourceTree = ""; }; - OBJ_58 /* grpclb.cc */ = {isa = PBXFileReference; path = grpclb.cc; sourceTree = ""; }; - OBJ_580 /* CompletionQueue.swift */ = {isa = PBXFileReference; path = CompletionQueue.swift; sourceTree = ""; }; - OBJ_581 /* Handler.swift */ = {isa = PBXFileReference; path = Handler.swift; sourceTree = ""; }; - OBJ_582 /* Metadata.swift */ = {isa = PBXFileReference; path = Metadata.swift; sourceTree = ""; }; - OBJ_583 /* Mutex.swift */ = {isa = PBXFileReference; path = Mutex.swift; sourceTree = ""; }; - OBJ_584 /* Operation.swift */ = {isa = PBXFileReference; path = Operation.swift; sourceTree = ""; }; - OBJ_585 /* OperationGroup.swift */ = {isa = PBXFileReference; path = OperationGroup.swift; sourceTree = ""; }; - OBJ_586 /* Roots.swift */ = {isa = PBXFileReference; path = Roots.swift; sourceTree = ""; }; - OBJ_587 /* Server.swift */ = {isa = PBXFileReference; path = Server.swift; sourceTree = ""; }; - OBJ_588 /* ServerStatus.swift */ = {isa = PBXFileReference; path = ServerStatus.swift; sourceTree = ""; }; - OBJ_589 /* StatusCode.swift */ = {isa = PBXFileReference; path = StatusCode.swift; sourceTree = ""; }; - OBJ_59 /* grpclb_channel_secure.cc */ = {isa = PBXFileReference; path = grpclb_channel_secure.cc; sourceTree = ""; }; - OBJ_590 /* gRPC.swift */ = {isa = PBXFileReference; path = gRPC.swift; sourceTree = ""; }; - OBJ_592 /* ClientCall.swift */ = {isa = PBXFileReference; path = ClientCall.swift; sourceTree = ""; }; - OBJ_593 /* ClientCallBidirectionalStreaming.swift */ = {isa = PBXFileReference; path = ClientCallBidirectionalStreaming.swift; sourceTree = ""; }; - OBJ_594 /* ClientCallClientStreaming.swift */ = {isa = PBXFileReference; path = ClientCallClientStreaming.swift; sourceTree = ""; }; - OBJ_595 /* ClientCallServerStreaming.swift */ = {isa = PBXFileReference; path = ClientCallServerStreaming.swift; sourceTree = ""; }; - OBJ_596 /* ClientCallUnary.swift */ = {isa = PBXFileReference; path = ClientCallUnary.swift; sourceTree = ""; }; - OBJ_597 /* RPCError.swift */ = {isa = PBXFileReference; path = RPCError.swift; sourceTree = ""; }; - OBJ_598 /* ServerSession.swift */ = {isa = PBXFileReference; path = ServerSession.swift; sourceTree = ""; }; - OBJ_599 /* ServerSessionBidirectionalStreaming.swift */ = {isa = PBXFileReference; path = ServerSessionBidirectionalStreaming.swift; sourceTree = ""; }; + OBJ_1237 /* IO.swift */ = {isa = PBXFileReference; path = IO.swift; sourceTree = ""; }; + OBJ_1238 /* IOData.swift */ = {isa = PBXFileReference; path = IOData.swift; sourceTree = ""; }; + OBJ_1239 /* IntegerTypes.swift */ = {isa = PBXFileReference; path = IntegerTypes.swift; sourceTree = ""; }; + OBJ_124 /* p_rsa.c */ = {isa = PBXFileReference; path = p_rsa.c; sourceTree = ""; }; + OBJ_1240 /* Interfaces.swift */ = {isa = PBXFileReference; path = Interfaces.swift; sourceTree = ""; }; + OBJ_1241 /* Linux.swift */ = {isa = PBXFileReference; path = Linux.swift; sourceTree = ""; }; + OBJ_1242 /* LinuxCPUSet.swift */ = {isa = PBXFileReference; path = LinuxCPUSet.swift; sourceTree = ""; }; + OBJ_1243 /* MarkedCircularBuffer.swift */ = {isa = PBXFileReference; path = MarkedCircularBuffer.swift; sourceTree = ""; }; + OBJ_1244 /* MulticastChannel.swift */ = {isa = PBXFileReference; path = MulticastChannel.swift; sourceTree = ""; }; + OBJ_1245 /* NIOAny.swift */ = {isa = PBXFileReference; path = NIOAny.swift; sourceTree = ""; }; + OBJ_1246 /* NonBlockingFileIO.swift */ = {isa = PBXFileReference; path = NonBlockingFileIO.swift; sourceTree = ""; }; + OBJ_1247 /* PendingDatagramWritesManager.swift */ = {isa = PBXFileReference; path = PendingDatagramWritesManager.swift; sourceTree = ""; }; + OBJ_1248 /* PendingWritesManager.swift */ = {isa = PBXFileReference; path = PendingWritesManager.swift; sourceTree = ""; }; + OBJ_1249 /* PriorityQueue.swift */ = {isa = PBXFileReference; path = PriorityQueue.swift; sourceTree = ""; }; + OBJ_125 /* p_rsa_asn1.c */ = {isa = PBXFileReference; path = p_rsa_asn1.c; sourceTree = ""; }; + OBJ_1250 /* RecvByteBufferAllocator.swift */ = {isa = PBXFileReference; path = RecvByteBufferAllocator.swift; sourceTree = ""; }; + OBJ_1251 /* Resolver.swift */ = {isa = PBXFileReference; path = Resolver.swift; sourceTree = ""; }; + OBJ_1252 /* Selectable.swift */ = {isa = PBXFileReference; path = Selectable.swift; sourceTree = ""; }; + OBJ_1253 /* Selector.swift */ = {isa = PBXFileReference; path = Selector.swift; sourceTree = ""; }; + OBJ_1254 /* ServerSocket.swift */ = {isa = PBXFileReference; path = ServerSocket.swift; sourceTree = ""; }; + OBJ_1255 /* Socket.swift */ = {isa = PBXFileReference; path = Socket.swift; sourceTree = ""; }; + OBJ_1256 /* SocketAddresses.swift */ = {isa = PBXFileReference; path = SocketAddresses.swift; sourceTree = ""; }; + OBJ_1257 /* SocketChannel.swift */ = {isa = PBXFileReference; path = SocketChannel.swift; sourceTree = ""; }; + OBJ_1258 /* SocketOptionProvider.swift */ = {isa = PBXFileReference; path = SocketOptionProvider.swift; sourceTree = ""; }; + OBJ_1259 /* System.swift */ = {isa = PBXFileReference; path = System.swift; sourceTree = ""; }; + OBJ_126 /* pbkdf.c */ = {isa = PBXFileReference; path = pbkdf.c; sourceTree = ""; }; + OBJ_1260 /* Thread.swift */ = {isa = PBXFileReference; path = Thread.swift; sourceTree = ""; }; + OBJ_1261 /* TypeAssistedChannelHandler.swift */ = {isa = PBXFileReference; path = TypeAssistedChannelHandler.swift; sourceTree = ""; }; + OBJ_1262 /* Utilities.swift */ = {isa = PBXFileReference; path = Utilities.swift; sourceTree = ""; }; + OBJ_1266 /* atomics.swift */ = {isa = PBXFileReference; path = atomics.swift; sourceTree = ""; }; + OBJ_1267 /* lock.swift */ = {isa = PBXFileReference; path = lock.swift; sourceTree = ""; }; + OBJ_127 /* print.c */ = {isa = PBXFileReference; path = print.c; sourceTree = ""; }; + OBJ_1271 /* ByteBuffer-foundation.swift */ = {isa = PBXFileReference; path = "ByteBuffer-foundation.swift"; sourceTree = ""; }; + OBJ_1273 /* ByteCollectionUtils.swift */ = {isa = PBXFileReference; path = ByteCollectionUtils.swift; sourceTree = ""; }; + OBJ_1274 /* HTTPDecoder.swift */ = {isa = PBXFileReference; path = HTTPDecoder.swift; sourceTree = ""; }; + OBJ_1275 /* HTTPEncoder.swift */ = {isa = PBXFileReference; path = HTTPEncoder.swift; sourceTree = ""; }; + OBJ_1276 /* HTTPPipelineSetup.swift */ = {isa = PBXFileReference; path = HTTPPipelineSetup.swift; sourceTree = ""; }; + OBJ_1277 /* HTTPResponseCompressor.swift */ = {isa = PBXFileReference; path = HTTPResponseCompressor.swift; sourceTree = ""; }; + OBJ_1278 /* HTTPServerPipelineHandler.swift */ = {isa = PBXFileReference; path = HTTPServerPipelineHandler.swift; sourceTree = ""; }; + OBJ_1279 /* HTTPServerProtocolErrorHandler.swift */ = {isa = PBXFileReference; path = HTTPServerProtocolErrorHandler.swift; sourceTree = ""; }; + OBJ_128 /* scrypt.c */ = {isa = PBXFileReference; path = scrypt.c; sourceTree = ""; }; + OBJ_1280 /* HTTPTypes.swift */ = {isa = PBXFileReference; path = HTTPTypes.swift; sourceTree = ""; }; + OBJ_1281 /* HTTPUpgradeHandler.swift */ = {isa = PBXFileReference; path = HTTPUpgradeHandler.swift; sourceTree = ""; }; + OBJ_1286 /* Heap.swift */ = {isa = PBXFileReference; path = Heap.swift; sourceTree = ""; }; + OBJ_1287 /* PriorityQueue.swift */ = {isa = PBXFileReference; path = PriorityQueue.swift; sourceTree = ""; }; + OBJ_1289 /* ApplicationProtocolNegotiationHandler.swift */ = {isa = PBXFileReference; path = ApplicationProtocolNegotiationHandler.swift; sourceTree = ""; }; + OBJ_129 /* sign.c */ = {isa = PBXFileReference; path = sign.c; sourceTree = ""; }; + OBJ_1290 /* SNIHandler.swift */ = {isa = PBXFileReference; path = SNIHandler.swift; sourceTree = ""; }; + OBJ_1291 /* TLSEvents.swift */ = {isa = PBXFileReference; path = TLSEvents.swift; sourceTree = ""; }; + OBJ_1294 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/swift-nio/Package.swift"; sourceTree = ""; }; + OBJ_1297 /* ArgumentConvertible.swift */ = {isa = PBXFileReference; path = ArgumentConvertible.swift; sourceTree = ""; }; + OBJ_1298 /* ArgumentDescription.swift */ = {isa = PBXFileReference; path = ArgumentDescription.swift; sourceTree = ""; }; + OBJ_1299 /* ArgumentParser.swift */ = {isa = PBXFileReference; path = ArgumentParser.swift; sourceTree = ""; }; + OBJ_13 /* a_bool.c */ = {isa = PBXFileReference; path = a_bool.c; sourceTree = ""; }; + OBJ_130 /* ex_data.c */ = {isa = PBXFileReference; path = ex_data.c; sourceTree = ""; }; + OBJ_1300 /* Command.swift */ = {isa = PBXFileReference; path = Command.swift; sourceTree = ""; }; + OBJ_1301 /* CommandRunner.swift */ = {isa = PBXFileReference; path = CommandRunner.swift; sourceTree = ""; }; + OBJ_1302 /* CommandType.swift */ = {isa = PBXFileReference; path = CommandType.swift; sourceTree = ""; }; + OBJ_1303 /* Commands.swift */ = {isa = PBXFileReference; path = Commands.swift; sourceTree = ""; }; + OBJ_1304 /* Error.swift */ = {isa = PBXFileReference; path = Error.swift; sourceTree = ""; }; + OBJ_1305 /* Group.swift */ = {isa = PBXFileReference; path = Group.swift; sourceTree = ""; }; + OBJ_1306 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = ../.build/checkouts/Commander/Package.swift; sourceTree = ""; }; + OBJ_1310 /* AnyMessageStorage.swift */ = {isa = PBXFileReference; path = AnyMessageStorage.swift; sourceTree = ""; }; + OBJ_1311 /* AnyUnpackError.swift */ = {isa = PBXFileReference; path = AnyUnpackError.swift; sourceTree = ""; }; + OBJ_1312 /* BinaryDecoder.swift */ = {isa = PBXFileReference; path = BinaryDecoder.swift; sourceTree = ""; }; + OBJ_1313 /* BinaryDecodingError.swift */ = {isa = PBXFileReference; path = BinaryDecodingError.swift; sourceTree = ""; }; + OBJ_1314 /* BinaryDecodingOptions.swift */ = {isa = PBXFileReference; path = BinaryDecodingOptions.swift; sourceTree = ""; }; + OBJ_1315 /* BinaryDelimited.swift */ = {isa = PBXFileReference; path = BinaryDelimited.swift; sourceTree = ""; }; + OBJ_1316 /* BinaryEncoder.swift */ = {isa = PBXFileReference; path = BinaryEncoder.swift; sourceTree = ""; }; + OBJ_1317 /* BinaryEncodingError.swift */ = {isa = PBXFileReference; path = BinaryEncodingError.swift; sourceTree = ""; }; + OBJ_1318 /* BinaryEncodingSizeVisitor.swift */ = {isa = PBXFileReference; path = BinaryEncodingSizeVisitor.swift; sourceTree = ""; }; + OBJ_1319 /* BinaryEncodingVisitor.swift */ = {isa = PBXFileReference; path = BinaryEncodingVisitor.swift; sourceTree = ""; }; + OBJ_1320 /* CustomJSONCodable.swift */ = {isa = PBXFileReference; path = CustomJSONCodable.swift; sourceTree = ""; }; + OBJ_1321 /* Decoder.swift */ = {isa = PBXFileReference; path = Decoder.swift; sourceTree = ""; }; + OBJ_1322 /* DoubleFormatter.swift */ = {isa = PBXFileReference; path = DoubleFormatter.swift; sourceTree = ""; }; + OBJ_1323 /* Enum.swift */ = {isa = PBXFileReference; path = Enum.swift; sourceTree = ""; }; + OBJ_1324 /* ExtensibleMessage.swift */ = {isa = PBXFileReference; path = ExtensibleMessage.swift; sourceTree = ""; }; + OBJ_1325 /* ExtensionFieldValueSet.swift */ = {isa = PBXFileReference; path = ExtensionFieldValueSet.swift; sourceTree = ""; }; + OBJ_1326 /* ExtensionFields.swift */ = {isa = PBXFileReference; path = ExtensionFields.swift; sourceTree = ""; }; + OBJ_1327 /* ExtensionMap.swift */ = {isa = PBXFileReference; path = ExtensionMap.swift; sourceTree = ""; }; + OBJ_1328 /* FieldTag.swift */ = {isa = PBXFileReference; path = FieldTag.swift; sourceTree = ""; }; + OBJ_1329 /* FieldTypes.swift */ = {isa = PBXFileReference; path = FieldTypes.swift; sourceTree = ""; }; + OBJ_133 /* aes.c */ = {isa = PBXFileReference; path = aes.c; sourceTree = ""; }; + OBJ_1330 /* Google_Protobuf_Any+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Any+Extensions.swift"; sourceTree = ""; }; + OBJ_1331 /* Google_Protobuf_Any+Registry.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Any+Registry.swift"; sourceTree = ""; }; + OBJ_1332 /* Google_Protobuf_Duration+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Duration+Extensions.swift"; sourceTree = ""; }; + OBJ_1333 /* Google_Protobuf_FieldMask+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_FieldMask+Extensions.swift"; sourceTree = ""; }; + OBJ_1334 /* Google_Protobuf_ListValue+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_ListValue+Extensions.swift"; sourceTree = ""; }; + OBJ_1335 /* Google_Protobuf_Struct+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Struct+Extensions.swift"; sourceTree = ""; }; + OBJ_1336 /* Google_Protobuf_Timestamp+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Timestamp+Extensions.swift"; sourceTree = ""; }; + OBJ_1337 /* Google_Protobuf_Value+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Value+Extensions.swift"; sourceTree = ""; }; + OBJ_1338 /* Google_Protobuf_Wrappers+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Wrappers+Extensions.swift"; sourceTree = ""; }; + OBJ_1339 /* HashVisitor.swift */ = {isa = PBXFileReference; path = HashVisitor.swift; sourceTree = ""; }; + OBJ_134 /* key_wrap.c */ = {isa = PBXFileReference; path = key_wrap.c; sourceTree = ""; }; + OBJ_1340 /* Internal.swift */ = {isa = PBXFileReference; path = Internal.swift; sourceTree = ""; }; + OBJ_1341 /* JSONDecoder.swift */ = {isa = PBXFileReference; path = JSONDecoder.swift; sourceTree = ""; }; + OBJ_1342 /* JSONDecodingError.swift */ = {isa = PBXFileReference; path = JSONDecodingError.swift; sourceTree = ""; }; + OBJ_1343 /* JSONDecodingOptions.swift */ = {isa = PBXFileReference; path = JSONDecodingOptions.swift; sourceTree = ""; }; + OBJ_1344 /* JSONEncoder.swift */ = {isa = PBXFileReference; path = JSONEncoder.swift; sourceTree = ""; }; + OBJ_1345 /* JSONEncodingError.swift */ = {isa = PBXFileReference; path = JSONEncodingError.swift; sourceTree = ""; }; + OBJ_1346 /* JSONEncodingOptions.swift */ = {isa = PBXFileReference; path = JSONEncodingOptions.swift; sourceTree = ""; }; + OBJ_1347 /* JSONEncodingVisitor.swift */ = {isa = PBXFileReference; path = JSONEncodingVisitor.swift; sourceTree = ""; }; + OBJ_1348 /* JSONMapEncodingVisitor.swift */ = {isa = PBXFileReference; path = JSONMapEncodingVisitor.swift; sourceTree = ""; }; + OBJ_1349 /* JSONScanner.swift */ = {isa = PBXFileReference; path = JSONScanner.swift; sourceTree = ""; }; + OBJ_135 /* mode_wrappers.c */ = {isa = PBXFileReference; path = mode_wrappers.c; sourceTree = ""; }; + OBJ_1350 /* MathUtils.swift */ = {isa = PBXFileReference; path = MathUtils.swift; sourceTree = ""; }; + OBJ_1351 /* Message+AnyAdditions.swift */ = {isa = PBXFileReference; path = "Message+AnyAdditions.swift"; sourceTree = ""; }; + OBJ_1352 /* Message+BinaryAdditions.swift */ = {isa = PBXFileReference; path = "Message+BinaryAdditions.swift"; sourceTree = ""; }; + OBJ_1353 /* Message+JSONAdditions.swift */ = {isa = PBXFileReference; path = "Message+JSONAdditions.swift"; sourceTree = ""; }; + OBJ_1354 /* Message+JSONArrayAdditions.swift */ = {isa = PBXFileReference; path = "Message+JSONArrayAdditions.swift"; sourceTree = ""; }; + OBJ_1355 /* Message+TextFormatAdditions.swift */ = {isa = PBXFileReference; path = "Message+TextFormatAdditions.swift"; sourceTree = ""; }; + OBJ_1356 /* Message.swift */ = {isa = PBXFileReference; path = Message.swift; sourceTree = ""; }; + OBJ_1357 /* MessageExtension.swift */ = {isa = PBXFileReference; path = MessageExtension.swift; sourceTree = ""; }; + OBJ_1358 /* NameMap.swift */ = {isa = PBXFileReference; path = NameMap.swift; sourceTree = ""; }; + OBJ_1359 /* ProtoNameProviding.swift */ = {isa = PBXFileReference; path = ProtoNameProviding.swift; sourceTree = ""; }; + OBJ_1360 /* ProtobufAPIVersionCheck.swift */ = {isa = PBXFileReference; path = ProtobufAPIVersionCheck.swift; sourceTree = ""; }; + OBJ_1361 /* ProtobufMap.swift */ = {isa = PBXFileReference; path = ProtobufMap.swift; sourceTree = ""; }; + OBJ_1362 /* SelectiveVisitor.swift */ = {isa = PBXFileReference; path = SelectiveVisitor.swift; sourceTree = ""; }; + OBJ_1363 /* SimpleExtensionMap.swift */ = {isa = PBXFileReference; path = SimpleExtensionMap.swift; sourceTree = ""; }; + OBJ_1364 /* StringUtils.swift */ = {isa = PBXFileReference; path = StringUtils.swift; sourceTree = ""; }; + OBJ_1365 /* TextFormatDecoder.swift */ = {isa = PBXFileReference; path = TextFormatDecoder.swift; sourceTree = ""; }; + OBJ_1366 /* TextFormatDecodingError.swift */ = {isa = PBXFileReference; path = TextFormatDecodingError.swift; sourceTree = ""; }; + OBJ_1367 /* TextFormatEncoder.swift */ = {isa = PBXFileReference; path = TextFormatEncoder.swift; sourceTree = ""; }; + OBJ_1368 /* TextFormatEncodingVisitor.swift */ = {isa = PBXFileReference; path = TextFormatEncodingVisitor.swift; sourceTree = ""; }; + OBJ_1369 /* TextFormatScanner.swift */ = {isa = PBXFileReference; path = TextFormatScanner.swift; sourceTree = ""; }; + OBJ_137 /* add.c */ = {isa = PBXFileReference; path = add.c; sourceTree = ""; }; + OBJ_1370 /* TimeUtils.swift */ = {isa = PBXFileReference; path = TimeUtils.swift; sourceTree = ""; }; + OBJ_1371 /* UnknownStorage.swift */ = {isa = PBXFileReference; path = UnknownStorage.swift; sourceTree = ""; }; + OBJ_1372 /* Varint.swift */ = {isa = PBXFileReference; path = Varint.swift; sourceTree = ""; }; + OBJ_1373 /* Version.swift */ = {isa = PBXFileReference; path = Version.swift; sourceTree = ""; }; + OBJ_1374 /* Visitor.swift */ = {isa = PBXFileReference; path = Visitor.swift; sourceTree = ""; }; + OBJ_1375 /* WireFormat.swift */ = {isa = PBXFileReference; path = WireFormat.swift; sourceTree = ""; }; + OBJ_1376 /* ZigZag.swift */ = {isa = PBXFileReference; path = ZigZag.swift; sourceTree = ""; }; + OBJ_1377 /* any.pb.swift */ = {isa = PBXFileReference; path = any.pb.swift; sourceTree = ""; }; + OBJ_1378 /* api.pb.swift */ = {isa = PBXFileReference; path = api.pb.swift; sourceTree = ""; }; + OBJ_1379 /* duration.pb.swift */ = {isa = PBXFileReference; path = duration.pb.swift; sourceTree = ""; }; + OBJ_138 /* bn.c */ = {isa = PBXFileReference; path = bn.c; sourceTree = ""; }; + OBJ_1380 /* empty.pb.swift */ = {isa = PBXFileReference; path = empty.pb.swift; sourceTree = ""; }; + OBJ_1381 /* field_mask.pb.swift */ = {isa = PBXFileReference; path = field_mask.pb.swift; sourceTree = ""; }; + OBJ_1382 /* source_context.pb.swift */ = {isa = PBXFileReference; path = source_context.pb.swift; sourceTree = ""; }; + OBJ_1383 /* struct.pb.swift */ = {isa = PBXFileReference; path = struct.pb.swift; sourceTree = ""; }; + OBJ_1384 /* timestamp.pb.swift */ = {isa = PBXFileReference; path = timestamp.pb.swift; sourceTree = ""; }; + OBJ_1385 /* type.pb.swift */ = {isa = PBXFileReference; path = type.pb.swift; sourceTree = ""; }; + OBJ_1386 /* wrappers.pb.swift */ = {isa = PBXFileReference; path = wrappers.pb.swift; sourceTree = ""; }; + OBJ_1388 /* Array+Extensions.swift */ = {isa = PBXFileReference; path = "Array+Extensions.swift"; sourceTree = ""; }; + OBJ_1389 /* CodePrinter.swift */ = {isa = PBXFileReference; path = CodePrinter.swift; sourceTree = ""; }; + OBJ_139 /* bytes.c */ = {isa = PBXFileReference; path = bytes.c; sourceTree = ""; }; + OBJ_1390 /* Descriptor+Extensions.swift */ = {isa = PBXFileReference; path = "Descriptor+Extensions.swift"; sourceTree = ""; }; + OBJ_1391 /* Descriptor.swift */ = {isa = PBXFileReference; path = Descriptor.swift; sourceTree = ""; }; + OBJ_1392 /* FieldNumbers.swift */ = {isa = PBXFileReference; path = FieldNumbers.swift; sourceTree = ""; }; + OBJ_1393 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift"; sourceTree = ""; }; + OBJ_1394 /* Google_Protobuf_SourceCodeInfo+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_SourceCodeInfo+Extensions.swift"; sourceTree = ""; }; + OBJ_1395 /* NamingUtils.swift */ = {isa = PBXFileReference; path = NamingUtils.swift; sourceTree = ""; }; + OBJ_1396 /* ProtoFileToModuleMappings.swift */ = {isa = PBXFileReference; path = ProtoFileToModuleMappings.swift; sourceTree = ""; }; + OBJ_1397 /* ProvidesLocationPath.swift */ = {isa = PBXFileReference; path = ProvidesLocationPath.swift; sourceTree = ""; }; + OBJ_1398 /* ProvidesSourceCodeLocation.swift */ = {isa = PBXFileReference; path = ProvidesSourceCodeLocation.swift; sourceTree = ""; }; + OBJ_1399 /* SwiftLanguage.swift */ = {isa = PBXFileReference; path = SwiftLanguage.swift; sourceTree = ""; }; + OBJ_14 /* a_d2i_fp.c */ = {isa = PBXFileReference; path = a_d2i_fp.c; sourceTree = ""; }; + OBJ_140 /* cmp.c */ = {isa = PBXFileReference; path = cmp.c; sourceTree = ""; }; + OBJ_1400 /* SwiftProtobufInfo.swift */ = {isa = PBXFileReference; path = SwiftProtobufInfo.swift; sourceTree = ""; }; + OBJ_1401 /* SwiftProtobufNamer.swift */ = {isa = PBXFileReference; path = SwiftProtobufNamer.swift; sourceTree = ""; }; + OBJ_1402 /* UnicodeScalar+Extensions.swift */ = {isa = PBXFileReference; path = "UnicodeScalar+Extensions.swift"; sourceTree = ""; }; + OBJ_1403 /* descriptor.pb.swift */ = {isa = PBXFileReference; path = descriptor.pb.swift; sourceTree = ""; }; + OBJ_1404 /* plugin.pb.swift */ = {isa = PBXFileReference; path = plugin.pb.swift; sourceTree = ""; }; + OBJ_1405 /* swift_protobuf_module_mappings.pb.swift */ = {isa = PBXFileReference; path = swift_protobuf_module_mappings.pb.swift; sourceTree = ""; }; + OBJ_1407 /* CommandLine+Extensions.swift */ = {isa = PBXFileReference; path = "CommandLine+Extensions.swift"; sourceTree = ""; }; + OBJ_1408 /* Descriptor+Extensions.swift */ = {isa = PBXFileReference; path = "Descriptor+Extensions.swift"; sourceTree = ""; }; + OBJ_1409 /* EnumGenerator.swift */ = {isa = PBXFileReference; path = EnumGenerator.swift; sourceTree = ""; }; + OBJ_141 /* ctx.c */ = {isa = PBXFileReference; path = ctx.c; sourceTree = ""; }; + OBJ_1410 /* ExtensionSetGenerator.swift */ = {isa = PBXFileReference; path = ExtensionSetGenerator.swift; sourceTree = ""; }; + OBJ_1411 /* FieldGenerator.swift */ = {isa = PBXFileReference; path = FieldGenerator.swift; sourceTree = ""; }; + OBJ_1412 /* FileGenerator.swift */ = {isa = PBXFileReference; path = FileGenerator.swift; sourceTree = ""; }; + OBJ_1413 /* FileIo.swift */ = {isa = PBXFileReference; path = FileIo.swift; sourceTree = ""; }; + OBJ_1414 /* GenerationError.swift */ = {isa = PBXFileReference; path = GenerationError.swift; sourceTree = ""; }; + OBJ_1415 /* GeneratorOptions.swift */ = {isa = PBXFileReference; path = GeneratorOptions.swift; sourceTree = ""; }; + OBJ_1416 /* Google_Protobuf_DescriptorProto+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_DescriptorProto+Extensions.swift"; sourceTree = ""; }; + OBJ_1417 /* Google_Protobuf_FileDescriptorProto+Extensions.swift */ = {isa = PBXFileReference; path = "Google_Protobuf_FileDescriptorProto+Extensions.swift"; sourceTree = ""; }; + OBJ_1418 /* MessageFieldGenerator.swift */ = {isa = PBXFileReference; path = MessageFieldGenerator.swift; sourceTree = ""; }; + OBJ_1419 /* MessageGenerator.swift */ = {isa = PBXFileReference; path = MessageGenerator.swift; sourceTree = ""; }; + OBJ_142 /* div.c */ = {isa = PBXFileReference; path = div.c; sourceTree = ""; }; + OBJ_1420 /* MessageStorageClassGenerator.swift */ = {isa = PBXFileReference; path = MessageStorageClassGenerator.swift; sourceTree = ""; }; + OBJ_1421 /* OneofGenerator.swift */ = {isa = PBXFileReference; path = OneofGenerator.swift; sourceTree = ""; }; + OBJ_1422 /* StringUtils.swift */ = {isa = PBXFileReference; path = StringUtils.swift; sourceTree = ""; }; + OBJ_1423 /* Version.swift */ = {isa = PBXFileReference; path = Version.swift; sourceTree = ""; }; + OBJ_1424 /* main.swift */ = {isa = PBXFileReference; path = main.swift; sourceTree = ""; }; + OBJ_1425 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = "../.build/checkouts/swift-protobuf/Package.swift"; sourceTree = ""; }; + OBJ_143 /* exponentiation.c */ = {isa = PBXFileReference; path = exponentiation.c; sourceTree = ""; }; + OBJ_144 /* gcd.c */ = {isa = PBXFileReference; path = gcd.c; sourceTree = ""; }; + OBJ_145 /* generic.c */ = {isa = PBXFileReference; path = generic.c; sourceTree = ""; }; + OBJ_1456 /* Docker */ = {isa = PBXFileReference; path = Docker; sourceTree = SOURCE_ROOT; }; + OBJ_1457 /* Examples */ = {isa = PBXFileReference; path = Examples; sourceTree = SOURCE_ROOT; }; + OBJ_1458 /* scripts */ = {isa = PBXFileReference; path = scripts; sourceTree = SOURCE_ROOT; }; + OBJ_1459 /* Assets */ = {isa = PBXFileReference; path = Assets; sourceTree = SOURCE_ROOT; }; + OBJ_146 /* jacobi.c */ = {isa = PBXFileReference; path = jacobi.c; sourceTree = ""; }; + OBJ_1460 /* OVERVIEW.md */ = {isa = PBXFileReference; path = OVERVIEW.md; sourceTree = ""; }; + OBJ_1461 /* fix-project-settings.rb */ = {isa = PBXFileReference; path = "fix-project-settings.rb"; sourceTree = ""; }; + OBJ_1462 /* LICENSE */ = {isa = PBXFileReference; path = LICENSE; sourceTree = ""; }; + OBJ_1463 /* PATENTS */ = {isa = PBXFileReference; path = PATENTS; sourceTree = ""; }; + OBJ_1464 /* AUTHORS */ = {isa = PBXFileReference; path = AUTHORS; sourceTree = ""; }; + OBJ_1465 /* Makefile */ = {isa = PBXFileReference; path = Makefile; sourceTree = ""; }; + OBJ_1466 /* patch-carthage-project.rb */ = {isa = PBXFileReference; path = "patch-carthage-project.rb"; sourceTree = ""; }; + OBJ_1467 /* LINUX.md */ = {isa = PBXFileReference; path = LINUX.md; sourceTree = ""; }; + OBJ_1468 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_1469 /* fix-carthage-paths.rb */ = {isa = PBXFileReference; path = "fix-carthage-paths.rb"; sourceTree = ""; }; + OBJ_147 /* montgomery.c */ = {isa = PBXFileReference; path = montgomery.c; sourceTree = ""; }; + OBJ_1470 /* CONTRIBUTING.md */ = {isa = PBXFileReference; path = CONTRIBUTING.md; sourceTree = ""; }; + OBJ_1471 /* DOCKER.md */ = {isa = PBXFileReference; path = DOCKER.md; sourceTree = ""; }; + OBJ_1472 /* SwiftGRPC.podspec */ = {isa = PBXFileReference; path = SwiftGRPC.podspec; sourceTree = ""; }; + OBJ_148 /* montgomery_inv.c */ = {isa = PBXFileReference; path = montgomery_inv.c; sourceTree = ""; }; + OBJ_149 /* mul.c */ = {isa = PBXFileReference; path = mul.c; sourceTree = ""; }; + OBJ_15 /* a_dup.c */ = {isa = PBXFileReference; path = a_dup.c; sourceTree = ""; }; + OBJ_150 /* prime.c */ = {isa = PBXFileReference; path = prime.c; sourceTree = ""; }; + OBJ_151 /* random.c */ = {isa = PBXFileReference; path = random.c; sourceTree = ""; }; + OBJ_152 /* rsaz_exp.c */ = {isa = PBXFileReference; path = rsaz_exp.c; sourceTree = ""; }; + OBJ_153 /* shift.c */ = {isa = PBXFileReference; path = shift.c; sourceTree = ""; }; + OBJ_154 /* sqrt.c */ = {isa = PBXFileReference; path = sqrt.c; sourceTree = ""; }; + OBJ_156 /* aead.c */ = {isa = PBXFileReference; path = aead.c; sourceTree = ""; }; + OBJ_157 /* cipher.c */ = {isa = PBXFileReference; path = cipher.c; sourceTree = ""; }; + OBJ_158 /* e_aes.c */ = {isa = PBXFileReference; path = e_aes.c; sourceTree = ""; }; + OBJ_159 /* e_des.c */ = {isa = PBXFileReference; path = e_des.c; sourceTree = ""; }; + OBJ_16 /* a_enum.c */ = {isa = PBXFileReference; path = a_enum.c; sourceTree = ""; }; + OBJ_161 /* des.c */ = {isa = PBXFileReference; path = des.c; sourceTree = ""; }; + OBJ_163 /* digest.c */ = {isa = PBXFileReference; path = digest.c; sourceTree = ""; }; + OBJ_164 /* digests.c */ = {isa = PBXFileReference; path = digests.c; sourceTree = ""; }; + OBJ_166 /* ec.c */ = {isa = PBXFileReference; path = ec.c; sourceTree = ""; }; + OBJ_167 /* ec_key.c */ = {isa = PBXFileReference; path = ec_key.c; sourceTree = ""; }; + OBJ_168 /* ec_montgomery.c */ = {isa = PBXFileReference; path = ec_montgomery.c; sourceTree = ""; }; + OBJ_169 /* oct.c */ = {isa = PBXFileReference; path = oct.c; sourceTree = ""; }; + OBJ_17 /* a_gentm.c */ = {isa = PBXFileReference; path = a_gentm.c; sourceTree = ""; }; + OBJ_170 /* p224-64.c */ = {isa = PBXFileReference; path = "p224-64.c"; sourceTree = ""; }; + OBJ_171 /* p256-x86_64.c */ = {isa = PBXFileReference; path = "p256-x86_64.c"; sourceTree = ""; }; + OBJ_172 /* simple.c */ = {isa = PBXFileReference; path = simple.c; sourceTree = ""; }; + OBJ_173 /* util.c */ = {isa = PBXFileReference; path = util.c; sourceTree = ""; }; + OBJ_174 /* wnaf.c */ = {isa = PBXFileReference; path = wnaf.c; sourceTree = ""; }; + OBJ_176 /* ecdsa.c */ = {isa = PBXFileReference; path = ecdsa.c; sourceTree = ""; }; + OBJ_178 /* hmac.c */ = {isa = PBXFileReference; path = hmac.c; sourceTree = ""; }; + OBJ_179 /* is_fips.c */ = {isa = PBXFileReference; path = is_fips.c; sourceTree = ""; }; + OBJ_18 /* a_i2d_fp.c */ = {isa = PBXFileReference; path = a_i2d_fp.c; sourceTree = ""; }; + OBJ_181 /* md4.c */ = {isa = PBXFileReference; path = md4.c; sourceTree = ""; }; + OBJ_183 /* md5.c */ = {isa = PBXFileReference; path = md5.c; sourceTree = ""; }; + OBJ_185 /* cbc.c */ = {isa = PBXFileReference; path = cbc.c; sourceTree = ""; }; + OBJ_186 /* ccm.c */ = {isa = PBXFileReference; path = ccm.c; sourceTree = ""; }; + OBJ_187 /* cfb.c */ = {isa = PBXFileReference; path = cfb.c; sourceTree = ""; }; + OBJ_188 /* ctr.c */ = {isa = PBXFileReference; path = ctr.c; sourceTree = ""; }; + OBJ_189 /* gcm.c */ = {isa = PBXFileReference; path = gcm.c; sourceTree = ""; }; + OBJ_19 /* a_int.c */ = {isa = PBXFileReference; path = a_int.c; sourceTree = ""; }; + OBJ_190 /* ofb.c */ = {isa = PBXFileReference; path = ofb.c; sourceTree = ""; }; + OBJ_191 /* polyval.c */ = {isa = PBXFileReference; path = polyval.c; sourceTree = ""; }; + OBJ_193 /* ctrdrbg.c */ = {isa = PBXFileReference; path = ctrdrbg.c; sourceTree = ""; }; + OBJ_194 /* rand.c */ = {isa = PBXFileReference; path = rand.c; sourceTree = ""; }; + OBJ_195 /* urandom.c */ = {isa = PBXFileReference; path = urandom.c; sourceTree = ""; }; + OBJ_197 /* blinding.c */ = {isa = PBXFileReference; path = blinding.c; sourceTree = ""; }; + OBJ_198 /* padding.c */ = {isa = PBXFileReference; path = padding.c; sourceTree = ""; }; + OBJ_199 /* rsa.c */ = {isa = PBXFileReference; path = rsa.c; sourceTree = ""; }; + OBJ_20 /* a_mbstr.c */ = {isa = PBXFileReference; path = a_mbstr.c; sourceTree = ""; }; + OBJ_200 /* rsa_impl.c */ = {isa = PBXFileReference; path = rsa_impl.c; sourceTree = ""; }; + OBJ_202 /* self_check.c */ = {isa = PBXFileReference; path = self_check.c; sourceTree = ""; }; + OBJ_204 /* sha1-altivec.c */ = {isa = PBXFileReference; path = "sha1-altivec.c"; sourceTree = ""; }; + OBJ_205 /* sha1.c */ = {isa = PBXFileReference; path = sha1.c; sourceTree = ""; }; + OBJ_206 /* sha256.c */ = {isa = PBXFileReference; path = sha256.c; sourceTree = ""; }; + OBJ_207 /* sha512.c */ = {isa = PBXFileReference; path = sha512.c; sourceTree = ""; }; + OBJ_209 /* kdf.c */ = {isa = PBXFileReference; path = kdf.c; sourceTree = ""; }; + OBJ_21 /* a_object.c */ = {isa = PBXFileReference; path = a_object.c; sourceTree = ""; }; + OBJ_211 /* hkdf.c */ = {isa = PBXFileReference; path = hkdf.c; sourceTree = ""; }; + OBJ_213 /* lhash.c */ = {isa = PBXFileReference; path = lhash.c; sourceTree = ""; }; + OBJ_214 /* mem.c */ = {isa = PBXFileReference; path = mem.c; sourceTree = ""; }; + OBJ_216 /* obj.c */ = {isa = PBXFileReference; path = obj.c; sourceTree = ""; }; + OBJ_217 /* obj_xref.c */ = {isa = PBXFileReference; path = obj_xref.c; sourceTree = ""; }; + OBJ_219 /* pem_all.c */ = {isa = PBXFileReference; path = pem_all.c; sourceTree = ""; }; + OBJ_22 /* a_octet.c */ = {isa = PBXFileReference; path = a_octet.c; sourceTree = ""; }; + OBJ_220 /* pem_info.c */ = {isa = PBXFileReference; path = pem_info.c; sourceTree = ""; }; + OBJ_221 /* pem_lib.c */ = {isa = PBXFileReference; path = pem_lib.c; sourceTree = ""; }; + OBJ_222 /* pem_oth.c */ = {isa = PBXFileReference; path = pem_oth.c; sourceTree = ""; }; + OBJ_223 /* pem_pk8.c */ = {isa = PBXFileReference; path = pem_pk8.c; sourceTree = ""; }; + OBJ_224 /* pem_pkey.c */ = {isa = PBXFileReference; path = pem_pkey.c; sourceTree = ""; }; + OBJ_225 /* pem_x509.c */ = {isa = PBXFileReference; path = pem_x509.c; sourceTree = ""; }; + OBJ_226 /* pem_xaux.c */ = {isa = PBXFileReference; path = pem_xaux.c; sourceTree = ""; }; + OBJ_228 /* pkcs7.c */ = {isa = PBXFileReference; path = pkcs7.c; sourceTree = ""; }; + OBJ_229 /* pkcs7_x509.c */ = {isa = PBXFileReference; path = pkcs7_x509.c; sourceTree = ""; }; + OBJ_23 /* a_print.c */ = {isa = PBXFileReference; path = a_print.c; sourceTree = ""; }; + OBJ_231 /* p5_pbev2.c */ = {isa = PBXFileReference; path = p5_pbev2.c; sourceTree = ""; }; + OBJ_232 /* pkcs8.c */ = {isa = PBXFileReference; path = pkcs8.c; sourceTree = ""; }; + OBJ_233 /* pkcs8_x509.c */ = {isa = PBXFileReference; path = pkcs8_x509.c; sourceTree = ""; }; + OBJ_235 /* poly1305.c */ = {isa = PBXFileReference; path = poly1305.c; sourceTree = ""; }; + OBJ_236 /* poly1305_arm.c */ = {isa = PBXFileReference; path = poly1305_arm.c; sourceTree = ""; }; + OBJ_237 /* poly1305_vec.c */ = {isa = PBXFileReference; path = poly1305_vec.c; sourceTree = ""; }; + OBJ_239 /* pool.c */ = {isa = PBXFileReference; path = pool.c; sourceTree = ""; }; + OBJ_24 /* a_strnid.c */ = {isa = PBXFileReference; path = a_strnid.c; sourceTree = ""; }; + OBJ_241 /* deterministic.c */ = {isa = PBXFileReference; path = deterministic.c; sourceTree = ""; }; + OBJ_242 /* forkunsafe.c */ = {isa = PBXFileReference; path = forkunsafe.c; sourceTree = ""; }; + OBJ_243 /* fuchsia.c */ = {isa = PBXFileReference; path = fuchsia.c; sourceTree = ""; }; + OBJ_244 /* rand_extra.c */ = {isa = PBXFileReference; path = rand_extra.c; sourceTree = ""; }; + OBJ_245 /* windows.c */ = {isa = PBXFileReference; path = windows.c; sourceTree = ""; }; + OBJ_247 /* rc4.c */ = {isa = PBXFileReference; path = rc4.c; sourceTree = ""; }; + OBJ_248 /* refcount_c11.c */ = {isa = PBXFileReference; path = refcount_c11.c; sourceTree = ""; }; + OBJ_249 /* refcount_lock.c */ = {isa = PBXFileReference; path = refcount_lock.c; sourceTree = ""; }; + OBJ_25 /* a_time.c */ = {isa = PBXFileReference; path = a_time.c; sourceTree = ""; }; + OBJ_251 /* rsa_asn1.c */ = {isa = PBXFileReference; path = rsa_asn1.c; sourceTree = ""; }; + OBJ_253 /* stack.c */ = {isa = PBXFileReference; path = stack.c; sourceTree = ""; }; + OBJ_254 /* thread.c */ = {isa = PBXFileReference; path = thread.c; sourceTree = ""; }; + OBJ_255 /* thread_none.c */ = {isa = PBXFileReference; path = thread_none.c; sourceTree = ""; }; + OBJ_256 /* thread_pthread.c */ = {isa = PBXFileReference; path = thread_pthread.c; sourceTree = ""; }; + OBJ_257 /* thread_win.c */ = {isa = PBXFileReference; path = thread_win.c; sourceTree = ""; }; + OBJ_259 /* a_digest.c */ = {isa = PBXFileReference; path = a_digest.c; sourceTree = ""; }; + OBJ_26 /* a_type.c */ = {isa = PBXFileReference; path = a_type.c; sourceTree = ""; }; + OBJ_260 /* a_sign.c */ = {isa = PBXFileReference; path = a_sign.c; sourceTree = ""; }; + OBJ_261 /* a_strex.c */ = {isa = PBXFileReference; path = a_strex.c; sourceTree = ""; }; + OBJ_262 /* a_verify.c */ = {isa = PBXFileReference; path = a_verify.c; sourceTree = ""; }; + OBJ_263 /* algorithm.c */ = {isa = PBXFileReference; path = algorithm.c; sourceTree = ""; }; + OBJ_264 /* asn1_gen.c */ = {isa = PBXFileReference; path = asn1_gen.c; sourceTree = ""; }; + OBJ_265 /* by_dir.c */ = {isa = PBXFileReference; path = by_dir.c; sourceTree = ""; }; + OBJ_266 /* by_file.c */ = {isa = PBXFileReference; path = by_file.c; sourceTree = ""; }; + OBJ_267 /* i2d_pr.c */ = {isa = PBXFileReference; path = i2d_pr.c; sourceTree = ""; }; + OBJ_268 /* rsa_pss.c */ = {isa = PBXFileReference; path = rsa_pss.c; sourceTree = ""; }; + OBJ_269 /* t_crl.c */ = {isa = PBXFileReference; path = t_crl.c; sourceTree = ""; }; + OBJ_27 /* a_utctm.c */ = {isa = PBXFileReference; path = a_utctm.c; sourceTree = ""; }; + OBJ_270 /* t_req.c */ = {isa = PBXFileReference; path = t_req.c; sourceTree = ""; }; + OBJ_271 /* t_x509.c */ = {isa = PBXFileReference; path = t_x509.c; sourceTree = ""; }; + OBJ_272 /* t_x509a.c */ = {isa = PBXFileReference; path = t_x509a.c; sourceTree = ""; }; + OBJ_273 /* x509.c */ = {isa = PBXFileReference; path = x509.c; sourceTree = ""; }; + OBJ_274 /* x509_att.c */ = {isa = PBXFileReference; path = x509_att.c; sourceTree = ""; }; + OBJ_275 /* x509_cmp.c */ = {isa = PBXFileReference; path = x509_cmp.c; sourceTree = ""; }; + OBJ_276 /* x509_d2.c */ = {isa = PBXFileReference; path = x509_d2.c; sourceTree = ""; }; + OBJ_277 /* x509_def.c */ = {isa = PBXFileReference; path = x509_def.c; sourceTree = ""; }; + OBJ_278 /* x509_ext.c */ = {isa = PBXFileReference; path = x509_ext.c; sourceTree = ""; }; + OBJ_279 /* x509_lu.c */ = {isa = PBXFileReference; path = x509_lu.c; sourceTree = ""; }; + OBJ_28 /* a_utf8.c */ = {isa = PBXFileReference; path = a_utf8.c; sourceTree = ""; }; + OBJ_280 /* x509_obj.c */ = {isa = PBXFileReference; path = x509_obj.c; sourceTree = ""; }; + OBJ_281 /* x509_r2x.c */ = {isa = PBXFileReference; path = x509_r2x.c; sourceTree = ""; }; + OBJ_282 /* x509_req.c */ = {isa = PBXFileReference; path = x509_req.c; sourceTree = ""; }; + OBJ_283 /* x509_set.c */ = {isa = PBXFileReference; path = x509_set.c; sourceTree = ""; }; + OBJ_284 /* x509_trs.c */ = {isa = PBXFileReference; path = x509_trs.c; sourceTree = ""; }; + OBJ_285 /* x509_txt.c */ = {isa = PBXFileReference; path = x509_txt.c; sourceTree = ""; }; + OBJ_286 /* x509_v3.c */ = {isa = PBXFileReference; path = x509_v3.c; sourceTree = ""; }; + OBJ_287 /* x509_vfy.c */ = {isa = PBXFileReference; path = x509_vfy.c; sourceTree = ""; }; + OBJ_288 /* x509_vpm.c */ = {isa = PBXFileReference; path = x509_vpm.c; sourceTree = ""; }; + OBJ_289 /* x509cset.c */ = {isa = PBXFileReference; path = x509cset.c; sourceTree = ""; }; + OBJ_29 /* asn1_lib.c */ = {isa = PBXFileReference; path = asn1_lib.c; sourceTree = ""; }; + OBJ_290 /* x509name.c */ = {isa = PBXFileReference; path = x509name.c; sourceTree = ""; }; + OBJ_291 /* x509rset.c */ = {isa = PBXFileReference; path = x509rset.c; sourceTree = ""; }; + OBJ_292 /* x509spki.c */ = {isa = PBXFileReference; path = x509spki.c; sourceTree = ""; }; + OBJ_293 /* x_algor.c */ = {isa = PBXFileReference; path = x_algor.c; sourceTree = ""; }; + OBJ_294 /* x_all.c */ = {isa = PBXFileReference; path = x_all.c; sourceTree = ""; }; + OBJ_295 /* x_attrib.c */ = {isa = PBXFileReference; path = x_attrib.c; sourceTree = ""; }; + OBJ_296 /* x_crl.c */ = {isa = PBXFileReference; path = x_crl.c; sourceTree = ""; }; + OBJ_297 /* x_exten.c */ = {isa = PBXFileReference; path = x_exten.c; sourceTree = ""; }; + OBJ_298 /* x_info.c */ = {isa = PBXFileReference; path = x_info.c; sourceTree = ""; }; + OBJ_299 /* x_name.c */ = {isa = PBXFileReference; path = x_name.c; sourceTree = ""; }; + OBJ_30 /* asn1_par.c */ = {isa = PBXFileReference; path = asn1_par.c; sourceTree = ""; }; + OBJ_300 /* x_pkey.c */ = {isa = PBXFileReference; path = x_pkey.c; sourceTree = ""; }; + OBJ_301 /* x_pubkey.c */ = {isa = PBXFileReference; path = x_pubkey.c; sourceTree = ""; }; + OBJ_302 /* x_req.c */ = {isa = PBXFileReference; path = x_req.c; sourceTree = ""; }; + OBJ_303 /* x_sig.c */ = {isa = PBXFileReference; path = x_sig.c; sourceTree = ""; }; + OBJ_304 /* x_spki.c */ = {isa = PBXFileReference; path = x_spki.c; sourceTree = ""; }; + OBJ_305 /* x_val.c */ = {isa = PBXFileReference; path = x_val.c; sourceTree = ""; }; + OBJ_306 /* x_x509.c */ = {isa = PBXFileReference; path = x_x509.c; sourceTree = ""; }; + OBJ_307 /* x_x509a.c */ = {isa = PBXFileReference; path = x_x509a.c; sourceTree = ""; }; + OBJ_309 /* pcy_cache.c */ = {isa = PBXFileReference; path = pcy_cache.c; sourceTree = ""; }; + OBJ_31 /* asn_pack.c */ = {isa = PBXFileReference; path = asn_pack.c; sourceTree = ""; }; + OBJ_310 /* pcy_data.c */ = {isa = PBXFileReference; path = pcy_data.c; sourceTree = ""; }; + OBJ_311 /* pcy_lib.c */ = {isa = PBXFileReference; path = pcy_lib.c; sourceTree = ""; }; + OBJ_312 /* pcy_map.c */ = {isa = PBXFileReference; path = pcy_map.c; sourceTree = ""; }; + OBJ_313 /* pcy_node.c */ = {isa = PBXFileReference; path = pcy_node.c; sourceTree = ""; }; + OBJ_314 /* pcy_tree.c */ = {isa = PBXFileReference; path = pcy_tree.c; sourceTree = ""; }; + OBJ_315 /* v3_akey.c */ = {isa = PBXFileReference; path = v3_akey.c; sourceTree = ""; }; + OBJ_316 /* v3_akeya.c */ = {isa = PBXFileReference; path = v3_akeya.c; sourceTree = ""; }; + OBJ_317 /* v3_alt.c */ = {isa = PBXFileReference; path = v3_alt.c; sourceTree = ""; }; + OBJ_318 /* v3_bcons.c */ = {isa = PBXFileReference; path = v3_bcons.c; sourceTree = ""; }; + OBJ_319 /* v3_bitst.c */ = {isa = PBXFileReference; path = v3_bitst.c; sourceTree = ""; }; + OBJ_32 /* f_enum.c */ = {isa = PBXFileReference; path = f_enum.c; sourceTree = ""; }; + OBJ_320 /* v3_conf.c */ = {isa = PBXFileReference; path = v3_conf.c; sourceTree = ""; }; + OBJ_321 /* v3_cpols.c */ = {isa = PBXFileReference; path = v3_cpols.c; sourceTree = ""; }; + OBJ_322 /* v3_crld.c */ = {isa = PBXFileReference; path = v3_crld.c; sourceTree = ""; }; + OBJ_323 /* v3_enum.c */ = {isa = PBXFileReference; path = v3_enum.c; sourceTree = ""; }; + OBJ_324 /* v3_extku.c */ = {isa = PBXFileReference; path = v3_extku.c; sourceTree = ""; }; + OBJ_325 /* v3_genn.c */ = {isa = PBXFileReference; path = v3_genn.c; sourceTree = ""; }; + OBJ_326 /* v3_ia5.c */ = {isa = PBXFileReference; path = v3_ia5.c; sourceTree = ""; }; + OBJ_327 /* v3_info.c */ = {isa = PBXFileReference; path = v3_info.c; sourceTree = ""; }; + OBJ_328 /* v3_int.c */ = {isa = PBXFileReference; path = v3_int.c; sourceTree = ""; }; + OBJ_329 /* v3_lib.c */ = {isa = PBXFileReference; path = v3_lib.c; sourceTree = ""; }; + OBJ_33 /* f_int.c */ = {isa = PBXFileReference; path = f_int.c; sourceTree = ""; }; + OBJ_330 /* v3_ncons.c */ = {isa = PBXFileReference; path = v3_ncons.c; sourceTree = ""; }; + OBJ_331 /* v3_pci.c */ = {isa = PBXFileReference; path = v3_pci.c; sourceTree = ""; }; + OBJ_332 /* v3_pcia.c */ = {isa = PBXFileReference; path = v3_pcia.c; sourceTree = ""; }; + OBJ_333 /* v3_pcons.c */ = {isa = PBXFileReference; path = v3_pcons.c; sourceTree = ""; }; + OBJ_334 /* v3_pku.c */ = {isa = PBXFileReference; path = v3_pku.c; sourceTree = ""; }; + OBJ_335 /* v3_pmaps.c */ = {isa = PBXFileReference; path = v3_pmaps.c; sourceTree = ""; }; + OBJ_336 /* v3_prn.c */ = {isa = PBXFileReference; path = v3_prn.c; sourceTree = ""; }; + OBJ_337 /* v3_purp.c */ = {isa = PBXFileReference; path = v3_purp.c; sourceTree = ""; }; + OBJ_338 /* v3_skey.c */ = {isa = PBXFileReference; path = v3_skey.c; sourceTree = ""; }; + OBJ_339 /* v3_sxnet.c */ = {isa = PBXFileReference; path = v3_sxnet.c; sourceTree = ""; }; + OBJ_34 /* f_string.c */ = {isa = PBXFileReference; path = f_string.c; sourceTree = ""; }; + OBJ_340 /* v3_utl.c */ = {isa = PBXFileReference; path = v3_utl.c; sourceTree = ""; }; + OBJ_342 /* bio_ssl.cc */ = {isa = PBXFileReference; path = bio_ssl.cc; sourceTree = ""; }; + OBJ_343 /* custom_extensions.cc */ = {isa = PBXFileReference; path = custom_extensions.cc; sourceTree = ""; }; + OBJ_344 /* d1_both.cc */ = {isa = PBXFileReference; path = d1_both.cc; sourceTree = ""; }; + OBJ_345 /* d1_lib.cc */ = {isa = PBXFileReference; path = d1_lib.cc; sourceTree = ""; }; + OBJ_346 /* d1_pkt.cc */ = {isa = PBXFileReference; path = d1_pkt.cc; sourceTree = ""; }; + OBJ_347 /* d1_srtp.cc */ = {isa = PBXFileReference; path = d1_srtp.cc; sourceTree = ""; }; + OBJ_348 /* dtls_method.cc */ = {isa = PBXFileReference; path = dtls_method.cc; sourceTree = ""; }; + OBJ_349 /* dtls_record.cc */ = {isa = PBXFileReference; path = dtls_record.cc; sourceTree = ""; }; + OBJ_35 /* tasn_dec.c */ = {isa = PBXFileReference; path = tasn_dec.c; sourceTree = ""; }; + OBJ_350 /* handoff.cc */ = {isa = PBXFileReference; path = handoff.cc; sourceTree = ""; }; + OBJ_351 /* handshake.cc */ = {isa = PBXFileReference; path = handshake.cc; sourceTree = ""; }; + OBJ_352 /* handshake_client.cc */ = {isa = PBXFileReference; path = handshake_client.cc; sourceTree = ""; }; + OBJ_353 /* handshake_server.cc */ = {isa = PBXFileReference; path = handshake_server.cc; sourceTree = ""; }; + OBJ_354 /* s3_both.cc */ = {isa = PBXFileReference; path = s3_both.cc; sourceTree = ""; }; + OBJ_355 /* s3_lib.cc */ = {isa = PBXFileReference; path = s3_lib.cc; sourceTree = ""; }; + OBJ_356 /* s3_pkt.cc */ = {isa = PBXFileReference; path = s3_pkt.cc; sourceTree = ""; }; + OBJ_357 /* ssl_aead_ctx.cc */ = {isa = PBXFileReference; path = ssl_aead_ctx.cc; sourceTree = ""; }; + OBJ_358 /* ssl_asn1.cc */ = {isa = PBXFileReference; path = ssl_asn1.cc; sourceTree = ""; }; + OBJ_359 /* ssl_buffer.cc */ = {isa = PBXFileReference; path = ssl_buffer.cc; sourceTree = ""; }; + OBJ_36 /* tasn_enc.c */ = {isa = PBXFileReference; path = tasn_enc.c; sourceTree = ""; }; + OBJ_360 /* ssl_cert.cc */ = {isa = PBXFileReference; path = ssl_cert.cc; sourceTree = ""; }; + OBJ_361 /* ssl_cipher.cc */ = {isa = PBXFileReference; path = ssl_cipher.cc; sourceTree = ""; }; + OBJ_362 /* ssl_file.cc */ = {isa = PBXFileReference; path = ssl_file.cc; sourceTree = ""; }; + OBJ_363 /* ssl_key_share.cc */ = {isa = PBXFileReference; path = ssl_key_share.cc; sourceTree = ""; }; + OBJ_364 /* ssl_lib.cc */ = {isa = PBXFileReference; path = ssl_lib.cc; sourceTree = ""; }; + OBJ_365 /* ssl_privkey.cc */ = {isa = PBXFileReference; path = ssl_privkey.cc; sourceTree = ""; }; + OBJ_366 /* ssl_session.cc */ = {isa = PBXFileReference; path = ssl_session.cc; sourceTree = ""; }; + OBJ_367 /* ssl_stat.cc */ = {isa = PBXFileReference; path = ssl_stat.cc; sourceTree = ""; }; + OBJ_368 /* ssl_transcript.cc */ = {isa = PBXFileReference; path = ssl_transcript.cc; sourceTree = ""; }; + OBJ_369 /* ssl_versions.cc */ = {isa = PBXFileReference; path = ssl_versions.cc; sourceTree = ""; }; + OBJ_37 /* tasn_fre.c */ = {isa = PBXFileReference; path = tasn_fre.c; sourceTree = ""; }; + OBJ_370 /* ssl_x509.cc */ = {isa = PBXFileReference; path = ssl_x509.cc; sourceTree = ""; }; + OBJ_371 /* t1_enc.cc */ = {isa = PBXFileReference; path = t1_enc.cc; sourceTree = ""; }; + OBJ_372 /* t1_lib.cc */ = {isa = PBXFileReference; path = t1_lib.cc; sourceTree = ""; }; + OBJ_373 /* tls13_both.cc */ = {isa = PBXFileReference; path = tls13_both.cc; sourceTree = ""; }; + OBJ_374 /* tls13_client.cc */ = {isa = PBXFileReference; path = tls13_client.cc; sourceTree = ""; }; + OBJ_375 /* tls13_enc.cc */ = {isa = PBXFileReference; path = tls13_enc.cc; sourceTree = ""; }; + OBJ_376 /* tls13_server.cc */ = {isa = PBXFileReference; path = tls13_server.cc; sourceTree = ""; }; + OBJ_377 /* tls_method.cc */ = {isa = PBXFileReference; path = tls_method.cc; sourceTree = ""; }; + OBJ_378 /* tls_record.cc */ = {isa = PBXFileReference; path = tls_record.cc; sourceTree = ""; }; + OBJ_38 /* tasn_new.c */ = {isa = PBXFileReference; path = tasn_new.c; sourceTree = ""; }; + OBJ_381 /* curve25519.c */ = {isa = PBXFileReference; path = curve25519.c; sourceTree = ""; }; + OBJ_382 /* p256.c */ = {isa = PBXFileReference; path = p256.c; sourceTree = ""; }; + OBJ_385 /* pem.h */ = {isa = PBXFileReference; path = pem.h; sourceTree = ""; }; + OBJ_386 /* nid.h */ = {isa = PBXFileReference; path = nid.h; sourceTree = ""; }; + OBJ_387 /* ssl3.h */ = {isa = PBXFileReference; path = ssl3.h; sourceTree = ""; }; + OBJ_388 /* ossl_typ.h */ = {isa = PBXFileReference; path = ossl_typ.h; sourceTree = ""; }; + OBJ_389 /* dtls1.h */ = {isa = PBXFileReference; path = dtls1.h; sourceTree = ""; }; + OBJ_39 /* tasn_typ.c */ = {isa = PBXFileReference; path = tasn_typ.c; sourceTree = ""; }; + OBJ_390 /* err.h */ = {isa = PBXFileReference; path = err.h; sourceTree = ""; }; + OBJ_391 /* bn.h */ = {isa = PBXFileReference; path = bn.h; sourceTree = ""; }; + OBJ_392 /* blowfish.h */ = {isa = PBXFileReference; path = blowfish.h; sourceTree = ""; }; + OBJ_393 /* engine.h */ = {isa = PBXFileReference; path = engine.h; sourceTree = ""; }; + OBJ_394 /* bytestring.h */ = {isa = PBXFileReference; path = bytestring.h; sourceTree = ""; }; + OBJ_395 /* x509.h */ = {isa = PBXFileReference; path = x509.h; sourceTree = ""; }; + OBJ_396 /* asn1_mac.h */ = {isa = PBXFileReference; path = asn1_mac.h; sourceTree = ""; }; + OBJ_397 /* pool.h */ = {isa = PBXFileReference; path = pool.h; sourceTree = ""; }; + OBJ_398 /* ec_key.h */ = {isa = PBXFileReference; path = ec_key.h; sourceTree = ""; }; + OBJ_399 /* base64.h */ = {isa = PBXFileReference; path = base64.h; sourceTree = ""; }; + OBJ_40 /* tasn_utl.c */ = {isa = PBXFileReference; path = tasn_utl.c; sourceTree = ""; }; + OBJ_400 /* is_boringssl.h */ = {isa = PBXFileReference; path = is_boringssl.h; sourceTree = ""; }; + OBJ_401 /* sha.h */ = {isa = PBXFileReference; path = sha.h; sourceTree = ""; }; + OBJ_402 /* asn1.h */ = {isa = PBXFileReference; path = asn1.h; sourceTree = ""; }; + OBJ_403 /* chacha.h */ = {isa = PBXFileReference; path = chacha.h; sourceTree = ""; }; + OBJ_404 /* opensslconf.h */ = {isa = PBXFileReference; path = opensslconf.h; sourceTree = ""; }; + OBJ_405 /* arm_arch.h */ = {isa = PBXFileReference; path = arm_arch.h; sourceTree = ""; }; + OBJ_406 /* bio.h */ = {isa = PBXFileReference; path = bio.h; sourceTree = ""; }; + OBJ_407 /* dh.h */ = {isa = PBXFileReference; path = dh.h; sourceTree = ""; }; + OBJ_408 /* digest.h */ = {isa = PBXFileReference; path = digest.h; sourceTree = ""; }; + OBJ_409 /* x509v3.h */ = {isa = PBXFileReference; path = x509v3.h; sourceTree = ""; }; + OBJ_41 /* time_support.c */ = {isa = PBXFileReference; path = time_support.c; sourceTree = ""; }; + OBJ_410 /* conf.h */ = {isa = PBXFileReference; path = conf.h; sourceTree = ""; }; + OBJ_411 /* poly1305.h */ = {isa = PBXFileReference; path = poly1305.h; sourceTree = ""; }; + OBJ_412 /* hkdf.h */ = {isa = PBXFileReference; path = hkdf.h; sourceTree = ""; }; + OBJ_413 /* type_check.h */ = {isa = PBXFileReference; path = type_check.h; sourceTree = ""; }; + OBJ_414 /* md5.h */ = {isa = PBXFileReference; path = md5.h; sourceTree = ""; }; + OBJ_415 /* x509_vfy.h */ = {isa = PBXFileReference; path = x509_vfy.h; sourceTree = ""; }; + OBJ_416 /* pkcs8.h */ = {isa = PBXFileReference; path = pkcs8.h; sourceTree = ""; }; + OBJ_417 /* safestack.h */ = {isa = PBXFileReference; path = safestack.h; sourceTree = ""; }; + OBJ_418 /* buf.h */ = {isa = PBXFileReference; path = buf.h; sourceTree = ""; }; + OBJ_419 /* obj.h */ = {isa = PBXFileReference; path = obj.h; sourceTree = ""; }; + OBJ_420 /* ecdsa.h */ = {isa = PBXFileReference; path = ecdsa.h; sourceTree = ""; }; + OBJ_421 /* cipher.h */ = {isa = PBXFileReference; path = cipher.h; sourceTree = ""; }; + OBJ_422 /* objects.h */ = {isa = PBXFileReference; path = objects.h; sourceTree = ""; }; + OBJ_423 /* pkcs12.h */ = {isa = PBXFileReference; path = pkcs12.h; sourceTree = ""; }; + OBJ_424 /* crypto.h */ = {isa = PBXFileReference; path = crypto.h; sourceTree = ""; }; + OBJ_425 /* opensslv.h */ = {isa = PBXFileReference; path = opensslv.h; sourceTree = ""; }; + OBJ_426 /* pkcs7.h */ = {isa = PBXFileReference; path = pkcs7.h; sourceTree = ""; }; + OBJ_427 /* obj_mac.h */ = {isa = PBXFileReference; path = obj_mac.h; sourceTree = ""; }; + OBJ_428 /* buffer.h */ = {isa = PBXFileReference; path = buffer.h; sourceTree = ""; }; + OBJ_429 /* ssl.h */ = {isa = PBXFileReference; path = ssl.h; sourceTree = ""; }; + OBJ_43 /* base64.c */ = {isa = PBXFileReference; path = base64.c; sourceTree = ""; }; + OBJ_430 /* thread.h */ = {isa = PBXFileReference; path = thread.h; sourceTree = ""; }; + OBJ_431 /* evp.h */ = {isa = PBXFileReference; path = evp.h; sourceTree = ""; }; + OBJ_432 /* md4.h */ = {isa = PBXFileReference; path = md4.h; sourceTree = ""; }; + OBJ_433 /* hmac.h */ = {isa = PBXFileReference; path = hmac.h; sourceTree = ""; }; + OBJ_434 /* aes.h */ = {isa = PBXFileReference; path = aes.h; sourceTree = ""; }; + OBJ_435 /* cast.h */ = {isa = PBXFileReference; path = cast.h; sourceTree = ""; }; + OBJ_436 /* rc4.h */ = {isa = PBXFileReference; path = rc4.h; sourceTree = ""; }; + OBJ_437 /* cpu.h */ = {isa = PBXFileReference; path = cpu.h; sourceTree = ""; }; + OBJ_438 /* stack.h */ = {isa = PBXFileReference; path = stack.h; sourceTree = ""; }; + OBJ_439 /* des.h */ = {isa = PBXFileReference; path = des.h; sourceTree = ""; }; + OBJ_440 /* ec.h */ = {isa = PBXFileReference; path = ec.h; sourceTree = ""; }; + OBJ_441 /* ecdh.h */ = {isa = PBXFileReference; path = ecdh.h; sourceTree = ""; }; + OBJ_442 /* rand.h */ = {isa = PBXFileReference; path = rand.h; sourceTree = ""; }; + OBJ_443 /* aead.h */ = {isa = PBXFileReference; path = aead.h; sourceTree = ""; }; + OBJ_444 /* lhash_macros.h */ = {isa = PBXFileReference; path = lhash_macros.h; sourceTree = ""; }; + OBJ_445 /* span.h */ = {isa = PBXFileReference; path = span.h; sourceTree = ""; }; + OBJ_446 /* rsa.h */ = {isa = PBXFileReference; path = rsa.h; sourceTree = ""; }; + OBJ_447 /* mem.h */ = {isa = PBXFileReference; path = mem.h; sourceTree = ""; }; + OBJ_448 /* ripemd.h */ = {isa = PBXFileReference; path = ripemd.h; sourceTree = ""; }; + OBJ_449 /* curve25519.h */ = {isa = PBXFileReference; path = curve25519.h; sourceTree = ""; }; + OBJ_45 /* bio.c */ = {isa = PBXFileReference; path = bio.c; sourceTree = ""; }; + OBJ_450 /* tls1.h */ = {isa = PBXFileReference; path = tls1.h; sourceTree = ""; }; + OBJ_451 /* dsa.h */ = {isa = PBXFileReference; path = dsa.h; sourceTree = ""; }; + OBJ_452 /* srtp.h */ = {isa = PBXFileReference; path = srtp.h; sourceTree = ""; }; + OBJ_453 /* asn1t.h */ = {isa = PBXFileReference; path = asn1t.h; sourceTree = ""; }; + OBJ_454 /* cmac.h */ = {isa = PBXFileReference; path = cmac.h; sourceTree = ""; }; + OBJ_455 /* lhash.h */ = {isa = PBXFileReference; path = lhash.h; sourceTree = ""; }; + OBJ_456 /* ex_data.h */ = {isa = PBXFileReference; path = ex_data.h; sourceTree = ""; }; + OBJ_457 /* base.h */ = {isa = PBXFileReference; path = base.h; sourceTree = ""; }; + OBJ_458 /* module.modulemap */ = {isa = PBXFileReference; name = module.modulemap; path = "../SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; sourceTree = ""; }; + OBJ_46 /* bio_mem.c */ = {isa = PBXFileReference; path = bio_mem.c; sourceTree = ""; }; + OBJ_460 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_462 /* byte_buffer.c */ = {isa = PBXFileReference; path = byte_buffer.c; sourceTree = ""; }; + OBJ_463 /* call.c */ = {isa = PBXFileReference; path = call.c; sourceTree = ""; }; + OBJ_464 /* channel.c */ = {isa = PBXFileReference; path = channel.c; sourceTree = ""; }; + OBJ_465 /* completion_queue.c */ = {isa = PBXFileReference; path = completion_queue.c; sourceTree = ""; }; + OBJ_466 /* event.c */ = {isa = PBXFileReference; path = event.c; sourceTree = ""; }; + OBJ_467 /* handler.c */ = {isa = PBXFileReference; path = handler.c; sourceTree = ""; }; + OBJ_468 /* internal.c */ = {isa = PBXFileReference; path = internal.c; sourceTree = ""; }; + OBJ_469 /* metadata.c */ = {isa = PBXFileReference; path = metadata.c; sourceTree = ""; }; + OBJ_47 /* connect.c */ = {isa = PBXFileReference; path = connect.c; sourceTree = ""; }; + OBJ_470 /* mutex.c */ = {isa = PBXFileReference; path = mutex.c; sourceTree = ""; }; + OBJ_471 /* observers.c */ = {isa = PBXFileReference; path = observers.c; sourceTree = ""; }; + OBJ_472 /* operations.c */ = {isa = PBXFileReference; path = operations.c; sourceTree = ""; }; + OBJ_473 /* server.c */ = {isa = PBXFileReference; path = server.c; sourceTree = ""; }; + OBJ_479 /* grpc_context.cc */ = {isa = PBXFileReference; path = grpc_context.cc; sourceTree = ""; }; + OBJ_48 /* fd.c */ = {isa = PBXFileReference; path = fd.c; sourceTree = ""; }; + OBJ_481 /* backup_poller.cc */ = {isa = PBXFileReference; path = backup_poller.cc; sourceTree = ""; }; + OBJ_482 /* channel_connectivity.cc */ = {isa = PBXFileReference; path = channel_connectivity.cc; sourceTree = ""; }; + OBJ_483 /* client_channel.cc */ = {isa = PBXFileReference; path = client_channel.cc; sourceTree = ""; }; + OBJ_484 /* client_channel_channelz.cc */ = {isa = PBXFileReference; path = client_channel_channelz.cc; sourceTree = ""; }; + OBJ_485 /* client_channel_factory.cc */ = {isa = PBXFileReference; path = client_channel_factory.cc; sourceTree = ""; }; + OBJ_486 /* client_channel_plugin.cc */ = {isa = PBXFileReference; path = client_channel_plugin.cc; sourceTree = ""; }; + OBJ_487 /* connector.cc */ = {isa = PBXFileReference; path = connector.cc; sourceTree = ""; }; + OBJ_488 /* global_subchannel_pool.cc */ = {isa = PBXFileReference; path = global_subchannel_pool.cc; sourceTree = ""; }; + OBJ_49 /* file.c */ = {isa = PBXFileReference; path = file.c; sourceTree = ""; }; + OBJ_490 /* health.pb.c */ = {isa = PBXFileReference; path = health.pb.c; sourceTree = ""; }; + OBJ_491 /* health_check_client.cc */ = {isa = PBXFileReference; path = health_check_client.cc; sourceTree = ""; }; + OBJ_492 /* http_connect_handshaker.cc */ = {isa = PBXFileReference; path = http_connect_handshaker.cc; sourceTree = ""; }; + OBJ_493 /* http_proxy.cc */ = {isa = PBXFileReference; path = http_proxy.cc; sourceTree = ""; }; + OBJ_494 /* lb_policy.cc */ = {isa = PBXFileReference; path = lb_policy.cc; sourceTree = ""; }; + OBJ_497 /* client_load_reporting_filter.cc */ = {isa = PBXFileReference; path = client_load_reporting_filter.cc; sourceTree = ""; }; + OBJ_498 /* grpclb.cc */ = {isa = PBXFileReference; path = grpclb.cc; sourceTree = ""; }; + OBJ_499 /* grpclb_channel_secure.cc */ = {isa = PBXFileReference; path = grpclb_channel_secure.cc; sourceTree = ""; }; + OBJ_50 /* hexdump.c */ = {isa = PBXFileReference; path = hexdump.c; sourceTree = ""; }; + OBJ_500 /* grpclb_client_stats.cc */ = {isa = PBXFileReference; path = grpclb_client_stats.cc; sourceTree = ""; }; + OBJ_501 /* load_balancer_api.cc */ = {isa = PBXFileReference; path = load_balancer_api.cc; sourceTree = ""; }; + OBJ_508 /* duration.pb.c */ = {isa = PBXFileReference; path = duration.pb.c; sourceTree = ""; }; + OBJ_509 /* timestamp.pb.c */ = {isa = PBXFileReference; path = timestamp.pb.c; sourceTree = ""; }; + OBJ_51 /* pair.c */ = {isa = PBXFileReference; path = pair.c; sourceTree = ""; }; + OBJ_510 /* load_balancer.pb.c */ = {isa = PBXFileReference; path = load_balancer.pb.c; sourceTree = ""; }; + OBJ_512 /* pick_first.cc */ = {isa = PBXFileReference; path = pick_first.cc; sourceTree = ""; }; + OBJ_514 /* round_robin.cc */ = {isa = PBXFileReference; path = round_robin.cc; sourceTree = ""; }; + OBJ_516 /* xds.cc */ = {isa = PBXFileReference; path = xds.cc; sourceTree = ""; }; + OBJ_517 /* xds_channel_secure.cc */ = {isa = PBXFileReference; path = xds_channel_secure.cc; sourceTree = ""; }; + OBJ_518 /* xds_client_stats.cc */ = {isa = PBXFileReference; path = xds_client_stats.cc; sourceTree = ""; }; + OBJ_519 /* xds_load_balancer_api.cc */ = {isa = PBXFileReference; path = xds_load_balancer_api.cc; sourceTree = ""; }; + OBJ_52 /* printf.c */ = {isa = PBXFileReference; path = printf.c; sourceTree = ""; }; + OBJ_520 /* lb_policy_registry.cc */ = {isa = PBXFileReference; path = lb_policy_registry.cc; sourceTree = ""; }; + OBJ_521 /* local_subchannel_pool.cc */ = {isa = PBXFileReference; path = local_subchannel_pool.cc; sourceTree = ""; }; + OBJ_522 /* parse_address.cc */ = {isa = PBXFileReference; path = parse_address.cc; sourceTree = ""; }; + OBJ_523 /* proxy_mapper.cc */ = {isa = PBXFileReference; path = proxy_mapper.cc; sourceTree = ""; }; + OBJ_524 /* proxy_mapper_registry.cc */ = {isa = PBXFileReference; path = proxy_mapper_registry.cc; sourceTree = ""; }; + OBJ_525 /* request_routing.cc */ = {isa = PBXFileReference; path = request_routing.cc; sourceTree = ""; }; + OBJ_526 /* resolver.cc */ = {isa = PBXFileReference; path = resolver.cc; sourceTree = ""; }; + OBJ_53 /* socket.c */ = {isa = PBXFileReference; path = socket.c; sourceTree = ""; }; + OBJ_530 /* dns_resolver_ares.cc */ = {isa = PBXFileReference; path = dns_resolver_ares.cc; sourceTree = ""; }; + OBJ_531 /* grpc_ares_ev_driver.cc */ = {isa = PBXFileReference; path = grpc_ares_ev_driver.cc; sourceTree = ""; }; + OBJ_532 /* grpc_ares_ev_driver_posix.cc */ = {isa = PBXFileReference; path = grpc_ares_ev_driver_posix.cc; sourceTree = ""; }; + OBJ_533 /* grpc_ares_ev_driver_windows.cc */ = {isa = PBXFileReference; path = grpc_ares_ev_driver_windows.cc; sourceTree = ""; }; + OBJ_534 /* grpc_ares_wrapper.cc */ = {isa = PBXFileReference; path = grpc_ares_wrapper.cc; sourceTree = ""; }; + OBJ_535 /* grpc_ares_wrapper_fallback.cc */ = {isa = PBXFileReference; path = grpc_ares_wrapper_fallback.cc; sourceTree = ""; }; + OBJ_536 /* grpc_ares_wrapper_posix.cc */ = {isa = PBXFileReference; path = grpc_ares_wrapper_posix.cc; sourceTree = ""; }; + OBJ_537 /* grpc_ares_wrapper_windows.cc */ = {isa = PBXFileReference; path = grpc_ares_wrapper_windows.cc; sourceTree = ""; }; + OBJ_539 /* dns_resolver.cc */ = {isa = PBXFileReference; path = dns_resolver.cc; sourceTree = ""; }; + OBJ_54 /* socket_helper.c */ = {isa = PBXFileReference; path = socket_helper.c; sourceTree = ""; }; + OBJ_541 /* fake_resolver.cc */ = {isa = PBXFileReference; path = fake_resolver.cc; sourceTree = ""; }; + OBJ_543 /* sockaddr_resolver.cc */ = {isa = PBXFileReference; path = sockaddr_resolver.cc; sourceTree = ""; }; + OBJ_544 /* resolver_registry.cc */ = {isa = PBXFileReference; path = resolver_registry.cc; sourceTree = ""; }; + OBJ_545 /* resolver_result_parsing.cc */ = {isa = PBXFileReference; path = resolver_result_parsing.cc; sourceTree = ""; }; + OBJ_546 /* retry_throttle.cc */ = {isa = PBXFileReference; path = retry_throttle.cc; sourceTree = ""; }; + OBJ_547 /* server_address.cc */ = {isa = PBXFileReference; path = server_address.cc; sourceTree = ""; }; + OBJ_548 /* subchannel.cc */ = {isa = PBXFileReference; path = subchannel.cc; sourceTree = ""; }; + OBJ_549 /* subchannel_pool_interface.cc */ = {isa = PBXFileReference; path = subchannel_pool_interface.cc; sourceTree = ""; }; + OBJ_551 /* deadline_filter.cc */ = {isa = PBXFileReference; path = deadline_filter.cc; sourceTree = ""; }; + OBJ_554 /* http_client_filter.cc */ = {isa = PBXFileReference; path = http_client_filter.cc; sourceTree = ""; }; + OBJ_555 /* client_authority_filter.cc */ = {isa = PBXFileReference; path = client_authority_filter.cc; sourceTree = ""; }; + OBJ_556 /* http_filters_plugin.cc */ = {isa = PBXFileReference; path = http_filters_plugin.cc; sourceTree = ""; }; + OBJ_558 /* message_compress_filter.cc */ = {isa = PBXFileReference; path = message_compress_filter.cc; sourceTree = ""; }; + OBJ_56 /* bn_asn1.c */ = {isa = PBXFileReference; path = bn_asn1.c; sourceTree = ""; }; + OBJ_560 /* http_server_filter.cc */ = {isa = PBXFileReference; path = http_server_filter.cc; sourceTree = ""; }; + OBJ_562 /* max_age_filter.cc */ = {isa = PBXFileReference; path = max_age_filter.cc; sourceTree = ""; }; + OBJ_564 /* message_size_filter.cc */ = {isa = PBXFileReference; path = message_size_filter.cc; sourceTree = ""; }; + OBJ_566 /* workaround_cronet_compression_filter.cc */ = {isa = PBXFileReference; path = workaround_cronet_compression_filter.cc; sourceTree = ""; }; + OBJ_567 /* workaround_utils.cc */ = {isa = PBXFileReference; path = workaround_utils.cc; sourceTree = ""; }; + OBJ_57 /* convert.c */ = {isa = PBXFileReference; path = convert.c; sourceTree = ""; }; + OBJ_571 /* alpn.cc */ = {isa = PBXFileReference; path = alpn.cc; sourceTree = ""; }; + OBJ_573 /* authority.cc */ = {isa = PBXFileReference; path = authority.cc; sourceTree = ""; }; + OBJ_574 /* chttp2_connector.cc */ = {isa = PBXFileReference; path = chttp2_connector.cc; sourceTree = ""; }; + OBJ_576 /* channel_create.cc */ = {isa = PBXFileReference; path = channel_create.cc; sourceTree = ""; }; + OBJ_577 /* channel_create_posix.cc */ = {isa = PBXFileReference; path = channel_create_posix.cc; sourceTree = ""; }; + OBJ_579 /* secure_channel_create.cc */ = {isa = PBXFileReference; path = secure_channel_create.cc; sourceTree = ""; }; + OBJ_581 /* chttp2_server.cc */ = {isa = PBXFileReference; path = chttp2_server.cc; sourceTree = ""; }; + OBJ_583 /* server_chttp2.cc */ = {isa = PBXFileReference; path = server_chttp2.cc; sourceTree = ""; }; + OBJ_584 /* server_chttp2_posix.cc */ = {isa = PBXFileReference; path = server_chttp2_posix.cc; sourceTree = ""; }; + OBJ_586 /* server_secure_chttp2.cc */ = {isa = PBXFileReference; path = server_secure_chttp2.cc; sourceTree = ""; }; + OBJ_588 /* bin_decoder.cc */ = {isa = PBXFileReference; path = bin_decoder.cc; sourceTree = ""; }; + OBJ_589 /* bin_encoder.cc */ = {isa = PBXFileReference; path = bin_encoder.cc; sourceTree = ""; }; + OBJ_59 /* buf.c */ = {isa = PBXFileReference; path = buf.c; sourceTree = ""; }; + OBJ_590 /* chttp2_plugin.cc */ = {isa = PBXFileReference; path = chttp2_plugin.cc; sourceTree = ""; }; + OBJ_591 /* chttp2_transport.cc */ = {isa = PBXFileReference; path = chttp2_transport.cc; sourceTree = ""; }; + OBJ_592 /* context_list.cc */ = {isa = PBXFileReference; path = context_list.cc; sourceTree = ""; }; + OBJ_593 /* flow_control.cc */ = {isa = PBXFileReference; path = flow_control.cc; sourceTree = ""; }; + OBJ_594 /* frame_data.cc */ = {isa = PBXFileReference; path = frame_data.cc; sourceTree = ""; }; + OBJ_595 /* frame_goaway.cc */ = {isa = PBXFileReference; path = frame_goaway.cc; sourceTree = ""; }; + OBJ_596 /* frame_ping.cc */ = {isa = PBXFileReference; path = frame_ping.cc; sourceTree = ""; }; + OBJ_597 /* frame_rst_stream.cc */ = {isa = PBXFileReference; path = frame_rst_stream.cc; sourceTree = ""; }; + OBJ_598 /* frame_settings.cc */ = {isa = PBXFileReference; path = frame_settings.cc; sourceTree = ""; }; + OBJ_599 /* frame_window_update.cc */ = {isa = PBXFileReference; path = frame_window_update.cc; sourceTree = ""; }; OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; - OBJ_60 /* grpclb_client_stats.cc */ = {isa = PBXFileReference; path = grpclb_client_stats.cc; sourceTree = ""; }; - OBJ_600 /* ServerSessionClientStreaming.swift */ = {isa = PBXFileReference; path = ServerSessionClientStreaming.swift; sourceTree = ""; }; - OBJ_601 /* ServerSessionServerStreaming.swift */ = {isa = PBXFileReference; path = ServerSessionServerStreaming.swift; sourceTree = ""; }; - OBJ_602 /* ServerSessionUnary.swift */ = {isa = PBXFileReference; path = ServerSessionUnary.swift; sourceTree = ""; }; - OBJ_603 /* ServiceClient.swift */ = {isa = PBXFileReference; path = ServiceClient.swift; sourceTree = ""; }; - OBJ_604 /* ServiceProvider.swift */ = {isa = PBXFileReference; path = ServiceProvider.swift; sourceTree = ""; }; - OBJ_605 /* ServiceServer.swift */ = {isa = PBXFileReference; path = ServiceServer.swift; sourceTree = ""; }; - OBJ_606 /* StreamReceiving.swift */ = {isa = PBXFileReference; path = StreamReceiving.swift; sourceTree = ""; }; - OBJ_607 /* StreamSending.swift */ = {isa = PBXFileReference; path = StreamSending.swift; sourceTree = ""; }; - OBJ_61 /* load_balancer_api.cc */ = {isa = PBXFileReference; path = load_balancer_api.cc; sourceTree = ""; }; - OBJ_611 /* a_bitstr.c */ = {isa = PBXFileReference; path = a_bitstr.c; sourceTree = ""; }; - OBJ_612 /* a_bool.c */ = {isa = PBXFileReference; path = a_bool.c; sourceTree = ""; }; - OBJ_613 /* a_d2i_fp.c */ = {isa = PBXFileReference; path = a_d2i_fp.c; sourceTree = ""; }; - OBJ_614 /* a_dup.c */ = {isa = PBXFileReference; path = a_dup.c; sourceTree = ""; }; - OBJ_615 /* a_enum.c */ = {isa = PBXFileReference; path = a_enum.c; sourceTree = ""; }; - OBJ_616 /* a_gentm.c */ = {isa = PBXFileReference; path = a_gentm.c; sourceTree = ""; }; - OBJ_617 /* a_i2d_fp.c */ = {isa = PBXFileReference; path = a_i2d_fp.c; sourceTree = ""; }; - OBJ_618 /* a_int.c */ = {isa = PBXFileReference; path = a_int.c; sourceTree = ""; }; - OBJ_619 /* a_mbstr.c */ = {isa = PBXFileReference; path = a_mbstr.c; sourceTree = ""; }; - OBJ_620 /* a_object.c */ = {isa = PBXFileReference; path = a_object.c; sourceTree = ""; }; - OBJ_621 /* a_octet.c */ = {isa = PBXFileReference; path = a_octet.c; sourceTree = ""; }; - OBJ_622 /* a_print.c */ = {isa = PBXFileReference; path = a_print.c; sourceTree = ""; }; - OBJ_623 /* a_strnid.c */ = {isa = PBXFileReference; path = a_strnid.c; sourceTree = ""; }; - OBJ_624 /* a_time.c */ = {isa = PBXFileReference; path = a_time.c; sourceTree = ""; }; - OBJ_625 /* a_type.c */ = {isa = PBXFileReference; path = a_type.c; sourceTree = ""; }; - OBJ_626 /* a_utctm.c */ = {isa = PBXFileReference; path = a_utctm.c; sourceTree = ""; }; - OBJ_627 /* a_utf8.c */ = {isa = PBXFileReference; path = a_utf8.c; sourceTree = ""; }; - OBJ_628 /* asn1_lib.c */ = {isa = PBXFileReference; path = asn1_lib.c; sourceTree = ""; }; - OBJ_629 /* asn1_par.c */ = {isa = PBXFileReference; path = asn1_par.c; sourceTree = ""; }; - OBJ_630 /* asn_pack.c */ = {isa = PBXFileReference; path = asn_pack.c; sourceTree = ""; }; - OBJ_631 /* f_enum.c */ = {isa = PBXFileReference; path = f_enum.c; sourceTree = ""; }; - OBJ_632 /* f_int.c */ = {isa = PBXFileReference; path = f_int.c; sourceTree = ""; }; - OBJ_633 /* f_string.c */ = {isa = PBXFileReference; path = f_string.c; sourceTree = ""; }; - OBJ_634 /* tasn_dec.c */ = {isa = PBXFileReference; path = tasn_dec.c; sourceTree = ""; }; - OBJ_635 /* tasn_enc.c */ = {isa = PBXFileReference; path = tasn_enc.c; sourceTree = ""; }; - OBJ_636 /* tasn_fre.c */ = {isa = PBXFileReference; path = tasn_fre.c; sourceTree = ""; }; - OBJ_637 /* tasn_new.c */ = {isa = PBXFileReference; path = tasn_new.c; sourceTree = ""; }; - OBJ_638 /* tasn_typ.c */ = {isa = PBXFileReference; path = tasn_typ.c; sourceTree = ""; }; - OBJ_639 /* tasn_utl.c */ = {isa = PBXFileReference; path = tasn_utl.c; sourceTree = ""; }; - OBJ_640 /* time_support.c */ = {isa = PBXFileReference; path = time_support.c; sourceTree = ""; }; - OBJ_642 /* base64.c */ = {isa = PBXFileReference; path = base64.c; sourceTree = ""; }; - OBJ_644 /* bio.c */ = {isa = PBXFileReference; path = bio.c; sourceTree = ""; }; - OBJ_645 /* bio_mem.c */ = {isa = PBXFileReference; path = bio_mem.c; sourceTree = ""; }; - OBJ_646 /* connect.c */ = {isa = PBXFileReference; path = connect.c; sourceTree = ""; }; - OBJ_647 /* fd.c */ = {isa = PBXFileReference; path = fd.c; sourceTree = ""; }; - OBJ_648 /* file.c */ = {isa = PBXFileReference; path = file.c; sourceTree = ""; }; - OBJ_649 /* hexdump.c */ = {isa = PBXFileReference; path = hexdump.c; sourceTree = ""; }; - OBJ_650 /* pair.c */ = {isa = PBXFileReference; path = pair.c; sourceTree = ""; }; - OBJ_651 /* printf.c */ = {isa = PBXFileReference; path = printf.c; sourceTree = ""; }; - OBJ_652 /* socket.c */ = {isa = PBXFileReference; path = socket.c; sourceTree = ""; }; - OBJ_653 /* socket_helper.c */ = {isa = PBXFileReference; path = socket_helper.c; sourceTree = ""; }; - OBJ_655 /* bn_asn1.c */ = {isa = PBXFileReference; path = bn_asn1.c; sourceTree = ""; }; - OBJ_656 /* convert.c */ = {isa = PBXFileReference; path = convert.c; sourceTree = ""; }; - OBJ_658 /* buf.c */ = {isa = PBXFileReference; path = buf.c; sourceTree = ""; }; - OBJ_66 /* load_balancer.pb.c */ = {isa = PBXFileReference; path = load_balancer.pb.c; sourceTree = ""; }; - OBJ_660 /* asn1_compat.c */ = {isa = PBXFileReference; path = asn1_compat.c; sourceTree = ""; }; - OBJ_661 /* ber.c */ = {isa = PBXFileReference; path = ber.c; sourceTree = ""; }; - OBJ_662 /* cbb.c */ = {isa = PBXFileReference; path = cbb.c; sourceTree = ""; }; - OBJ_663 /* cbs.c */ = {isa = PBXFileReference; path = cbs.c; sourceTree = ""; }; - OBJ_665 /* chacha.c */ = {isa = PBXFileReference; path = chacha.c; sourceTree = ""; }; - OBJ_667 /* cipher_extra.c */ = {isa = PBXFileReference; path = cipher_extra.c; sourceTree = ""; }; - OBJ_668 /* derive_key.c */ = {isa = PBXFileReference; path = derive_key.c; sourceTree = ""; }; - OBJ_669 /* e_aesctrhmac.c */ = {isa = PBXFileReference; path = e_aesctrhmac.c; sourceTree = ""; }; - OBJ_670 /* e_aesgcmsiv.c */ = {isa = PBXFileReference; path = e_aesgcmsiv.c; sourceTree = ""; }; - OBJ_671 /* e_chacha20poly1305.c */ = {isa = PBXFileReference; path = e_chacha20poly1305.c; sourceTree = ""; }; - OBJ_672 /* e_null.c */ = {isa = PBXFileReference; path = e_null.c; sourceTree = ""; }; - OBJ_673 /* e_rc2.c */ = {isa = PBXFileReference; path = e_rc2.c; sourceTree = ""; }; - OBJ_674 /* e_rc4.c */ = {isa = PBXFileReference; path = e_rc4.c; sourceTree = ""; }; - OBJ_675 /* e_ssl3.c */ = {isa = PBXFileReference; path = e_ssl3.c; sourceTree = ""; }; - OBJ_676 /* e_tls.c */ = {isa = PBXFileReference; path = e_tls.c; sourceTree = ""; }; - OBJ_677 /* tls_cbc.c */ = {isa = PBXFileReference; path = tls_cbc.c; sourceTree = ""; }; - OBJ_679 /* cmac.c */ = {isa = PBXFileReference; path = cmac.c; sourceTree = ""; }; - OBJ_68 /* pick_first.cc */ = {isa = PBXFileReference; path = pick_first.cc; sourceTree = ""; }; - OBJ_681 /* conf.c */ = {isa = PBXFileReference; path = conf.c; sourceTree = ""; }; - OBJ_682 /* cpu-aarch64-linux.c */ = {isa = PBXFileReference; path = "cpu-aarch64-linux.c"; sourceTree = ""; }; - OBJ_683 /* cpu-arm-linux.c */ = {isa = PBXFileReference; path = "cpu-arm-linux.c"; sourceTree = ""; }; - OBJ_684 /* cpu-arm.c */ = {isa = PBXFileReference; path = "cpu-arm.c"; sourceTree = ""; }; - OBJ_685 /* cpu-intel.c */ = {isa = PBXFileReference; path = "cpu-intel.c"; sourceTree = ""; }; - OBJ_686 /* cpu-ppc64le.c */ = {isa = PBXFileReference; path = "cpu-ppc64le.c"; sourceTree = ""; }; - OBJ_687 /* crypto.c */ = {isa = PBXFileReference; path = crypto.c; sourceTree = ""; }; - OBJ_689 /* spake25519.c */ = {isa = PBXFileReference; path = spake25519.c; sourceTree = ""; }; - OBJ_690 /* x25519-x86_64.c */ = {isa = PBXFileReference; path = "x25519-x86_64.c"; sourceTree = ""; }; - OBJ_692 /* check.c */ = {isa = PBXFileReference; path = check.c; sourceTree = ""; }; - OBJ_693 /* dh.c */ = {isa = PBXFileReference; path = dh.c; sourceTree = ""; }; - OBJ_694 /* dh_asn1.c */ = {isa = PBXFileReference; path = dh_asn1.c; sourceTree = ""; }; - OBJ_695 /* params.c */ = {isa = PBXFileReference; path = params.c; sourceTree = ""; }; - OBJ_697 /* digest_extra.c */ = {isa = PBXFileReference; path = digest_extra.c; sourceTree = ""; }; - OBJ_699 /* dsa.c */ = {isa = PBXFileReference; path = dsa.c; sourceTree = ""; }; - OBJ_70 /* round_robin.cc */ = {isa = PBXFileReference; path = round_robin.cc; sourceTree = ""; }; - OBJ_700 /* dsa_asn1.c */ = {isa = PBXFileReference; path = dsa_asn1.c; sourceTree = ""; }; - OBJ_702 /* ec_asn1.c */ = {isa = PBXFileReference; path = ec_asn1.c; sourceTree = ""; }; - OBJ_704 /* ecdh.c */ = {isa = PBXFileReference; path = ecdh.c; sourceTree = ""; }; - OBJ_706 /* ecdsa_asn1.c */ = {isa = PBXFileReference; path = ecdsa_asn1.c; sourceTree = ""; }; - OBJ_708 /* engine.c */ = {isa = PBXFileReference; path = engine.c; sourceTree = ""; }; - OBJ_71 /* lb_policy_factory.cc */ = {isa = PBXFileReference; path = lb_policy_factory.cc; sourceTree = ""; }; - OBJ_710 /* err.c */ = {isa = PBXFileReference; path = err.c; sourceTree = ""; }; - OBJ_711 /* err_data.c */ = {isa = PBXFileReference; path = err_data.c; sourceTree = ""; }; - OBJ_713 /* digestsign.c */ = {isa = PBXFileReference; path = digestsign.c; sourceTree = ""; }; - OBJ_714 /* evp.c */ = {isa = PBXFileReference; path = evp.c; sourceTree = ""; }; - OBJ_715 /* evp_asn1.c */ = {isa = PBXFileReference; path = evp_asn1.c; sourceTree = ""; }; - OBJ_716 /* evp_ctx.c */ = {isa = PBXFileReference; path = evp_ctx.c; sourceTree = ""; }; - OBJ_717 /* p_dsa_asn1.c */ = {isa = PBXFileReference; path = p_dsa_asn1.c; sourceTree = ""; }; - OBJ_718 /* p_ec.c */ = {isa = PBXFileReference; path = p_ec.c; sourceTree = ""; }; - OBJ_719 /* p_ec_asn1.c */ = {isa = PBXFileReference; path = p_ec_asn1.c; sourceTree = ""; }; - OBJ_72 /* lb_policy_registry.cc */ = {isa = PBXFileReference; path = lb_policy_registry.cc; sourceTree = ""; }; - OBJ_720 /* p_ed25519.c */ = {isa = PBXFileReference; path = p_ed25519.c; sourceTree = ""; }; - OBJ_721 /* p_ed25519_asn1.c */ = {isa = PBXFileReference; path = p_ed25519_asn1.c; sourceTree = ""; }; - OBJ_722 /* p_rsa.c */ = {isa = PBXFileReference; path = p_rsa.c; sourceTree = ""; }; - OBJ_723 /* p_rsa_asn1.c */ = {isa = PBXFileReference; path = p_rsa_asn1.c; sourceTree = ""; }; - OBJ_724 /* pbkdf.c */ = {isa = PBXFileReference; path = pbkdf.c; sourceTree = ""; }; - OBJ_725 /* print.c */ = {isa = PBXFileReference; path = print.c; sourceTree = ""; }; - OBJ_726 /* scrypt.c */ = {isa = PBXFileReference; path = scrypt.c; sourceTree = ""; }; - OBJ_727 /* sign.c */ = {isa = PBXFileReference; path = sign.c; sourceTree = ""; }; - OBJ_728 /* ex_data.c */ = {isa = PBXFileReference; path = ex_data.c; sourceTree = ""; }; - OBJ_73 /* method_params.cc */ = {isa = PBXFileReference; path = method_params.cc; sourceTree = ""; }; - OBJ_731 /* aes.c */ = {isa = PBXFileReference; path = aes.c; sourceTree = ""; }; - OBJ_732 /* key_wrap.c */ = {isa = PBXFileReference; path = key_wrap.c; sourceTree = ""; }; - OBJ_733 /* mode_wrappers.c */ = {isa = PBXFileReference; path = mode_wrappers.c; sourceTree = ""; }; - OBJ_735 /* add.c */ = {isa = PBXFileReference; path = add.c; sourceTree = ""; }; - OBJ_736 /* bn.c */ = {isa = PBXFileReference; path = bn.c; sourceTree = ""; }; - OBJ_737 /* bytes.c */ = {isa = PBXFileReference; path = bytes.c; sourceTree = ""; }; - OBJ_738 /* cmp.c */ = {isa = PBXFileReference; path = cmp.c; sourceTree = ""; }; - OBJ_739 /* ctx.c */ = {isa = PBXFileReference; path = ctx.c; sourceTree = ""; }; - OBJ_74 /* parse_address.cc */ = {isa = PBXFileReference; path = parse_address.cc; sourceTree = ""; }; - OBJ_740 /* div.c */ = {isa = PBXFileReference; path = div.c; sourceTree = ""; }; - OBJ_741 /* exponentiation.c */ = {isa = PBXFileReference; path = exponentiation.c; sourceTree = ""; }; - OBJ_742 /* gcd.c */ = {isa = PBXFileReference; path = gcd.c; sourceTree = ""; }; - OBJ_743 /* generic.c */ = {isa = PBXFileReference; path = generic.c; sourceTree = ""; }; - OBJ_744 /* jacobi.c */ = {isa = PBXFileReference; path = jacobi.c; sourceTree = ""; }; - OBJ_745 /* montgomery.c */ = {isa = PBXFileReference; path = montgomery.c; sourceTree = ""; }; - OBJ_746 /* montgomery_inv.c */ = {isa = PBXFileReference; path = montgomery_inv.c; sourceTree = ""; }; - OBJ_747 /* mul.c */ = {isa = PBXFileReference; path = mul.c; sourceTree = ""; }; - OBJ_748 /* prime.c */ = {isa = PBXFileReference; path = prime.c; sourceTree = ""; }; - OBJ_749 /* random.c */ = {isa = PBXFileReference; path = random.c; sourceTree = ""; }; - OBJ_75 /* proxy_mapper.cc */ = {isa = PBXFileReference; path = proxy_mapper.cc; sourceTree = ""; }; - OBJ_750 /* rsaz_exp.c */ = {isa = PBXFileReference; path = rsaz_exp.c; sourceTree = ""; }; - OBJ_751 /* shift.c */ = {isa = PBXFileReference; path = shift.c; sourceTree = ""; }; - OBJ_752 /* sqrt.c */ = {isa = PBXFileReference; path = sqrt.c; sourceTree = ""; }; - OBJ_754 /* aead.c */ = {isa = PBXFileReference; path = aead.c; sourceTree = ""; }; - OBJ_755 /* cipher.c */ = {isa = PBXFileReference; path = cipher.c; sourceTree = ""; }; - OBJ_756 /* e_aes.c */ = {isa = PBXFileReference; path = e_aes.c; sourceTree = ""; }; - OBJ_757 /* e_des.c */ = {isa = PBXFileReference; path = e_des.c; sourceTree = ""; }; - OBJ_759 /* des.c */ = {isa = PBXFileReference; path = des.c; sourceTree = ""; }; - OBJ_76 /* proxy_mapper_registry.cc */ = {isa = PBXFileReference; path = proxy_mapper_registry.cc; sourceTree = ""; }; - OBJ_761 /* digest.c */ = {isa = PBXFileReference; path = digest.c; sourceTree = ""; }; - OBJ_762 /* digests.c */ = {isa = PBXFileReference; path = digests.c; sourceTree = ""; }; - OBJ_764 /* ec.c */ = {isa = PBXFileReference; path = ec.c; sourceTree = ""; }; - OBJ_765 /* ec_key.c */ = {isa = PBXFileReference; path = ec_key.c; sourceTree = ""; }; - OBJ_766 /* ec_montgomery.c */ = {isa = PBXFileReference; path = ec_montgomery.c; sourceTree = ""; }; - OBJ_767 /* oct.c */ = {isa = PBXFileReference; path = oct.c; sourceTree = ""; }; - OBJ_768 /* p224-64.c */ = {isa = PBXFileReference; path = "p224-64.c"; sourceTree = ""; }; - OBJ_769 /* p256-64.c */ = {isa = PBXFileReference; path = "p256-64.c"; sourceTree = ""; }; - OBJ_77 /* resolver.cc */ = {isa = PBXFileReference; path = resolver.cc; sourceTree = ""; }; - OBJ_770 /* p256-x86_64.c */ = {isa = PBXFileReference; path = "p256-x86_64.c"; sourceTree = ""; }; - OBJ_771 /* simple.c */ = {isa = PBXFileReference; path = simple.c; sourceTree = ""; }; - OBJ_772 /* util-64.c */ = {isa = PBXFileReference; path = "util-64.c"; sourceTree = ""; }; - OBJ_773 /* wnaf.c */ = {isa = PBXFileReference; path = wnaf.c; sourceTree = ""; }; - OBJ_775 /* ecdsa.c */ = {isa = PBXFileReference; path = ecdsa.c; sourceTree = ""; }; - OBJ_777 /* hmac.c */ = {isa = PBXFileReference; path = hmac.c; sourceTree = ""; }; - OBJ_778 /* is_fips.c */ = {isa = PBXFileReference; path = is_fips.c; sourceTree = ""; }; - OBJ_780 /* md4.c */ = {isa = PBXFileReference; path = md4.c; sourceTree = ""; }; - OBJ_782 /* md5.c */ = {isa = PBXFileReference; path = md5.c; sourceTree = ""; }; - OBJ_784 /* cbc.c */ = {isa = PBXFileReference; path = cbc.c; sourceTree = ""; }; - OBJ_785 /* cfb.c */ = {isa = PBXFileReference; path = cfb.c; sourceTree = ""; }; - OBJ_786 /* ctr.c */ = {isa = PBXFileReference; path = ctr.c; sourceTree = ""; }; - OBJ_787 /* gcm.c */ = {isa = PBXFileReference; path = gcm.c; sourceTree = ""; }; - OBJ_788 /* ofb.c */ = {isa = PBXFileReference; path = ofb.c; sourceTree = ""; }; - OBJ_789 /* polyval.c */ = {isa = PBXFileReference; path = polyval.c; sourceTree = ""; }; - OBJ_791 /* ctrdrbg.c */ = {isa = PBXFileReference; path = ctrdrbg.c; sourceTree = ""; }; - OBJ_792 /* rand.c */ = {isa = PBXFileReference; path = rand.c; sourceTree = ""; }; - OBJ_793 /* urandom.c */ = {isa = PBXFileReference; path = urandom.c; sourceTree = ""; }; - OBJ_795 /* blinding.c */ = {isa = PBXFileReference; path = blinding.c; sourceTree = ""; }; - OBJ_796 /* padding.c */ = {isa = PBXFileReference; path = padding.c; sourceTree = ""; }; - OBJ_797 /* rsa.c */ = {isa = PBXFileReference; path = rsa.c; sourceTree = ""; }; - OBJ_798 /* rsa_impl.c */ = {isa = PBXFileReference; path = rsa_impl.c; sourceTree = ""; }; - OBJ_800 /* sha1-altivec.c */ = {isa = PBXFileReference; path = "sha1-altivec.c"; sourceTree = ""; }; - OBJ_801 /* sha1.c */ = {isa = PBXFileReference; path = sha1.c; sourceTree = ""; }; - OBJ_802 /* sha256.c */ = {isa = PBXFileReference; path = sha256.c; sourceTree = ""; }; - OBJ_803 /* sha512.c */ = {isa = PBXFileReference; path = sha512.c; sourceTree = ""; }; - OBJ_805 /* hkdf.c */ = {isa = PBXFileReference; path = hkdf.c; sourceTree = ""; }; - OBJ_807 /* lhash.c */ = {isa = PBXFileReference; path = lhash.c; sourceTree = ""; }; - OBJ_808 /* mem.c */ = {isa = PBXFileReference; path = mem.c; sourceTree = ""; }; - OBJ_81 /* dns_resolver_ares.cc */ = {isa = PBXFileReference; path = dns_resolver_ares.cc; sourceTree = ""; }; - OBJ_810 /* obj.c */ = {isa = PBXFileReference; path = obj.c; sourceTree = ""; }; - OBJ_811 /* obj_xref.c */ = {isa = PBXFileReference; path = obj_xref.c; sourceTree = ""; }; - OBJ_813 /* pem_all.c */ = {isa = PBXFileReference; path = pem_all.c; sourceTree = ""; }; - OBJ_814 /* pem_info.c */ = {isa = PBXFileReference; path = pem_info.c; sourceTree = ""; }; - OBJ_815 /* pem_lib.c */ = {isa = PBXFileReference; path = pem_lib.c; sourceTree = ""; }; - OBJ_816 /* pem_oth.c */ = {isa = PBXFileReference; path = pem_oth.c; sourceTree = ""; }; - OBJ_817 /* pem_pk8.c */ = {isa = PBXFileReference; path = pem_pk8.c; sourceTree = ""; }; - OBJ_818 /* pem_pkey.c */ = {isa = PBXFileReference; path = pem_pkey.c; sourceTree = ""; }; - OBJ_819 /* pem_x509.c */ = {isa = PBXFileReference; path = pem_x509.c; sourceTree = ""; }; - OBJ_82 /* grpc_ares_ev_driver_posix.cc */ = {isa = PBXFileReference; path = grpc_ares_ev_driver_posix.cc; sourceTree = ""; }; - OBJ_820 /* pem_xaux.c */ = {isa = PBXFileReference; path = pem_xaux.c; sourceTree = ""; }; - OBJ_822 /* pkcs7.c */ = {isa = PBXFileReference; path = pkcs7.c; sourceTree = ""; }; - OBJ_823 /* pkcs7_x509.c */ = {isa = PBXFileReference; path = pkcs7_x509.c; sourceTree = ""; }; - OBJ_825 /* p5_pbev2.c */ = {isa = PBXFileReference; path = p5_pbev2.c; sourceTree = ""; }; - OBJ_826 /* pkcs8.c */ = {isa = PBXFileReference; path = pkcs8.c; sourceTree = ""; }; - OBJ_827 /* pkcs8_x509.c */ = {isa = PBXFileReference; path = pkcs8_x509.c; sourceTree = ""; }; - OBJ_829 /* poly1305.c */ = {isa = PBXFileReference; path = poly1305.c; sourceTree = ""; }; - OBJ_83 /* grpc_ares_wrapper.cc */ = {isa = PBXFileReference; path = grpc_ares_wrapper.cc; sourceTree = ""; }; - OBJ_830 /* poly1305_arm.c */ = {isa = PBXFileReference; path = poly1305_arm.c; sourceTree = ""; }; - OBJ_831 /* poly1305_vec.c */ = {isa = PBXFileReference; path = poly1305_vec.c; sourceTree = ""; }; - OBJ_833 /* pool.c */ = {isa = PBXFileReference; path = pool.c; sourceTree = ""; }; - OBJ_835 /* deterministic.c */ = {isa = PBXFileReference; path = deterministic.c; sourceTree = ""; }; - OBJ_836 /* forkunsafe.c */ = {isa = PBXFileReference; path = forkunsafe.c; sourceTree = ""; }; - OBJ_837 /* fuchsia.c */ = {isa = PBXFileReference; path = fuchsia.c; sourceTree = ""; }; - OBJ_838 /* rand_extra.c */ = {isa = PBXFileReference; path = rand_extra.c; sourceTree = ""; }; - OBJ_839 /* windows.c */ = {isa = PBXFileReference; path = windows.c; sourceTree = ""; }; - OBJ_84 /* grpc_ares_wrapper_fallback.cc */ = {isa = PBXFileReference; path = grpc_ares_wrapper_fallback.cc; sourceTree = ""; }; - OBJ_841 /* rc4.c */ = {isa = PBXFileReference; path = rc4.c; sourceTree = ""; }; - OBJ_842 /* refcount_c11.c */ = {isa = PBXFileReference; path = refcount_c11.c; sourceTree = ""; }; - OBJ_843 /* refcount_lock.c */ = {isa = PBXFileReference; path = refcount_lock.c; sourceTree = ""; }; - OBJ_845 /* rsa_asn1.c */ = {isa = PBXFileReference; path = rsa_asn1.c; sourceTree = ""; }; - OBJ_847 /* stack.c */ = {isa = PBXFileReference; path = stack.c; sourceTree = ""; }; - OBJ_848 /* thread.c */ = {isa = PBXFileReference; path = thread.c; sourceTree = ""; }; - OBJ_849 /* thread_none.c */ = {isa = PBXFileReference; path = thread_none.c; sourceTree = ""; }; - OBJ_850 /* thread_pthread.c */ = {isa = PBXFileReference; path = thread_pthread.c; sourceTree = ""; }; - OBJ_851 /* thread_win.c */ = {isa = PBXFileReference; path = thread_win.c; sourceTree = ""; }; - OBJ_853 /* a_digest.c */ = {isa = PBXFileReference; path = a_digest.c; sourceTree = ""; }; - OBJ_854 /* a_sign.c */ = {isa = PBXFileReference; path = a_sign.c; sourceTree = ""; }; - OBJ_855 /* a_strex.c */ = {isa = PBXFileReference; path = a_strex.c; sourceTree = ""; }; - OBJ_856 /* a_verify.c */ = {isa = PBXFileReference; path = a_verify.c; sourceTree = ""; }; - OBJ_857 /* algorithm.c */ = {isa = PBXFileReference; path = algorithm.c; sourceTree = ""; }; - OBJ_858 /* asn1_gen.c */ = {isa = PBXFileReference; path = asn1_gen.c; sourceTree = ""; }; - OBJ_859 /* by_dir.c */ = {isa = PBXFileReference; path = by_dir.c; sourceTree = ""; }; - OBJ_86 /* dns_resolver.cc */ = {isa = PBXFileReference; path = dns_resolver.cc; sourceTree = ""; }; - OBJ_860 /* by_file.c */ = {isa = PBXFileReference; path = by_file.c; sourceTree = ""; }; - OBJ_861 /* i2d_pr.c */ = {isa = PBXFileReference; path = i2d_pr.c; sourceTree = ""; }; - OBJ_862 /* rsa_pss.c */ = {isa = PBXFileReference; path = rsa_pss.c; sourceTree = ""; }; - OBJ_863 /* t_crl.c */ = {isa = PBXFileReference; path = t_crl.c; sourceTree = ""; }; - OBJ_864 /* t_req.c */ = {isa = PBXFileReference; path = t_req.c; sourceTree = ""; }; - OBJ_865 /* t_x509.c */ = {isa = PBXFileReference; path = t_x509.c; sourceTree = ""; }; - OBJ_866 /* t_x509a.c */ = {isa = PBXFileReference; path = t_x509a.c; sourceTree = ""; }; - OBJ_867 /* x509.c */ = {isa = PBXFileReference; path = x509.c; sourceTree = ""; }; - OBJ_868 /* x509_att.c */ = {isa = PBXFileReference; path = x509_att.c; sourceTree = ""; }; - OBJ_869 /* x509_cmp.c */ = {isa = PBXFileReference; path = x509_cmp.c; sourceTree = ""; }; - OBJ_870 /* x509_d2.c */ = {isa = PBXFileReference; path = x509_d2.c; sourceTree = ""; }; - OBJ_871 /* x509_def.c */ = {isa = PBXFileReference; path = x509_def.c; sourceTree = ""; }; - OBJ_872 /* x509_ext.c */ = {isa = PBXFileReference; path = x509_ext.c; sourceTree = ""; }; - OBJ_873 /* x509_lu.c */ = {isa = PBXFileReference; path = x509_lu.c; sourceTree = ""; }; - OBJ_874 /* x509_obj.c */ = {isa = PBXFileReference; path = x509_obj.c; sourceTree = ""; }; - OBJ_875 /* x509_r2x.c */ = {isa = PBXFileReference; path = x509_r2x.c; sourceTree = ""; }; - OBJ_876 /* x509_req.c */ = {isa = PBXFileReference; path = x509_req.c; sourceTree = ""; }; - OBJ_877 /* x509_set.c */ = {isa = PBXFileReference; path = x509_set.c; sourceTree = ""; }; - OBJ_878 /* x509_trs.c */ = {isa = PBXFileReference; path = x509_trs.c; sourceTree = ""; }; - OBJ_879 /* x509_txt.c */ = {isa = PBXFileReference; path = x509_txt.c; sourceTree = ""; }; - OBJ_88 /* fake_resolver.cc */ = {isa = PBXFileReference; path = fake_resolver.cc; sourceTree = ""; }; - OBJ_880 /* x509_v3.c */ = {isa = PBXFileReference; path = x509_v3.c; sourceTree = ""; }; - OBJ_881 /* x509_vfy.c */ = {isa = PBXFileReference; path = x509_vfy.c; sourceTree = ""; }; - OBJ_882 /* x509_vpm.c */ = {isa = PBXFileReference; path = x509_vpm.c; sourceTree = ""; }; - OBJ_883 /* x509cset.c */ = {isa = PBXFileReference; path = x509cset.c; sourceTree = ""; }; - OBJ_884 /* x509name.c */ = {isa = PBXFileReference; path = x509name.c; sourceTree = ""; }; - OBJ_885 /* x509rset.c */ = {isa = PBXFileReference; path = x509rset.c; sourceTree = ""; }; - OBJ_886 /* x509spki.c */ = {isa = PBXFileReference; path = x509spki.c; sourceTree = ""; }; - OBJ_887 /* x_algor.c */ = {isa = PBXFileReference; path = x_algor.c; sourceTree = ""; }; - OBJ_888 /* x_all.c */ = {isa = PBXFileReference; path = x_all.c; sourceTree = ""; }; - OBJ_889 /* x_attrib.c */ = {isa = PBXFileReference; path = x_attrib.c; sourceTree = ""; }; - OBJ_890 /* x_crl.c */ = {isa = PBXFileReference; path = x_crl.c; sourceTree = ""; }; - OBJ_891 /* x_exten.c */ = {isa = PBXFileReference; path = x_exten.c; sourceTree = ""; }; - OBJ_892 /* x_info.c */ = {isa = PBXFileReference; path = x_info.c; sourceTree = ""; }; - OBJ_893 /* x_name.c */ = {isa = PBXFileReference; path = x_name.c; sourceTree = ""; }; - OBJ_894 /* x_pkey.c */ = {isa = PBXFileReference; path = x_pkey.c; sourceTree = ""; }; - OBJ_895 /* x_pubkey.c */ = {isa = PBXFileReference; path = x_pubkey.c; sourceTree = ""; }; - OBJ_896 /* x_req.c */ = {isa = PBXFileReference; path = x_req.c; sourceTree = ""; }; - OBJ_897 /* x_sig.c */ = {isa = PBXFileReference; path = x_sig.c; sourceTree = ""; }; - OBJ_898 /* x_spki.c */ = {isa = PBXFileReference; path = x_spki.c; sourceTree = ""; }; - OBJ_899 /* x_val.c */ = {isa = PBXFileReference; path = x_val.c; sourceTree = ""; }; - OBJ_9 /* Generator-Client.swift */ = {isa = PBXFileReference; path = "Generator-Client.swift"; sourceTree = ""; }; - OBJ_90 /* sockaddr_resolver.cc */ = {isa = PBXFileReference; path = sockaddr_resolver.cc; sourceTree = ""; }; - OBJ_900 /* x_x509.c */ = {isa = PBXFileReference; path = x_x509.c; sourceTree = ""; }; - OBJ_901 /* x_x509a.c */ = {isa = PBXFileReference; path = x_x509a.c; sourceTree = ""; }; - OBJ_903 /* pcy_cache.c */ = {isa = PBXFileReference; path = pcy_cache.c; sourceTree = ""; }; - OBJ_904 /* pcy_data.c */ = {isa = PBXFileReference; path = pcy_data.c; sourceTree = ""; }; - OBJ_905 /* pcy_lib.c */ = {isa = PBXFileReference; path = pcy_lib.c; sourceTree = ""; }; - OBJ_906 /* pcy_map.c */ = {isa = PBXFileReference; path = pcy_map.c; sourceTree = ""; }; - OBJ_907 /* pcy_node.c */ = {isa = PBXFileReference; path = pcy_node.c; sourceTree = ""; }; - OBJ_908 /* pcy_tree.c */ = {isa = PBXFileReference; path = pcy_tree.c; sourceTree = ""; }; - OBJ_909 /* v3_akey.c */ = {isa = PBXFileReference; path = v3_akey.c; sourceTree = ""; }; - OBJ_91 /* resolver_registry.cc */ = {isa = PBXFileReference; path = resolver_registry.cc; sourceTree = ""; }; - OBJ_910 /* v3_akeya.c */ = {isa = PBXFileReference; path = v3_akeya.c; sourceTree = ""; }; - OBJ_911 /* v3_alt.c */ = {isa = PBXFileReference; path = v3_alt.c; sourceTree = ""; }; - OBJ_912 /* v3_bcons.c */ = {isa = PBXFileReference; path = v3_bcons.c; sourceTree = ""; }; - OBJ_913 /* v3_bitst.c */ = {isa = PBXFileReference; path = v3_bitst.c; sourceTree = ""; }; - OBJ_914 /* v3_conf.c */ = {isa = PBXFileReference; path = v3_conf.c; sourceTree = ""; }; - OBJ_915 /* v3_cpols.c */ = {isa = PBXFileReference; path = v3_cpols.c; sourceTree = ""; }; - OBJ_916 /* v3_crld.c */ = {isa = PBXFileReference; path = v3_crld.c; sourceTree = ""; }; - OBJ_917 /* v3_enum.c */ = {isa = PBXFileReference; path = v3_enum.c; sourceTree = ""; }; - OBJ_918 /* v3_extku.c */ = {isa = PBXFileReference; path = v3_extku.c; sourceTree = ""; }; - OBJ_919 /* v3_genn.c */ = {isa = PBXFileReference; path = v3_genn.c; sourceTree = ""; }; - OBJ_92 /* retry_throttle.cc */ = {isa = PBXFileReference; path = retry_throttle.cc; sourceTree = ""; }; - OBJ_920 /* v3_ia5.c */ = {isa = PBXFileReference; path = v3_ia5.c; sourceTree = ""; }; - OBJ_921 /* v3_info.c */ = {isa = PBXFileReference; path = v3_info.c; sourceTree = ""; }; - OBJ_922 /* v3_int.c */ = {isa = PBXFileReference; path = v3_int.c; sourceTree = ""; }; - OBJ_923 /* v3_lib.c */ = {isa = PBXFileReference; path = v3_lib.c; sourceTree = ""; }; - OBJ_924 /* v3_ncons.c */ = {isa = PBXFileReference; path = v3_ncons.c; sourceTree = ""; }; - OBJ_925 /* v3_pci.c */ = {isa = PBXFileReference; path = v3_pci.c; sourceTree = ""; }; - OBJ_926 /* v3_pcia.c */ = {isa = PBXFileReference; path = v3_pcia.c; sourceTree = ""; }; - OBJ_927 /* v3_pcons.c */ = {isa = PBXFileReference; path = v3_pcons.c; sourceTree = ""; }; - OBJ_928 /* v3_pku.c */ = {isa = PBXFileReference; path = v3_pku.c; sourceTree = ""; }; - OBJ_929 /* v3_pmaps.c */ = {isa = PBXFileReference; path = v3_pmaps.c; sourceTree = ""; }; - OBJ_93 /* subchannel.cc */ = {isa = PBXFileReference; path = subchannel.cc; sourceTree = ""; }; - OBJ_930 /* v3_prn.c */ = {isa = PBXFileReference; path = v3_prn.c; sourceTree = ""; }; - OBJ_931 /* v3_purp.c */ = {isa = PBXFileReference; path = v3_purp.c; sourceTree = ""; }; - OBJ_932 /* v3_skey.c */ = {isa = PBXFileReference; path = v3_skey.c; sourceTree = ""; }; - OBJ_933 /* v3_sxnet.c */ = {isa = PBXFileReference; path = v3_sxnet.c; sourceTree = ""; }; - OBJ_934 /* v3_utl.c */ = {isa = PBXFileReference; path = v3_utl.c; sourceTree = ""; }; - OBJ_935 /* err_data.c */ = {isa = PBXFileReference; path = err_data.c; sourceTree = ""; }; - OBJ_937 /* bio_ssl.cc */ = {isa = PBXFileReference; path = bio_ssl.cc; sourceTree = ""; }; - OBJ_938 /* custom_extensions.cc */ = {isa = PBXFileReference; path = custom_extensions.cc; sourceTree = ""; }; - OBJ_939 /* d1_both.cc */ = {isa = PBXFileReference; path = d1_both.cc; sourceTree = ""; }; - OBJ_94 /* subchannel_index.cc */ = {isa = PBXFileReference; path = subchannel_index.cc; sourceTree = ""; }; - OBJ_940 /* d1_lib.cc */ = {isa = PBXFileReference; path = d1_lib.cc; sourceTree = ""; }; - OBJ_941 /* d1_pkt.cc */ = {isa = PBXFileReference; path = d1_pkt.cc; sourceTree = ""; }; - OBJ_942 /* d1_srtp.cc */ = {isa = PBXFileReference; path = d1_srtp.cc; sourceTree = ""; }; - OBJ_943 /* dtls_method.cc */ = {isa = PBXFileReference; path = dtls_method.cc; sourceTree = ""; }; - OBJ_944 /* dtls_record.cc */ = {isa = PBXFileReference; path = dtls_record.cc; sourceTree = ""; }; - OBJ_945 /* handshake.cc */ = {isa = PBXFileReference; path = handshake.cc; sourceTree = ""; }; - OBJ_946 /* handshake_client.cc */ = {isa = PBXFileReference; path = handshake_client.cc; sourceTree = ""; }; - OBJ_947 /* handshake_server.cc */ = {isa = PBXFileReference; path = handshake_server.cc; sourceTree = ""; }; - OBJ_948 /* s3_both.cc */ = {isa = PBXFileReference; path = s3_both.cc; sourceTree = ""; }; - OBJ_949 /* s3_lib.cc */ = {isa = PBXFileReference; path = s3_lib.cc; sourceTree = ""; }; - OBJ_95 /* uri_parser.cc */ = {isa = PBXFileReference; path = uri_parser.cc; sourceTree = ""; }; - OBJ_950 /* s3_pkt.cc */ = {isa = PBXFileReference; path = s3_pkt.cc; sourceTree = ""; }; - OBJ_951 /* ssl_aead_ctx.cc */ = {isa = PBXFileReference; path = ssl_aead_ctx.cc; sourceTree = ""; }; - OBJ_952 /* ssl_asn1.cc */ = {isa = PBXFileReference; path = ssl_asn1.cc; sourceTree = ""; }; - OBJ_953 /* ssl_buffer.cc */ = {isa = PBXFileReference; path = ssl_buffer.cc; sourceTree = ""; }; - OBJ_954 /* ssl_cert.cc */ = {isa = PBXFileReference; path = ssl_cert.cc; sourceTree = ""; }; - OBJ_955 /* ssl_cipher.cc */ = {isa = PBXFileReference; path = ssl_cipher.cc; sourceTree = ""; }; - OBJ_956 /* ssl_file.cc */ = {isa = PBXFileReference; path = ssl_file.cc; sourceTree = ""; }; - OBJ_957 /* ssl_key_share.cc */ = {isa = PBXFileReference; path = ssl_key_share.cc; sourceTree = ""; }; - OBJ_958 /* ssl_lib.cc */ = {isa = PBXFileReference; path = ssl_lib.cc; sourceTree = ""; }; - OBJ_959 /* ssl_privkey.cc */ = {isa = PBXFileReference; path = ssl_privkey.cc; sourceTree = ""; }; - OBJ_960 /* ssl_session.cc */ = {isa = PBXFileReference; path = ssl_session.cc; sourceTree = ""; }; - OBJ_961 /* ssl_stat.cc */ = {isa = PBXFileReference; path = ssl_stat.cc; sourceTree = ""; }; - OBJ_962 /* ssl_transcript.cc */ = {isa = PBXFileReference; path = ssl_transcript.cc; sourceTree = ""; }; - OBJ_963 /* ssl_versions.cc */ = {isa = PBXFileReference; path = ssl_versions.cc; sourceTree = ""; }; - OBJ_964 /* ssl_x509.cc */ = {isa = PBXFileReference; path = ssl_x509.cc; sourceTree = ""; }; - OBJ_965 /* t1_enc.cc */ = {isa = PBXFileReference; path = t1_enc.cc; sourceTree = ""; }; - OBJ_966 /* t1_lib.cc */ = {isa = PBXFileReference; path = t1_lib.cc; sourceTree = ""; }; - OBJ_967 /* tls13_both.cc */ = {isa = PBXFileReference; path = tls13_both.cc; sourceTree = ""; }; - OBJ_968 /* tls13_client.cc */ = {isa = PBXFileReference; path = tls13_client.cc; sourceTree = ""; }; - OBJ_969 /* tls13_enc.cc */ = {isa = PBXFileReference; path = tls13_enc.cc; sourceTree = ""; }; - OBJ_97 /* deadline_filter.cc */ = {isa = PBXFileReference; path = deadline_filter.cc; sourceTree = ""; }; - OBJ_970 /* tls13_server.cc */ = {isa = PBXFileReference; path = tls13_server.cc; sourceTree = ""; }; - OBJ_971 /* tls_method.cc */ = {isa = PBXFileReference; path = tls_method.cc; sourceTree = ""; }; - OBJ_972 /* tls_record.cc */ = {isa = PBXFileReference; path = tls_record.cc; sourceTree = ""; }; - OBJ_975 /* curve25519.c */ = {isa = PBXFileReference; path = curve25519.c; sourceTree = ""; }; - OBJ_978 /* pem.h */ = {isa = PBXFileReference; path = pem.h; sourceTree = ""; }; - OBJ_979 /* nid.h */ = {isa = PBXFileReference; path = nid.h; sourceTree = ""; }; - OBJ_980 /* ssl3.h */ = {isa = PBXFileReference; path = ssl3.h; sourceTree = ""; }; - OBJ_981 /* ossl_typ.h */ = {isa = PBXFileReference; path = ossl_typ.h; sourceTree = ""; }; - OBJ_982 /* dtls1.h */ = {isa = PBXFileReference; path = dtls1.h; sourceTree = ""; }; - OBJ_983 /* err.h */ = {isa = PBXFileReference; path = err.h; sourceTree = ""; }; - OBJ_984 /* bn.h */ = {isa = PBXFileReference; path = bn.h; sourceTree = ""; }; - OBJ_985 /* blowfish.h */ = {isa = PBXFileReference; path = blowfish.h; sourceTree = ""; }; - OBJ_986 /* engine.h */ = {isa = PBXFileReference; path = engine.h; sourceTree = ""; }; - OBJ_987 /* bytestring.h */ = {isa = PBXFileReference; path = bytestring.h; sourceTree = ""; }; - OBJ_988 /* x509.h */ = {isa = PBXFileReference; path = x509.h; sourceTree = ""; }; - OBJ_989 /* asn1_mac.h */ = {isa = PBXFileReference; path = asn1_mac.h; sourceTree = ""; }; - OBJ_990 /* pool.h */ = {isa = PBXFileReference; path = pool.h; sourceTree = ""; }; - OBJ_991 /* ec_key.h */ = {isa = PBXFileReference; path = ec_key.h; sourceTree = ""; }; - OBJ_992 /* base64.h */ = {isa = PBXFileReference; path = base64.h; sourceTree = ""; }; - OBJ_993 /* is_boringssl.h */ = {isa = PBXFileReference; path = is_boringssl.h; sourceTree = ""; }; - OBJ_994 /* sha.h */ = {isa = PBXFileReference; path = sha.h; sourceTree = ""; }; - OBJ_995 /* asn1.h */ = {isa = PBXFileReference; path = asn1.h; sourceTree = ""; }; - OBJ_996 /* chacha.h */ = {isa = PBXFileReference; path = chacha.h; sourceTree = ""; }; - OBJ_997 /* opensslconf.h */ = {isa = PBXFileReference; path = opensslconf.h; sourceTree = ""; }; - OBJ_998 /* arm_arch.h */ = {isa = PBXFileReference; path = arm_arch.h; sourceTree = ""; }; - OBJ_999 /* bio.h */ = {isa = PBXFileReference; path = bio.h; sourceTree = ""; }; + OBJ_600 /* hpack_encoder.cc */ = {isa = PBXFileReference; path = hpack_encoder.cc; sourceTree = ""; }; + OBJ_601 /* hpack_parser.cc */ = {isa = PBXFileReference; path = hpack_parser.cc; sourceTree = ""; }; + OBJ_602 /* hpack_table.cc */ = {isa = PBXFileReference; path = hpack_table.cc; sourceTree = ""; }; + OBJ_603 /* http2_settings.cc */ = {isa = PBXFileReference; path = http2_settings.cc; sourceTree = ""; }; + OBJ_604 /* huffsyms.cc */ = {isa = PBXFileReference; path = huffsyms.cc; sourceTree = ""; }; + OBJ_605 /* incoming_metadata.cc */ = {isa = PBXFileReference; path = incoming_metadata.cc; sourceTree = ""; }; + OBJ_606 /* parsing.cc */ = {isa = PBXFileReference; path = parsing.cc; sourceTree = ""; }; + OBJ_607 /* stream_lists.cc */ = {isa = PBXFileReference; path = stream_lists.cc; sourceTree = ""; }; + OBJ_608 /* stream_map.cc */ = {isa = PBXFileReference; path = stream_map.cc; sourceTree = ""; }; + OBJ_609 /* varint.cc */ = {isa = PBXFileReference; path = varint.cc; sourceTree = ""; }; + OBJ_61 /* asn1_compat.c */ = {isa = PBXFileReference; path = asn1_compat.c; sourceTree = ""; }; + OBJ_610 /* writing.cc */ = {isa = PBXFileReference; path = writing.cc; sourceTree = ""; }; + OBJ_612 /* inproc_plugin.cc */ = {isa = PBXFileReference; path = inproc_plugin.cc; sourceTree = ""; }; + OBJ_613 /* inproc_transport.cc */ = {isa = PBXFileReference; path = inproc_transport.cc; sourceTree = ""; }; + OBJ_616 /* avl.cc */ = {isa = PBXFileReference; path = avl.cc; sourceTree = ""; }; + OBJ_618 /* backoff.cc */ = {isa = PBXFileReference; path = backoff.cc; sourceTree = ""; }; + OBJ_62 /* ber.c */ = {isa = PBXFileReference; path = ber.c; sourceTree = ""; }; + OBJ_620 /* channel_args.cc */ = {isa = PBXFileReference; path = channel_args.cc; sourceTree = ""; }; + OBJ_621 /* channel_stack.cc */ = {isa = PBXFileReference; path = channel_stack.cc; sourceTree = ""; }; + OBJ_622 /* channel_stack_builder.cc */ = {isa = PBXFileReference; path = channel_stack_builder.cc; sourceTree = ""; }; + OBJ_623 /* channel_trace.cc */ = {isa = PBXFileReference; path = channel_trace.cc; sourceTree = ""; }; + OBJ_624 /* channelz.cc */ = {isa = PBXFileReference; path = channelz.cc; sourceTree = ""; }; + OBJ_625 /* channelz_registry.cc */ = {isa = PBXFileReference; path = channelz_registry.cc; sourceTree = ""; }; + OBJ_626 /* connected_channel.cc */ = {isa = PBXFileReference; path = connected_channel.cc; sourceTree = ""; }; + OBJ_627 /* handshaker.cc */ = {isa = PBXFileReference; path = handshaker.cc; sourceTree = ""; }; + OBJ_628 /* handshaker_registry.cc */ = {isa = PBXFileReference; path = handshaker_registry.cc; sourceTree = ""; }; + OBJ_629 /* status_util.cc */ = {isa = PBXFileReference; path = status_util.cc; sourceTree = ""; }; + OBJ_63 /* cbb.c */ = {isa = PBXFileReference; path = cbb.c; sourceTree = ""; }; + OBJ_631 /* compression.cc */ = {isa = PBXFileReference; path = compression.cc; sourceTree = ""; }; + OBJ_632 /* compression_internal.cc */ = {isa = PBXFileReference; path = compression_internal.cc; sourceTree = ""; }; + OBJ_633 /* message_compress.cc */ = {isa = PBXFileReference; path = message_compress.cc; sourceTree = ""; }; + OBJ_634 /* stream_compression.cc */ = {isa = PBXFileReference; path = stream_compression.cc; sourceTree = ""; }; + OBJ_635 /* stream_compression_gzip.cc */ = {isa = PBXFileReference; path = stream_compression_gzip.cc; sourceTree = ""; }; + OBJ_636 /* stream_compression_identity.cc */ = {isa = PBXFileReference; path = stream_compression_identity.cc; sourceTree = ""; }; + OBJ_638 /* stats.cc */ = {isa = PBXFileReference; path = stats.cc; sourceTree = ""; }; + OBJ_639 /* stats_data.cc */ = {isa = PBXFileReference; path = stats_data.cc; sourceTree = ""; }; + OBJ_64 /* cbs.c */ = {isa = PBXFileReference; path = cbs.c; sourceTree = ""; }; + OBJ_640 /* trace.cc */ = {isa = PBXFileReference; path = trace.cc; sourceTree = ""; }; + OBJ_642 /* alloc.cc */ = {isa = PBXFileReference; path = alloc.cc; sourceTree = ""; }; + OBJ_643 /* arena.cc */ = {isa = PBXFileReference; path = arena.cc; sourceTree = ""; }; + OBJ_644 /* atm.cc */ = {isa = PBXFileReference; path = atm.cc; sourceTree = ""; }; + OBJ_645 /* cpu_iphone.cc */ = {isa = PBXFileReference; path = cpu_iphone.cc; sourceTree = ""; }; + OBJ_646 /* cpu_linux.cc */ = {isa = PBXFileReference; path = cpu_linux.cc; sourceTree = ""; }; + OBJ_647 /* cpu_posix.cc */ = {isa = PBXFileReference; path = cpu_posix.cc; sourceTree = ""; }; + OBJ_648 /* cpu_windows.cc */ = {isa = PBXFileReference; path = cpu_windows.cc; sourceTree = ""; }; + OBJ_649 /* env_linux.cc */ = {isa = PBXFileReference; path = env_linux.cc; sourceTree = ""; }; + OBJ_650 /* env_posix.cc */ = {isa = PBXFileReference; path = env_posix.cc; sourceTree = ""; }; + OBJ_651 /* env_windows.cc */ = {isa = PBXFileReference; path = env_windows.cc; sourceTree = ""; }; + OBJ_652 /* host_port.cc */ = {isa = PBXFileReference; path = host_port.cc; sourceTree = ""; }; + OBJ_653 /* log.cc */ = {isa = PBXFileReference; path = log.cc; sourceTree = ""; }; + OBJ_654 /* log_android.cc */ = {isa = PBXFileReference; path = log_android.cc; sourceTree = ""; }; + OBJ_655 /* log_linux.cc */ = {isa = PBXFileReference; path = log_linux.cc; sourceTree = ""; }; + OBJ_656 /* log_posix.cc */ = {isa = PBXFileReference; path = log_posix.cc; sourceTree = ""; }; + OBJ_657 /* log_windows.cc */ = {isa = PBXFileReference; path = log_windows.cc; sourceTree = ""; }; + OBJ_658 /* mpscq.cc */ = {isa = PBXFileReference; path = mpscq.cc; sourceTree = ""; }; + OBJ_659 /* murmur_hash.cc */ = {isa = PBXFileReference; path = murmur_hash.cc; sourceTree = ""; }; + OBJ_66 /* chacha.c */ = {isa = PBXFileReference; path = chacha.c; sourceTree = ""; }; + OBJ_660 /* string.cc */ = {isa = PBXFileReference; path = string.cc; sourceTree = ""; }; + OBJ_661 /* string_posix.cc */ = {isa = PBXFileReference; path = string_posix.cc; sourceTree = ""; }; + OBJ_662 /* string_util_windows.cc */ = {isa = PBXFileReference; path = string_util_windows.cc; sourceTree = ""; }; + OBJ_663 /* string_windows.cc */ = {isa = PBXFileReference; path = string_windows.cc; sourceTree = ""; }; + OBJ_664 /* sync.cc */ = {isa = PBXFileReference; path = sync.cc; sourceTree = ""; }; + OBJ_665 /* sync_posix.cc */ = {isa = PBXFileReference; path = sync_posix.cc; sourceTree = ""; }; + OBJ_666 /* sync_windows.cc */ = {isa = PBXFileReference; path = sync_windows.cc; sourceTree = ""; }; + OBJ_667 /* time.cc */ = {isa = PBXFileReference; path = time.cc; sourceTree = ""; }; + OBJ_668 /* time_posix.cc */ = {isa = PBXFileReference; path = time_posix.cc; sourceTree = ""; }; + OBJ_669 /* time_precise.cc */ = {isa = PBXFileReference; path = time_precise.cc; sourceTree = ""; }; + OBJ_670 /* time_windows.cc */ = {isa = PBXFileReference; path = time_windows.cc; sourceTree = ""; }; + OBJ_671 /* tls_pthread.cc */ = {isa = PBXFileReference; path = tls_pthread.cc; sourceTree = ""; }; + OBJ_672 /* tmpfile_msys.cc */ = {isa = PBXFileReference; path = tmpfile_msys.cc; sourceTree = ""; }; + OBJ_673 /* tmpfile_posix.cc */ = {isa = PBXFileReference; path = tmpfile_posix.cc; sourceTree = ""; }; + OBJ_674 /* tmpfile_windows.cc */ = {isa = PBXFileReference; path = tmpfile_windows.cc; sourceTree = ""; }; + OBJ_675 /* wrap_memcpy.cc */ = {isa = PBXFileReference; path = wrap_memcpy.cc; sourceTree = ""; }; + OBJ_677 /* fork.cc */ = {isa = PBXFileReference; path = fork.cc; sourceTree = ""; }; + OBJ_678 /* thd_posix.cc */ = {isa = PBXFileReference; path = thd_posix.cc; sourceTree = ""; }; + OBJ_679 /* thd_windows.cc */ = {isa = PBXFileReference; path = thd_windows.cc; sourceTree = ""; }; + OBJ_68 /* cipher_extra.c */ = {isa = PBXFileReference; path = cipher_extra.c; sourceTree = ""; }; + OBJ_681 /* format_request.cc */ = {isa = PBXFileReference; path = format_request.cc; sourceTree = ""; }; + OBJ_682 /* httpcli.cc */ = {isa = PBXFileReference; path = httpcli.cc; sourceTree = ""; }; + OBJ_683 /* httpcli_security_connector.cc */ = {isa = PBXFileReference; path = httpcli_security_connector.cc; sourceTree = ""; }; + OBJ_684 /* parser.cc */ = {isa = PBXFileReference; path = parser.cc; sourceTree = ""; }; + OBJ_686 /* buffer_list.cc */ = {isa = PBXFileReference; path = buffer_list.cc; sourceTree = ""; }; + OBJ_687 /* call_combiner.cc */ = {isa = PBXFileReference; path = call_combiner.cc; sourceTree = ""; }; + OBJ_688 /* combiner.cc */ = {isa = PBXFileReference; path = combiner.cc; sourceTree = ""; }; + OBJ_689 /* endpoint.cc */ = {isa = PBXFileReference; path = endpoint.cc; sourceTree = ""; }; + OBJ_69 /* derive_key.c */ = {isa = PBXFileReference; path = derive_key.c; sourceTree = ""; }; + OBJ_690 /* endpoint_pair_posix.cc */ = {isa = PBXFileReference; path = endpoint_pair_posix.cc; sourceTree = ""; }; + OBJ_691 /* endpoint_pair_uv.cc */ = {isa = PBXFileReference; path = endpoint_pair_uv.cc; sourceTree = ""; }; + OBJ_692 /* endpoint_pair_windows.cc */ = {isa = PBXFileReference; path = endpoint_pair_windows.cc; sourceTree = ""; }; + OBJ_693 /* error.cc */ = {isa = PBXFileReference; path = error.cc; sourceTree = ""; }; + OBJ_694 /* ev_epoll1_linux.cc */ = {isa = PBXFileReference; path = ev_epoll1_linux.cc; sourceTree = ""; }; + OBJ_695 /* ev_epollex_linux.cc */ = {isa = PBXFileReference; path = ev_epollex_linux.cc; sourceTree = ""; }; + OBJ_696 /* ev_poll_posix.cc */ = {isa = PBXFileReference; path = ev_poll_posix.cc; sourceTree = ""; }; + OBJ_697 /* ev_posix.cc */ = {isa = PBXFileReference; path = ev_posix.cc; sourceTree = ""; }; + OBJ_698 /* ev_windows.cc */ = {isa = PBXFileReference; path = ev_windows.cc; sourceTree = ""; }; + OBJ_699 /* exec_ctx.cc */ = {isa = PBXFileReference; path = exec_ctx.cc; sourceTree = ""; }; + OBJ_70 /* e_aesccm.c */ = {isa = PBXFileReference; path = e_aesccm.c; sourceTree = ""; }; + OBJ_700 /* executor.cc */ = {isa = PBXFileReference; path = executor.cc; sourceTree = ""; }; + OBJ_701 /* fork_posix.cc */ = {isa = PBXFileReference; path = fork_posix.cc; sourceTree = ""; }; + OBJ_702 /* fork_windows.cc */ = {isa = PBXFileReference; path = fork_windows.cc; sourceTree = ""; }; + OBJ_703 /* gethostname_fallback.cc */ = {isa = PBXFileReference; path = gethostname_fallback.cc; sourceTree = ""; }; + OBJ_704 /* gethostname_host_name_max.cc */ = {isa = PBXFileReference; path = gethostname_host_name_max.cc; sourceTree = ""; }; + OBJ_705 /* gethostname_sysconf.cc */ = {isa = PBXFileReference; path = gethostname_sysconf.cc; sourceTree = ""; }; + OBJ_706 /* grpc_if_nametoindex_posix.cc */ = {isa = PBXFileReference; path = grpc_if_nametoindex_posix.cc; sourceTree = ""; }; + OBJ_707 /* grpc_if_nametoindex_unsupported.cc */ = {isa = PBXFileReference; path = grpc_if_nametoindex_unsupported.cc; sourceTree = ""; }; + OBJ_708 /* internal_errqueue.cc */ = {isa = PBXFileReference; path = internal_errqueue.cc; sourceTree = ""; }; + OBJ_709 /* iocp_windows.cc */ = {isa = PBXFileReference; path = iocp_windows.cc; sourceTree = ""; }; + OBJ_71 /* e_aesctrhmac.c */ = {isa = PBXFileReference; path = e_aesctrhmac.c; sourceTree = ""; }; + OBJ_710 /* iomgr.cc */ = {isa = PBXFileReference; path = iomgr.cc; sourceTree = ""; }; + OBJ_711 /* iomgr_custom.cc */ = {isa = PBXFileReference; path = iomgr_custom.cc; sourceTree = ""; }; + OBJ_712 /* iomgr_internal.cc */ = {isa = PBXFileReference; path = iomgr_internal.cc; sourceTree = ""; }; + OBJ_713 /* iomgr_posix.cc */ = {isa = PBXFileReference; path = iomgr_posix.cc; sourceTree = ""; }; + OBJ_714 /* iomgr_uv.cc */ = {isa = PBXFileReference; path = iomgr_uv.cc; sourceTree = ""; }; + OBJ_715 /* iomgr_windows.cc */ = {isa = PBXFileReference; path = iomgr_windows.cc; sourceTree = ""; }; + OBJ_716 /* is_epollexclusive_available.cc */ = {isa = PBXFileReference; path = is_epollexclusive_available.cc; sourceTree = ""; }; + OBJ_717 /* load_file.cc */ = {isa = PBXFileReference; path = load_file.cc; sourceTree = ""; }; + OBJ_718 /* lockfree_event.cc */ = {isa = PBXFileReference; path = lockfree_event.cc; sourceTree = ""; }; + OBJ_719 /* polling_entity.cc */ = {isa = PBXFileReference; path = polling_entity.cc; sourceTree = ""; }; + OBJ_72 /* e_aesgcmsiv.c */ = {isa = PBXFileReference; path = e_aesgcmsiv.c; sourceTree = ""; }; + OBJ_720 /* pollset.cc */ = {isa = PBXFileReference; path = pollset.cc; sourceTree = ""; }; + OBJ_721 /* pollset_custom.cc */ = {isa = PBXFileReference; path = pollset_custom.cc; sourceTree = ""; }; + OBJ_722 /* pollset_set.cc */ = {isa = PBXFileReference; path = pollset_set.cc; sourceTree = ""; }; + OBJ_723 /* pollset_set_custom.cc */ = {isa = PBXFileReference; path = pollset_set_custom.cc; sourceTree = ""; }; + OBJ_724 /* pollset_set_windows.cc */ = {isa = PBXFileReference; path = pollset_set_windows.cc; sourceTree = ""; }; + OBJ_725 /* pollset_uv.cc */ = {isa = PBXFileReference; path = pollset_uv.cc; sourceTree = ""; }; + OBJ_726 /* pollset_windows.cc */ = {isa = PBXFileReference; path = pollset_windows.cc; sourceTree = ""; }; + OBJ_727 /* resolve_address.cc */ = {isa = PBXFileReference; path = resolve_address.cc; sourceTree = ""; }; + OBJ_728 /* resolve_address_custom.cc */ = {isa = PBXFileReference; path = resolve_address_custom.cc; sourceTree = ""; }; + OBJ_729 /* resolve_address_posix.cc */ = {isa = PBXFileReference; path = resolve_address_posix.cc; sourceTree = ""; }; + OBJ_73 /* e_chacha20poly1305.c */ = {isa = PBXFileReference; path = e_chacha20poly1305.c; sourceTree = ""; }; + OBJ_730 /* resolve_address_windows.cc */ = {isa = PBXFileReference; path = resolve_address_windows.cc; sourceTree = ""; }; + OBJ_731 /* resource_quota.cc */ = {isa = PBXFileReference; path = resource_quota.cc; sourceTree = ""; }; + OBJ_732 /* sockaddr_utils.cc */ = {isa = PBXFileReference; path = sockaddr_utils.cc; sourceTree = ""; }; + OBJ_733 /* socket_factory_posix.cc */ = {isa = PBXFileReference; path = socket_factory_posix.cc; sourceTree = ""; }; + OBJ_734 /* socket_mutator.cc */ = {isa = PBXFileReference; path = socket_mutator.cc; sourceTree = ""; }; + OBJ_735 /* socket_utils_common_posix.cc */ = {isa = PBXFileReference; path = socket_utils_common_posix.cc; sourceTree = ""; }; + OBJ_736 /* socket_utils_linux.cc */ = {isa = PBXFileReference; path = socket_utils_linux.cc; sourceTree = ""; }; + OBJ_737 /* socket_utils_posix.cc */ = {isa = PBXFileReference; path = socket_utils_posix.cc; sourceTree = ""; }; + OBJ_738 /* socket_utils_uv.cc */ = {isa = PBXFileReference; path = socket_utils_uv.cc; sourceTree = ""; }; + OBJ_739 /* socket_utils_windows.cc */ = {isa = PBXFileReference; path = socket_utils_windows.cc; sourceTree = ""; }; + OBJ_74 /* e_null.c */ = {isa = PBXFileReference; path = e_null.c; sourceTree = ""; }; + OBJ_740 /* socket_windows.cc */ = {isa = PBXFileReference; path = socket_windows.cc; sourceTree = ""; }; + OBJ_741 /* tcp_client.cc */ = {isa = PBXFileReference; path = tcp_client.cc; sourceTree = ""; }; + OBJ_742 /* tcp_client_custom.cc */ = {isa = PBXFileReference; path = tcp_client_custom.cc; sourceTree = ""; }; + OBJ_743 /* tcp_client_posix.cc */ = {isa = PBXFileReference; path = tcp_client_posix.cc; sourceTree = ""; }; + OBJ_744 /* tcp_client_windows.cc */ = {isa = PBXFileReference; path = tcp_client_windows.cc; sourceTree = ""; }; + OBJ_745 /* tcp_custom.cc */ = {isa = PBXFileReference; path = tcp_custom.cc; sourceTree = ""; }; + OBJ_746 /* tcp_posix.cc */ = {isa = PBXFileReference; path = tcp_posix.cc; sourceTree = ""; }; + OBJ_747 /* tcp_server.cc */ = {isa = PBXFileReference; path = tcp_server.cc; sourceTree = ""; }; + OBJ_748 /* tcp_server_custom.cc */ = {isa = PBXFileReference; path = tcp_server_custom.cc; sourceTree = ""; }; + OBJ_749 /* tcp_server_posix.cc */ = {isa = PBXFileReference; path = tcp_server_posix.cc; sourceTree = ""; }; + OBJ_75 /* e_rc2.c */ = {isa = PBXFileReference; path = e_rc2.c; sourceTree = ""; }; + OBJ_750 /* tcp_server_utils_posix_common.cc */ = {isa = PBXFileReference; path = tcp_server_utils_posix_common.cc; sourceTree = ""; }; + OBJ_751 /* tcp_server_utils_posix_ifaddrs.cc */ = {isa = PBXFileReference; path = tcp_server_utils_posix_ifaddrs.cc; sourceTree = ""; }; + OBJ_752 /* tcp_server_utils_posix_noifaddrs.cc */ = {isa = PBXFileReference; path = tcp_server_utils_posix_noifaddrs.cc; sourceTree = ""; }; + OBJ_753 /* tcp_server_windows.cc */ = {isa = PBXFileReference; path = tcp_server_windows.cc; sourceTree = ""; }; + OBJ_754 /* tcp_uv.cc */ = {isa = PBXFileReference; path = tcp_uv.cc; sourceTree = ""; }; + OBJ_755 /* tcp_windows.cc */ = {isa = PBXFileReference; path = tcp_windows.cc; sourceTree = ""; }; + OBJ_756 /* time_averaged_stats.cc */ = {isa = PBXFileReference; path = time_averaged_stats.cc; sourceTree = ""; }; + OBJ_757 /* timer.cc */ = {isa = PBXFileReference; path = timer.cc; sourceTree = ""; }; + OBJ_758 /* timer_custom.cc */ = {isa = PBXFileReference; path = timer_custom.cc; sourceTree = ""; }; + OBJ_759 /* timer_generic.cc */ = {isa = PBXFileReference; path = timer_generic.cc; sourceTree = ""; }; + OBJ_76 /* e_rc4.c */ = {isa = PBXFileReference; path = e_rc4.c; sourceTree = ""; }; + OBJ_760 /* timer_heap.cc */ = {isa = PBXFileReference; path = timer_heap.cc; sourceTree = ""; }; + OBJ_761 /* timer_manager.cc */ = {isa = PBXFileReference; path = timer_manager.cc; sourceTree = ""; }; + OBJ_762 /* timer_uv.cc */ = {isa = PBXFileReference; path = timer_uv.cc; sourceTree = ""; }; + OBJ_763 /* udp_server.cc */ = {isa = PBXFileReference; path = udp_server.cc; sourceTree = ""; }; + OBJ_764 /* unix_sockets_posix.cc */ = {isa = PBXFileReference; path = unix_sockets_posix.cc; sourceTree = ""; }; + OBJ_765 /* unix_sockets_posix_noop.cc */ = {isa = PBXFileReference; path = unix_sockets_posix_noop.cc; sourceTree = ""; }; + OBJ_766 /* wakeup_fd_cv.cc */ = {isa = PBXFileReference; path = wakeup_fd_cv.cc; sourceTree = ""; }; + OBJ_767 /* wakeup_fd_eventfd.cc */ = {isa = PBXFileReference; path = wakeup_fd_eventfd.cc; sourceTree = ""; }; + OBJ_768 /* wakeup_fd_nospecial.cc */ = {isa = PBXFileReference; path = wakeup_fd_nospecial.cc; sourceTree = ""; }; + OBJ_769 /* wakeup_fd_pipe.cc */ = {isa = PBXFileReference; path = wakeup_fd_pipe.cc; sourceTree = ""; }; + OBJ_77 /* e_ssl3.c */ = {isa = PBXFileReference; path = e_ssl3.c; sourceTree = ""; }; + OBJ_770 /* wakeup_fd_posix.cc */ = {isa = PBXFileReference; path = wakeup_fd_posix.cc; sourceTree = ""; }; + OBJ_772 /* json.cc */ = {isa = PBXFileReference; path = json.cc; sourceTree = ""; }; + OBJ_773 /* json_reader.cc */ = {isa = PBXFileReference; path = json_reader.cc; sourceTree = ""; }; + OBJ_774 /* json_string.cc */ = {isa = PBXFileReference; path = json_string.cc; sourceTree = ""; }; + OBJ_775 /* json_writer.cc */ = {isa = PBXFileReference; path = json_writer.cc; sourceTree = ""; }; + OBJ_777 /* basic_timers.cc */ = {isa = PBXFileReference; path = basic_timers.cc; sourceTree = ""; }; + OBJ_778 /* stap_timers.cc */ = {isa = PBXFileReference; path = stap_timers.cc; sourceTree = ""; }; + OBJ_78 /* e_tls.c */ = {isa = PBXFileReference; path = e_tls.c; sourceTree = ""; }; + OBJ_781 /* security_context.cc */ = {isa = PBXFileReference; path = security_context.cc; sourceTree = ""; }; + OBJ_784 /* alts_credentials.cc */ = {isa = PBXFileReference; path = alts_credentials.cc; sourceTree = ""; }; + OBJ_785 /* check_gcp_environment.cc */ = {isa = PBXFileReference; path = check_gcp_environment.cc; sourceTree = ""; }; + OBJ_786 /* check_gcp_environment_linux.cc */ = {isa = PBXFileReference; path = check_gcp_environment_linux.cc; sourceTree = ""; }; + OBJ_787 /* check_gcp_environment_no_op.cc */ = {isa = PBXFileReference; path = check_gcp_environment_no_op.cc; sourceTree = ""; }; + OBJ_788 /* check_gcp_environment_windows.cc */ = {isa = PBXFileReference; path = check_gcp_environment_windows.cc; sourceTree = ""; }; + OBJ_789 /* grpc_alts_credentials_client_options.cc */ = {isa = PBXFileReference; path = grpc_alts_credentials_client_options.cc; sourceTree = ""; }; + OBJ_79 /* tls_cbc.c */ = {isa = PBXFileReference; path = tls_cbc.c; sourceTree = ""; }; + OBJ_790 /* grpc_alts_credentials_options.cc */ = {isa = PBXFileReference; path = grpc_alts_credentials_options.cc; sourceTree = ""; }; + OBJ_791 /* grpc_alts_credentials_server_options.cc */ = {isa = PBXFileReference; path = grpc_alts_credentials_server_options.cc; sourceTree = ""; }; + OBJ_793 /* composite_credentials.cc */ = {isa = PBXFileReference; path = composite_credentials.cc; sourceTree = ""; }; + OBJ_794 /* credentials.cc */ = {isa = PBXFileReference; path = credentials.cc; sourceTree = ""; }; + OBJ_795 /* credentials_metadata.cc */ = {isa = PBXFileReference; path = credentials_metadata.cc; sourceTree = ""; }; + OBJ_797 /* fake_credentials.cc */ = {isa = PBXFileReference; path = fake_credentials.cc; sourceTree = ""; }; + OBJ_799 /* credentials_generic.cc */ = {isa = PBXFileReference; path = credentials_generic.cc; sourceTree = ""; }; + OBJ_800 /* google_default_credentials.cc */ = {isa = PBXFileReference; path = google_default_credentials.cc; sourceTree = ""; }; + OBJ_802 /* iam_credentials.cc */ = {isa = PBXFileReference; path = iam_credentials.cc; sourceTree = ""; }; + OBJ_804 /* json_token.cc */ = {isa = PBXFileReference; path = json_token.cc; sourceTree = ""; }; + OBJ_805 /* jwt_credentials.cc */ = {isa = PBXFileReference; path = jwt_credentials.cc; sourceTree = ""; }; + OBJ_806 /* jwt_verifier.cc */ = {isa = PBXFileReference; path = jwt_verifier.cc; sourceTree = ""; }; + OBJ_808 /* local_credentials.cc */ = {isa = PBXFileReference; path = local_credentials.cc; sourceTree = ""; }; + OBJ_81 /* cmac.c */ = {isa = PBXFileReference; path = cmac.c; sourceTree = ""; }; + OBJ_810 /* oauth2_credentials.cc */ = {isa = PBXFileReference; path = oauth2_credentials.cc; sourceTree = ""; }; + OBJ_812 /* plugin_credentials.cc */ = {isa = PBXFileReference; path = plugin_credentials.cc; sourceTree = ""; }; + OBJ_814 /* ssl_credentials.cc */ = {isa = PBXFileReference; path = ssl_credentials.cc; sourceTree = ""; }; + OBJ_816 /* grpc_tls_credentials_options.cc */ = {isa = PBXFileReference; path = grpc_tls_credentials_options.cc; sourceTree = ""; }; + OBJ_819 /* alts_security_connector.cc */ = {isa = PBXFileReference; path = alts_security_connector.cc; sourceTree = ""; }; + OBJ_821 /* fake_security_connector.cc */ = {isa = PBXFileReference; path = fake_security_connector.cc; sourceTree = ""; }; + OBJ_822 /* load_system_roots_fallback.cc */ = {isa = PBXFileReference; path = load_system_roots_fallback.cc; sourceTree = ""; }; + OBJ_823 /* load_system_roots_linux.cc */ = {isa = PBXFileReference; path = load_system_roots_linux.cc; sourceTree = ""; }; + OBJ_825 /* local_security_connector.cc */ = {isa = PBXFileReference; path = local_security_connector.cc; sourceTree = ""; }; + OBJ_826 /* security_connector.cc */ = {isa = PBXFileReference; path = security_connector.cc; sourceTree = ""; }; + OBJ_828 /* ssl_security_connector.cc */ = {isa = PBXFileReference; path = ssl_security_connector.cc; sourceTree = ""; }; + OBJ_829 /* ssl_utils.cc */ = {isa = PBXFileReference; path = ssl_utils.cc; sourceTree = ""; }; + OBJ_83 /* conf.c */ = {isa = PBXFileReference; path = conf.c; sourceTree = ""; }; + OBJ_831 /* client_auth_filter.cc */ = {isa = PBXFileReference; path = client_auth_filter.cc; sourceTree = ""; }; + OBJ_832 /* secure_endpoint.cc */ = {isa = PBXFileReference; path = secure_endpoint.cc; sourceTree = ""; }; + OBJ_833 /* security_handshaker.cc */ = {isa = PBXFileReference; path = security_handshaker.cc; sourceTree = ""; }; + OBJ_834 /* server_auth_filter.cc */ = {isa = PBXFileReference; path = server_auth_filter.cc; sourceTree = ""; }; + OBJ_835 /* target_authority_table.cc */ = {isa = PBXFileReference; path = target_authority_table.cc; sourceTree = ""; }; + OBJ_836 /* tsi_error.cc */ = {isa = PBXFileReference; path = tsi_error.cc; sourceTree = ""; }; + OBJ_838 /* json_util.cc */ = {isa = PBXFileReference; path = json_util.cc; sourceTree = ""; }; + OBJ_84 /* cpu-aarch64-fuchsia.c */ = {isa = PBXFileReference; path = "cpu-aarch64-fuchsia.c"; sourceTree = ""; }; + OBJ_840 /* b64.cc */ = {isa = PBXFileReference; path = b64.cc; sourceTree = ""; }; + OBJ_841 /* percent_encoding.cc */ = {isa = PBXFileReference; path = percent_encoding.cc; sourceTree = ""; }; + OBJ_842 /* slice.cc */ = {isa = PBXFileReference; path = slice.cc; sourceTree = ""; }; + OBJ_843 /* slice_buffer.cc */ = {isa = PBXFileReference; path = slice_buffer.cc; sourceTree = ""; }; + OBJ_844 /* slice_intern.cc */ = {isa = PBXFileReference; path = slice_intern.cc; sourceTree = ""; }; + OBJ_845 /* slice_string_helpers.cc */ = {isa = PBXFileReference; path = slice_string_helpers.cc; sourceTree = ""; }; + OBJ_847 /* api_trace.cc */ = {isa = PBXFileReference; path = api_trace.cc; sourceTree = ""; }; + OBJ_848 /* byte_buffer.cc */ = {isa = PBXFileReference; path = byte_buffer.cc; sourceTree = ""; }; + OBJ_849 /* byte_buffer_reader.cc */ = {isa = PBXFileReference; path = byte_buffer_reader.cc; sourceTree = ""; }; + OBJ_85 /* cpu-aarch64-linux.c */ = {isa = PBXFileReference; path = "cpu-aarch64-linux.c"; sourceTree = ""; }; + OBJ_850 /* call.cc */ = {isa = PBXFileReference; path = call.cc; sourceTree = ""; }; + OBJ_851 /* call_details.cc */ = {isa = PBXFileReference; path = call_details.cc; sourceTree = ""; }; + OBJ_852 /* call_log_batch.cc */ = {isa = PBXFileReference; path = call_log_batch.cc; sourceTree = ""; }; + OBJ_853 /* channel.cc */ = {isa = PBXFileReference; path = channel.cc; sourceTree = ""; }; + OBJ_854 /* channel_init.cc */ = {isa = PBXFileReference; path = channel_init.cc; sourceTree = ""; }; + OBJ_855 /* channel_ping.cc */ = {isa = PBXFileReference; path = channel_ping.cc; sourceTree = ""; }; + OBJ_856 /* channel_stack_type.cc */ = {isa = PBXFileReference; path = channel_stack_type.cc; sourceTree = ""; }; + OBJ_857 /* completion_queue.cc */ = {isa = PBXFileReference; path = completion_queue.cc; sourceTree = ""; }; + OBJ_858 /* completion_queue_factory.cc */ = {isa = PBXFileReference; path = completion_queue_factory.cc; sourceTree = ""; }; + OBJ_859 /* event_string.cc */ = {isa = PBXFileReference; path = event_string.cc; sourceTree = ""; }; + OBJ_86 /* cpu-arm-linux.c */ = {isa = PBXFileReference; path = "cpu-arm-linux.c"; sourceTree = ""; }; + OBJ_860 /* init.cc */ = {isa = PBXFileReference; path = init.cc; sourceTree = ""; }; + OBJ_861 /* init_secure.cc */ = {isa = PBXFileReference; path = init_secure.cc; sourceTree = ""; }; + OBJ_862 /* lame_client.cc */ = {isa = PBXFileReference; path = lame_client.cc; sourceTree = ""; }; + OBJ_863 /* metadata_array.cc */ = {isa = PBXFileReference; path = metadata_array.cc; sourceTree = ""; }; + OBJ_864 /* server.cc */ = {isa = PBXFileReference; path = server.cc; sourceTree = ""; }; + OBJ_865 /* validate_metadata.cc */ = {isa = PBXFileReference; path = validate_metadata.cc; sourceTree = ""; }; + OBJ_866 /* version.cc */ = {isa = PBXFileReference; path = version.cc; sourceTree = ""; }; + OBJ_868 /* bdp_estimator.cc */ = {isa = PBXFileReference; path = bdp_estimator.cc; sourceTree = ""; }; + OBJ_869 /* byte_stream.cc */ = {isa = PBXFileReference; path = byte_stream.cc; sourceTree = ""; }; + OBJ_87 /* cpu-arm.c */ = {isa = PBXFileReference; path = "cpu-arm.c"; sourceTree = ""; }; + OBJ_870 /* connectivity_state.cc */ = {isa = PBXFileReference; path = connectivity_state.cc; sourceTree = ""; }; + OBJ_871 /* error_utils.cc */ = {isa = PBXFileReference; path = error_utils.cc; sourceTree = ""; }; + OBJ_872 /* metadata.cc */ = {isa = PBXFileReference; path = metadata.cc; sourceTree = ""; }; + OBJ_873 /* metadata_batch.cc */ = {isa = PBXFileReference; path = metadata_batch.cc; sourceTree = ""; }; + OBJ_874 /* pid_controller.cc */ = {isa = PBXFileReference; path = pid_controller.cc; sourceTree = ""; }; + OBJ_875 /* service_config.cc */ = {isa = PBXFileReference; path = service_config.cc; sourceTree = ""; }; + OBJ_876 /* static_metadata.cc */ = {isa = PBXFileReference; path = static_metadata.cc; sourceTree = ""; }; + OBJ_877 /* status_conversion.cc */ = {isa = PBXFileReference; path = status_conversion.cc; sourceTree = ""; }; + OBJ_878 /* status_metadata.cc */ = {isa = PBXFileReference; path = status_metadata.cc; sourceTree = ""; }; + OBJ_879 /* timeout_encoding.cc */ = {isa = PBXFileReference; path = timeout_encoding.cc; sourceTree = ""; }; + OBJ_88 /* cpu-intel.c */ = {isa = PBXFileReference; path = "cpu-intel.c"; sourceTree = ""; }; + OBJ_880 /* transport.cc */ = {isa = PBXFileReference; path = transport.cc; sourceTree = ""; }; + OBJ_881 /* transport_op_string.cc */ = {isa = PBXFileReference; path = transport_op_string.cc; sourceTree = ""; }; + OBJ_883 /* uri_parser.cc */ = {isa = PBXFileReference; path = uri_parser.cc; sourceTree = ""; }; + OBJ_885 /* grpc_plugin_registry.cc */ = {isa = PBXFileReference; path = grpc_plugin_registry.cc; sourceTree = ""; }; + OBJ_889 /* aes_gcm.cc */ = {isa = PBXFileReference; path = aes_gcm.cc; sourceTree = ""; }; + OBJ_89 /* cpu-ppc64le.c */ = {isa = PBXFileReference; path = "cpu-ppc64le.c"; sourceTree = ""; }; + OBJ_890 /* gsec.cc */ = {isa = PBXFileReference; path = gsec.cc; sourceTree = ""; }; + OBJ_892 /* alts_counter.cc */ = {isa = PBXFileReference; path = alts_counter.cc; sourceTree = ""; }; + OBJ_893 /* alts_crypter.cc */ = {isa = PBXFileReference; path = alts_crypter.cc; sourceTree = ""; }; + OBJ_894 /* alts_frame_protector.cc */ = {isa = PBXFileReference; path = alts_frame_protector.cc; sourceTree = ""; }; + OBJ_895 /* alts_record_protocol_crypter_common.cc */ = {isa = PBXFileReference; path = alts_record_protocol_crypter_common.cc; sourceTree = ""; }; + OBJ_896 /* alts_seal_privacy_integrity_crypter.cc */ = {isa = PBXFileReference; path = alts_seal_privacy_integrity_crypter.cc; sourceTree = ""; }; + OBJ_897 /* alts_unseal_privacy_integrity_crypter.cc */ = {isa = PBXFileReference; path = alts_unseal_privacy_integrity_crypter.cc; sourceTree = ""; }; + OBJ_898 /* frame_handler.cc */ = {isa = PBXFileReference; path = frame_handler.cc; sourceTree = ""; }; + OBJ_9 /* README.md */ = {isa = PBXFileReference; path = README.md; sourceTree = ""; }; + OBJ_90 /* crypto.c */ = {isa = PBXFileReference; path = crypto.c; sourceTree = ""; }; + OBJ_900 /* alts_handshaker_client.cc */ = {isa = PBXFileReference; path = alts_handshaker_client.cc; sourceTree = ""; }; + OBJ_901 /* alts_handshaker_service_api.cc */ = {isa = PBXFileReference; path = alts_handshaker_service_api.cc; sourceTree = ""; }; + OBJ_902 /* alts_handshaker_service_api_util.cc */ = {isa = PBXFileReference; path = alts_handshaker_service_api_util.cc; sourceTree = ""; }; + OBJ_903 /* alts_shared_resource.cc */ = {isa = PBXFileReference; path = alts_shared_resource.cc; sourceTree = ""; }; + OBJ_904 /* alts_tsi_handshaker.cc */ = {isa = PBXFileReference; path = alts_tsi_handshaker.cc; sourceTree = ""; }; + OBJ_905 /* alts_tsi_utils.cc */ = {isa = PBXFileReference; path = alts_tsi_utils.cc; sourceTree = ""; }; + OBJ_906 /* altscontext.pb.c */ = {isa = PBXFileReference; path = altscontext.pb.c; sourceTree = ""; }; + OBJ_907 /* handshaker.pb.c */ = {isa = PBXFileReference; path = handshaker.pb.c; sourceTree = ""; }; + OBJ_908 /* transport_security_common.pb.c */ = {isa = PBXFileReference; path = transport_security_common.pb.c; sourceTree = ""; }; + OBJ_909 /* transport_security_common_api.cc */ = {isa = PBXFileReference; path = transport_security_common_api.cc; sourceTree = ""; }; + OBJ_911 /* alts_grpc_integrity_only_record_protocol.cc */ = {isa = PBXFileReference; path = alts_grpc_integrity_only_record_protocol.cc; sourceTree = ""; }; + OBJ_912 /* alts_grpc_privacy_integrity_record_protocol.cc */ = {isa = PBXFileReference; path = alts_grpc_privacy_integrity_record_protocol.cc; sourceTree = ""; }; + OBJ_913 /* alts_grpc_record_protocol_common.cc */ = {isa = PBXFileReference; path = alts_grpc_record_protocol_common.cc; sourceTree = ""; }; + OBJ_914 /* alts_iovec_record_protocol.cc */ = {isa = PBXFileReference; path = alts_iovec_record_protocol.cc; sourceTree = ""; }; + OBJ_915 /* alts_zero_copy_grpc_protector.cc */ = {isa = PBXFileReference; path = alts_zero_copy_grpc_protector.cc; sourceTree = ""; }; + OBJ_916 /* fake_transport_security.cc */ = {isa = PBXFileReference; path = fake_transport_security.cc; sourceTree = ""; }; + OBJ_917 /* local_transport_security.cc */ = {isa = PBXFileReference; path = local_transport_security.cc; sourceTree = ""; }; + OBJ_92 /* spake25519.c */ = {isa = PBXFileReference; path = spake25519.c; sourceTree = ""; }; + OBJ_920 /* ssl_session_boringssl.cc */ = {isa = PBXFileReference; path = ssl_session_boringssl.cc; sourceTree = ""; }; + OBJ_921 /* ssl_session_cache.cc */ = {isa = PBXFileReference; path = ssl_session_cache.cc; sourceTree = ""; }; + OBJ_922 /* ssl_session_openssl.cc */ = {isa = PBXFileReference; path = ssl_session_openssl.cc; sourceTree = ""; }; + OBJ_923 /* ssl_transport_security.cc */ = {isa = PBXFileReference; path = ssl_transport_security.cc; sourceTree = ""; }; + OBJ_924 /* transport_security.cc */ = {isa = PBXFileReference; path = transport_security.cc; sourceTree = ""; }; + OBJ_925 /* transport_security_grpc.cc */ = {isa = PBXFileReference; path = transport_security_grpc.cc; sourceTree = ""; }; + OBJ_928 /* pb_common.c */ = {isa = PBXFileReference; path = pb_common.c; sourceTree = ""; }; + OBJ_929 /* pb_decode.c */ = {isa = PBXFileReference; path = pb_decode.c; sourceTree = ""; }; + OBJ_930 /* pb_encode.c */ = {isa = PBXFileReference; path = pb_encode.c; sourceTree = ""; }; + OBJ_932 /* pb_common.h */ = {isa = PBXFileReference; path = pb_common.h; sourceTree = ""; }; + OBJ_933 /* cgrpc.h */ = {isa = PBXFileReference; path = cgrpc.h; sourceTree = ""; }; + OBJ_934 /* pb.h */ = {isa = PBXFileReference; path = pb.h; sourceTree = ""; }; + OBJ_935 /* pb_encode.h */ = {isa = PBXFileReference; path = pb_encode.h; sourceTree = ""; }; + OBJ_936 /* pb_decode.h */ = {isa = PBXFileReference; path = pb_decode.h; sourceTree = ""; }; + OBJ_938 /* grpc.h */ = {isa = PBXFileReference; path = grpc.h; sourceTree = ""; }; + OBJ_939 /* status.h */ = {isa = PBXFileReference; path = status.h; sourceTree = ""; }; + OBJ_94 /* check.c */ = {isa = PBXFileReference; path = check.c; sourceTree = ""; }; + OBJ_940 /* census.h */ = {isa = PBXFileReference; path = census.h; sourceTree = ""; }; + OBJ_941 /* slice.h */ = {isa = PBXFileReference; path = slice.h; sourceTree = ""; }; + OBJ_942 /* compression.h */ = {isa = PBXFileReference; path = compression.h; sourceTree = ""; }; + OBJ_943 /* fork.h */ = {isa = PBXFileReference; path = fork.h; sourceTree = ""; }; + OBJ_944 /* byte_buffer_reader.h */ = {isa = PBXFileReference; path = byte_buffer_reader.h; sourceTree = ""; }; + OBJ_945 /* grpc_security_constants.h */ = {isa = PBXFileReference; path = grpc_security_constants.h; sourceTree = ""; }; + OBJ_946 /* byte_buffer.h */ = {isa = PBXFileReference; path = byte_buffer.h; sourceTree = ""; }; + OBJ_947 /* slice_buffer.h */ = {isa = PBXFileReference; path = slice_buffer.h; sourceTree = ""; }; + OBJ_948 /* grpc_posix.h */ = {isa = PBXFileReference; path = grpc_posix.h; sourceTree = ""; }; + OBJ_949 /* grpc_security.h */ = {isa = PBXFileReference; path = grpc_security.h; sourceTree = ""; }; + OBJ_95 /* dh.c */ = {isa = PBXFileReference; path = dh.c; sourceTree = ""; }; + OBJ_950 /* load_reporting.h */ = {isa = PBXFileReference; path = load_reporting.h; sourceTree = ""; }; + OBJ_952 /* time.h */ = {isa = PBXFileReference; path = time.h; sourceTree = ""; }; + OBJ_953 /* port_platform.h */ = {isa = PBXFileReference; path = port_platform.h; sourceTree = ""; }; + OBJ_954 /* log_windows.h */ = {isa = PBXFileReference; path = log_windows.h; sourceTree = ""; }; + OBJ_955 /* sync.h */ = {isa = PBXFileReference; path = sync.h; sourceTree = ""; }; + OBJ_956 /* string_util.h */ = {isa = PBXFileReference; path = string_util.h; sourceTree = ""; }; + OBJ_957 /* sync_custom.h */ = {isa = PBXFileReference; path = sync_custom.h; sourceTree = ""; }; + OBJ_958 /* thd_id.h */ = {isa = PBXFileReference; path = thd_id.h; sourceTree = ""; }; + OBJ_959 /* workaround_list.h */ = {isa = PBXFileReference; path = workaround_list.h; sourceTree = ""; }; + OBJ_96 /* dh_asn1.c */ = {isa = PBXFileReference; path = dh_asn1.c; sourceTree = ""; }; + OBJ_960 /* atm_gcc_sync.h */ = {isa = PBXFileReference; path = atm_gcc_sync.h; sourceTree = ""; }; + OBJ_961 /* atm_gcc_atomic.h */ = {isa = PBXFileReference; path = atm_gcc_atomic.h; sourceTree = ""; }; + OBJ_962 /* atm.h */ = {isa = PBXFileReference; path = atm.h; sourceTree = ""; }; + OBJ_963 /* sync_generic.h */ = {isa = PBXFileReference; path = sync_generic.h; sourceTree = ""; }; + OBJ_964 /* log.h */ = {isa = PBXFileReference; path = log.h; sourceTree = ""; }; + OBJ_965 /* cpu.h */ = {isa = PBXFileReference; path = cpu.h; sourceTree = ""; }; + OBJ_966 /* sync_posix.h */ = {isa = PBXFileReference; path = sync_posix.h; sourceTree = ""; }; + OBJ_967 /* atm_windows.h */ = {isa = PBXFileReference; path = atm_windows.h; sourceTree = ""; }; + OBJ_968 /* sync_windows.h */ = {isa = PBXFileReference; path = sync_windows.h; sourceTree = ""; }; + OBJ_969 /* alloc.h */ = {isa = PBXFileReference; path = alloc.h; sourceTree = ""; }; + OBJ_97 /* params.c */ = {isa = PBXFileReference; path = params.c; sourceTree = ""; }; + OBJ_972 /* port_platform.h */ = {isa = PBXFileReference; path = port_platform.h; sourceTree = ""; }; + OBJ_973 /* status.h */ = {isa = PBXFileReference; path = status.h; sourceTree = ""; }; + OBJ_974 /* gpr_types.h */ = {isa = PBXFileReference; path = gpr_types.h; sourceTree = ""; }; + OBJ_975 /* sync.h */ = {isa = PBXFileReference; path = sync.h; sourceTree = ""; }; + OBJ_976 /* grpc_types.h */ = {isa = PBXFileReference; path = grpc_types.h; sourceTree = ""; }; + OBJ_977 /* sync_custom.h */ = {isa = PBXFileReference; path = sync_custom.h; sourceTree = ""; }; + OBJ_978 /* gpr_slice.h */ = {isa = PBXFileReference; path = gpr_slice.h; sourceTree = ""; }; + OBJ_979 /* slice.h */ = {isa = PBXFileReference; path = slice.h; sourceTree = ""; }; + OBJ_980 /* compression_types.h */ = {isa = PBXFileReference; path = compression_types.h; sourceTree = ""; }; + OBJ_981 /* atm_gcc_sync.h */ = {isa = PBXFileReference; path = atm_gcc_sync.h; sourceTree = ""; }; + OBJ_982 /* atm_gcc_atomic.h */ = {isa = PBXFileReference; path = atm_gcc_atomic.h; sourceTree = ""; }; + OBJ_983 /* atm.h */ = {isa = PBXFileReference; path = atm.h; sourceTree = ""; }; + OBJ_984 /* sync_generic.h */ = {isa = PBXFileReference; path = sync_generic.h; sourceTree = ""; }; + OBJ_985 /* log.h */ = {isa = PBXFileReference; path = log.h; sourceTree = ""; }; + OBJ_986 /* fork.h */ = {isa = PBXFileReference; path = fork.h; sourceTree = ""; }; + OBJ_987 /* byte_buffer_reader.h */ = {isa = PBXFileReference; path = byte_buffer_reader.h; sourceTree = ""; }; + OBJ_988 /* sync_posix.h */ = {isa = PBXFileReference; path = sync_posix.h; sourceTree = ""; }; + OBJ_989 /* atm_windows.h */ = {isa = PBXFileReference; path = atm_windows.h; sourceTree = ""; }; + OBJ_99 /* digest_extra.c */ = {isa = PBXFileReference; path = digest_extra.c; sourceTree = ""; }; + OBJ_990 /* propagation_bits.h */ = {isa = PBXFileReference; path = propagation_bits.h; sourceTree = ""; }; + OBJ_991 /* byte_buffer.h */ = {isa = PBXFileReference; path = byte_buffer.h; sourceTree = ""; }; + OBJ_992 /* connectivity_state.h */ = {isa = PBXFileReference; path = connectivity_state.h; sourceTree = ""; }; + OBJ_993 /* sync_windows.h */ = {isa = PBXFileReference; path = sync_windows.h; sourceTree = ""; }; + OBJ_994 /* module.modulemap */ = {isa = PBXFileReference; name = module.modulemap; path = ../Sources/CgRPC/include/module.modulemap; sourceTree = ""; }; + OBJ_996 /* ssl.crt */ = {isa = PBXFileReference; path = ssl.crt; sourceTree = ""; }; + OBJ_997 /* echo.proto */ = {isa = PBXFileReference; path = echo.proto; sourceTree = ""; }; + OBJ_998 /* Makefile */ = {isa = PBXFileReference; path = Makefile; sourceTree = ""; }; + OBJ_999 /* RUNME */ = {isa = PBXFileReference; path = RUNME; sourceTree = ""; }; SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */ = {isa = PBXFileReference; path = BoringSSL.framework; sourceTree = BUILT_PRODUCTS_DIR; }; SwiftGRPC::CgRPC::Product /* CgRPC.framework */ = {isa = PBXFileReference; path = CgRPC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; SwiftGRPC::Echo::Product /* Echo */ = {isa = PBXFileReference; path = Echo; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2344,26 +2432,26 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - OBJ_1720 /* Frameworks */ = { + OBJ_1796 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; files = ( ); }; - OBJ_2145 /* Frameworks */ = { + OBJ_2245 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; files = ( - OBJ_2146 /* BoringSSL.framework in Frameworks */, + OBJ_2246 /* BoringSSL.framework in Frameworks */, ); }; - OBJ_2514 /* Frameworks */ = { + OBJ_2614 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; files = ( - OBJ_2515 /* SwiftProtobuf.framework in Frameworks */, - OBJ_2516 /* CgRPC.framework in Frameworks */, - OBJ_2517 /* BoringSSL.framework in Frameworks */, + OBJ_2615 /* SwiftProtobuf.framework in Frameworks */, + OBJ_2616 /* CgRPC.framework in Frameworks */, + OBJ_2617 /* BoringSSL.framework in Frameworks */, ); }; - OBJ_2778 /* Frameworks */ = { + OBJ_2878 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; files = ( ); @@ -2371,3067 +2459,3235 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - OBJ_103 /* message_compress */ = { + OBJ_10 /* crypto */ = { + isa = PBXGroup; + children = ( + OBJ_11 /* asn1 */, + OBJ_42 /* base64 */, + OBJ_44 /* bio */, + OBJ_55 /* bn_extra */, + OBJ_58 /* buf */, + OBJ_60 /* bytestring */, + OBJ_65 /* chacha */, + OBJ_67 /* cipher_extra */, + OBJ_80 /* cmac */, + OBJ_82 /* conf */, + OBJ_84 /* cpu-aarch64-fuchsia.c */, + OBJ_85 /* cpu-aarch64-linux.c */, + OBJ_86 /* cpu-arm-linux.c */, + OBJ_87 /* cpu-arm.c */, + OBJ_88 /* cpu-intel.c */, + OBJ_89 /* cpu-ppc64le.c */, + OBJ_90 /* crypto.c */, + OBJ_91 /* curve25519 */, + OBJ_93 /* dh */, + OBJ_98 /* digest_extra */, + OBJ_100 /* dsa */, + OBJ_103 /* ec_extra */, + OBJ_105 /* ecdh */, + OBJ_107 /* ecdsa_extra */, + OBJ_109 /* engine */, + OBJ_111 /* err */, + OBJ_114 /* evp */, + OBJ_130 /* ex_data.c */, + OBJ_131 /* fipsmodule */, + OBJ_210 /* hkdf */, + OBJ_212 /* lhash */, + OBJ_214 /* mem.c */, + OBJ_215 /* obj */, + OBJ_218 /* pem */, + OBJ_227 /* pkcs7 */, + OBJ_230 /* pkcs8 */, + OBJ_234 /* poly1305 */, + OBJ_238 /* pool */, + OBJ_240 /* rand_extra */, + OBJ_246 /* rc4 */, + OBJ_248 /* refcount_c11.c */, + OBJ_249 /* refcount_lock.c */, + OBJ_250 /* rsa_extra */, + OBJ_252 /* stack */, + OBJ_254 /* thread.c */, + OBJ_255 /* thread_none.c */, + OBJ_256 /* thread_pthread.c */, + OBJ_257 /* thread_win.c */, + OBJ_258 /* x509 */, + OBJ_308 /* x509v3 */, + ); + name = crypto; + path = crypto; + sourceTree = ""; + }; + OBJ_100 /* dsa */ = { isa = PBXGroup; children = ( - OBJ_104 /* message_compress_filter.cc */, + OBJ_101 /* dsa.c */, + OBJ_102 /* dsa_asn1.c */, ); - name = message_compress; - path = message_compress; + name = dsa; + path = dsa; sourceTree = ""; }; - OBJ_105 /* server */ = { + OBJ_1004 /* Generated */ = { isa = PBXGroup; children = ( - OBJ_106 /* http_server_filter.cc */, + OBJ_1005 /* echo.grpc.swift */, + OBJ_1006 /* echo.pb.swift */, ); - name = server; - path = server; + name = Generated; + path = Generated; sourceTree = ""; }; - OBJ_1052 /* Tests */ = { + OBJ_1008 /* EchoNIO */ = { isa = PBXGroup; children = ( - OBJ_1053 /* SwiftGRPCNIOTests */, - OBJ_1068 /* SwiftGRPCTests */, + OBJ_1009 /* echo.proto */, + OBJ_1010 /* Makefile */, + OBJ_1011 /* RUNME */, + OBJ_1012 /* README.md */, + OBJ_1013 /* EchoProviderNIO.swift */, + OBJ_1014 /* Generated */, + OBJ_1017 /* main.swift */, ); - name = Tests; - path = ""; + name = EchoNIO; + path = Sources/Examples/EchoNIO; sourceTree = SOURCE_ROOT; }; - OBJ_1053 /* SwiftGRPCNIOTests */ = { + OBJ_1014 /* Generated */ = { isa = PBXGroup; children = ( - OBJ_1054 /* EchoProviderNIO.swift */, - OBJ_1055 /* GRPCChannelHandlerResponseCapturingTestCase.swift */, - OBJ_1056 /* GRPCChannelHandlerTests.swift */, - OBJ_1057 /* HTTP1ToRawGRPCServerCodecTests.swift */, - OBJ_1058 /* LengthPrefixedMessageReaderTests.swift */, - OBJ_1059 /* NIOBasicEchoTestCase.swift */, - OBJ_1060 /* NIOClientCancellingTests.swift */, - OBJ_1061 /* NIOClientTimeoutTests.swift */, - OBJ_1062 /* NIOServerTests.swift */, - OBJ_1063 /* NIOServerWebTests.swift */, - OBJ_1064 /* ServerThrowingTests.swift */, - OBJ_1065 /* TestHelpers.swift */, - OBJ_1066 /* echo.grpc.swift */, - OBJ_1067 /* echo.pb.swift */, + OBJ_1015 /* echo.grpc.swift */, + OBJ_1016 /* echo.pb.swift */, ); - name = SwiftGRPCNIOTests; - path = Tests/SwiftGRPCNIOTests; + name = Generated; + path = Generated; + sourceTree = ""; + }; + OBJ_1018 /* RootsEncoder */ = { + isa = PBXGroup; + children = ( + OBJ_1019 /* main.swift */, + ); + name = RootsEncoder; + path = Sources/RootsEncoder; sourceTree = SOURCE_ROOT; }; - OBJ_1068 /* SwiftGRPCTests */ = { - isa = PBXGroup; - children = ( - OBJ_1069 /* BasicEchoTestCase.swift */, - OBJ_1070 /* ChannelArgumentTests.swift */, - OBJ_1071 /* ChannelConnectivityTests.swift */, - OBJ_1072 /* ChannelShutdownTests.swift */, - OBJ_1073 /* ClientCancellingTests.swift */, - OBJ_1074 /* ClientTestExample.swift */, - OBJ_1075 /* ClientTimeoutTests.swift */, - OBJ_1076 /* CompletionQueueTests.swift */, - OBJ_1077 /* ConnectionFailureTests.swift */, - OBJ_1078 /* EchoProvider.swift */, - OBJ_1079 /* EchoTests.swift */, - OBJ_1080 /* GRPCTests.swift */, - OBJ_1081 /* MetadataTests.swift */, - OBJ_1082 /* ServerCancellingTests.swift */, - OBJ_1083 /* ServerTestExample.swift */, - OBJ_1084 /* ServerThrowingTests.swift */, - OBJ_1085 /* ServerTimeoutTests.swift */, - OBJ_1086 /* ServiceClientTests.swift */, - OBJ_1087 /* TestKeys.swift */, - OBJ_1088 /* echo.grpc.swift */, - OBJ_1089 /* echo.pb.swift */, + OBJ_1020 /* Simple */ = { + isa = PBXGroup; + children = ( + OBJ_1021 /* README.md */, + OBJ_1022 /* main.swift */, ); - name = SwiftGRPCTests; - path = Tests/SwiftGRPCTests; + name = Simple; + path = Sources/Examples/Simple; sourceTree = SOURCE_ROOT; }; - OBJ_107 /* load_reporting */ = { + OBJ_1023 /* SwiftGRPC */ = { isa = PBXGroup; children = ( - OBJ_108 /* server_load_reporting_filter.cc */, - OBJ_109 /* server_load_reporting_plugin.cc */, + OBJ_1024 /* Core */, + OBJ_1045 /* Runtime */, + ); + name = SwiftGRPC; + path = Sources/SwiftGRPC; + sourceTree = SOURCE_ROOT; + }; + OBJ_1024 /* Core */ = { + isa = PBXGroup; + children = ( + OBJ_1025 /* ByteBuffer.swift */, + OBJ_1026 /* Call.swift */, + OBJ_1027 /* CallError.swift */, + OBJ_1028 /* CallResult.swift */, + OBJ_1029 /* Channel.swift */, + OBJ_1030 /* ChannelArgument.swift */, + OBJ_1031 /* ChannelConnectivityObserver.swift */, + OBJ_1032 /* ChannelConnectivityState.swift */, + OBJ_1033 /* ClientNetworkMonitor.swift */, + OBJ_1034 /* CompletionQueue.swift */, + OBJ_1035 /* Handler.swift */, + OBJ_1036 /* Metadata.swift */, + OBJ_1037 /* Mutex.swift */, + OBJ_1038 /* Operation.swift */, + OBJ_1039 /* OperationGroup.swift */, + OBJ_1040 /* Roots.swift */, + OBJ_1041 /* Server.swift */, + OBJ_1042 /* ServerStatus.swift */, + OBJ_1043 /* StatusCode.swift */, + OBJ_1044 /* gRPC.swift */, ); - name = load_reporting; - path = load_reporting; + name = Core; + path = Core; sourceTree = ""; }; - OBJ_1095 /* Dependencies */ = { + OBJ_103 /* ec_extra */ = { isa = PBXGroup; children = ( - OBJ_1096 /* swift-nio-http2 0.2.1 */, - OBJ_1122 /* swift-nio 1.13.0 */, - OBJ_1240 /* Commander 0.8.0 */, - OBJ_1252 /* SwiftProtobuf 1.3.1 */, + OBJ_104 /* ec_asn1.c */, ); - name = Dependencies; - path = ""; + name = ec_extra; + path = ec_extra; sourceTree = ""; }; - OBJ_1096 /* swift-nio-http2 0.2.1 */ = { + OBJ_1045 /* Runtime */ = { isa = PBXGroup; children = ( - OBJ_1097 /* CNIONghttp2 */, - OBJ_1102 /* NIOHTTP2Server */, - OBJ_1103 /* NIOHTTP2 */, - OBJ_1120 /* NIOHPACK */, - OBJ_1121 /* Package.swift */, + OBJ_1046 /* ClientCall.swift */, + OBJ_1047 /* ClientCallBidirectionalStreaming.swift */, + OBJ_1048 /* ClientCallClientStreaming.swift */, + OBJ_1049 /* ClientCallServerStreaming.swift */, + OBJ_1050 /* ClientCallUnary.swift */, + OBJ_1051 /* RPCError.swift */, + OBJ_1052 /* ServerSession.swift */, + OBJ_1053 /* ServerSessionBidirectionalStreaming.swift */, + OBJ_1054 /* ServerSessionClientStreaming.swift */, + OBJ_1055 /* ServerSessionServerStreaming.swift */, + OBJ_1056 /* ServerSessionUnary.swift */, + OBJ_1057 /* ServiceClient.swift */, + OBJ_1058 /* ServiceProvider.swift */, + OBJ_1059 /* ServiceServer.swift */, + OBJ_1060 /* StreamReceiving.swift */, + OBJ_1061 /* StreamSending.swift */, ); - name = "swift-nio-http2 0.2.1"; - path = ""; - sourceTree = SOURCE_ROOT; + name = Runtime; + path = Runtime; + sourceTree = ""; }; - OBJ_1097 /* CNIONghttp2 */ = { + OBJ_105 /* ecdh */ = { isa = PBXGroup; children = ( - OBJ_1098 /* shims.c */, - OBJ_1099 /* include */, + OBJ_106 /* ecdh.c */, ); - name = CNIONghttp2; - path = ".build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2"; + name = ecdh; + path = ecdh; + sourceTree = ""; + }; + OBJ_1062 /* SwiftGRPCNIO */ = { + isa = PBXGroup; + children = ( + OBJ_1063 /* CallHandlers */, + OBJ_1069 /* ClientCalls */, + OBJ_1077 /* ClientOptions.swift */, + OBJ_1078 /* CompressionMechanism.swift */, + OBJ_1079 /* GRPCChannelHandler.swift */, + OBJ_1080 /* GRPCClient.swift */, + OBJ_1081 /* GRPCClientChannelHandler.swift */, + OBJ_1082 /* GRPCClientCodec.swift */, + OBJ_1083 /* GRPCError.swift */, + OBJ_1084 /* GRPCServer.swift */, + OBJ_1085 /* GRPCServerCodec.swift */, + OBJ_1086 /* GRPCStatus.swift */, + OBJ_1087 /* GRPCTimeout.swift */, + OBJ_1088 /* HTTP1ToRawGRPCClientCodec.swift */, + OBJ_1089 /* HTTP1ToRawGRPCServerCodec.swift */, + OBJ_1090 /* HTTPProtocolSwitcher.swift */, + OBJ_1091 /* LengthPrefixedMessageReader.swift */, + OBJ_1092 /* LengthPrefixedMessageWriter.swift */, + OBJ_1093 /* LoggingServerErrorDelegate.swift */, + OBJ_1094 /* ServerCallContexts */, + OBJ_1098 /* ServerErrorDelegate.swift */, + OBJ_1099 /* StatusCode.swift */, + OBJ_1100 /* StreamEvent.swift */, + OBJ_1101 /* WebCORSHandler.swift */, + ); + name = SwiftGRPCNIO; + path = Sources/SwiftGRPCNIO; sourceTree = SOURCE_ROOT; }; - OBJ_1099 /* include */ = { + OBJ_1063 /* CallHandlers */ = { isa = PBXGroup; children = ( - OBJ_1100 /* c_nio_nghttp2.h */, - OBJ_1101 /* module.modulemap */, + OBJ_1064 /* BaseCallHandler.swift */, + OBJ_1065 /* BidirectionalStreamingCallHandler.swift */, + OBJ_1066 /* ClientStreamingCallHandler.swift */, + OBJ_1067 /* ServerStreamingCallHandler.swift */, + OBJ_1068 /* UnaryCallHandler.swift */, ); - name = include; - path = include; + name = CallHandlers; + path = CallHandlers; sourceTree = ""; }; - OBJ_110 /* max_age */ = { + OBJ_1069 /* ClientCalls */ = { isa = PBXGroup; children = ( - OBJ_111 /* max_age_filter.cc */, + OBJ_1070 /* BaseClientCall.swift */, + OBJ_1071 /* BidirectionalStreamingClientCall.swift */, + OBJ_1072 /* ClientCall.swift */, + OBJ_1073 /* ClientStreamingClientCall.swift */, + OBJ_1074 /* ResponseObserver.swift */, + OBJ_1075 /* ServerStreamingClientCall.swift */, + OBJ_1076 /* UnaryClientCall.swift */, ); - name = max_age; - path = max_age; + name = ClientCalls; + path = ClientCalls; sourceTree = ""; }; - OBJ_1102 /* NIOHTTP2Server */ = { + OBJ_107 /* ecdsa_extra */ = { isa = PBXGroup; children = ( + OBJ_108 /* ecdsa_asn1.c */, ); - name = NIOHTTP2Server; - path = ".build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/NIOHTTP2Server"; - sourceTree = SOURCE_ROOT; + name = ecdsa_extra; + path = ecdsa_extra; + sourceTree = ""; }; - OBJ_1103 /* NIOHTTP2 */ = { - isa = PBXGroup; - children = ( - OBJ_1104 /* HTTP2DataProvider.swift */, - OBJ_1105 /* HTTP2Error.swift */, - OBJ_1106 /* HTTP2ErrorCode.swift */, - OBJ_1107 /* HTTP2Frame.swift */, - OBJ_1108 /* HTTP2HeaderBlock.swift */, - OBJ_1109 /* HTTP2Parser.swift */, - OBJ_1110 /* HTTP2PingData.swift */, - OBJ_1111 /* HTTP2PipelineHelpers.swift */, - OBJ_1112 /* HTTP2Settings.swift */, - OBJ_1113 /* HTTP2Stream.swift */, - OBJ_1114 /* HTTP2StreamChannel.swift */, - OBJ_1115 /* HTTP2StreamID.swift */, - OBJ_1116 /* HTTP2StreamMultiplexer.swift */, - OBJ_1117 /* HTTP2ToHTTP1Codec.swift */, - OBJ_1118 /* HTTP2UserEvents.swift */, - OBJ_1119 /* NGHTTP2Session.swift */, + OBJ_109 /* engine */ = { + isa = PBXGroup; + children = ( + OBJ_110 /* engine.c */, ); - name = NIOHTTP2; - path = ".build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/NIOHTTP2"; - sourceTree = SOURCE_ROOT; + name = engine; + path = engine; + sourceTree = ""; }; - OBJ_112 /* message_size */ = { + OBJ_1094 /* ServerCallContexts */ = { isa = PBXGroup; children = ( - OBJ_113 /* message_size_filter.cc */, + OBJ_1095 /* ServerCallContext.swift */, + OBJ_1096 /* StreamingResponseCallContext.swift */, + OBJ_1097 /* UnaryResponseCallContext.swift */, ); - name = message_size; - path = message_size; + name = ServerCallContexts; + path = ServerCallContexts; + sourceTree = ""; + }; + OBJ_11 /* asn1 */ = { + isa = PBXGroup; + children = ( + OBJ_12 /* a_bitstr.c */, + OBJ_13 /* a_bool.c */, + OBJ_14 /* a_d2i_fp.c */, + OBJ_15 /* a_dup.c */, + OBJ_16 /* a_enum.c */, + OBJ_17 /* a_gentm.c */, + OBJ_18 /* a_i2d_fp.c */, + OBJ_19 /* a_int.c */, + OBJ_20 /* a_mbstr.c */, + OBJ_21 /* a_object.c */, + OBJ_22 /* a_octet.c */, + OBJ_23 /* a_print.c */, + OBJ_24 /* a_strnid.c */, + OBJ_25 /* a_time.c */, + OBJ_26 /* a_type.c */, + OBJ_27 /* a_utctm.c */, + OBJ_28 /* a_utf8.c */, + OBJ_29 /* asn1_lib.c */, + OBJ_30 /* asn1_par.c */, + OBJ_31 /* asn_pack.c */, + OBJ_32 /* f_enum.c */, + OBJ_33 /* f_int.c */, + OBJ_34 /* f_string.c */, + OBJ_35 /* tasn_dec.c */, + OBJ_36 /* tasn_enc.c */, + OBJ_37 /* tasn_fre.c */, + OBJ_38 /* tasn_new.c */, + OBJ_39 /* tasn_typ.c */, + OBJ_40 /* tasn_utl.c */, + OBJ_41 /* time_support.c */, + ); + name = asn1; + path = asn1; sourceTree = ""; }; - OBJ_1120 /* NIOHPACK */ = { + OBJ_1102 /* protoc-gen-swiftgrpc */ = { isa = PBXGroup; children = ( + OBJ_1103 /* README.md */, + OBJ_1104 /* Generator-Client.swift */, + OBJ_1105 /* Generator-Methods.swift */, + OBJ_1106 /* Generator-Names.swift */, + OBJ_1107 /* Generator-Server.swift */, + OBJ_1108 /* Generator.swift */, + OBJ_1109 /* StreamingType.swift */, + OBJ_1110 /* main.swift */, + OBJ_1111 /* options.swift */, ); - name = NIOHPACK; - path = ".build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/NIOHPACK"; + name = "protoc-gen-swiftgrpc"; + path = "Sources/protoc-gen-swiftgrpc"; sourceTree = SOURCE_ROOT; }; - OBJ_1122 /* swift-nio 1.13.0 */ = { - isa = PBXGroup; - children = ( - OBJ_1123 /* NIOTLS */, - OBJ_1127 /* CNIODarwin */, - OBJ_1131 /* CNIOZlib */, - OBJ_1135 /* NIOChatServer */, - OBJ_1136 /* NIOEchoClient */, - OBJ_1137 /* NIOHTTP1Server */, - OBJ_1138 /* NIO */, - OBJ_1194 /* NIOWebSocket */, - OBJ_1195 /* CNIOHTTPParser */, - OBJ_1200 /* NIOConcurrencyHelpers */, - OBJ_1203 /* NIOFoundationCompat */, - OBJ_1205 /* CNIOSHA1 */, - OBJ_1209 /* NIOWebSocketServer */, - OBJ_1210 /* NIOPerformanceTester */, - OBJ_1211 /* NIOHTTP1 */, - OBJ_1221 /* CNIOAtomics */, - OBJ_1227 /* NIOChatClient */, - OBJ_1228 /* CNIOLinux */, - OBJ_1234 /* NIOMulticastChat */, - OBJ_1235 /* NIOPriorityQueue */, - OBJ_1238 /* NIOEchoServer */, - OBJ_1239 /* Package.swift */, - ); - name = "swift-nio 1.13.0"; - path = ""; - sourceTree = SOURCE_ROOT; + OBJ_111 /* err */ = { + isa = PBXGroup; + children = ( + OBJ_112 /* err.c */, + OBJ_113 /* err_data.c */, + ); + name = err; + path = err; + sourceTree = ""; }; - OBJ_1123 /* NIOTLS */ = { + OBJ_1112 /* Tests */ = { isa = PBXGroup; children = ( - OBJ_1124 /* ApplicationProtocolNegotiationHandler.swift */, - OBJ_1125 /* SNIHandler.swift */, - OBJ_1126 /* TLSEvents.swift */, + OBJ_1113 /* SwiftGRPCNIOTests */, + OBJ_1128 /* SwiftGRPCTests */, ); - name = NIOTLS; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOTLS"; + name = Tests; + path = ""; sourceTree = SOURCE_ROOT; }; - OBJ_1127 /* CNIODarwin */ = { + OBJ_1113 /* SwiftGRPCNIOTests */ = { isa = PBXGroup; children = ( - OBJ_1128 /* shim.c */, - OBJ_1129 /* include */, + OBJ_1114 /* EchoProviderNIO.swift */, + OBJ_1115 /* GRPCChannelHandlerResponseCapturingTestCase.swift */, + OBJ_1116 /* GRPCChannelHandlerTests.swift */, + OBJ_1117 /* HTTP1ToRawGRPCServerCodecTests.swift */, + OBJ_1118 /* LengthPrefixedMessageReaderTests.swift */, + OBJ_1119 /* NIOBasicEchoTestCase.swift */, + OBJ_1120 /* NIOClientCancellingTests.swift */, + OBJ_1121 /* NIOClientTimeoutTests.swift */, + OBJ_1122 /* NIOServerTests.swift */, + OBJ_1123 /* NIOServerWebTests.swift */, + OBJ_1124 /* ServerThrowingTests.swift */, + OBJ_1125 /* TestHelpers.swift */, + OBJ_1126 /* echo.grpc.swift */, + OBJ_1127 /* echo.pb.swift */, ); - name = CNIODarwin; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin"; + name = SwiftGRPCNIOTests; + path = Tests/SwiftGRPCNIOTests; + sourceTree = SOURCE_ROOT; + }; + OBJ_1128 /* SwiftGRPCTests */ = { + isa = PBXGroup; + children = ( + OBJ_1129 /* BasicEchoTestCase.swift */, + OBJ_1130 /* ChannelArgumentTests.swift */, + OBJ_1131 /* ChannelConnectivityTests.swift */, + OBJ_1132 /* ChannelShutdownTests.swift */, + OBJ_1133 /* ClientCancellingTests.swift */, + OBJ_1134 /* ClientTestExample.swift */, + OBJ_1135 /* ClientTimeoutTests.swift */, + OBJ_1136 /* CompletionQueueTests.swift */, + OBJ_1137 /* ConnectionFailureTests.swift */, + OBJ_1138 /* EchoProvider.swift */, + OBJ_1139 /* EchoTests.swift */, + OBJ_1140 /* GRPCTests.swift */, + OBJ_1141 /* MetadataTests.swift */, + OBJ_1142 /* ServerCancellingTests.swift */, + OBJ_1143 /* ServerTestExample.swift */, + OBJ_1144 /* ServerThrowingTests.swift */, + OBJ_1145 /* ServerTimeoutTests.swift */, + OBJ_1146 /* ServiceClientTests.swift */, + OBJ_1147 /* TestKeys.swift */, + OBJ_1148 /* echo.grpc.swift */, + OBJ_1149 /* echo.pb.swift */, + ); + name = SwiftGRPCTests; + path = Tests/SwiftGRPCTests; sourceTree = SOURCE_ROOT; }; - OBJ_1129 /* include */ = { + OBJ_114 /* evp */ = { + isa = PBXGroup; + children = ( + OBJ_115 /* digestsign.c */, + OBJ_116 /* evp.c */, + OBJ_117 /* evp_asn1.c */, + OBJ_118 /* evp_ctx.c */, + OBJ_119 /* p_dsa_asn1.c */, + OBJ_120 /* p_ec.c */, + OBJ_121 /* p_ec_asn1.c */, + OBJ_122 /* p_ed25519.c */, + OBJ_123 /* p_ed25519_asn1.c */, + OBJ_124 /* p_rsa.c */, + OBJ_125 /* p_rsa_asn1.c */, + OBJ_126 /* pbkdf.c */, + OBJ_127 /* print.c */, + OBJ_128 /* scrypt.c */, + OBJ_129 /* sign.c */, + ); + name = evp; + path = evp; + sourceTree = ""; + }; + OBJ_1150 /* Dependencies */ = { isa = PBXGroup; children = ( - OBJ_1130 /* CNIODarwin.h */, + OBJ_1151 /* swift-nio-http2 0.2.1 */, + OBJ_1177 /* swift-nio 1.13.2 */, + OBJ_1295 /* Commander 0.8.0 */, + OBJ_1307 /* SwiftProtobuf 1.4.0 */, ); - name = include; - path = include; + name = Dependencies; + path = ""; sourceTree = ""; }; - OBJ_1131 /* CNIOZlib */ = { + OBJ_1151 /* swift-nio-http2 0.2.1 */ = { isa = PBXGroup; children = ( - OBJ_1132 /* empty.c */, - OBJ_1133 /* include */, + OBJ_1152 /* CNIONghttp2 */, + OBJ_1157 /* NIOHPACK */, + OBJ_1158 /* NIOHTTP2 */, + OBJ_1175 /* NIOHTTP2Server */, + OBJ_1176 /* Package.swift */, ); - name = CNIOZlib; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib"; + name = "swift-nio-http2 0.2.1"; + path = ""; + sourceTree = SOURCE_ROOT; + }; + OBJ_1152 /* CNIONghttp2 */ = { + isa = PBXGroup; + children = ( + OBJ_1153 /* shims.c */, + OBJ_1154 /* include */, + ); + name = CNIONghttp2; + path = ".build/checkouts/swift-nio-http2/Sources/CNIONghttp2"; sourceTree = SOURCE_ROOT; }; - OBJ_1133 /* include */ = { + OBJ_1154 /* include */ = { isa = PBXGroup; children = ( - OBJ_1134 /* CNIOZlib.h */, + OBJ_1155 /* c_nio_nghttp2.h */, + OBJ_1156 /* module.modulemap */, ); name = include; path = include; sourceTree = ""; }; - OBJ_1135 /* NIOChatServer */ = { + OBJ_1157 /* NIOHPACK */ = { isa = PBXGroup; children = ( ); - name = NIOChatServer; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOChatServer"; + name = NIOHPACK; + path = ".build/checkouts/swift-nio-http2/Sources/NIOHPACK"; sourceTree = SOURCE_ROOT; }; - OBJ_1136 /* NIOEchoClient */ = { - isa = PBXGroup; - children = ( + OBJ_1158 /* NIOHTTP2 */ = { + isa = PBXGroup; + children = ( + OBJ_1159 /* HTTP2DataProvider.swift */, + OBJ_1160 /* HTTP2Error.swift */, + OBJ_1161 /* HTTP2ErrorCode.swift */, + OBJ_1162 /* HTTP2Frame.swift */, + OBJ_1163 /* HTTP2HeaderBlock.swift */, + OBJ_1164 /* HTTP2Parser.swift */, + OBJ_1165 /* HTTP2PingData.swift */, + OBJ_1166 /* HTTP2PipelineHelpers.swift */, + OBJ_1167 /* HTTP2Settings.swift */, + OBJ_1168 /* HTTP2Stream.swift */, + OBJ_1169 /* HTTP2StreamChannel.swift */, + OBJ_1170 /* HTTP2StreamID.swift */, + OBJ_1171 /* HTTP2StreamMultiplexer.swift */, + OBJ_1172 /* HTTP2ToHTTP1Codec.swift */, + OBJ_1173 /* HTTP2UserEvents.swift */, + OBJ_1174 /* NGHTTP2Session.swift */, ); - name = NIOEchoClient; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOEchoClient"; + name = NIOHTTP2; + path = ".build/checkouts/swift-nio-http2/Sources/NIOHTTP2"; sourceTree = SOURCE_ROOT; }; - OBJ_1137 /* NIOHTTP1Server */ = { + OBJ_1175 /* NIOHTTP2Server */ = { isa = PBXGroup; children = ( ); - name = NIOHTTP1Server; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOHTTP1Server"; + name = NIOHTTP2Server; + path = ".build/checkouts/swift-nio-http2/Sources/NIOHTTP2Server"; sourceTree = SOURCE_ROOT; }; - OBJ_1138 /* NIO */ = { - isa = PBXGroup; - children = ( - OBJ_1139 /* AddressedEnvelope.swift */, - OBJ_1140 /* BaseSocket.swift */, - OBJ_1141 /* BaseSocketChannel.swift */, - OBJ_1142 /* BlockingIOThreadPool.swift */, - OBJ_1143 /* Bootstrap.swift */, - OBJ_1144 /* ByteBuffer-aux.swift */, - OBJ_1145 /* ByteBuffer-core.swift */, - OBJ_1146 /* ByteBuffer-int.swift */, - OBJ_1147 /* ByteBuffer-views.swift */, - OBJ_1148 /* Channel.swift */, - OBJ_1149 /* ChannelHandler.swift */, - OBJ_1150 /* ChannelHandlers.swift */, - OBJ_1151 /* ChannelInvoker.swift */, - OBJ_1152 /* ChannelOption.swift */, - OBJ_1153 /* ChannelPipeline.swift */, - OBJ_1154 /* CircularBuffer.swift */, - OBJ_1155 /* Codec.swift */, - OBJ_1156 /* CompositeError.swift */, - OBJ_1157 /* ContiguousCollection.swift */, - OBJ_1158 /* DeadChannel.swift */, - OBJ_1159 /* Embedded.swift */, - OBJ_1160 /* EventLoop.swift */, - OBJ_1161 /* EventLoopFuture.swift */, - OBJ_1162 /* FileDescriptor.swift */, - OBJ_1163 /* FileHandle.swift */, - OBJ_1164 /* FileRegion.swift */, - OBJ_1165 /* GetaddrinfoResolver.swift */, - OBJ_1166 /* HappyEyeballs.swift */, - OBJ_1167 /* Heap.swift */, - OBJ_1168 /* IO.swift */, - OBJ_1169 /* IOData.swift */, - OBJ_1170 /* IntegerTypes.swift */, - OBJ_1171 /* Interfaces.swift */, - OBJ_1172 /* Linux.swift */, - OBJ_1173 /* LinuxCPUSet.swift */, - OBJ_1174 /* MarkedCircularBuffer.swift */, - OBJ_1175 /* MulticastChannel.swift */, - OBJ_1176 /* NIOAny.swift */, - OBJ_1177 /* NonBlockingFileIO.swift */, - OBJ_1178 /* PendingDatagramWritesManager.swift */, - OBJ_1179 /* PendingWritesManager.swift */, - OBJ_1180 /* PriorityQueue.swift */, - OBJ_1181 /* RecvByteBufferAllocator.swift */, - OBJ_1182 /* Resolver.swift */, - OBJ_1183 /* Selectable.swift */, - OBJ_1184 /* Selector.swift */, - OBJ_1185 /* ServerSocket.swift */, - OBJ_1186 /* Socket.swift */, - OBJ_1187 /* SocketAddresses.swift */, - OBJ_1188 /* SocketChannel.swift */, - OBJ_1189 /* SocketOptionProvider.swift */, - OBJ_1190 /* System.swift */, - OBJ_1191 /* Thread.swift */, - OBJ_1192 /* TypeAssistedChannelHandler.swift */, - OBJ_1193 /* Utilities.swift */, - ); - name = NIO; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIO"; + OBJ_1177 /* swift-nio 1.13.2 */ = { + isa = PBXGroup; + children = ( + OBJ_1178 /* CNIOAtomics */, + OBJ_1184 /* CNIODarwin */, + OBJ_1188 /* CNIOHTTPParser */, + OBJ_1193 /* CNIOLinux */, + OBJ_1199 /* CNIOSHA1 */, + OBJ_1203 /* CNIOZlib */, + OBJ_1207 /* NIO */, + OBJ_1263 /* NIOChatClient */, + OBJ_1264 /* NIOChatServer */, + OBJ_1265 /* NIOConcurrencyHelpers */, + OBJ_1268 /* NIOEchoClient */, + OBJ_1269 /* NIOEchoServer */, + OBJ_1270 /* NIOFoundationCompat */, + OBJ_1272 /* NIOHTTP1 */, + OBJ_1282 /* NIOHTTP1Server */, + OBJ_1283 /* NIOMulticastChat */, + OBJ_1284 /* NIOPerformanceTester */, + OBJ_1285 /* NIOPriorityQueue */, + OBJ_1288 /* NIOTLS */, + OBJ_1292 /* NIOWebSocket */, + OBJ_1293 /* NIOWebSocketServer */, + OBJ_1294 /* Package.swift */, + ); + name = "swift-nio 1.13.2"; + path = ""; sourceTree = SOURCE_ROOT; }; - OBJ_114 /* workarounds */ = { + OBJ_1178 /* CNIOAtomics */ = { isa = PBXGroup; children = ( - OBJ_115 /* workaround_cronet_compression_filter.cc */, - OBJ_116 /* workaround_utils.cc */, + OBJ_1179 /* src */, + OBJ_1181 /* include */, ); - name = workarounds; - path = workarounds; - sourceTree = ""; + name = CNIOAtomics; + path = ".build/checkouts/swift-nio/Sources/CNIOAtomics"; + sourceTree = SOURCE_ROOT; }; - OBJ_117 /* transport */ = { + OBJ_1179 /* src */ = { isa = PBXGroup; children = ( - OBJ_118 /* chttp2 */, - OBJ_159 /* inproc */, + OBJ_1180 /* c-atomics.c */, ); - name = transport; - path = transport; + name = src; + path = src; sourceTree = ""; }; - OBJ_118 /* chttp2 */ = { + OBJ_1181 /* include */ = { isa = PBXGroup; children = ( - OBJ_119 /* alpn */, - OBJ_121 /* client */, - OBJ_129 /* server */, - OBJ_136 /* transport */, + OBJ_1182 /* CNIOAtomics.h */, + OBJ_1183 /* cpp_magic.h */, ); - name = chttp2; - path = chttp2; + name = include; + path = include; sourceTree = ""; }; - OBJ_119 /* alpn */ = { + OBJ_1184 /* CNIODarwin */ = { isa = PBXGroup; children = ( - OBJ_120 /* alpn.cc */, + OBJ_1185 /* shim.c */, + OBJ_1186 /* include */, ); - name = alpn; - path = alpn; - sourceTree = ""; + name = CNIODarwin; + path = ".build/checkouts/swift-nio/Sources/CNIODarwin"; + sourceTree = SOURCE_ROOT; }; - OBJ_1194 /* NIOWebSocket */ = { + OBJ_1186 /* include */ = { isa = PBXGroup; children = ( + OBJ_1187 /* CNIODarwin.h */, ); - name = NIOWebSocket; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOWebSocket"; - sourceTree = SOURCE_ROOT; + name = include; + path = include; + sourceTree = ""; }; - OBJ_1195 /* CNIOHTTPParser */ = { + OBJ_1188 /* CNIOHTTPParser */ = { isa = PBXGroup; children = ( - OBJ_1196 /* c_nio_http_parser.c */, - OBJ_1197 /* include */, + OBJ_1189 /* c_nio_http_parser.c */, + OBJ_1190 /* include */, ); name = CNIOHTTPParser; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser"; + path = ".build/checkouts/swift-nio/Sources/CNIOHTTPParser"; sourceTree = SOURCE_ROOT; }; - OBJ_1197 /* include */ = { + OBJ_1190 /* include */ = { isa = PBXGroup; children = ( - OBJ_1198 /* c_nio_http_parser.h */, - OBJ_1199 /* CNIOHTTPParser.h */, + OBJ_1191 /* c_nio_http_parser.h */, + OBJ_1192 /* CNIOHTTPParser.h */, ); name = include; path = include; sourceTree = ""; }; - OBJ_1200 /* NIOConcurrencyHelpers */ = { + OBJ_1193 /* CNIOLinux */ = { isa = PBXGroup; children = ( - OBJ_1201 /* atomics.swift */, - OBJ_1202 /* lock.swift */, + OBJ_1194 /* ifaddrs-android.c */, + OBJ_1195 /* shim.c */, + OBJ_1196 /* include */, ); - name = NIOConcurrencyHelpers; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOConcurrencyHelpers"; + name = CNIOLinux; + path = ".build/checkouts/swift-nio/Sources/CNIOLinux"; sourceTree = SOURCE_ROOT; }; - OBJ_1203 /* NIOFoundationCompat */ = { + OBJ_1196 /* include */ = { isa = PBXGroup; children = ( - OBJ_1204 /* ByteBuffer-foundation.swift */, + OBJ_1197 /* CNIOLinux.h */, + OBJ_1198 /* ifaddrs-android.h */, ); - name = NIOFoundationCompat; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOFoundationCompat"; - sourceTree = SOURCE_ROOT; + name = include; + path = include; + sourceTree = ""; }; - OBJ_1205 /* CNIOSHA1 */ = { + OBJ_1199 /* CNIOSHA1 */ = { isa = PBXGroup; children = ( - OBJ_1206 /* c_nio_sha1.c */, - OBJ_1207 /* include */, + OBJ_1200 /* c_nio_sha1.c */, + OBJ_1201 /* include */, ); name = CNIOSHA1; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1"; + path = ".build/checkouts/swift-nio/Sources/CNIOSHA1"; sourceTree = SOURCE_ROOT; }; - OBJ_1207 /* include */ = { + OBJ_1201 /* include */ = { isa = PBXGroup; children = ( - OBJ_1208 /* CNIOSHA1.h */, + OBJ_1202 /* CNIOSHA1.h */, ); name = include; path = include; sourceTree = ""; }; - OBJ_1209 /* NIOWebSocketServer */ = { + OBJ_1203 /* CNIOZlib */ = { isa = PBXGroup; children = ( + OBJ_1204 /* empty.c */, + OBJ_1205 /* include */, ); - name = NIOWebSocketServer; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOWebSocketServer"; + name = CNIOZlib; + path = ".build/checkouts/swift-nio/Sources/CNIOZlib"; sourceTree = SOURCE_ROOT; }; - OBJ_121 /* client */ = { + OBJ_1205 /* include */ = { isa = PBXGroup; children = ( - OBJ_122 /* authority.cc */, - OBJ_123 /* chttp2_connector.cc */, - OBJ_124 /* insecure */, - OBJ_127 /* secure */, + OBJ_1206 /* CNIOZlib.h */, ); - name = client; - path = client; + name = include; + path = include; sourceTree = ""; }; - OBJ_1210 /* NIOPerformanceTester */ = { + OBJ_1207 /* NIO */ = { + isa = PBXGroup; + children = ( + OBJ_1208 /* AddressedEnvelope.swift */, + OBJ_1209 /* BaseSocket.swift */, + OBJ_1210 /* BaseSocketChannel.swift */, + OBJ_1211 /* BlockingIOThreadPool.swift */, + OBJ_1212 /* Bootstrap.swift */, + OBJ_1213 /* ByteBuffer-aux.swift */, + OBJ_1214 /* ByteBuffer-core.swift */, + OBJ_1215 /* ByteBuffer-int.swift */, + OBJ_1216 /* ByteBuffer-views.swift */, + OBJ_1217 /* Channel.swift */, + OBJ_1218 /* ChannelHandler.swift */, + OBJ_1219 /* ChannelHandlers.swift */, + OBJ_1220 /* ChannelInvoker.swift */, + OBJ_1221 /* ChannelOption.swift */, + OBJ_1222 /* ChannelPipeline.swift */, + OBJ_1223 /* CircularBuffer.swift */, + OBJ_1224 /* Codec.swift */, + OBJ_1225 /* CompositeError.swift */, + OBJ_1226 /* ContiguousCollection.swift */, + OBJ_1227 /* DeadChannel.swift */, + OBJ_1228 /* Embedded.swift */, + OBJ_1229 /* EventLoop.swift */, + OBJ_1230 /* EventLoopFuture.swift */, + OBJ_1231 /* FileDescriptor.swift */, + OBJ_1232 /* FileHandle.swift */, + OBJ_1233 /* FileRegion.swift */, + OBJ_1234 /* GetaddrinfoResolver.swift */, + OBJ_1235 /* HappyEyeballs.swift */, + OBJ_1236 /* Heap.swift */, + OBJ_1237 /* IO.swift */, + OBJ_1238 /* IOData.swift */, + OBJ_1239 /* IntegerTypes.swift */, + OBJ_1240 /* Interfaces.swift */, + OBJ_1241 /* Linux.swift */, + OBJ_1242 /* LinuxCPUSet.swift */, + OBJ_1243 /* MarkedCircularBuffer.swift */, + OBJ_1244 /* MulticastChannel.swift */, + OBJ_1245 /* NIOAny.swift */, + OBJ_1246 /* NonBlockingFileIO.swift */, + OBJ_1247 /* PendingDatagramWritesManager.swift */, + OBJ_1248 /* PendingWritesManager.swift */, + OBJ_1249 /* PriorityQueue.swift */, + OBJ_1250 /* RecvByteBufferAllocator.swift */, + OBJ_1251 /* Resolver.swift */, + OBJ_1252 /* Selectable.swift */, + OBJ_1253 /* Selector.swift */, + OBJ_1254 /* ServerSocket.swift */, + OBJ_1255 /* Socket.swift */, + OBJ_1256 /* SocketAddresses.swift */, + OBJ_1257 /* SocketChannel.swift */, + OBJ_1258 /* SocketOptionProvider.swift */, + OBJ_1259 /* System.swift */, + OBJ_1260 /* Thread.swift */, + OBJ_1261 /* TypeAssistedChannelHandler.swift */, + OBJ_1262 /* Utilities.swift */, + ); + name = NIO; + path = ".build/checkouts/swift-nio/Sources/NIO"; + sourceTree = SOURCE_ROOT; + }; + OBJ_1263 /* NIOChatClient */ = { isa = PBXGroup; children = ( ); - name = NIOPerformanceTester; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOPerformanceTester"; + name = NIOChatClient; + path = ".build/checkouts/swift-nio/Sources/NIOChatClient"; sourceTree = SOURCE_ROOT; }; - OBJ_1211 /* NIOHTTP1 */ = { + OBJ_1264 /* NIOChatServer */ = { isa = PBXGroup; children = ( - OBJ_1212 /* ByteCollectionUtils.swift */, - OBJ_1213 /* HTTPDecoder.swift */, - OBJ_1214 /* HTTPEncoder.swift */, - OBJ_1215 /* HTTPPipelineSetup.swift */, - OBJ_1216 /* HTTPResponseCompressor.swift */, - OBJ_1217 /* HTTPServerPipelineHandler.swift */, - OBJ_1218 /* HTTPServerProtocolErrorHandler.swift */, - OBJ_1219 /* HTTPTypes.swift */, - OBJ_1220 /* HTTPUpgradeHandler.swift */, ); - name = NIOHTTP1; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOHTTP1"; + name = NIOChatServer; + path = ".build/checkouts/swift-nio/Sources/NIOChatServer"; sourceTree = SOURCE_ROOT; }; - OBJ_1221 /* CNIOAtomics */ = { + OBJ_1265 /* NIOConcurrencyHelpers */ = { isa = PBXGroup; children = ( - OBJ_1222 /* src */, - OBJ_1224 /* include */, + OBJ_1266 /* atomics.swift */, + OBJ_1267 /* lock.swift */, ); - name = CNIOAtomics; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics"; + name = NIOConcurrencyHelpers; + path = ".build/checkouts/swift-nio/Sources/NIOConcurrencyHelpers"; sourceTree = SOURCE_ROOT; }; - OBJ_1222 /* src */ = { + OBJ_1268 /* NIOEchoClient */ = { isa = PBXGroup; children = ( - OBJ_1223 /* c-atomics.c */, ); - name = src; - path = src; - sourceTree = ""; + name = NIOEchoClient; + path = ".build/checkouts/swift-nio/Sources/NIOEchoClient"; + sourceTree = SOURCE_ROOT; }; - OBJ_1224 /* include */ = { + OBJ_1269 /* NIOEchoServer */ = { isa = PBXGroup; children = ( - OBJ_1225 /* CNIOAtomics.h */, - OBJ_1226 /* cpp_magic.h */, ); - name = include; - path = include; - sourceTree = ""; + name = NIOEchoServer; + path = ".build/checkouts/swift-nio/Sources/NIOEchoServer"; + sourceTree = SOURCE_ROOT; }; - OBJ_1227 /* NIOChatClient */ = { + OBJ_1270 /* NIOFoundationCompat */ = { isa = PBXGroup; children = ( + OBJ_1271 /* ByteBuffer-foundation.swift */, ); - name = NIOChatClient; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOChatClient"; + name = NIOFoundationCompat; + path = ".build/checkouts/swift-nio/Sources/NIOFoundationCompat"; sourceTree = SOURCE_ROOT; }; - OBJ_1228 /* CNIOLinux */ = { + OBJ_1272 /* NIOHTTP1 */ = { isa = PBXGroup; children = ( - OBJ_1229 /* ifaddrs-android.c */, - OBJ_1230 /* shim.c */, - OBJ_1231 /* include */, + OBJ_1273 /* ByteCollectionUtils.swift */, + OBJ_1274 /* HTTPDecoder.swift */, + OBJ_1275 /* HTTPEncoder.swift */, + OBJ_1276 /* HTTPPipelineSetup.swift */, + OBJ_1277 /* HTTPResponseCompressor.swift */, + OBJ_1278 /* HTTPServerPipelineHandler.swift */, + OBJ_1279 /* HTTPServerProtocolErrorHandler.swift */, + OBJ_1280 /* HTTPTypes.swift */, + OBJ_1281 /* HTTPUpgradeHandler.swift */, ); - name = CNIOLinux; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux"; + name = NIOHTTP1; + path = ".build/checkouts/swift-nio/Sources/NIOHTTP1"; sourceTree = SOURCE_ROOT; }; - OBJ_1231 /* include */ = { + OBJ_1282 /* NIOHTTP1Server */ = { isa = PBXGroup; children = ( - OBJ_1232 /* CNIOLinux.h */, - OBJ_1233 /* ifaddrs-android.h */, ); - name = include; - path = include; - sourceTree = ""; + name = NIOHTTP1Server; + path = ".build/checkouts/swift-nio/Sources/NIOHTTP1Server"; + sourceTree = SOURCE_ROOT; }; - OBJ_1234 /* NIOMulticastChat */ = { + OBJ_1283 /* NIOMulticastChat */ = { isa = PBXGroup; children = ( ); name = NIOMulticastChat; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOMulticastChat"; + path = ".build/checkouts/swift-nio/Sources/NIOMulticastChat"; sourceTree = SOURCE_ROOT; }; - OBJ_1235 /* NIOPriorityQueue */ = { + OBJ_1284 /* NIOPerformanceTester */ = { isa = PBXGroup; children = ( - OBJ_1236 /* Heap.swift */, - OBJ_1237 /* PriorityQueue.swift */, + ); + name = NIOPerformanceTester; + path = ".build/checkouts/swift-nio/Sources/NIOPerformanceTester"; + sourceTree = SOURCE_ROOT; + }; + OBJ_1285 /* NIOPriorityQueue */ = { + isa = PBXGroup; + children = ( + OBJ_1286 /* Heap.swift */, + OBJ_1287 /* PriorityQueue.swift */, ); name = NIOPriorityQueue; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOPriorityQueue"; + path = ".build/checkouts/swift-nio/Sources/NIOPriorityQueue"; sourceTree = SOURCE_ROOT; }; - OBJ_1238 /* NIOEchoServer */ = { + OBJ_1288 /* NIOTLS */ = { isa = PBXGroup; children = ( + OBJ_1289 /* ApplicationProtocolNegotiationHandler.swift */, + OBJ_1290 /* SNIHandler.swift */, + OBJ_1291 /* TLSEvents.swift */, ); - name = NIOEchoServer; - path = ".build/checkouts/swift-nio.git--5531377063216196022/Sources/NIOEchoServer"; + name = NIOTLS; + path = ".build/checkouts/swift-nio/Sources/NIOTLS"; sourceTree = SOURCE_ROOT; }; - OBJ_124 /* insecure */ = { + OBJ_1292 /* NIOWebSocket */ = { isa = PBXGroup; children = ( - OBJ_125 /* channel_create.cc */, - OBJ_126 /* channel_create_posix.cc */, ); - name = insecure; - path = insecure; - sourceTree = ""; + name = NIOWebSocket; + path = ".build/checkouts/swift-nio/Sources/NIOWebSocket"; + sourceTree = SOURCE_ROOT; + }; + OBJ_1293 /* NIOWebSocketServer */ = { + isa = PBXGroup; + children = ( + ); + name = NIOWebSocketServer; + path = ".build/checkouts/swift-nio/Sources/NIOWebSocketServer"; + sourceTree = SOURCE_ROOT; }; - OBJ_1240 /* Commander 0.8.0 */ = { + OBJ_1295 /* Commander 0.8.0 */ = { isa = PBXGroup; children = ( - OBJ_1241 /* Commander */, - OBJ_1251 /* Package.swift */, + OBJ_1296 /* Commander */, + OBJ_1306 /* Package.swift */, ); name = "Commander 0.8.0"; path = ""; sourceTree = SOURCE_ROOT; }; - OBJ_1241 /* Commander */ = { + OBJ_1296 /* Commander */ = { isa = PBXGroup; children = ( - OBJ_1242 /* ArgumentConvertible.swift */, - OBJ_1243 /* ArgumentDescription.swift */, - OBJ_1244 /* ArgumentParser.swift */, - OBJ_1245 /* Command.swift */, - OBJ_1246 /* CommandRunner.swift */, - OBJ_1247 /* CommandType.swift */, - OBJ_1248 /* Commands.swift */, - OBJ_1249 /* Error.swift */, - OBJ_1250 /* Group.swift */, + OBJ_1297 /* ArgumentConvertible.swift */, + OBJ_1298 /* ArgumentDescription.swift */, + OBJ_1299 /* ArgumentParser.swift */, + OBJ_1300 /* Command.swift */, + OBJ_1301 /* CommandRunner.swift */, + OBJ_1302 /* CommandType.swift */, + OBJ_1303 /* Commands.swift */, + OBJ_1304 /* Error.swift */, + OBJ_1305 /* Group.swift */, ); name = Commander; - path = ".build/checkouts/Commander.git--4520459584696957767/Sources/Commander"; + path = .build/checkouts/Commander/Sources/Commander; sourceTree = SOURCE_ROOT; }; - OBJ_1252 /* SwiftProtobuf 1.3.1 */ = { + OBJ_1307 /* SwiftProtobuf 1.4.0 */ = { isa = PBXGroup; children = ( - OBJ_1253 /* SwiftProtobuf */, - OBJ_1331 /* protoc-gen-swift */, - OBJ_1350 /* Conformance */, - OBJ_1351 /* SwiftProtobufPluginLibrary */, - OBJ_1370 /* Package.swift */, + OBJ_1308 /* Conformance */, + OBJ_1309 /* SwiftProtobuf */, + OBJ_1387 /* SwiftProtobufPluginLibrary */, + OBJ_1406 /* protoc-gen-swift */, + OBJ_1425 /* Package.swift */, ); - name = "SwiftProtobuf 1.3.1"; + name = "SwiftProtobuf 1.4.0"; path = ""; sourceTree = SOURCE_ROOT; }; - OBJ_1253 /* SwiftProtobuf */ = { - isa = PBXGroup; - children = ( - OBJ_1254 /* AnyMessageStorage.swift */, - OBJ_1255 /* AnyUnpackError.swift */, - OBJ_1256 /* BinaryDecoder.swift */, - OBJ_1257 /* BinaryDecodingError.swift */, - OBJ_1258 /* BinaryDecodingOptions.swift */, - OBJ_1259 /* BinaryDelimited.swift */, - OBJ_1260 /* BinaryEncoder.swift */, - OBJ_1261 /* BinaryEncodingError.swift */, - OBJ_1262 /* BinaryEncodingSizeVisitor.swift */, - OBJ_1263 /* BinaryEncodingVisitor.swift */, - OBJ_1264 /* CustomJSONCodable.swift */, - OBJ_1265 /* Decoder.swift */, - OBJ_1266 /* DoubleFormatter.swift */, - OBJ_1267 /* Enum.swift */, - OBJ_1268 /* ExtensibleMessage.swift */, - OBJ_1269 /* ExtensionFieldValueSet.swift */, - OBJ_1270 /* ExtensionFields.swift */, - OBJ_1271 /* ExtensionMap.swift */, - OBJ_1272 /* FieldTag.swift */, - OBJ_1273 /* FieldTypes.swift */, - OBJ_1274 /* Google_Protobuf_Any+Extensions.swift */, - OBJ_1275 /* Google_Protobuf_Any+Registry.swift */, - OBJ_1276 /* Google_Protobuf_Duration+Extensions.swift */, - OBJ_1277 /* Google_Protobuf_FieldMask+Extensions.swift */, - OBJ_1278 /* Google_Protobuf_ListValue+Extensions.swift */, - OBJ_1279 /* Google_Protobuf_Struct+Extensions.swift */, - OBJ_1280 /* Google_Protobuf_Timestamp+Extensions.swift */, - OBJ_1281 /* Google_Protobuf_Value+Extensions.swift */, - OBJ_1282 /* Google_Protobuf_Wrappers+Extensions.swift */, - OBJ_1283 /* HashVisitor.swift */, - OBJ_1284 /* Internal.swift */, - OBJ_1285 /* JSONDecoder.swift */, - OBJ_1286 /* JSONDecodingError.swift */, - OBJ_1287 /* JSONDecodingOptions.swift */, - OBJ_1288 /* JSONEncoder.swift */, - OBJ_1289 /* JSONEncodingError.swift */, - OBJ_1290 /* JSONEncodingOptions.swift */, - OBJ_1291 /* JSONEncodingVisitor.swift */, - OBJ_1292 /* JSONMapEncodingVisitor.swift */, - OBJ_1293 /* JSONScanner.swift */, - OBJ_1294 /* MathUtils.swift */, - OBJ_1295 /* Message+AnyAdditions.swift */, - OBJ_1296 /* Message+BinaryAdditions.swift */, - OBJ_1297 /* Message+JSONAdditions.swift */, - OBJ_1298 /* Message+JSONArrayAdditions.swift */, - OBJ_1299 /* Message+TextFormatAdditions.swift */, - OBJ_1300 /* Message.swift */, - OBJ_1301 /* MessageExtension.swift */, - OBJ_1302 /* NameMap.swift */, - OBJ_1303 /* ProtoNameProviding.swift */, - OBJ_1304 /* ProtobufAPIVersionCheck.swift */, - OBJ_1305 /* ProtobufMap.swift */, - OBJ_1306 /* SelectiveVisitor.swift */, - OBJ_1307 /* SimpleExtensionMap.swift */, - OBJ_1308 /* StringUtils.swift */, - OBJ_1309 /* TextFormatDecoder.swift */, - OBJ_1310 /* TextFormatDecodingError.swift */, - OBJ_1311 /* TextFormatEncoder.swift */, - OBJ_1312 /* TextFormatEncodingVisitor.swift */, - OBJ_1313 /* TextFormatScanner.swift */, - OBJ_1314 /* TimeUtils.swift */, - OBJ_1315 /* UnknownStorage.swift */, - OBJ_1316 /* Varint.swift */, - OBJ_1317 /* Version.swift */, - OBJ_1318 /* Visitor.swift */, - OBJ_1319 /* WireFormat.swift */, - OBJ_1320 /* ZigZag.swift */, - OBJ_1321 /* any.pb.swift */, - OBJ_1322 /* api.pb.swift */, - OBJ_1323 /* duration.pb.swift */, - OBJ_1324 /* empty.pb.swift */, - OBJ_1325 /* field_mask.pb.swift */, - OBJ_1326 /* source_context.pb.swift */, - OBJ_1327 /* struct.pb.swift */, - OBJ_1328 /* timestamp.pb.swift */, - OBJ_1329 /* type.pb.swift */, - OBJ_1330 /* wrappers.pb.swift */, + OBJ_1308 /* Conformance */ = { + isa = PBXGroup; + children = ( + ); + name = Conformance; + path = ".build/checkouts/swift-protobuf/Sources/Conformance"; + sourceTree = SOURCE_ROOT; + }; + OBJ_1309 /* SwiftProtobuf */ = { + isa = PBXGroup; + children = ( + OBJ_1310 /* AnyMessageStorage.swift */, + OBJ_1311 /* AnyUnpackError.swift */, + OBJ_1312 /* BinaryDecoder.swift */, + OBJ_1313 /* BinaryDecodingError.swift */, + OBJ_1314 /* BinaryDecodingOptions.swift */, + OBJ_1315 /* BinaryDelimited.swift */, + OBJ_1316 /* BinaryEncoder.swift */, + OBJ_1317 /* BinaryEncodingError.swift */, + OBJ_1318 /* BinaryEncodingSizeVisitor.swift */, + OBJ_1319 /* BinaryEncodingVisitor.swift */, + OBJ_1320 /* CustomJSONCodable.swift */, + OBJ_1321 /* Decoder.swift */, + OBJ_1322 /* DoubleFormatter.swift */, + OBJ_1323 /* Enum.swift */, + OBJ_1324 /* ExtensibleMessage.swift */, + OBJ_1325 /* ExtensionFieldValueSet.swift */, + OBJ_1326 /* ExtensionFields.swift */, + OBJ_1327 /* ExtensionMap.swift */, + OBJ_1328 /* FieldTag.swift */, + OBJ_1329 /* FieldTypes.swift */, + OBJ_1330 /* Google_Protobuf_Any+Extensions.swift */, + OBJ_1331 /* Google_Protobuf_Any+Registry.swift */, + OBJ_1332 /* Google_Protobuf_Duration+Extensions.swift */, + OBJ_1333 /* Google_Protobuf_FieldMask+Extensions.swift */, + OBJ_1334 /* Google_Protobuf_ListValue+Extensions.swift */, + OBJ_1335 /* Google_Protobuf_Struct+Extensions.swift */, + OBJ_1336 /* Google_Protobuf_Timestamp+Extensions.swift */, + OBJ_1337 /* Google_Protobuf_Value+Extensions.swift */, + OBJ_1338 /* Google_Protobuf_Wrappers+Extensions.swift */, + OBJ_1339 /* HashVisitor.swift */, + OBJ_1340 /* Internal.swift */, + OBJ_1341 /* JSONDecoder.swift */, + OBJ_1342 /* JSONDecodingError.swift */, + OBJ_1343 /* JSONDecodingOptions.swift */, + OBJ_1344 /* JSONEncoder.swift */, + OBJ_1345 /* JSONEncodingError.swift */, + OBJ_1346 /* JSONEncodingOptions.swift */, + OBJ_1347 /* JSONEncodingVisitor.swift */, + OBJ_1348 /* JSONMapEncodingVisitor.swift */, + OBJ_1349 /* JSONScanner.swift */, + OBJ_1350 /* MathUtils.swift */, + OBJ_1351 /* Message+AnyAdditions.swift */, + OBJ_1352 /* Message+BinaryAdditions.swift */, + OBJ_1353 /* Message+JSONAdditions.swift */, + OBJ_1354 /* Message+JSONArrayAdditions.swift */, + OBJ_1355 /* Message+TextFormatAdditions.swift */, + OBJ_1356 /* Message.swift */, + OBJ_1357 /* MessageExtension.swift */, + OBJ_1358 /* NameMap.swift */, + OBJ_1359 /* ProtoNameProviding.swift */, + OBJ_1360 /* ProtobufAPIVersionCheck.swift */, + OBJ_1361 /* ProtobufMap.swift */, + OBJ_1362 /* SelectiveVisitor.swift */, + OBJ_1363 /* SimpleExtensionMap.swift */, + OBJ_1364 /* StringUtils.swift */, + OBJ_1365 /* TextFormatDecoder.swift */, + OBJ_1366 /* TextFormatDecodingError.swift */, + OBJ_1367 /* TextFormatEncoder.swift */, + OBJ_1368 /* TextFormatEncodingVisitor.swift */, + OBJ_1369 /* TextFormatScanner.swift */, + OBJ_1370 /* TimeUtils.swift */, + OBJ_1371 /* UnknownStorage.swift */, + OBJ_1372 /* Varint.swift */, + OBJ_1373 /* Version.swift */, + OBJ_1374 /* Visitor.swift */, + OBJ_1375 /* WireFormat.swift */, + OBJ_1376 /* ZigZag.swift */, + OBJ_1377 /* any.pb.swift */, + OBJ_1378 /* api.pb.swift */, + OBJ_1379 /* duration.pb.swift */, + OBJ_1380 /* empty.pb.swift */, + OBJ_1381 /* field_mask.pb.swift */, + OBJ_1382 /* source_context.pb.swift */, + OBJ_1383 /* struct.pb.swift */, + OBJ_1384 /* timestamp.pb.swift */, + OBJ_1385 /* type.pb.swift */, + OBJ_1386 /* wrappers.pb.swift */, ); name = SwiftProtobuf; - path = ".build/checkouts/swift-protobuf.git-2901371442460970160/Sources/SwiftProtobuf"; + path = ".build/checkouts/swift-protobuf/Sources/SwiftProtobuf"; sourceTree = SOURCE_ROOT; }; - OBJ_127 /* secure */ = { - isa = PBXGroup; - children = ( - OBJ_128 /* secure_channel_create.cc */, + OBJ_131 /* fipsmodule */ = { + isa = PBXGroup; + children = ( + OBJ_132 /* aes */, + OBJ_136 /* bn */, + OBJ_155 /* cipher */, + OBJ_160 /* des */, + OBJ_162 /* digest */, + OBJ_165 /* ec */, + OBJ_175 /* ecdsa */, + OBJ_177 /* hmac */, + OBJ_179 /* is_fips.c */, + OBJ_180 /* md4 */, + OBJ_182 /* md5 */, + OBJ_184 /* modes */, + OBJ_192 /* rand */, + OBJ_196 /* rsa */, + OBJ_201 /* self_check */, + OBJ_203 /* sha */, + OBJ_208 /* tls */, ); - name = secure; - path = secure; + name = fipsmodule; + path = fipsmodule; sourceTree = ""; }; - OBJ_129 /* server */ = { + OBJ_132 /* aes */ = { isa = PBXGroup; children = ( - OBJ_130 /* chttp2_server.cc */, - OBJ_131 /* insecure */, - OBJ_134 /* secure */, + OBJ_133 /* aes.c */, + OBJ_134 /* key_wrap.c */, + OBJ_135 /* mode_wrappers.c */, ); - name = server; - path = server; + name = aes; + path = aes; sourceTree = ""; }; - OBJ_131 /* insecure */ = { - isa = PBXGroup; - children = ( - OBJ_132 /* server_chttp2.cc */, - OBJ_133 /* server_chttp2_posix.cc */, + OBJ_136 /* bn */ = { + isa = PBXGroup; + children = ( + OBJ_137 /* add.c */, + OBJ_138 /* bn.c */, + OBJ_139 /* bytes.c */, + OBJ_140 /* cmp.c */, + OBJ_141 /* ctx.c */, + OBJ_142 /* div.c */, + OBJ_143 /* exponentiation.c */, + OBJ_144 /* gcd.c */, + OBJ_145 /* generic.c */, + OBJ_146 /* jacobi.c */, + OBJ_147 /* montgomery.c */, + OBJ_148 /* montgomery_inv.c */, + OBJ_149 /* mul.c */, + OBJ_150 /* prime.c */, + OBJ_151 /* random.c */, + OBJ_152 /* rsaz_exp.c */, + OBJ_153 /* shift.c */, + OBJ_154 /* sqrt.c */, ); - name = insecure; - path = insecure; + name = bn; + path = bn; sourceTree = ""; }; - OBJ_1331 /* protoc-gen-swift */ = { - isa = PBXGroup; - children = ( - OBJ_1332 /* CommandLine+Extensions.swift */, - OBJ_1333 /* Descriptor+Extensions.swift */, - OBJ_1334 /* EnumGenerator.swift */, - OBJ_1335 /* ExtensionSetGenerator.swift */, - OBJ_1336 /* FieldGenerator.swift */, - OBJ_1337 /* FileGenerator.swift */, - OBJ_1338 /* FileIo.swift */, - OBJ_1339 /* GenerationError.swift */, - OBJ_1340 /* GeneratorOptions.swift */, - OBJ_1341 /* Google_Protobuf_DescriptorProto+Extensions.swift */, - OBJ_1342 /* Google_Protobuf_FileDescriptorProto+Extensions.swift */, - OBJ_1343 /* MessageFieldGenerator.swift */, - OBJ_1344 /* MessageGenerator.swift */, - OBJ_1345 /* MessageStorageClassGenerator.swift */, - OBJ_1346 /* OneofGenerator.swift */, - OBJ_1347 /* StringUtils.swift */, - OBJ_1348 /* Version.swift */, - OBJ_1349 /* main.swift */, + OBJ_1387 /* SwiftProtobufPluginLibrary */ = { + isa = PBXGroup; + children = ( + OBJ_1388 /* Array+Extensions.swift */, + OBJ_1389 /* CodePrinter.swift */, + OBJ_1390 /* Descriptor+Extensions.swift */, + OBJ_1391 /* Descriptor.swift */, + OBJ_1392 /* FieldNumbers.swift */, + OBJ_1393 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift */, + OBJ_1394 /* Google_Protobuf_SourceCodeInfo+Extensions.swift */, + OBJ_1395 /* NamingUtils.swift */, + OBJ_1396 /* ProtoFileToModuleMappings.swift */, + OBJ_1397 /* ProvidesLocationPath.swift */, + OBJ_1398 /* ProvidesSourceCodeLocation.swift */, + OBJ_1399 /* SwiftLanguage.swift */, + OBJ_1400 /* SwiftProtobufInfo.swift */, + OBJ_1401 /* SwiftProtobufNamer.swift */, + OBJ_1402 /* UnicodeScalar+Extensions.swift */, + OBJ_1403 /* descriptor.pb.swift */, + OBJ_1404 /* plugin.pb.swift */, + OBJ_1405 /* swift_protobuf_module_mappings.pb.swift */, ); - name = "protoc-gen-swift"; - path = ".build/checkouts/swift-protobuf.git-2901371442460970160/Sources/protoc-gen-swift"; + name = SwiftProtobufPluginLibrary; + path = ".build/checkouts/swift-protobuf/Sources/SwiftProtobufPluginLibrary"; sourceTree = SOURCE_ROOT; }; - OBJ_134 /* secure */ = { - isa = PBXGroup; - children = ( - OBJ_135 /* server_secure_chttp2.cc */, + OBJ_1406 /* protoc-gen-swift */ = { + isa = PBXGroup; + children = ( + OBJ_1407 /* CommandLine+Extensions.swift */, + OBJ_1408 /* Descriptor+Extensions.swift */, + OBJ_1409 /* EnumGenerator.swift */, + OBJ_1410 /* ExtensionSetGenerator.swift */, + OBJ_1411 /* FieldGenerator.swift */, + OBJ_1412 /* FileGenerator.swift */, + OBJ_1413 /* FileIo.swift */, + OBJ_1414 /* GenerationError.swift */, + OBJ_1415 /* GeneratorOptions.swift */, + OBJ_1416 /* Google_Protobuf_DescriptorProto+Extensions.swift */, + OBJ_1417 /* Google_Protobuf_FileDescriptorProto+Extensions.swift */, + OBJ_1418 /* MessageFieldGenerator.swift */, + OBJ_1419 /* MessageGenerator.swift */, + OBJ_1420 /* MessageStorageClassGenerator.swift */, + OBJ_1421 /* OneofGenerator.swift */, + OBJ_1422 /* StringUtils.swift */, + OBJ_1423 /* Version.swift */, + OBJ_1424 /* main.swift */, ); - name = secure; - path = secure; - sourceTree = ""; + name = "protoc-gen-swift"; + path = ".build/checkouts/swift-protobuf/Sources/protoc-gen-swift"; + sourceTree = SOURCE_ROOT; }; - OBJ_1350 /* Conformance */ = { - isa = PBXGroup; - children = ( - ); - name = Conformance; - path = ".build/checkouts/swift-protobuf.git-2901371442460970160/Sources/Conformance"; - sourceTree = SOURCE_ROOT; - }; - OBJ_1351 /* SwiftProtobufPluginLibrary */ = { - isa = PBXGroup; - children = ( - OBJ_1352 /* Array+Extensions.swift */, - OBJ_1353 /* CodePrinter.swift */, - OBJ_1354 /* Descriptor+Extensions.swift */, - OBJ_1355 /* Descriptor.swift */, - OBJ_1356 /* FieldNumbers.swift */, - OBJ_1357 /* Google_Protobuf_Compiler_CodeGeneratorResponse+Extensions.swift */, - OBJ_1358 /* Google_Protobuf_SourceCodeInfo+Extensions.swift */, - OBJ_1359 /* NamingUtils.swift */, - OBJ_1360 /* ProtoFileToModuleMappings.swift */, - OBJ_1361 /* ProvidesLocationPath.swift */, - OBJ_1362 /* ProvidesSourceCodeLocation.swift */, - OBJ_1363 /* SwiftLanguage.swift */, - OBJ_1364 /* SwiftProtobufInfo.swift */, - OBJ_1365 /* SwiftProtobufNamer.swift */, - OBJ_1366 /* UnicodeScalar+Extensions.swift */, - OBJ_1367 /* descriptor.pb.swift */, - OBJ_1368 /* plugin.pb.swift */, - OBJ_1369 /* swift_protobuf_module_mappings.pb.swift */, - ); - name = SwiftProtobufPluginLibrary; - path = ".build/checkouts/swift-protobuf.git-2901371442460970160/Sources/SwiftProtobufPluginLibrary"; - sourceTree = SOURCE_ROOT; - }; - OBJ_136 /* transport */ = { - isa = PBXGroup; - children = ( - OBJ_137 /* bin_decoder.cc */, - OBJ_138 /* bin_encoder.cc */, - OBJ_139 /* chttp2_plugin.cc */, - OBJ_140 /* chttp2_transport.cc */, - OBJ_141 /* flow_control.cc */, - OBJ_142 /* frame_data.cc */, - OBJ_143 /* frame_goaway.cc */, - OBJ_144 /* frame_ping.cc */, - OBJ_145 /* frame_rst_stream.cc */, - OBJ_146 /* frame_settings.cc */, - OBJ_147 /* frame_window_update.cc */, - OBJ_148 /* hpack_encoder.cc */, - OBJ_149 /* hpack_parser.cc */, - OBJ_150 /* hpack_table.cc */, - OBJ_151 /* http2_settings.cc */, - OBJ_152 /* huffsyms.cc */, - OBJ_153 /* incoming_metadata.cc */, - OBJ_154 /* parsing.cc */, - OBJ_155 /* stream_lists.cc */, - OBJ_156 /* stream_map.cc */, - OBJ_157 /* varint.cc */, - OBJ_158 /* writing.cc */, - ); - name = transport; - path = transport; - sourceTree = ""; - }; - OBJ_1371 /* Products */ = { + OBJ_1426 /* Products */ = { isa = PBXGroup; children = ( + swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */, + swift-nio::CNIOLinux::Product /* CNIOLinux.framework */, + swift-nio::NIO::Product /* NIO.framework */, SwiftGRPC::RootsEncoder::Product /* RootsEncoder */, swift-nio::NIOHTTP1::Product /* NIOHTTP1.framework */, + SwiftGRPC::EchoNIO::Product /* EchoNIO */, + swift-nio::CNIODarwin::Product /* CNIODarwin.framework */, + swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */, + SwiftGRPC::SwiftGRPCNIOTests::Product /* SwiftGRPCNIOTests.xctest */, SwiftProtobuf::SwiftProtobuf::Product /* SwiftProtobuf.framework */, - swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */, + SwiftProtobuf::protoc-gen-swift::Product /* protoc-gen-swift */, SwiftGRPC::Simple::Product /* Simple */, - SwiftGRPC::CgRPC::Product /* CgRPC.framework */, - swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */, - swift-nio::NIO::Product /* NIO.framework */, - SwiftGRPC::SwiftGRPCTests::Product /* SwiftGRPCTests.xctest */, - swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */, - swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */, - swift-nio::NIOTLS::Product /* NIOTLS.framework */, Commander::Commander::Product /* Commander.framework */, - swift-nio::NIOConcurrencyHelpers::Product /* NIOConcurrencyHelpers.framework */, - SwiftGRPC::SwiftGRPCNIOTests::Product /* SwiftGRPCNIOTests.xctest */, - SwiftGRPC::Echo::Product /* Echo */, + swift-nio::CNIOAtomics::Product /* CNIOAtomics.framework */, SwiftGRPC::SwiftGRPC::Product /* SwiftGRPC.framework */, - swift-nio::CNIOLinux::Product /* CNIOLinux.framework */, + SwiftProtobuf::SwiftProtobufPluginLibrary::Product /* SwiftProtobufPluginLibrary.framework */, swift-nio-http2::CNIONghttp2::Product /* CNIONghttp2.framework */, - swift-nio::NIOPriorityQueue::Product /* NIOPriorityQueue.framework */, - SwiftProtobuf::protoc-gen-swift::Product /* protoc-gen-swift */, - swift-nio::CNIOZlib::Product /* CNIOZlib.framework */, swift-nio::NIOFoundationCompat::Product /* NIOFoundationCompat.framework */, - SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */, + swift-nio-http2::NIOHTTP2::Product /* NIOHTTP2.framework */, SwiftGRPC::SwiftGRPCNIO::Product /* SwiftGRPCNIO.framework */, - swift-nio::CNIODarwin::Product /* CNIODarwin.framework */, - SwiftProtobuf::SwiftProtobufPluginLibrary::Product /* SwiftProtobufPluginLibrary.framework */, - SwiftGRPC::EchoNIO::Product /* EchoNIO */, + swift-nio::CNIOHTTPParser::Product /* CNIOHTTPParser.framework */, + SwiftGRPC::CgRPC::Product /* CgRPC.framework */, + SwiftGRPC::SwiftGRPCTests::Product /* SwiftGRPCTests.xctest */, + swift-nio::NIOTLS::Product /* NIOTLS.framework */, SwiftGRPC::protoc-gen-swiftgrpc::Product /* protoc-gen-swiftgrpc */, + swift-nio::CNIOZlib::Product /* CNIOZlib.framework */, + SwiftGRPC::Echo::Product /* Echo */, + swift-nio::CNIOSHA1::Product /* CNIOSHA1.framework */, + SwiftGRPC::BoringSSL::Product /* BoringSSL.framework */, ); name = Products; path = ""; sourceTree = BUILT_PRODUCTS_DIR; }; - OBJ_159 /* inproc */ = { + OBJ_155 /* cipher */ = { isa = PBXGroup; children = ( - OBJ_160 /* inproc_plugin.cc */, - OBJ_161 /* inproc_transport.cc */, + OBJ_156 /* aead.c */, + OBJ_157 /* cipher.c */, + OBJ_158 /* e_aes.c */, + OBJ_159 /* e_des.c */, ); - name = inproc; - path = inproc; + name = cipher; + path = cipher; sourceTree = ""; }; - OBJ_162 /* lib */ = { + OBJ_160 /* des */ = { isa = PBXGroup; children = ( - OBJ_163 /* avl */, - OBJ_165 /* backoff */, - OBJ_167 /* channel */, - OBJ_178 /* compression */, - OBJ_185 /* debug */, - OBJ_189 /* gpr */, - OBJ_225 /* gprpp */, - OBJ_228 /* http */, - OBJ_233 /* iomgr */, - OBJ_317 /* json */, - OBJ_322 /* profiling */, - OBJ_325 /* security */, - OBJ_371 /* slice */, - OBJ_378 /* surface */, - OBJ_399 /* transport */, + OBJ_161 /* des.c */, ); - name = lib; - path = lib; + name = des; + path = des; sourceTree = ""; }; - OBJ_163 /* avl */ = { + OBJ_162 /* digest */ = { isa = PBXGroup; children = ( - OBJ_164 /* avl.cc */, + OBJ_163 /* digest.c */, + OBJ_164 /* digests.c */, ); - name = avl; - path = avl; + name = digest; + path = digest; sourceTree = ""; }; - OBJ_165 /* backoff */ = { + OBJ_165 /* ec */ = { isa = PBXGroup; children = ( - OBJ_166 /* backoff.cc */, + OBJ_166 /* ec.c */, + OBJ_167 /* ec_key.c */, + OBJ_168 /* ec_montgomery.c */, + OBJ_169 /* oct.c */, + OBJ_170 /* p224-64.c */, + OBJ_171 /* p256-x86_64.c */, + OBJ_172 /* simple.c */, + OBJ_173 /* util.c */, + OBJ_174 /* wnaf.c */, ); - name = backoff; - path = backoff; + name = ec; + path = ec; sourceTree = ""; }; - OBJ_167 /* channel */ = { + OBJ_175 /* ecdsa */ = { isa = PBXGroup; children = ( - OBJ_168 /* channel_args.cc */, - OBJ_169 /* channel_stack.cc */, - OBJ_170 /* channel_stack_builder.cc */, - OBJ_171 /* channel_trace.cc */, - OBJ_172 /* channel_trace_registry.cc */, - OBJ_173 /* connected_channel.cc */, - OBJ_174 /* handshaker.cc */, - OBJ_175 /* handshaker_factory.cc */, - OBJ_176 /* handshaker_registry.cc */, - OBJ_177 /* status_util.cc */, + OBJ_176 /* ecdsa.c */, ); - name = channel; - path = channel; + name = ecdsa; + path = ecdsa; sourceTree = ""; }; - OBJ_17 /* EchoNIO */ = { + OBJ_177 /* hmac */ = { isa = PBXGroup; children = ( - OBJ_18 /* EchoProviderNIO.swift */, - OBJ_19 /* Generated */, - OBJ_22 /* main.swift */, + OBJ_178 /* hmac.c */, ); - name = EchoNIO; - path = Sources/Examples/EchoNIO; - sourceTree = SOURCE_ROOT; + name = hmac; + path = hmac; + sourceTree = ""; }; - OBJ_178 /* compression */ = { + OBJ_180 /* md4 */ = { isa = PBXGroup; children = ( - OBJ_179 /* compression.cc */, - OBJ_180 /* compression_internal.cc */, - OBJ_181 /* message_compress.cc */, - OBJ_182 /* stream_compression.cc */, - OBJ_183 /* stream_compression_gzip.cc */, - OBJ_184 /* stream_compression_identity.cc */, + OBJ_181 /* md4.c */, ); - name = compression; - path = compression; + name = md4; + path = md4; sourceTree = ""; }; - OBJ_185 /* debug */ = { + OBJ_182 /* md5 */ = { isa = PBXGroup; children = ( - OBJ_186 /* stats.cc */, - OBJ_187 /* stats_data.cc */, - OBJ_188 /* trace.cc */, + OBJ_183 /* md5.c */, ); - name = debug; - path = debug; + name = md5; + path = md5; sourceTree = ""; }; - OBJ_189 /* gpr */ = { - isa = PBXGroup; - children = ( - OBJ_190 /* alloc.cc */, - OBJ_191 /* arena.cc */, - OBJ_192 /* atm.cc */, - OBJ_193 /* cpu_iphone.cc */, - OBJ_194 /* cpu_linux.cc */, - OBJ_195 /* cpu_posix.cc */, - OBJ_196 /* cpu_windows.cc */, - OBJ_197 /* env_linux.cc */, - OBJ_198 /* env_posix.cc */, - OBJ_199 /* env_windows.cc */, - OBJ_200 /* fork.cc */, - OBJ_201 /* host_port.cc */, - OBJ_202 /* log.cc */, - OBJ_203 /* log_android.cc */, - OBJ_204 /* log_linux.cc */, - OBJ_205 /* log_posix.cc */, - OBJ_206 /* log_windows.cc */, - OBJ_207 /* mpscq.cc */, - OBJ_208 /* murmur_hash.cc */, - OBJ_209 /* string.cc */, - OBJ_210 /* string_posix.cc */, - OBJ_211 /* string_util_windows.cc */, - OBJ_212 /* string_windows.cc */, - OBJ_213 /* sync.cc */, - OBJ_214 /* sync_posix.cc */, - OBJ_215 /* sync_windows.cc */, - OBJ_216 /* time.cc */, - OBJ_217 /* time_posix.cc */, - OBJ_218 /* time_precise.cc */, - OBJ_219 /* time_windows.cc */, - OBJ_220 /* tls_pthread.cc */, - OBJ_221 /* tmpfile_msys.cc */, - OBJ_222 /* tmpfile_posix.cc */, - OBJ_223 /* tmpfile_windows.cc */, - OBJ_224 /* wrap_memcpy.cc */, + OBJ_184 /* modes */ = { + isa = PBXGroup; + children = ( + OBJ_185 /* cbc.c */, + OBJ_186 /* ccm.c */, + OBJ_187 /* cfb.c */, + OBJ_188 /* ctr.c */, + OBJ_189 /* gcm.c */, + OBJ_190 /* ofb.c */, + OBJ_191 /* polyval.c */, ); - name = gpr; - path = gpr; + name = modes; + path = modes; sourceTree = ""; }; - OBJ_19 /* Generated */ = { + OBJ_192 /* rand */ = { isa = PBXGroup; children = ( - OBJ_20 /* echo.grpc.swift */, - OBJ_21 /* echo.pb.swift */, + OBJ_193 /* ctrdrbg.c */, + OBJ_194 /* rand.c */, + OBJ_195 /* urandom.c */, ); - name = Generated; - path = Generated; + name = rand; + path = rand; sourceTree = ""; }; - OBJ_225 /* gprpp */ = { + OBJ_196 /* rsa */ = { isa = PBXGroup; children = ( - OBJ_226 /* thd_posix.cc */, - OBJ_227 /* thd_windows.cc */, + OBJ_197 /* blinding.c */, + OBJ_198 /* padding.c */, + OBJ_199 /* rsa.c */, + OBJ_200 /* rsa_impl.c */, ); - name = gprpp; - path = gprpp; + name = rsa; + path = rsa; sourceTree = ""; }; - OBJ_228 /* http */ = { + OBJ_201 /* self_check */ = { isa = PBXGroup; children = ( - OBJ_229 /* format_request.cc */, - OBJ_230 /* httpcli.cc */, - OBJ_231 /* httpcli_security_connector.cc */, - OBJ_232 /* parser.cc */, + OBJ_202 /* self_check.c */, ); - name = http; - path = http; + name = self_check; + path = self_check; sourceTree = ""; }; - OBJ_23 /* RootsEncoder */ = { + OBJ_203 /* sha */ = { isa = PBXGroup; children = ( - OBJ_24 /* main.swift */, + OBJ_204 /* sha1-altivec.c */, + OBJ_205 /* sha1.c */, + OBJ_206 /* sha256.c */, + OBJ_207 /* sha512.c */, ); - name = RootsEncoder; - path = Sources/RootsEncoder; - sourceTree = SOURCE_ROOT; + name = sha; + path = sha; + sourceTree = ""; }; - OBJ_233 /* iomgr */ = { - isa = PBXGroup; - children = ( - OBJ_234 /* call_combiner.cc */, - OBJ_235 /* combiner.cc */, - OBJ_236 /* endpoint.cc */, - OBJ_237 /* endpoint_pair_posix.cc */, - OBJ_238 /* endpoint_pair_uv.cc */, - OBJ_239 /* endpoint_pair_windows.cc */, - OBJ_240 /* error.cc */, - OBJ_241 /* ev_epoll1_linux.cc */, - OBJ_242 /* ev_epollex_linux.cc */, - OBJ_243 /* ev_epollsig_linux.cc */, - OBJ_244 /* ev_poll_posix.cc */, - OBJ_245 /* ev_posix.cc */, - OBJ_246 /* ev_windows.cc */, - OBJ_247 /* exec_ctx.cc */, - OBJ_248 /* executor.cc */, - OBJ_249 /* fork_posix.cc */, - OBJ_250 /* fork_windows.cc */, - OBJ_251 /* gethostname_fallback.cc */, - OBJ_252 /* gethostname_host_name_max.cc */, - OBJ_253 /* gethostname_sysconf.cc */, - OBJ_254 /* iocp_windows.cc */, - OBJ_255 /* iomgr.cc */, - OBJ_256 /* iomgr_custom.cc */, - OBJ_257 /* iomgr_internal.cc */, - OBJ_258 /* iomgr_posix.cc */, - OBJ_259 /* iomgr_uv.cc */, - OBJ_260 /* iomgr_windows.cc */, - OBJ_261 /* is_epollexclusive_available.cc */, - OBJ_262 /* load_file.cc */, - OBJ_263 /* lockfree_event.cc */, - OBJ_264 /* network_status_tracker.cc */, - OBJ_265 /* polling_entity.cc */, - OBJ_266 /* pollset.cc */, - OBJ_267 /* pollset_custom.cc */, - OBJ_268 /* pollset_set.cc */, - OBJ_269 /* pollset_set_custom.cc */, - OBJ_270 /* pollset_set_windows.cc */, - OBJ_271 /* pollset_uv.cc */, - OBJ_272 /* pollset_windows.cc */, - OBJ_273 /* resolve_address.cc */, - OBJ_274 /* resolve_address_custom.cc */, - OBJ_275 /* resolve_address_posix.cc */, - OBJ_276 /* resolve_address_windows.cc */, - OBJ_277 /* resource_quota.cc */, - OBJ_278 /* sockaddr_utils.cc */, - OBJ_279 /* socket_factory_posix.cc */, - OBJ_280 /* socket_mutator.cc */, - OBJ_281 /* socket_utils_common_posix.cc */, - OBJ_282 /* socket_utils_linux.cc */, - OBJ_283 /* socket_utils_posix.cc */, - OBJ_284 /* socket_utils_uv.cc */, - OBJ_285 /* socket_utils_windows.cc */, - OBJ_286 /* socket_windows.cc */, - OBJ_287 /* tcp_client.cc */, - OBJ_288 /* tcp_client_custom.cc */, - OBJ_289 /* tcp_client_posix.cc */, - OBJ_290 /* tcp_client_windows.cc */, - OBJ_291 /* tcp_custom.cc */, - OBJ_292 /* tcp_posix.cc */, - OBJ_293 /* tcp_server.cc */, - OBJ_294 /* tcp_server_custom.cc */, - OBJ_295 /* tcp_server_posix.cc */, - OBJ_296 /* tcp_server_utils_posix_common.cc */, - OBJ_297 /* tcp_server_utils_posix_ifaddrs.cc */, - OBJ_298 /* tcp_server_utils_posix_noifaddrs.cc */, - OBJ_299 /* tcp_server_windows.cc */, - OBJ_300 /* tcp_uv.cc */, - OBJ_301 /* tcp_windows.cc */, - OBJ_302 /* time_averaged_stats.cc */, - OBJ_303 /* timer.cc */, - OBJ_304 /* timer_custom.cc */, - OBJ_305 /* timer_generic.cc */, - OBJ_306 /* timer_heap.cc */, - OBJ_307 /* timer_manager.cc */, - OBJ_308 /* timer_uv.cc */, - OBJ_309 /* udp_server.cc */, - OBJ_310 /* unix_sockets_posix.cc */, - OBJ_311 /* unix_sockets_posix_noop.cc */, - OBJ_312 /* wakeup_fd_cv.cc */, - OBJ_313 /* wakeup_fd_eventfd.cc */, - OBJ_314 /* wakeup_fd_nospecial.cc */, - OBJ_315 /* wakeup_fd_pipe.cc */, - OBJ_316 /* wakeup_fd_posix.cc */, + OBJ_208 /* tls */ = { + isa = PBXGroup; + children = ( + OBJ_209 /* kdf.c */, ); - name = iomgr; - path = iomgr; + name = tls; + path = tls; sourceTree = ""; }; - OBJ_25 /* CgRPC */ = { + OBJ_210 /* hkdf */ = { isa = PBXGroup; children = ( - OBJ_26 /* shim */, - OBJ_39 /* src */, - OBJ_457 /* third_party */, - OBJ_462 /* include */, + OBJ_211 /* hkdf.c */, ); - name = CgRPC; - path = Sources/CgRPC; - sourceTree = SOURCE_ROOT; + name = hkdf; + path = hkdf; + sourceTree = ""; }; - OBJ_26 /* shim */ = { + OBJ_212 /* lhash */ = { isa = PBXGroup; children = ( - OBJ_27 /* byte_buffer.c */, - OBJ_28 /* call.c */, - OBJ_29 /* channel.c */, - OBJ_30 /* completion_queue.c */, - OBJ_31 /* event.c */, - OBJ_32 /* handler.c */, - OBJ_33 /* internal.c */, - OBJ_34 /* metadata.c */, - OBJ_35 /* mutex.c */, - OBJ_36 /* observers.c */, - OBJ_37 /* operations.c */, - OBJ_38 /* server.c */, + OBJ_213 /* lhash.c */, ); - name = shim; - path = shim; + name = lhash; + path = lhash; sourceTree = ""; }; - OBJ_317 /* json */ = { + OBJ_215 /* obj */ = { isa = PBXGroup; children = ( - OBJ_318 /* json.cc */, - OBJ_319 /* json_reader.cc */, - OBJ_320 /* json_string.cc */, - OBJ_321 /* json_writer.cc */, + OBJ_216 /* obj.c */, + OBJ_217 /* obj_xref.c */, ); - name = json; - path = json; + name = obj; + path = obj; sourceTree = ""; }; - OBJ_322 /* profiling */ = { + OBJ_218 /* pem */ = { isa = PBXGroup; children = ( - OBJ_323 /* basic_timers.cc */, - OBJ_324 /* stap_timers.cc */, + OBJ_219 /* pem_all.c */, + OBJ_220 /* pem_info.c */, + OBJ_221 /* pem_lib.c */, + OBJ_222 /* pem_oth.c */, + OBJ_223 /* pem_pk8.c */, + OBJ_224 /* pem_pkey.c */, + OBJ_225 /* pem_x509.c */, + OBJ_226 /* pem_xaux.c */, ); - name = profiling; - path = profiling; + name = pem; + path = pem; sourceTree = ""; }; - OBJ_325 /* security */ = { + OBJ_227 /* pkcs7 */ = { isa = PBXGroup; children = ( - OBJ_326 /* context */, - OBJ_328 /* credentials */, - OBJ_359 /* security_connector */, - OBJ_362 /* transport */, - OBJ_369 /* util */, + OBJ_228 /* pkcs7.c */, + OBJ_229 /* pkcs7_x509.c */, ); - name = security; - path = security; + name = pkcs7; + path = pkcs7; sourceTree = ""; }; - OBJ_326 /* context */ = { + OBJ_230 /* pkcs8 */ = { isa = PBXGroup; children = ( - OBJ_327 /* security_context.cc */, + OBJ_231 /* p5_pbev2.c */, + OBJ_232 /* pkcs8.c */, + OBJ_233 /* pkcs8_x509.c */, ); - name = context; - path = context; + name = pkcs8; + path = pkcs8; sourceTree = ""; }; - OBJ_328 /* credentials */ = { + OBJ_234 /* poly1305 */ = { isa = PBXGroup; children = ( - OBJ_329 /* alts */, - OBJ_338 /* composite */, - OBJ_340 /* credentials.cc */, - OBJ_341 /* credentials_metadata.cc */, - OBJ_342 /* fake */, - OBJ_344 /* google_default */, - OBJ_347 /* iam */, - OBJ_349 /* jwt */, - OBJ_353 /* oauth2 */, - OBJ_355 /* plugin */, - OBJ_357 /* ssl */, + OBJ_235 /* poly1305.c */, + OBJ_236 /* poly1305_arm.c */, + OBJ_237 /* poly1305_vec.c */, ); - name = credentials; - path = credentials; + name = poly1305; + path = poly1305; sourceTree = ""; }; - OBJ_329 /* alts */ = { + OBJ_238 /* pool */ = { isa = PBXGroup; children = ( - OBJ_330 /* alts_credentials.cc */, - OBJ_331 /* check_gcp_environment.cc */, - OBJ_332 /* check_gcp_environment_linux.cc */, - OBJ_333 /* check_gcp_environment_no_op.cc */, - OBJ_334 /* check_gcp_environment_windows.cc */, - OBJ_335 /* grpc_alts_credentials_client_options.cc */, - OBJ_336 /* grpc_alts_credentials_options.cc */, - OBJ_337 /* grpc_alts_credentials_server_options.cc */, + OBJ_239 /* pool.c */, ); - name = alts; - path = alts; + name = pool; + path = pool; sourceTree = ""; }; - OBJ_338 /* composite */ = { + OBJ_240 /* rand_extra */ = { isa = PBXGroup; children = ( - OBJ_339 /* composite_credentials.cc */, + OBJ_241 /* deterministic.c */, + OBJ_242 /* forkunsafe.c */, + OBJ_243 /* fuchsia.c */, + OBJ_244 /* rand_extra.c */, + OBJ_245 /* windows.c */, ); - name = composite; - path = composite; + name = rand_extra; + path = rand_extra; sourceTree = ""; }; - OBJ_342 /* fake */ = { + OBJ_246 /* rc4 */ = { isa = PBXGroup; children = ( - OBJ_343 /* fake_credentials.cc */, + OBJ_247 /* rc4.c */, ); - name = fake; - path = fake; + name = rc4; + path = rc4; sourceTree = ""; }; - OBJ_344 /* google_default */ = { + OBJ_250 /* rsa_extra */ = { isa = PBXGroup; children = ( - OBJ_345 /* credentials_generic.cc */, - OBJ_346 /* google_default_credentials.cc */, + OBJ_251 /* rsa_asn1.c */, ); - name = google_default; - path = google_default; + name = rsa_extra; + path = rsa_extra; sourceTree = ""; }; - OBJ_347 /* iam */ = { + OBJ_252 /* stack */ = { isa = PBXGroup; children = ( - OBJ_348 /* iam_credentials.cc */, + OBJ_253 /* stack.c */, ); - name = iam; - path = iam; + name = stack; + path = stack; sourceTree = ""; }; - OBJ_349 /* jwt */ = { + OBJ_258 /* x509 */ = { + isa = PBXGroup; + children = ( + OBJ_259 /* a_digest.c */, + OBJ_260 /* a_sign.c */, + OBJ_261 /* a_strex.c */, + OBJ_262 /* a_verify.c */, + OBJ_263 /* algorithm.c */, + OBJ_264 /* asn1_gen.c */, + OBJ_265 /* by_dir.c */, + OBJ_266 /* by_file.c */, + OBJ_267 /* i2d_pr.c */, + OBJ_268 /* rsa_pss.c */, + OBJ_269 /* t_crl.c */, + OBJ_270 /* t_req.c */, + OBJ_271 /* t_x509.c */, + OBJ_272 /* t_x509a.c */, + OBJ_273 /* x509.c */, + OBJ_274 /* x509_att.c */, + OBJ_275 /* x509_cmp.c */, + OBJ_276 /* x509_d2.c */, + OBJ_277 /* x509_def.c */, + OBJ_278 /* x509_ext.c */, + OBJ_279 /* x509_lu.c */, + OBJ_280 /* x509_obj.c */, + OBJ_281 /* x509_r2x.c */, + OBJ_282 /* x509_req.c */, + OBJ_283 /* x509_set.c */, + OBJ_284 /* x509_trs.c */, + OBJ_285 /* x509_txt.c */, + OBJ_286 /* x509_v3.c */, + OBJ_287 /* x509_vfy.c */, + OBJ_288 /* x509_vpm.c */, + OBJ_289 /* x509cset.c */, + OBJ_290 /* x509name.c */, + OBJ_291 /* x509rset.c */, + OBJ_292 /* x509spki.c */, + OBJ_293 /* x_algor.c */, + OBJ_294 /* x_all.c */, + OBJ_295 /* x_attrib.c */, + OBJ_296 /* x_crl.c */, + OBJ_297 /* x_exten.c */, + OBJ_298 /* x_info.c */, + OBJ_299 /* x_name.c */, + OBJ_300 /* x_pkey.c */, + OBJ_301 /* x_pubkey.c */, + OBJ_302 /* x_req.c */, + OBJ_303 /* x_sig.c */, + OBJ_304 /* x_spki.c */, + OBJ_305 /* x_val.c */, + OBJ_306 /* x_x509.c */, + OBJ_307 /* x_x509a.c */, + ); + name = x509; + path = x509; + sourceTree = ""; + }; + OBJ_308 /* x509v3 */ = { + isa = PBXGroup; + children = ( + OBJ_309 /* pcy_cache.c */, + OBJ_310 /* pcy_data.c */, + OBJ_311 /* pcy_lib.c */, + OBJ_312 /* pcy_map.c */, + OBJ_313 /* pcy_node.c */, + OBJ_314 /* pcy_tree.c */, + OBJ_315 /* v3_akey.c */, + OBJ_316 /* v3_akeya.c */, + OBJ_317 /* v3_alt.c */, + OBJ_318 /* v3_bcons.c */, + OBJ_319 /* v3_bitst.c */, + OBJ_320 /* v3_conf.c */, + OBJ_321 /* v3_cpols.c */, + OBJ_322 /* v3_crld.c */, + OBJ_323 /* v3_enum.c */, + OBJ_324 /* v3_extku.c */, + OBJ_325 /* v3_genn.c */, + OBJ_326 /* v3_ia5.c */, + OBJ_327 /* v3_info.c */, + OBJ_328 /* v3_int.c */, + OBJ_329 /* v3_lib.c */, + OBJ_330 /* v3_ncons.c */, + OBJ_331 /* v3_pci.c */, + OBJ_332 /* v3_pcia.c */, + OBJ_333 /* v3_pcons.c */, + OBJ_334 /* v3_pku.c */, + OBJ_335 /* v3_pmaps.c */, + OBJ_336 /* v3_prn.c */, + OBJ_337 /* v3_purp.c */, + OBJ_338 /* v3_skey.c */, + OBJ_339 /* v3_sxnet.c */, + OBJ_340 /* v3_utl.c */, + ); + name = x509v3; + path = x509v3; + sourceTree = ""; + }; + OBJ_341 /* ssl */ = { + isa = PBXGroup; + children = ( + OBJ_342 /* bio_ssl.cc */, + OBJ_343 /* custom_extensions.cc */, + OBJ_344 /* d1_both.cc */, + OBJ_345 /* d1_lib.cc */, + OBJ_346 /* d1_pkt.cc */, + OBJ_347 /* d1_srtp.cc */, + OBJ_348 /* dtls_method.cc */, + OBJ_349 /* dtls_record.cc */, + OBJ_350 /* handoff.cc */, + OBJ_351 /* handshake.cc */, + OBJ_352 /* handshake_client.cc */, + OBJ_353 /* handshake_server.cc */, + OBJ_354 /* s3_both.cc */, + OBJ_355 /* s3_lib.cc */, + OBJ_356 /* s3_pkt.cc */, + OBJ_357 /* ssl_aead_ctx.cc */, + OBJ_358 /* ssl_asn1.cc */, + OBJ_359 /* ssl_buffer.cc */, + OBJ_360 /* ssl_cert.cc */, + OBJ_361 /* ssl_cipher.cc */, + OBJ_362 /* ssl_file.cc */, + OBJ_363 /* ssl_key_share.cc */, + OBJ_364 /* ssl_lib.cc */, + OBJ_365 /* ssl_privkey.cc */, + OBJ_366 /* ssl_session.cc */, + OBJ_367 /* ssl_stat.cc */, + OBJ_368 /* ssl_transcript.cc */, + OBJ_369 /* ssl_versions.cc */, + OBJ_370 /* ssl_x509.cc */, + OBJ_371 /* t1_enc.cc */, + OBJ_372 /* t1_lib.cc */, + OBJ_373 /* tls13_both.cc */, + OBJ_374 /* tls13_client.cc */, + OBJ_375 /* tls13_enc.cc */, + OBJ_376 /* tls13_server.cc */, + OBJ_377 /* tls_method.cc */, + OBJ_378 /* tls_record.cc */, + ); + name = ssl; + path = ssl; + sourceTree = ""; + }; + OBJ_379 /* third_party */ = { isa = PBXGroup; children = ( - OBJ_350 /* json_token.cc */, - OBJ_351 /* jwt_credentials.cc */, - OBJ_352 /* jwt_verifier.cc */, + OBJ_380 /* fiat */, ); - name = jwt; - path = jwt; + name = third_party; + path = third_party; sourceTree = ""; }; - OBJ_353 /* oauth2 */ = { + OBJ_380 /* fiat */ = { isa = PBXGroup; children = ( - OBJ_354 /* oauth2_credentials.cc */, + OBJ_381 /* curve25519.c */, + OBJ_382 /* p256.c */, ); - name = oauth2; - path = oauth2; + name = fiat; + path = fiat; sourceTree = ""; }; - OBJ_355 /* plugin */ = { + OBJ_383 /* include */ = { isa = PBXGroup; children = ( - OBJ_356 /* plugin_credentials.cc */, + OBJ_384 /* openssl */, + OBJ_458 /* module.modulemap */, ); - name = plugin; - path = plugin; + name = include; + path = include; + sourceTree = ""; + }; + OBJ_384 /* openssl */ = { + isa = PBXGroup; + children = ( + OBJ_385 /* pem.h */, + OBJ_386 /* nid.h */, + OBJ_387 /* ssl3.h */, + OBJ_388 /* ossl_typ.h */, + OBJ_389 /* dtls1.h */, + OBJ_390 /* err.h */, + OBJ_391 /* bn.h */, + OBJ_392 /* blowfish.h */, + OBJ_393 /* engine.h */, + OBJ_394 /* bytestring.h */, + OBJ_395 /* x509.h */, + OBJ_396 /* asn1_mac.h */, + OBJ_397 /* pool.h */, + OBJ_398 /* ec_key.h */, + OBJ_399 /* base64.h */, + OBJ_400 /* is_boringssl.h */, + OBJ_401 /* sha.h */, + OBJ_402 /* asn1.h */, + OBJ_403 /* chacha.h */, + OBJ_404 /* opensslconf.h */, + OBJ_405 /* arm_arch.h */, + OBJ_406 /* bio.h */, + OBJ_407 /* dh.h */, + OBJ_408 /* digest.h */, + OBJ_409 /* x509v3.h */, + OBJ_410 /* conf.h */, + OBJ_411 /* poly1305.h */, + OBJ_412 /* hkdf.h */, + OBJ_413 /* type_check.h */, + OBJ_414 /* md5.h */, + OBJ_415 /* x509_vfy.h */, + OBJ_416 /* pkcs8.h */, + OBJ_417 /* safestack.h */, + OBJ_418 /* buf.h */, + OBJ_419 /* obj.h */, + OBJ_420 /* ecdsa.h */, + OBJ_421 /* cipher.h */, + OBJ_422 /* objects.h */, + OBJ_423 /* pkcs12.h */, + OBJ_424 /* crypto.h */, + OBJ_425 /* opensslv.h */, + OBJ_426 /* pkcs7.h */, + OBJ_427 /* obj_mac.h */, + OBJ_428 /* buffer.h */, + OBJ_429 /* ssl.h */, + OBJ_430 /* thread.h */, + OBJ_431 /* evp.h */, + OBJ_432 /* md4.h */, + OBJ_433 /* hmac.h */, + OBJ_434 /* aes.h */, + OBJ_435 /* cast.h */, + OBJ_436 /* rc4.h */, + OBJ_437 /* cpu.h */, + OBJ_438 /* stack.h */, + OBJ_439 /* des.h */, + OBJ_440 /* ec.h */, + OBJ_441 /* ecdh.h */, + OBJ_442 /* rand.h */, + OBJ_443 /* aead.h */, + OBJ_444 /* lhash_macros.h */, + OBJ_445 /* span.h */, + OBJ_446 /* rsa.h */, + OBJ_447 /* mem.h */, + OBJ_448 /* ripemd.h */, + OBJ_449 /* curve25519.h */, + OBJ_450 /* tls1.h */, + OBJ_451 /* dsa.h */, + OBJ_452 /* srtp.h */, + OBJ_453 /* asn1t.h */, + OBJ_454 /* cmac.h */, + OBJ_455 /* lhash.h */, + OBJ_456 /* ex_data.h */, + OBJ_457 /* base.h */, + ); + name = openssl; + path = openssl; sourceTree = ""; }; - OBJ_357 /* ssl */ = { + OBJ_42 /* base64 */ = { isa = PBXGroup; children = ( - OBJ_358 /* ssl_credentials.cc */, + OBJ_43 /* base64.c */, ); - name = ssl; - path = ssl; + name = base64; + path = base64; sourceTree = ""; }; - OBJ_359 /* security_connector */ = { + OBJ_44 /* bio */ = { isa = PBXGroup; children = ( - OBJ_360 /* alts_security_connector.cc */, - OBJ_361 /* security_connector.cc */, + OBJ_45 /* bio.c */, + OBJ_46 /* bio_mem.c */, + OBJ_47 /* connect.c */, + OBJ_48 /* fd.c */, + OBJ_49 /* file.c */, + OBJ_50 /* hexdump.c */, + OBJ_51 /* pair.c */, + OBJ_52 /* printf.c */, + OBJ_53 /* socket.c */, + OBJ_54 /* socket_helper.c */, ); - name = security_connector; - path = security_connector; + name = bio; + path = bio; sourceTree = ""; }; - OBJ_362 /* transport */ = { + OBJ_459 /* CgRPC */ = { isa = PBXGroup; children = ( - OBJ_363 /* client_auth_filter.cc */, - OBJ_364 /* secure_endpoint.cc */, - OBJ_365 /* security_handshaker.cc */, - OBJ_366 /* server_auth_filter.cc */, - OBJ_367 /* target_authority_table.cc */, - OBJ_368 /* tsi_error.cc */, + OBJ_460 /* README.md */, + OBJ_461 /* shim */, + OBJ_474 /* src */, + OBJ_926 /* third_party */, + OBJ_931 /* include */, ); - name = transport; - path = transport; - sourceTree = ""; + name = CgRPC; + path = Sources/CgRPC; + sourceTree = SOURCE_ROOT; }; - OBJ_369 /* util */ = { + OBJ_461 /* shim */ = { isa = PBXGroup; children = ( - OBJ_370 /* json_util.cc */, + OBJ_462 /* byte_buffer.c */, + OBJ_463 /* call.c */, + OBJ_464 /* channel.c */, + OBJ_465 /* completion_queue.c */, + OBJ_466 /* event.c */, + OBJ_467 /* handler.c */, + OBJ_468 /* internal.c */, + OBJ_469 /* metadata.c */, + OBJ_470 /* mutex.c */, + OBJ_471 /* observers.c */, + OBJ_472 /* operations.c */, + OBJ_473 /* server.c */, ); - name = util; - path = util; + name = shim; + path = shim; sourceTree = ""; }; - OBJ_371 /* slice */ = { + OBJ_474 /* src */ = { isa = PBXGroup; children = ( - OBJ_372 /* b64.cc */, - OBJ_373 /* percent_encoding.cc */, - OBJ_374 /* slice.cc */, - OBJ_375 /* slice_buffer.cc */, - OBJ_376 /* slice_intern.cc */, - OBJ_377 /* slice_string_helpers.cc */, + OBJ_475 /* core */, ); - name = slice; - path = slice; + name = src; + path = src; sourceTree = ""; }; - OBJ_378 /* surface */ = { - isa = PBXGroup; - children = ( - OBJ_379 /* api_trace.cc */, - OBJ_380 /* byte_buffer.cc */, - OBJ_381 /* byte_buffer_reader.cc */, - OBJ_382 /* call.cc */, - OBJ_383 /* call_details.cc */, - OBJ_384 /* call_log_batch.cc */, - OBJ_385 /* channel.cc */, - OBJ_386 /* channel_init.cc */, - OBJ_387 /* channel_ping.cc */, - OBJ_388 /* channel_stack_type.cc */, - OBJ_389 /* completion_queue.cc */, - OBJ_390 /* completion_queue_factory.cc */, - OBJ_391 /* event_string.cc */, - OBJ_392 /* init.cc */, - OBJ_393 /* init_secure.cc */, - OBJ_394 /* lame_client.cc */, - OBJ_395 /* metadata_array.cc */, - OBJ_396 /* server.cc */, - OBJ_397 /* validate_metadata.cc */, - OBJ_398 /* version.cc */, + OBJ_475 /* core */ = { + isa = PBXGroup; + children = ( + OBJ_476 /* ext */, + OBJ_614 /* lib */, + OBJ_884 /* plugin_registry */, + OBJ_886 /* tsi */, ); - name = surface; - path = surface; + name = core; + path = core; sourceTree = ""; }; - OBJ_39 /* src */ = { + OBJ_476 /* ext */ = { isa = PBXGroup; children = ( - OBJ_40 /* core */, + OBJ_477 /* filters */, + OBJ_568 /* transport */, ); - name = src; - path = src; + name = ext; + path = ext; sourceTree = ""; }; - OBJ_399 /* transport */ = { + OBJ_477 /* filters */ = { isa = PBXGroup; children = ( - OBJ_400 /* bdp_estimator.cc */, - OBJ_401 /* byte_stream.cc */, - OBJ_402 /* connectivity_state.cc */, - OBJ_403 /* error_utils.cc */, - OBJ_404 /* metadata.cc */, - OBJ_405 /* metadata_batch.cc */, - OBJ_406 /* pid_controller.cc */, - OBJ_407 /* service_config.cc */, - OBJ_408 /* static_metadata.cc */, - OBJ_409 /* status_conversion.cc */, - OBJ_410 /* status_metadata.cc */, - OBJ_411 /* timeout_encoding.cc */, - OBJ_412 /* transport.cc */, - OBJ_413 /* transport_op_string.cc */, + OBJ_478 /* census */, + OBJ_480 /* client_channel */, + OBJ_550 /* deadline */, + OBJ_552 /* http */, + OBJ_561 /* max_age */, + OBJ_563 /* message_size */, + OBJ_565 /* workarounds */, ); - name = transport; - path = transport; + name = filters; + path = filters; sourceTree = ""; }; - OBJ_40 /* core */ = { + OBJ_478 /* census */ = { isa = PBXGroup; children = ( - OBJ_41 /* ext */, - OBJ_162 /* lib */, - OBJ_414 /* plugin_registry */, - OBJ_416 /* tsi */, + OBJ_479 /* grpc_context.cc */, ); - name = core; - path = core; + name = census; + path = census; sourceTree = ""; }; - OBJ_41 /* ext */ = { + OBJ_480 /* client_channel */ = { + isa = PBXGroup; + children = ( + OBJ_481 /* backup_poller.cc */, + OBJ_482 /* channel_connectivity.cc */, + OBJ_483 /* client_channel.cc */, + OBJ_484 /* client_channel_channelz.cc */, + OBJ_485 /* client_channel_factory.cc */, + OBJ_486 /* client_channel_plugin.cc */, + OBJ_487 /* connector.cc */, + OBJ_488 /* global_subchannel_pool.cc */, + OBJ_489 /* health */, + OBJ_492 /* http_connect_handshaker.cc */, + OBJ_493 /* http_proxy.cc */, + OBJ_494 /* lb_policy.cc */, + OBJ_495 /* lb_policy */, + OBJ_520 /* lb_policy_registry.cc */, + OBJ_521 /* local_subchannel_pool.cc */, + OBJ_522 /* parse_address.cc */, + OBJ_523 /* proxy_mapper.cc */, + OBJ_524 /* proxy_mapper_registry.cc */, + OBJ_525 /* request_routing.cc */, + OBJ_526 /* resolver.cc */, + OBJ_527 /* resolver */, + OBJ_544 /* resolver_registry.cc */, + OBJ_545 /* resolver_result_parsing.cc */, + OBJ_546 /* retry_throttle.cc */, + OBJ_547 /* server_address.cc */, + OBJ_548 /* subchannel.cc */, + OBJ_549 /* subchannel_pool_interface.cc */, + ); + name = client_channel; + path = client_channel; + sourceTree = ""; + }; + OBJ_489 /* health */ = { isa = PBXGroup; children = ( - OBJ_42 /* census */, - OBJ_44 /* filters */, - OBJ_117 /* transport */, + OBJ_490 /* health.pb.c */, + OBJ_491 /* health_check_client.cc */, ); - name = ext; - path = ext; + name = health; + path = health; sourceTree = ""; }; - OBJ_414 /* plugin_registry */ = { + OBJ_495 /* lb_policy */ = { isa = PBXGroup; children = ( - OBJ_415 /* grpc_plugin_registry.cc */, + OBJ_496 /* grpclb */, + OBJ_511 /* pick_first */, + OBJ_513 /* round_robin */, + OBJ_515 /* xds */, ); - name = plugin_registry; - path = plugin_registry; + name = lb_policy; + path = lb_policy; sourceTree = ""; }; - OBJ_416 /* tsi */ = { + OBJ_496 /* grpclb */ = { isa = PBXGroup; children = ( - OBJ_417 /* alts */, - OBJ_446 /* alts_transport_security.cc */, - OBJ_447 /* fake_transport_security.cc */, - OBJ_448 /* ssl */, - OBJ_453 /* ssl_transport_security.cc */, - OBJ_454 /* transport_security.cc */, - OBJ_455 /* transport_security_adapter.cc */, - OBJ_456 /* transport_security_grpc.cc */, + OBJ_497 /* client_load_reporting_filter.cc */, + OBJ_498 /* grpclb.cc */, + OBJ_499 /* grpclb_channel_secure.cc */, + OBJ_500 /* grpclb_client_stats.cc */, + OBJ_501 /* load_balancer_api.cc */, + OBJ_502 /* proto */, ); - name = tsi; - path = tsi; + name = grpclb; + path = grpclb; sourceTree = ""; }; - OBJ_417 /* alts */ = { + OBJ_5 = { isa = PBXGroup; children = ( - OBJ_418 /* crypt */, - OBJ_421 /* frame_protector */, - OBJ_429 /* handshaker */, - OBJ_440 /* zero_copy_frame_protector */, + OBJ_6 /* Package.swift */, + OBJ_7 /* Sources */, + OBJ_1112 /* Tests */, + OBJ_1150 /* Dependencies */, + OBJ_1426 /* Products */, + OBJ_1456 /* Docker */, + OBJ_1457 /* Examples */, + OBJ_1458 /* scripts */, + OBJ_1459 /* Assets */, + OBJ_1460 /* OVERVIEW.md */, + OBJ_1461 /* fix-project-settings.rb */, + OBJ_1462 /* LICENSE */, + OBJ_1463 /* PATENTS */, + OBJ_1464 /* AUTHORS */, + OBJ_1465 /* Makefile */, + OBJ_1466 /* patch-carthage-project.rb */, + OBJ_1467 /* LINUX.md */, + OBJ_1468 /* README.md */, + OBJ_1469 /* fix-carthage-paths.rb */, + OBJ_1470 /* CONTRIBUTING.md */, + OBJ_1471 /* DOCKER.md */, + OBJ_1472 /* SwiftGRPC.podspec */, ); - name = alts; - path = alts; + indentWidth = 2; + path = ""; sourceTree = ""; + tabWidth = 2; + usesTabs = 0; }; - OBJ_418 /* crypt */ = { + OBJ_502 /* proto */ = { isa = PBXGroup; children = ( - OBJ_419 /* aes_gcm.cc */, - OBJ_420 /* gsec.cc */, + OBJ_503 /* grpc */, ); - name = crypt; - path = crypt; + name = proto; + path = proto; sourceTree = ""; }; - OBJ_42 /* census */ = { + OBJ_503 /* grpc */ = { isa = PBXGroup; children = ( - OBJ_43 /* grpc_context.cc */, + OBJ_504 /* lb */, ); - name = census; - path = census; + name = grpc; + path = grpc; sourceTree = ""; }; - OBJ_421 /* frame_protector */ = { + OBJ_504 /* lb */ = { isa = PBXGroup; children = ( - OBJ_422 /* alts_counter.cc */, - OBJ_423 /* alts_crypter.cc */, - OBJ_424 /* alts_frame_protector.cc */, - OBJ_425 /* alts_record_protocol_crypter_common.cc */, - OBJ_426 /* alts_seal_privacy_integrity_crypter.cc */, - OBJ_427 /* alts_unseal_privacy_integrity_crypter.cc */, - OBJ_428 /* frame_handler.cc */, + OBJ_505 /* v1 */, ); - name = frame_protector; - path = frame_protector; + name = lb; + path = lb; sourceTree = ""; }; - OBJ_429 /* handshaker */ = { + OBJ_505 /* v1 */ = { isa = PBXGroup; children = ( - OBJ_430 /* alts_handshaker_client.cc */, - OBJ_431 /* alts_handshaker_service_api.cc */, - OBJ_432 /* alts_handshaker_service_api_util.cc */, - OBJ_433 /* alts_tsi_event.cc */, - OBJ_434 /* alts_tsi_handshaker.cc */, - OBJ_435 /* alts_tsi_utils.cc */, - OBJ_436 /* altscontext.pb.c */, - OBJ_437 /* handshaker.pb.c */, - OBJ_438 /* transport_security_common.pb.c */, - OBJ_439 /* transport_security_common_api.cc */, + OBJ_506 /* google */, + OBJ_510 /* load_balancer.pb.c */, ); - name = handshaker; - path = handshaker; + name = v1; + path = v1; sourceTree = ""; }; - OBJ_44 /* filters */ = { + OBJ_506 /* google */ = { isa = PBXGroup; children = ( - OBJ_45 /* client_channel */, - OBJ_96 /* deadline */, - OBJ_98 /* http */, - OBJ_107 /* load_reporting */, - OBJ_110 /* max_age */, - OBJ_112 /* message_size */, - OBJ_114 /* workarounds */, + OBJ_507 /* protobuf */, ); - name = filters; - path = filters; + name = google; + path = google; sourceTree = ""; }; - OBJ_440 /* zero_copy_frame_protector */ = { + OBJ_507 /* protobuf */ = { isa = PBXGroup; children = ( - OBJ_441 /* alts_grpc_integrity_only_record_protocol.cc */, - OBJ_442 /* alts_grpc_privacy_integrity_record_protocol.cc */, - OBJ_443 /* alts_grpc_record_protocol_common.cc */, - OBJ_444 /* alts_iovec_record_protocol.cc */, - OBJ_445 /* alts_zero_copy_grpc_protector.cc */, + OBJ_508 /* duration.pb.c */, + OBJ_509 /* timestamp.pb.c */, ); - name = zero_copy_frame_protector; - path = zero_copy_frame_protector; + name = protobuf; + path = protobuf; sourceTree = ""; }; - OBJ_448 /* ssl */ = { + OBJ_511 /* pick_first */ = { isa = PBXGroup; children = ( - OBJ_449 /* session_cache */, + OBJ_512 /* pick_first.cc */, ); - name = ssl; - path = ssl; + name = pick_first; + path = pick_first; sourceTree = ""; }; - OBJ_449 /* session_cache */ = { + OBJ_513 /* round_robin */ = { isa = PBXGroup; children = ( - OBJ_450 /* ssl_session_boringssl.cc */, - OBJ_451 /* ssl_session_cache.cc */, - OBJ_452 /* ssl_session_openssl.cc */, + OBJ_514 /* round_robin.cc */, ); - name = session_cache; - path = session_cache; + name = round_robin; + path = round_robin; sourceTree = ""; }; - OBJ_45 /* client_channel */ = { - isa = PBXGroup; - children = ( - OBJ_46 /* backup_poller.cc */, - OBJ_47 /* channel_connectivity.cc */, - OBJ_48 /* client_channel.cc */, - OBJ_49 /* client_channel_factory.cc */, - OBJ_50 /* client_channel_plugin.cc */, - OBJ_51 /* connector.cc */, - OBJ_52 /* http_connect_handshaker.cc */, - OBJ_53 /* http_proxy.cc */, - OBJ_54 /* lb_policy.cc */, - OBJ_55 /* lb_policy */, - OBJ_71 /* lb_policy_factory.cc */, - OBJ_72 /* lb_policy_registry.cc */, - OBJ_73 /* method_params.cc */, - OBJ_74 /* parse_address.cc */, - OBJ_75 /* proxy_mapper.cc */, - OBJ_76 /* proxy_mapper_registry.cc */, - OBJ_77 /* resolver.cc */, - OBJ_78 /* resolver */, - OBJ_91 /* resolver_registry.cc */, - OBJ_92 /* retry_throttle.cc */, - OBJ_93 /* subchannel.cc */, - OBJ_94 /* subchannel_index.cc */, - OBJ_95 /* uri_parser.cc */, + OBJ_515 /* xds */ = { + isa = PBXGroup; + children = ( + OBJ_516 /* xds.cc */, + OBJ_517 /* xds_channel_secure.cc */, + OBJ_518 /* xds_client_stats.cc */, + OBJ_519 /* xds_load_balancer_api.cc */, ); - name = client_channel; - path = client_channel; + name = xds; + path = xds; sourceTree = ""; }; - OBJ_457 /* third_party */ = { + OBJ_527 /* resolver */ = { isa = PBXGroup; children = ( - OBJ_458 /* nanopb */, + OBJ_528 /* dns */, + OBJ_540 /* fake */, + OBJ_542 /* sockaddr */, ); - name = third_party; - path = third_party; + name = resolver; + path = resolver; sourceTree = ""; }; - OBJ_458 /* nanopb */ = { + OBJ_528 /* dns */ = { isa = PBXGroup; children = ( - OBJ_459 /* pb_common.c */, - OBJ_460 /* pb_decode.c */, - OBJ_461 /* pb_encode.c */, + OBJ_529 /* c_ares */, + OBJ_538 /* native */, ); - name = nanopb; - path = nanopb; + name = dns; + path = dns; sourceTree = ""; }; - OBJ_462 /* include */ = { + OBJ_529 /* c_ares */ = { isa = PBXGroup; children = ( - OBJ_463 /* cgrpc.h */, - OBJ_464 /* grpc */, - OBJ_520 /* module.modulemap */, + OBJ_530 /* dns_resolver_ares.cc */, + OBJ_531 /* grpc_ares_ev_driver.cc */, + OBJ_532 /* grpc_ares_ev_driver_posix.cc */, + OBJ_533 /* grpc_ares_ev_driver_windows.cc */, + OBJ_534 /* grpc_ares_wrapper.cc */, + OBJ_535 /* grpc_ares_wrapper_fallback.cc */, + OBJ_536 /* grpc_ares_wrapper_posix.cc */, + OBJ_537 /* grpc_ares_wrapper_windows.cc */, ); - name = include; - path = include; + name = c_ares; + path = c_ares; sourceTree = ""; }; - OBJ_464 /* grpc */ = { + OBJ_538 /* native */ = { isa = PBXGroup; children = ( - OBJ_465 /* grpc.h */, - OBJ_466 /* status.h */, - OBJ_467 /* census.h */, - OBJ_468 /* slice.h */, - OBJ_469 /* compression.h */, - OBJ_470 /* fork.h */, - OBJ_471 /* byte_buffer_reader.h */, - OBJ_472 /* grpc_security_constants.h */, - OBJ_473 /* byte_buffer.h */, - OBJ_474 /* slice_buffer.h */, - OBJ_475 /* grpc_posix.h */, - OBJ_476 /* grpc_security.h */, - OBJ_477 /* load_reporting.h */, - OBJ_478 /* support */, - OBJ_497 /* impl */, + OBJ_539 /* dns_resolver.cc */, ); - name = grpc; - path = grpc; + name = native; + path = native; sourceTree = ""; }; - OBJ_478 /* support */ = { - isa = PBXGroup; - children = ( - OBJ_479 /* time.h */, - OBJ_480 /* port_platform.h */, - OBJ_481 /* log_windows.h */, - OBJ_482 /* sync.h */, - OBJ_483 /* string_util.h */, - OBJ_484 /* sync_custom.h */, - OBJ_485 /* thd_id.h */, - OBJ_486 /* workaround_list.h */, - OBJ_487 /* atm_gcc_sync.h */, - OBJ_488 /* atm_gcc_atomic.h */, - OBJ_489 /* atm.h */, - OBJ_490 /* sync_generic.h */, - OBJ_491 /* log.h */, - OBJ_492 /* cpu.h */, - OBJ_493 /* sync_posix.h */, - OBJ_494 /* atm_windows.h */, - OBJ_495 /* sync_windows.h */, - OBJ_496 /* alloc.h */, + OBJ_540 /* fake */ = { + isa = PBXGroup; + children = ( + OBJ_541 /* fake_resolver.cc */, ); - name = support; - path = support; + name = fake; + path = fake; sourceTree = ""; }; - OBJ_497 /* impl */ = { + OBJ_542 /* sockaddr */ = { isa = PBXGroup; children = ( - OBJ_498 /* codegen */, + OBJ_543 /* sockaddr_resolver.cc */, ); - name = impl; - path = impl; + name = sockaddr; + path = sockaddr; sourceTree = ""; }; - OBJ_498 /* codegen */ = { - isa = PBXGroup; - children = ( - OBJ_499 /* port_platform.h */, - OBJ_500 /* status.h */, - OBJ_501 /* gpr_types.h */, - OBJ_502 /* sync.h */, - OBJ_503 /* grpc_types.h */, - OBJ_504 /* sync_custom.h */, - OBJ_505 /* gpr_slice.h */, - OBJ_506 /* slice.h */, - OBJ_507 /* compression_types.h */, - OBJ_508 /* atm_gcc_sync.h */, - OBJ_509 /* atm_gcc_atomic.h */, - OBJ_510 /* atm.h */, - OBJ_511 /* sync_generic.h */, - OBJ_512 /* fork.h */, - OBJ_513 /* byte_buffer_reader.h */, - OBJ_514 /* sync_posix.h */, - OBJ_515 /* atm_windows.h */, - OBJ_516 /* propagation_bits.h */, - OBJ_517 /* byte_buffer.h */, - OBJ_518 /* connectivity_state.h */, - OBJ_519 /* sync_windows.h */, + OBJ_55 /* bn_extra */ = { + isa = PBXGroup; + children = ( + OBJ_56 /* bn_asn1.c */, + OBJ_57 /* convert.c */, ); - name = codegen; - path = codegen; + name = bn_extra; + path = bn_extra; sourceTree = ""; }; - OBJ_5 = { + OBJ_550 /* deadline */ = { isa = PBXGroup; children = ( - OBJ_6 /* Package.swift */, - OBJ_7 /* Sources */, - OBJ_1052 /* Tests */, - OBJ_1090 /* Docker */, - OBJ_1091 /* Examples */, - OBJ_1092 /* scripts */, - OBJ_1093 /* Assets */, - OBJ_1094 /* DerivedData */, - OBJ_1095 /* Dependencies */, - OBJ_1371 /* Products */, + OBJ_551 /* deadline_filter.cc */, ); - indentWidth = 2; - path = ""; + name = deadline; + path = deadline; sourceTree = ""; - tabWidth = 2; - usesTabs = 0; }; - OBJ_521 /* Simple */ = { + OBJ_552 /* http */ = { isa = PBXGroup; children = ( - OBJ_522 /* main.swift */, - ); - name = Simple; - path = Sources/Examples/Simple; - sourceTree = SOURCE_ROOT; - }; - OBJ_523 /* SwiftGRPCNIO */ = { - isa = PBXGroup; - children = ( - OBJ_524 /* CallHandlers */, - OBJ_530 /* ClientCalls */, - OBJ_538 /* ClientOptions.swift */, - OBJ_539 /* CompressionMechanism.swift */, - OBJ_540 /* GRPCChannelHandler.swift */, - OBJ_541 /* GRPCClient.swift */, - OBJ_542 /* GRPCClientChannelHandler.swift */, - OBJ_543 /* GRPCClientCodec.swift */, - OBJ_544 /* GRPCError.swift */, - OBJ_545 /* GRPCServer.swift */, - OBJ_546 /* GRPCServerCodec.swift */, - OBJ_547 /* GRPCStatus.swift */, - OBJ_548 /* GRPCTimeout.swift */, - OBJ_549 /* HTTP1ToRawGRPCClientCodec.swift */, - OBJ_550 /* HTTP1ToRawGRPCServerCodec.swift */, - OBJ_551 /* HTTPProtocolSwitcher.swift */, - OBJ_552 /* LengthPrefixedMessageReader.swift */, - OBJ_553 /* LengthPrefixedMessageWriter.swift */, - OBJ_554 /* LoggingServerErrorDelegate.swift */, - OBJ_555 /* ServerCallContexts */, - OBJ_559 /* ServerErrorDelegate.swift */, - OBJ_560 /* StatusCode.swift */, - OBJ_561 /* StreamEvent.swift */, - OBJ_562 /* WebCORSHandler.swift */, + OBJ_553 /* client */, + OBJ_555 /* client_authority_filter.cc */, + OBJ_556 /* http_filters_plugin.cc */, + OBJ_557 /* message_compress */, + OBJ_559 /* server */, ); - name = SwiftGRPCNIO; - path = Sources/SwiftGRPCNIO; - sourceTree = SOURCE_ROOT; + name = http; + path = http; + sourceTree = ""; }; - OBJ_524 /* CallHandlers */ = { + OBJ_553 /* client */ = { isa = PBXGroup; children = ( - OBJ_525 /* BaseCallHandler.swift */, - OBJ_526 /* BidirectionalStreamingCallHandler.swift */, - OBJ_527 /* ClientStreamingCallHandler.swift */, - OBJ_528 /* ServerStreamingCallHandler.swift */, - OBJ_529 /* UnaryCallHandler.swift */, + OBJ_554 /* http_client_filter.cc */, ); - name = CallHandlers; - path = CallHandlers; + name = client; + path = client; sourceTree = ""; }; - OBJ_530 /* ClientCalls */ = { + OBJ_557 /* message_compress */ = { isa = PBXGroup; children = ( - OBJ_531 /* BaseClientCall.swift */, - OBJ_532 /* BidirectionalStreamingClientCall.swift */, - OBJ_533 /* ClientCall.swift */, - OBJ_534 /* ClientStreamingClientCall.swift */, - OBJ_535 /* ResponseObserver.swift */, - OBJ_536 /* ServerStreamingClientCall.swift */, - OBJ_537 /* UnaryClientCall.swift */, + OBJ_558 /* message_compress_filter.cc */, ); - name = ClientCalls; - path = ClientCalls; + name = message_compress; + path = message_compress; sourceTree = ""; }; - OBJ_55 /* lb_policy */ = { + OBJ_559 /* server */ = { isa = PBXGroup; children = ( - OBJ_56 /* grpclb */, - OBJ_67 /* pick_first */, - OBJ_69 /* round_robin */, + OBJ_560 /* http_server_filter.cc */, ); - name = lb_policy; - path = lb_policy; + name = server; + path = server; sourceTree = ""; }; - OBJ_555 /* ServerCallContexts */ = { + OBJ_561 /* max_age */ = { isa = PBXGroup; children = ( - OBJ_556 /* ServerCallContext.swift */, - OBJ_557 /* StreamingResponseCallContext.swift */, - OBJ_558 /* UnaryResponseCallContext.swift */, + OBJ_562 /* max_age_filter.cc */, ); - name = ServerCallContexts; - path = ServerCallContexts; + name = max_age; + path = max_age; sourceTree = ""; }; - OBJ_56 /* grpclb */ = { + OBJ_563 /* message_size */ = { isa = PBXGroup; children = ( - OBJ_57 /* client_load_reporting_filter.cc */, - OBJ_58 /* grpclb.cc */, - OBJ_59 /* grpclb_channel_secure.cc */, - OBJ_60 /* grpclb_client_stats.cc */, - OBJ_61 /* load_balancer_api.cc */, - OBJ_62 /* proto */, + OBJ_564 /* message_size_filter.cc */, ); - name = grpclb; - path = grpclb; + name = message_size; + path = message_size; sourceTree = ""; }; - OBJ_563 /* Echo */ = { + OBJ_565 /* workarounds */ = { isa = PBXGroup; children = ( - OBJ_564 /* EchoProvider.swift */, - OBJ_565 /* Generated */, - OBJ_568 /* main.swift */, + OBJ_566 /* workaround_cronet_compression_filter.cc */, + OBJ_567 /* workaround_utils.cc */, ); - name = Echo; - path = Sources/Examples/Echo; - sourceTree = SOURCE_ROOT; + name = workarounds; + path = workarounds; + sourceTree = ""; }; - OBJ_565 /* Generated */ = { + OBJ_568 /* transport */ = { isa = PBXGroup; children = ( - OBJ_566 /* echo.grpc.swift */, - OBJ_567 /* echo.pb.swift */, + OBJ_569 /* chttp2 */, + OBJ_611 /* inproc */, ); - name = Generated; - path = Generated; + name = transport; + path = transport; sourceTree = ""; }; - OBJ_569 /* SwiftGRPC */ = { + OBJ_569 /* chttp2 */ = { isa = PBXGroup; children = ( - OBJ_570 /* Core */, - OBJ_591 /* Runtime */, - ); - name = SwiftGRPC; - path = Sources/SwiftGRPC; - sourceTree = SOURCE_ROOT; - }; - OBJ_570 /* Core */ = { - isa = PBXGroup; - children = ( - OBJ_571 /* ByteBuffer.swift */, - OBJ_572 /* Call.swift */, - OBJ_573 /* CallError.swift */, - OBJ_574 /* CallResult.swift */, - OBJ_575 /* Channel.swift */, - OBJ_576 /* ChannelArgument.swift */, - OBJ_577 /* ChannelConnectivityObserver.swift */, - OBJ_578 /* ChannelConnectivityState.swift */, - OBJ_579 /* ClientNetworkMonitor.swift */, - OBJ_580 /* CompletionQueue.swift */, - OBJ_581 /* Handler.swift */, - OBJ_582 /* Metadata.swift */, - OBJ_583 /* Mutex.swift */, - OBJ_584 /* Operation.swift */, - OBJ_585 /* OperationGroup.swift */, - OBJ_586 /* Roots.swift */, - OBJ_587 /* Server.swift */, - OBJ_588 /* ServerStatus.swift */, - OBJ_589 /* StatusCode.swift */, - OBJ_590 /* gRPC.swift */, + OBJ_570 /* alpn */, + OBJ_572 /* client */, + OBJ_580 /* server */, + OBJ_587 /* transport */, ); - name = Core; - path = Core; + name = chttp2; + path = chttp2; sourceTree = ""; }; - OBJ_591 /* Runtime */ = { + OBJ_570 /* alpn */ = { isa = PBXGroup; children = ( - OBJ_592 /* ClientCall.swift */, - OBJ_593 /* ClientCallBidirectionalStreaming.swift */, - OBJ_594 /* ClientCallClientStreaming.swift */, - OBJ_595 /* ClientCallServerStreaming.swift */, - OBJ_596 /* ClientCallUnary.swift */, - OBJ_597 /* RPCError.swift */, - OBJ_598 /* ServerSession.swift */, - OBJ_599 /* ServerSessionBidirectionalStreaming.swift */, - OBJ_600 /* ServerSessionClientStreaming.swift */, - OBJ_601 /* ServerSessionServerStreaming.swift */, - OBJ_602 /* ServerSessionUnary.swift */, - OBJ_603 /* ServiceClient.swift */, - OBJ_604 /* ServiceProvider.swift */, - OBJ_605 /* ServiceServer.swift */, - OBJ_606 /* StreamReceiving.swift */, - OBJ_607 /* StreamSending.swift */, + OBJ_571 /* alpn.cc */, ); - name = Runtime; - path = Runtime; + name = alpn; + path = alpn; sourceTree = ""; }; - OBJ_608 /* BoringSSL */ = { + OBJ_572 /* client */ = { isa = PBXGroup; children = ( - OBJ_609 /* crypto */, - OBJ_935 /* err_data.c */, - OBJ_936 /* ssl */, - OBJ_973 /* third_party */, - OBJ_976 /* include */, - ); - name = BoringSSL; - path = Sources/BoringSSL; - sourceTree = SOURCE_ROOT; - }; - OBJ_609 /* crypto */ = { - isa = PBXGroup; - children = ( - OBJ_610 /* asn1 */, - OBJ_641 /* base64 */, - OBJ_643 /* bio */, - OBJ_654 /* bn_extra */, - OBJ_657 /* buf */, - OBJ_659 /* bytestring */, - OBJ_664 /* chacha */, - OBJ_666 /* cipher_extra */, - OBJ_678 /* cmac */, - OBJ_680 /* conf */, - OBJ_682 /* cpu-aarch64-linux.c */, - OBJ_683 /* cpu-arm-linux.c */, - OBJ_684 /* cpu-arm.c */, - OBJ_685 /* cpu-intel.c */, - OBJ_686 /* cpu-ppc64le.c */, - OBJ_687 /* crypto.c */, - OBJ_688 /* curve25519 */, - OBJ_691 /* dh */, - OBJ_696 /* digest_extra */, - OBJ_698 /* dsa */, - OBJ_701 /* ec_extra */, - OBJ_703 /* ecdh */, - OBJ_705 /* ecdsa_extra */, - OBJ_707 /* engine */, - OBJ_709 /* err */, - OBJ_712 /* evp */, - OBJ_728 /* ex_data.c */, - OBJ_729 /* fipsmodule */, - OBJ_804 /* hkdf */, - OBJ_806 /* lhash */, - OBJ_808 /* mem.c */, - OBJ_809 /* obj */, - OBJ_812 /* pem */, - OBJ_821 /* pkcs7 */, - OBJ_824 /* pkcs8 */, - OBJ_828 /* poly1305 */, - OBJ_832 /* pool */, - OBJ_834 /* rand_extra */, - OBJ_840 /* rc4 */, - OBJ_842 /* refcount_c11.c */, - OBJ_843 /* refcount_lock.c */, - OBJ_844 /* rsa_extra */, - OBJ_846 /* stack */, - OBJ_848 /* thread.c */, - OBJ_849 /* thread_none.c */, - OBJ_850 /* thread_pthread.c */, - OBJ_851 /* thread_win.c */, - OBJ_852 /* x509 */, - OBJ_902 /* x509v3 */, + OBJ_573 /* authority.cc */, + OBJ_574 /* chttp2_connector.cc */, + OBJ_575 /* insecure */, + OBJ_578 /* secure */, ); - name = crypto; - path = crypto; + name = client; + path = client; sourceTree = ""; }; - OBJ_610 /* asn1 */ = { - isa = PBXGroup; - children = ( - OBJ_611 /* a_bitstr.c */, - OBJ_612 /* a_bool.c */, - OBJ_613 /* a_d2i_fp.c */, - OBJ_614 /* a_dup.c */, - OBJ_615 /* a_enum.c */, - OBJ_616 /* a_gentm.c */, - OBJ_617 /* a_i2d_fp.c */, - OBJ_618 /* a_int.c */, - OBJ_619 /* a_mbstr.c */, - OBJ_620 /* a_object.c */, - OBJ_621 /* a_octet.c */, - OBJ_622 /* a_print.c */, - OBJ_623 /* a_strnid.c */, - OBJ_624 /* a_time.c */, - OBJ_625 /* a_type.c */, - OBJ_626 /* a_utctm.c */, - OBJ_627 /* a_utf8.c */, - OBJ_628 /* asn1_lib.c */, - OBJ_629 /* asn1_par.c */, - OBJ_630 /* asn_pack.c */, - OBJ_631 /* f_enum.c */, - OBJ_632 /* f_int.c */, - OBJ_633 /* f_string.c */, - OBJ_634 /* tasn_dec.c */, - OBJ_635 /* tasn_enc.c */, - OBJ_636 /* tasn_fre.c */, - OBJ_637 /* tasn_new.c */, - OBJ_638 /* tasn_typ.c */, - OBJ_639 /* tasn_utl.c */, - OBJ_640 /* time_support.c */, + OBJ_575 /* insecure */ = { + isa = PBXGroup; + children = ( + OBJ_576 /* channel_create.cc */, + OBJ_577 /* channel_create_posix.cc */, ); - name = asn1; - path = asn1; + name = insecure; + path = insecure; sourceTree = ""; }; - OBJ_62 /* proto */ = { + OBJ_578 /* secure */ = { isa = PBXGroup; children = ( - OBJ_63 /* grpc */, + OBJ_579 /* secure_channel_create.cc */, ); - name = proto; - path = proto; + name = secure; + path = secure; sourceTree = ""; }; - OBJ_63 /* grpc */ = { + OBJ_58 /* buf */ = { isa = PBXGroup; children = ( - OBJ_64 /* lb */, + OBJ_59 /* buf.c */, ); - name = grpc; - path = grpc; + name = buf; + path = buf; sourceTree = ""; }; - OBJ_64 /* lb */ = { + OBJ_580 /* server */ = { isa = PBXGroup; children = ( - OBJ_65 /* v1 */, + OBJ_581 /* chttp2_server.cc */, + OBJ_582 /* insecure */, + OBJ_585 /* secure */, ); - name = lb; - path = lb; + name = server; + path = server; sourceTree = ""; }; - OBJ_641 /* base64 */ = { + OBJ_582 /* insecure */ = { isa = PBXGroup; children = ( - OBJ_642 /* base64.c */, + OBJ_583 /* server_chttp2.cc */, + OBJ_584 /* server_chttp2_posix.cc */, ); - name = base64; - path = base64; + name = insecure; + path = insecure; sourceTree = ""; }; - OBJ_643 /* bio */ = { + OBJ_585 /* secure */ = { isa = PBXGroup; children = ( - OBJ_644 /* bio.c */, - OBJ_645 /* bio_mem.c */, - OBJ_646 /* connect.c */, - OBJ_647 /* fd.c */, - OBJ_648 /* file.c */, - OBJ_649 /* hexdump.c */, - OBJ_650 /* pair.c */, - OBJ_651 /* printf.c */, - OBJ_652 /* socket.c */, - OBJ_653 /* socket_helper.c */, + OBJ_586 /* server_secure_chttp2.cc */, ); - name = bio; - path = bio; + name = secure; + path = secure; sourceTree = ""; }; - OBJ_65 /* v1 */ = { - isa = PBXGroup; - children = ( - OBJ_66 /* load_balancer.pb.c */, + OBJ_587 /* transport */ = { + isa = PBXGroup; + children = ( + OBJ_588 /* bin_decoder.cc */, + OBJ_589 /* bin_encoder.cc */, + OBJ_590 /* chttp2_plugin.cc */, + OBJ_591 /* chttp2_transport.cc */, + OBJ_592 /* context_list.cc */, + OBJ_593 /* flow_control.cc */, + OBJ_594 /* frame_data.cc */, + OBJ_595 /* frame_goaway.cc */, + OBJ_596 /* frame_ping.cc */, + OBJ_597 /* frame_rst_stream.cc */, + OBJ_598 /* frame_settings.cc */, + OBJ_599 /* frame_window_update.cc */, + OBJ_600 /* hpack_encoder.cc */, + OBJ_601 /* hpack_parser.cc */, + OBJ_602 /* hpack_table.cc */, + OBJ_603 /* http2_settings.cc */, + OBJ_604 /* huffsyms.cc */, + OBJ_605 /* incoming_metadata.cc */, + OBJ_606 /* parsing.cc */, + OBJ_607 /* stream_lists.cc */, + OBJ_608 /* stream_map.cc */, + OBJ_609 /* varint.cc */, + OBJ_610 /* writing.cc */, ); - name = v1; - path = v1; + name = transport; + path = transport; sourceTree = ""; }; - OBJ_654 /* bn_extra */ = { + OBJ_60 /* bytestring */ = { isa = PBXGroup; children = ( - OBJ_655 /* bn_asn1.c */, - OBJ_656 /* convert.c */, + OBJ_61 /* asn1_compat.c */, + OBJ_62 /* ber.c */, + OBJ_63 /* cbb.c */, + OBJ_64 /* cbs.c */, ); - name = bn_extra; - path = bn_extra; + name = bytestring; + path = bytestring; sourceTree = ""; }; - OBJ_657 /* buf */ = { + OBJ_611 /* inproc */ = { isa = PBXGroup; children = ( - OBJ_658 /* buf.c */, + OBJ_612 /* inproc_plugin.cc */, + OBJ_613 /* inproc_transport.cc */, ); - name = buf; - path = buf; + name = inproc; + path = inproc; sourceTree = ""; }; - OBJ_659 /* bytestring */ = { + OBJ_614 /* lib */ = { isa = PBXGroup; children = ( - OBJ_660 /* asn1_compat.c */, - OBJ_661 /* ber.c */, - OBJ_662 /* cbb.c */, - OBJ_663 /* cbs.c */, + OBJ_615 /* avl */, + OBJ_617 /* backoff */, + OBJ_619 /* channel */, + OBJ_630 /* compression */, + OBJ_637 /* debug */, + OBJ_641 /* gpr */, + OBJ_676 /* gprpp */, + OBJ_680 /* http */, + OBJ_685 /* iomgr */, + OBJ_771 /* json */, + OBJ_776 /* profiling */, + OBJ_779 /* security */, + OBJ_839 /* slice */, + OBJ_846 /* surface */, + OBJ_867 /* transport */, + OBJ_882 /* uri */, ); - name = bytestring; - path = bytestring; + name = lib; + path = lib; sourceTree = ""; }; - OBJ_664 /* chacha */ = { + OBJ_615 /* avl */ = { isa = PBXGroup; children = ( - OBJ_665 /* chacha.c */, + OBJ_616 /* avl.cc */, ); - name = chacha; - path = chacha; + name = avl; + path = avl; sourceTree = ""; }; - OBJ_666 /* cipher_extra */ = { + OBJ_617 /* backoff */ = { isa = PBXGroup; children = ( - OBJ_667 /* cipher_extra.c */, - OBJ_668 /* derive_key.c */, - OBJ_669 /* e_aesctrhmac.c */, - OBJ_670 /* e_aesgcmsiv.c */, - OBJ_671 /* e_chacha20poly1305.c */, - OBJ_672 /* e_null.c */, - OBJ_673 /* e_rc2.c */, - OBJ_674 /* e_rc4.c */, - OBJ_675 /* e_ssl3.c */, - OBJ_676 /* e_tls.c */, - OBJ_677 /* tls_cbc.c */, + OBJ_618 /* backoff.cc */, ); - name = cipher_extra; - path = cipher_extra; + name = backoff; + path = backoff; sourceTree = ""; }; - OBJ_67 /* pick_first */ = { + OBJ_619 /* channel */ = { isa = PBXGroup; children = ( - OBJ_68 /* pick_first.cc */, + OBJ_620 /* channel_args.cc */, + OBJ_621 /* channel_stack.cc */, + OBJ_622 /* channel_stack_builder.cc */, + OBJ_623 /* channel_trace.cc */, + OBJ_624 /* channelz.cc */, + OBJ_625 /* channelz_registry.cc */, + OBJ_626 /* connected_channel.cc */, + OBJ_627 /* handshaker.cc */, + OBJ_628 /* handshaker_registry.cc */, + OBJ_629 /* status_util.cc */, ); - name = pick_first; - path = pick_first; + name = channel; + path = channel; sourceTree = ""; }; - OBJ_678 /* cmac */ = { + OBJ_630 /* compression */ = { isa = PBXGroup; children = ( - OBJ_679 /* cmac.c */, + OBJ_631 /* compression.cc */, + OBJ_632 /* compression_internal.cc */, + OBJ_633 /* message_compress.cc */, + OBJ_634 /* stream_compression.cc */, + OBJ_635 /* stream_compression_gzip.cc */, + OBJ_636 /* stream_compression_identity.cc */, ); - name = cmac; - path = cmac; + name = compression; + path = compression; sourceTree = ""; }; - OBJ_680 /* conf */ = { + OBJ_637 /* debug */ = { isa = PBXGroup; children = ( - OBJ_681 /* conf.c */, + OBJ_638 /* stats.cc */, + OBJ_639 /* stats_data.cc */, + OBJ_640 /* trace.cc */, ); - name = conf; - path = conf; + name = debug; + path = debug; sourceTree = ""; }; - OBJ_688 /* curve25519 */ = { - isa = PBXGroup; - children = ( - OBJ_689 /* spake25519.c */, - OBJ_690 /* x25519-x86_64.c */, + OBJ_641 /* gpr */ = { + isa = PBXGroup; + children = ( + OBJ_642 /* alloc.cc */, + OBJ_643 /* arena.cc */, + OBJ_644 /* atm.cc */, + OBJ_645 /* cpu_iphone.cc */, + OBJ_646 /* cpu_linux.cc */, + OBJ_647 /* cpu_posix.cc */, + OBJ_648 /* cpu_windows.cc */, + OBJ_649 /* env_linux.cc */, + OBJ_650 /* env_posix.cc */, + OBJ_651 /* env_windows.cc */, + OBJ_652 /* host_port.cc */, + OBJ_653 /* log.cc */, + OBJ_654 /* log_android.cc */, + OBJ_655 /* log_linux.cc */, + OBJ_656 /* log_posix.cc */, + OBJ_657 /* log_windows.cc */, + OBJ_658 /* mpscq.cc */, + OBJ_659 /* murmur_hash.cc */, + OBJ_660 /* string.cc */, + OBJ_661 /* string_posix.cc */, + OBJ_662 /* string_util_windows.cc */, + OBJ_663 /* string_windows.cc */, + OBJ_664 /* sync.cc */, + OBJ_665 /* sync_posix.cc */, + OBJ_666 /* sync_windows.cc */, + OBJ_667 /* time.cc */, + OBJ_668 /* time_posix.cc */, + OBJ_669 /* time_precise.cc */, + OBJ_670 /* time_windows.cc */, + OBJ_671 /* tls_pthread.cc */, + OBJ_672 /* tmpfile_msys.cc */, + OBJ_673 /* tmpfile_posix.cc */, + OBJ_674 /* tmpfile_windows.cc */, + OBJ_675 /* wrap_memcpy.cc */, ); - name = curve25519; - path = curve25519; + name = gpr; + path = gpr; sourceTree = ""; }; - OBJ_69 /* round_robin */ = { + OBJ_65 /* chacha */ = { isa = PBXGroup; children = ( - OBJ_70 /* round_robin.cc */, + OBJ_66 /* chacha.c */, ); - name = round_robin; - path = round_robin; + name = chacha; + path = chacha; sourceTree = ""; }; - OBJ_691 /* dh */ = { + OBJ_67 /* cipher_extra */ = { isa = PBXGroup; children = ( - OBJ_692 /* check.c */, - OBJ_693 /* dh.c */, - OBJ_694 /* dh_asn1.c */, - OBJ_695 /* params.c */, + OBJ_68 /* cipher_extra.c */, + OBJ_69 /* derive_key.c */, + OBJ_70 /* e_aesccm.c */, + OBJ_71 /* e_aesctrhmac.c */, + OBJ_72 /* e_aesgcmsiv.c */, + OBJ_73 /* e_chacha20poly1305.c */, + OBJ_74 /* e_null.c */, + OBJ_75 /* e_rc2.c */, + OBJ_76 /* e_rc4.c */, + OBJ_77 /* e_ssl3.c */, + OBJ_78 /* e_tls.c */, + OBJ_79 /* tls_cbc.c */, ); - name = dh; - path = dh; + name = cipher_extra; + path = cipher_extra; sourceTree = ""; }; - OBJ_696 /* digest_extra */ = { + OBJ_676 /* gprpp */ = { isa = PBXGroup; children = ( - OBJ_697 /* digest_extra.c */, + OBJ_677 /* fork.cc */, + OBJ_678 /* thd_posix.cc */, + OBJ_679 /* thd_windows.cc */, ); - name = digest_extra; - path = digest_extra; + name = gprpp; + path = gprpp; sourceTree = ""; }; - OBJ_698 /* dsa */ = { + OBJ_680 /* http */ = { isa = PBXGroup; children = ( - OBJ_699 /* dsa.c */, - OBJ_700 /* dsa_asn1.c */, + OBJ_681 /* format_request.cc */, + OBJ_682 /* httpcli.cc */, + OBJ_683 /* httpcli_security_connector.cc */, + OBJ_684 /* parser.cc */, ); - name = dsa; - path = dsa; + name = http; + path = http; + sourceTree = ""; + }; + OBJ_685 /* iomgr */ = { + isa = PBXGroup; + children = ( + OBJ_686 /* buffer_list.cc */, + OBJ_687 /* call_combiner.cc */, + OBJ_688 /* combiner.cc */, + OBJ_689 /* endpoint.cc */, + OBJ_690 /* endpoint_pair_posix.cc */, + OBJ_691 /* endpoint_pair_uv.cc */, + OBJ_692 /* endpoint_pair_windows.cc */, + OBJ_693 /* error.cc */, + OBJ_694 /* ev_epoll1_linux.cc */, + OBJ_695 /* ev_epollex_linux.cc */, + OBJ_696 /* ev_poll_posix.cc */, + OBJ_697 /* ev_posix.cc */, + OBJ_698 /* ev_windows.cc */, + OBJ_699 /* exec_ctx.cc */, + OBJ_700 /* executor.cc */, + OBJ_701 /* fork_posix.cc */, + OBJ_702 /* fork_windows.cc */, + OBJ_703 /* gethostname_fallback.cc */, + OBJ_704 /* gethostname_host_name_max.cc */, + OBJ_705 /* gethostname_sysconf.cc */, + OBJ_706 /* grpc_if_nametoindex_posix.cc */, + OBJ_707 /* grpc_if_nametoindex_unsupported.cc */, + OBJ_708 /* internal_errqueue.cc */, + OBJ_709 /* iocp_windows.cc */, + OBJ_710 /* iomgr.cc */, + OBJ_711 /* iomgr_custom.cc */, + OBJ_712 /* iomgr_internal.cc */, + OBJ_713 /* iomgr_posix.cc */, + OBJ_714 /* iomgr_uv.cc */, + OBJ_715 /* iomgr_windows.cc */, + OBJ_716 /* is_epollexclusive_available.cc */, + OBJ_717 /* load_file.cc */, + OBJ_718 /* lockfree_event.cc */, + OBJ_719 /* polling_entity.cc */, + OBJ_720 /* pollset.cc */, + OBJ_721 /* pollset_custom.cc */, + OBJ_722 /* pollset_set.cc */, + OBJ_723 /* pollset_set_custom.cc */, + OBJ_724 /* pollset_set_windows.cc */, + OBJ_725 /* pollset_uv.cc */, + OBJ_726 /* pollset_windows.cc */, + OBJ_727 /* resolve_address.cc */, + OBJ_728 /* resolve_address_custom.cc */, + OBJ_729 /* resolve_address_posix.cc */, + OBJ_730 /* resolve_address_windows.cc */, + OBJ_731 /* resource_quota.cc */, + OBJ_732 /* sockaddr_utils.cc */, + OBJ_733 /* socket_factory_posix.cc */, + OBJ_734 /* socket_mutator.cc */, + OBJ_735 /* socket_utils_common_posix.cc */, + OBJ_736 /* socket_utils_linux.cc */, + OBJ_737 /* socket_utils_posix.cc */, + OBJ_738 /* socket_utils_uv.cc */, + OBJ_739 /* socket_utils_windows.cc */, + OBJ_740 /* socket_windows.cc */, + OBJ_741 /* tcp_client.cc */, + OBJ_742 /* tcp_client_custom.cc */, + OBJ_743 /* tcp_client_posix.cc */, + OBJ_744 /* tcp_client_windows.cc */, + OBJ_745 /* tcp_custom.cc */, + OBJ_746 /* tcp_posix.cc */, + OBJ_747 /* tcp_server.cc */, + OBJ_748 /* tcp_server_custom.cc */, + OBJ_749 /* tcp_server_posix.cc */, + OBJ_750 /* tcp_server_utils_posix_common.cc */, + OBJ_751 /* tcp_server_utils_posix_ifaddrs.cc */, + OBJ_752 /* tcp_server_utils_posix_noifaddrs.cc */, + OBJ_753 /* tcp_server_windows.cc */, + OBJ_754 /* tcp_uv.cc */, + OBJ_755 /* tcp_windows.cc */, + OBJ_756 /* time_averaged_stats.cc */, + OBJ_757 /* timer.cc */, + OBJ_758 /* timer_custom.cc */, + OBJ_759 /* timer_generic.cc */, + OBJ_760 /* timer_heap.cc */, + OBJ_761 /* timer_manager.cc */, + OBJ_762 /* timer_uv.cc */, + OBJ_763 /* udp_server.cc */, + OBJ_764 /* unix_sockets_posix.cc */, + OBJ_765 /* unix_sockets_posix_noop.cc */, + OBJ_766 /* wakeup_fd_cv.cc */, + OBJ_767 /* wakeup_fd_eventfd.cc */, + OBJ_768 /* wakeup_fd_nospecial.cc */, + OBJ_769 /* wakeup_fd_pipe.cc */, + OBJ_770 /* wakeup_fd_posix.cc */, + ); + name = iomgr; + path = iomgr; sourceTree = ""; }; OBJ_7 /* Sources */ = { isa = PBXGroup; children = ( - OBJ_8 /* protoc-gen-swiftgrpc */, - OBJ_17 /* EchoNIO */, - OBJ_23 /* RootsEncoder */, - OBJ_25 /* CgRPC */, - OBJ_521 /* Simple */, - OBJ_523 /* SwiftGRPCNIO */, - OBJ_563 /* Echo */, - OBJ_569 /* SwiftGRPC */, - OBJ_608 /* BoringSSL */, + OBJ_8 /* BoringSSL */, + OBJ_459 /* CgRPC */, + OBJ_995 /* Echo */, + OBJ_1008 /* EchoNIO */, + OBJ_1018 /* RootsEncoder */, + OBJ_1020 /* Simple */, + OBJ_1023 /* SwiftGRPC */, + OBJ_1062 /* SwiftGRPCNIO */, + OBJ_1102 /* protoc-gen-swiftgrpc */, ); name = Sources; path = ""; sourceTree = SOURCE_ROOT; }; - OBJ_701 /* ec_extra */ = { + OBJ_771 /* json */ = { isa = PBXGroup; children = ( - OBJ_702 /* ec_asn1.c */, + OBJ_772 /* json.cc */, + OBJ_773 /* json_reader.cc */, + OBJ_774 /* json_string.cc */, + OBJ_775 /* json_writer.cc */, ); - name = ec_extra; - path = ec_extra; + name = json; + path = json; sourceTree = ""; }; - OBJ_703 /* ecdh */ = { + OBJ_776 /* profiling */ = { isa = PBXGroup; children = ( - OBJ_704 /* ecdh.c */, + OBJ_777 /* basic_timers.cc */, + OBJ_778 /* stap_timers.cc */, ); - name = ecdh; - path = ecdh; + name = profiling; + path = profiling; sourceTree = ""; }; - OBJ_705 /* ecdsa_extra */ = { + OBJ_779 /* security */ = { isa = PBXGroup; children = ( - OBJ_706 /* ecdsa_asn1.c */, + OBJ_780 /* context */, + OBJ_782 /* credentials */, + OBJ_817 /* security_connector */, + OBJ_830 /* transport */, + OBJ_837 /* util */, ); - name = ecdsa_extra; - path = ecdsa_extra; + name = security; + path = security; sourceTree = ""; }; - OBJ_707 /* engine */ = { + OBJ_780 /* context */ = { isa = PBXGroup; children = ( - OBJ_708 /* engine.c */, + OBJ_781 /* security_context.cc */, ); - name = engine; - path = engine; + name = context; + path = context; sourceTree = ""; }; - OBJ_709 /* err */ = { + OBJ_782 /* credentials */ = { isa = PBXGroup; children = ( - OBJ_710 /* err.c */, - OBJ_711 /* err_data.c */, + OBJ_783 /* alts */, + OBJ_792 /* composite */, + OBJ_794 /* credentials.cc */, + OBJ_795 /* credentials_metadata.cc */, + OBJ_796 /* fake */, + OBJ_798 /* google_default */, + OBJ_801 /* iam */, + OBJ_803 /* jwt */, + OBJ_807 /* local */, + OBJ_809 /* oauth2 */, + OBJ_811 /* plugin */, + OBJ_813 /* ssl */, + OBJ_815 /* tls */, ); - name = err; - path = err; + name = credentials; + path = credentials; sourceTree = ""; }; - OBJ_712 /* evp */ = { + OBJ_783 /* alts */ = { isa = PBXGroup; children = ( - OBJ_713 /* digestsign.c */, - OBJ_714 /* evp.c */, - OBJ_715 /* evp_asn1.c */, - OBJ_716 /* evp_ctx.c */, - OBJ_717 /* p_dsa_asn1.c */, - OBJ_718 /* p_ec.c */, - OBJ_719 /* p_ec_asn1.c */, - OBJ_720 /* p_ed25519.c */, - OBJ_721 /* p_ed25519_asn1.c */, - OBJ_722 /* p_rsa.c */, - OBJ_723 /* p_rsa_asn1.c */, - OBJ_724 /* pbkdf.c */, - OBJ_725 /* print.c */, - OBJ_726 /* scrypt.c */, - OBJ_727 /* sign.c */, + OBJ_784 /* alts_credentials.cc */, + OBJ_785 /* check_gcp_environment.cc */, + OBJ_786 /* check_gcp_environment_linux.cc */, + OBJ_787 /* check_gcp_environment_no_op.cc */, + OBJ_788 /* check_gcp_environment_windows.cc */, + OBJ_789 /* grpc_alts_credentials_client_options.cc */, + OBJ_790 /* grpc_alts_credentials_options.cc */, + OBJ_791 /* grpc_alts_credentials_server_options.cc */, ); - name = evp; - path = evp; + name = alts; + path = alts; sourceTree = ""; }; - OBJ_729 /* fipsmodule */ = { + OBJ_792 /* composite */ = { isa = PBXGroup; children = ( - OBJ_730 /* aes */, - OBJ_734 /* bn */, - OBJ_753 /* cipher */, - OBJ_758 /* des */, - OBJ_760 /* digest */, - OBJ_763 /* ec */, - OBJ_774 /* ecdsa */, - OBJ_776 /* hmac */, - OBJ_778 /* is_fips.c */, - OBJ_779 /* md4 */, - OBJ_781 /* md5 */, - OBJ_783 /* modes */, - OBJ_790 /* rand */, - OBJ_794 /* rsa */, - OBJ_799 /* sha */, + OBJ_793 /* composite_credentials.cc */, ); - name = fipsmodule; - path = fipsmodule; + name = composite; + path = composite; sourceTree = ""; }; - OBJ_730 /* aes */ = { + OBJ_796 /* fake */ = { isa = PBXGroup; children = ( - OBJ_731 /* aes.c */, - OBJ_732 /* key_wrap.c */, - OBJ_733 /* mode_wrappers.c */, + OBJ_797 /* fake_credentials.cc */, ); - name = aes; - path = aes; + name = fake; + path = fake; sourceTree = ""; }; - OBJ_734 /* bn */ = { - isa = PBXGroup; - children = ( - OBJ_735 /* add.c */, - OBJ_736 /* bn.c */, - OBJ_737 /* bytes.c */, - OBJ_738 /* cmp.c */, - OBJ_739 /* ctx.c */, - OBJ_740 /* div.c */, - OBJ_741 /* exponentiation.c */, - OBJ_742 /* gcd.c */, - OBJ_743 /* generic.c */, - OBJ_744 /* jacobi.c */, - OBJ_745 /* montgomery.c */, - OBJ_746 /* montgomery_inv.c */, - OBJ_747 /* mul.c */, - OBJ_748 /* prime.c */, - OBJ_749 /* random.c */, - OBJ_750 /* rsaz_exp.c */, - OBJ_751 /* shift.c */, - OBJ_752 /* sqrt.c */, + OBJ_798 /* google_default */ = { + isa = PBXGroup; + children = ( + OBJ_799 /* credentials_generic.cc */, + OBJ_800 /* google_default_credentials.cc */, ); - name = bn; - path = bn; + name = google_default; + path = google_default; sourceTree = ""; }; - OBJ_753 /* cipher */ = { + OBJ_8 /* BoringSSL */ = { isa = PBXGroup; children = ( - OBJ_754 /* aead.c */, - OBJ_755 /* cipher.c */, - OBJ_756 /* e_aes.c */, - OBJ_757 /* e_des.c */, + OBJ_9 /* README.md */, + OBJ_10 /* crypto */, + OBJ_341 /* ssl */, + OBJ_379 /* third_party */, + OBJ_383 /* include */, ); - name = cipher; - path = cipher; - sourceTree = ""; + name = BoringSSL; + path = Sources/BoringSSL; + sourceTree = SOURCE_ROOT; }; - OBJ_758 /* des */ = { + OBJ_80 /* cmac */ = { isa = PBXGroup; children = ( - OBJ_759 /* des.c */, + OBJ_81 /* cmac.c */, ); - name = des; - path = des; + name = cmac; + path = cmac; sourceTree = ""; }; - OBJ_760 /* digest */ = { + OBJ_801 /* iam */ = { isa = PBXGroup; children = ( - OBJ_761 /* digest.c */, - OBJ_762 /* digests.c */, + OBJ_802 /* iam_credentials.cc */, ); - name = digest; - path = digest; + name = iam; + path = iam; sourceTree = ""; }; - OBJ_763 /* ec */ = { + OBJ_803 /* jwt */ = { isa = PBXGroup; children = ( - OBJ_764 /* ec.c */, - OBJ_765 /* ec_key.c */, - OBJ_766 /* ec_montgomery.c */, - OBJ_767 /* oct.c */, - OBJ_768 /* p224-64.c */, - OBJ_769 /* p256-64.c */, - OBJ_770 /* p256-x86_64.c */, - OBJ_771 /* simple.c */, - OBJ_772 /* util-64.c */, - OBJ_773 /* wnaf.c */, + OBJ_804 /* json_token.cc */, + OBJ_805 /* jwt_credentials.cc */, + OBJ_806 /* jwt_verifier.cc */, ); - name = ec; - path = ec; + name = jwt; + path = jwt; sourceTree = ""; }; - OBJ_774 /* ecdsa */ = { + OBJ_807 /* local */ = { isa = PBXGroup; children = ( - OBJ_775 /* ecdsa.c */, + OBJ_808 /* local_credentials.cc */, ); - name = ecdsa; - path = ecdsa; + name = local; + path = local; sourceTree = ""; }; - OBJ_776 /* hmac */ = { + OBJ_809 /* oauth2 */ = { isa = PBXGroup; children = ( - OBJ_777 /* hmac.c */, + OBJ_810 /* oauth2_credentials.cc */, ); - name = hmac; - path = hmac; + name = oauth2; + path = oauth2; sourceTree = ""; }; - OBJ_779 /* md4 */ = { + OBJ_811 /* plugin */ = { isa = PBXGroup; children = ( - OBJ_780 /* md4.c */, + OBJ_812 /* plugin_credentials.cc */, ); - name = md4; - path = md4; + name = plugin; + path = plugin; sourceTree = ""; }; - OBJ_78 /* resolver */ = { + OBJ_813 /* ssl */ = { isa = PBXGroup; children = ( - OBJ_79 /* dns */, - OBJ_87 /* fake */, - OBJ_89 /* sockaddr */, + OBJ_814 /* ssl_credentials.cc */, ); - name = resolver; - path = resolver; + name = ssl; + path = ssl; sourceTree = ""; }; - OBJ_781 /* md5 */ = { + OBJ_815 /* tls */ = { isa = PBXGroup; children = ( - OBJ_782 /* md5.c */, + OBJ_816 /* grpc_tls_credentials_options.cc */, ); - name = md5; - path = md5; + name = tls; + path = tls; sourceTree = ""; }; - OBJ_783 /* modes */ = { + OBJ_817 /* security_connector */ = { isa = PBXGroup; children = ( - OBJ_784 /* cbc.c */, - OBJ_785 /* cfb.c */, - OBJ_786 /* ctr.c */, - OBJ_787 /* gcm.c */, - OBJ_788 /* ofb.c */, - OBJ_789 /* polyval.c */, + OBJ_818 /* alts */, + OBJ_820 /* fake */, + OBJ_822 /* load_system_roots_fallback.cc */, + OBJ_823 /* load_system_roots_linux.cc */, + OBJ_824 /* local */, + OBJ_826 /* security_connector.cc */, + OBJ_827 /* ssl */, + OBJ_829 /* ssl_utils.cc */, ); - name = modes; - path = modes; + name = security_connector; + path = security_connector; sourceTree = ""; }; - OBJ_79 /* dns */ = { + OBJ_818 /* alts */ = { isa = PBXGroup; children = ( - OBJ_80 /* c_ares */, - OBJ_85 /* native */, + OBJ_819 /* alts_security_connector.cc */, ); - name = dns; - path = dns; + name = alts; + path = alts; sourceTree = ""; }; - OBJ_790 /* rand */ = { + OBJ_82 /* conf */ = { isa = PBXGroup; children = ( - OBJ_791 /* ctrdrbg.c */, - OBJ_792 /* rand.c */, - OBJ_793 /* urandom.c */, + OBJ_83 /* conf.c */, ); - name = rand; - path = rand; + name = conf; + path = conf; sourceTree = ""; }; - OBJ_794 /* rsa */ = { + OBJ_820 /* fake */ = { isa = PBXGroup; children = ( - OBJ_795 /* blinding.c */, - OBJ_796 /* padding.c */, - OBJ_797 /* rsa.c */, - OBJ_798 /* rsa_impl.c */, + OBJ_821 /* fake_security_connector.cc */, ); - name = rsa; - path = rsa; + name = fake; + path = fake; sourceTree = ""; }; - OBJ_799 /* sha */ = { + OBJ_824 /* local */ = { isa = PBXGroup; children = ( - OBJ_800 /* sha1-altivec.c */, - OBJ_801 /* sha1.c */, - OBJ_802 /* sha256.c */, - OBJ_803 /* sha512.c */, + OBJ_825 /* local_security_connector.cc */, ); - name = sha; - path = sha; + name = local; + path = local; sourceTree = ""; }; - OBJ_8 /* protoc-gen-swiftgrpc */ = { + OBJ_827 /* ssl */ = { isa = PBXGroup; children = ( - OBJ_9 /* Generator-Client.swift */, - OBJ_10 /* Generator-Methods.swift */, - OBJ_11 /* Generator-Names.swift */, - OBJ_12 /* Generator-Server.swift */, - OBJ_13 /* Generator.swift */, - OBJ_14 /* StreamingType.swift */, - OBJ_15 /* main.swift */, - OBJ_16 /* options.swift */, + OBJ_828 /* ssl_security_connector.cc */, ); - name = "protoc-gen-swiftgrpc"; - path = "Sources/protoc-gen-swiftgrpc"; - sourceTree = SOURCE_ROOT; + name = ssl; + path = ssl; + sourceTree = ""; }; - OBJ_80 /* c_ares */ = { + OBJ_830 /* transport */ = { isa = PBXGroup; children = ( - OBJ_81 /* dns_resolver_ares.cc */, - OBJ_82 /* grpc_ares_ev_driver_posix.cc */, - OBJ_83 /* grpc_ares_wrapper.cc */, - OBJ_84 /* grpc_ares_wrapper_fallback.cc */, + OBJ_831 /* client_auth_filter.cc */, + OBJ_832 /* secure_endpoint.cc */, + OBJ_833 /* security_handshaker.cc */, + OBJ_834 /* server_auth_filter.cc */, + OBJ_835 /* target_authority_table.cc */, + OBJ_836 /* tsi_error.cc */, ); - name = c_ares; - path = c_ares; + name = transport; + path = transport; sourceTree = ""; }; - OBJ_804 /* hkdf */ = { + OBJ_837 /* util */ = { isa = PBXGroup; children = ( - OBJ_805 /* hkdf.c */, + OBJ_838 /* json_util.cc */, ); - name = hkdf; - path = hkdf; + name = util; + path = util; sourceTree = ""; }; - OBJ_806 /* lhash */ = { + OBJ_839 /* slice */ = { isa = PBXGroup; children = ( - OBJ_807 /* lhash.c */, + OBJ_840 /* b64.cc */, + OBJ_841 /* percent_encoding.cc */, + OBJ_842 /* slice.cc */, + OBJ_843 /* slice_buffer.cc */, + OBJ_844 /* slice_intern.cc */, + OBJ_845 /* slice_string_helpers.cc */, ); - name = lhash; - path = lhash; + name = slice; + path = slice; sourceTree = ""; }; - OBJ_809 /* obj */ = { - isa = PBXGroup; - children = ( - OBJ_810 /* obj.c */, - OBJ_811 /* obj_xref.c */, + OBJ_846 /* surface */ = { + isa = PBXGroup; + children = ( + OBJ_847 /* api_trace.cc */, + OBJ_848 /* byte_buffer.cc */, + OBJ_849 /* byte_buffer_reader.cc */, + OBJ_850 /* call.cc */, + OBJ_851 /* call_details.cc */, + OBJ_852 /* call_log_batch.cc */, + OBJ_853 /* channel.cc */, + OBJ_854 /* channel_init.cc */, + OBJ_855 /* channel_ping.cc */, + OBJ_856 /* channel_stack_type.cc */, + OBJ_857 /* completion_queue.cc */, + OBJ_858 /* completion_queue_factory.cc */, + OBJ_859 /* event_string.cc */, + OBJ_860 /* init.cc */, + OBJ_861 /* init_secure.cc */, + OBJ_862 /* lame_client.cc */, + OBJ_863 /* metadata_array.cc */, + OBJ_864 /* server.cc */, + OBJ_865 /* validate_metadata.cc */, + OBJ_866 /* version.cc */, ); - name = obj; - path = obj; + name = surface; + path = surface; sourceTree = ""; }; - OBJ_812 /* pem */ = { + OBJ_867 /* transport */ = { isa = PBXGroup; children = ( - OBJ_813 /* pem_all.c */, - OBJ_814 /* pem_info.c */, - OBJ_815 /* pem_lib.c */, - OBJ_816 /* pem_oth.c */, - OBJ_817 /* pem_pk8.c */, - OBJ_818 /* pem_pkey.c */, - OBJ_819 /* pem_x509.c */, - OBJ_820 /* pem_xaux.c */, + OBJ_868 /* bdp_estimator.cc */, + OBJ_869 /* byte_stream.cc */, + OBJ_870 /* connectivity_state.cc */, + OBJ_871 /* error_utils.cc */, + OBJ_872 /* metadata.cc */, + OBJ_873 /* metadata_batch.cc */, + OBJ_874 /* pid_controller.cc */, + OBJ_875 /* service_config.cc */, + OBJ_876 /* static_metadata.cc */, + OBJ_877 /* status_conversion.cc */, + OBJ_878 /* status_metadata.cc */, + OBJ_879 /* timeout_encoding.cc */, + OBJ_880 /* transport.cc */, + OBJ_881 /* transport_op_string.cc */, ); - name = pem; - path = pem; + name = transport; + path = transport; sourceTree = ""; }; - OBJ_821 /* pkcs7 */ = { + OBJ_882 /* uri */ = { isa = PBXGroup; children = ( - OBJ_822 /* pkcs7.c */, - OBJ_823 /* pkcs7_x509.c */, + OBJ_883 /* uri_parser.cc */, ); - name = pkcs7; - path = pkcs7; + name = uri; + path = uri; sourceTree = ""; }; - OBJ_824 /* pkcs8 */ = { + OBJ_884 /* plugin_registry */ = { isa = PBXGroup; children = ( - OBJ_825 /* p5_pbev2.c */, - OBJ_826 /* pkcs8.c */, - OBJ_827 /* pkcs8_x509.c */, + OBJ_885 /* grpc_plugin_registry.cc */, ); - name = pkcs8; - path = pkcs8; + name = plugin_registry; + path = plugin_registry; sourceTree = ""; }; - OBJ_828 /* poly1305 */ = { + OBJ_886 /* tsi */ = { isa = PBXGroup; children = ( - OBJ_829 /* poly1305.c */, - OBJ_830 /* poly1305_arm.c */, - OBJ_831 /* poly1305_vec.c */, + OBJ_887 /* alts */, + OBJ_916 /* fake_transport_security.cc */, + OBJ_917 /* local_transport_security.cc */, + OBJ_918 /* ssl */, + OBJ_923 /* ssl_transport_security.cc */, + OBJ_924 /* transport_security.cc */, + OBJ_925 /* transport_security_grpc.cc */, ); - name = poly1305; - path = poly1305; + name = tsi; + path = tsi; sourceTree = ""; }; - OBJ_832 /* pool */ = { + OBJ_887 /* alts */ = { isa = PBXGroup; children = ( - OBJ_833 /* pool.c */, + OBJ_888 /* crypt */, + OBJ_891 /* frame_protector */, + OBJ_899 /* handshaker */, + OBJ_910 /* zero_copy_frame_protector */, ); - name = pool; - path = pool; + name = alts; + path = alts; sourceTree = ""; }; - OBJ_834 /* rand_extra */ = { + OBJ_888 /* crypt */ = { isa = PBXGroup; children = ( - OBJ_835 /* deterministic.c */, - OBJ_836 /* forkunsafe.c */, - OBJ_837 /* fuchsia.c */, - OBJ_838 /* rand_extra.c */, - OBJ_839 /* windows.c */, + OBJ_889 /* aes_gcm.cc */, + OBJ_890 /* gsec.cc */, ); - name = rand_extra; - path = rand_extra; + name = crypt; + path = crypt; sourceTree = ""; }; - OBJ_840 /* rc4 */ = { + OBJ_891 /* frame_protector */ = { isa = PBXGroup; children = ( - OBJ_841 /* rc4.c */, + OBJ_892 /* alts_counter.cc */, + OBJ_893 /* alts_crypter.cc */, + OBJ_894 /* alts_frame_protector.cc */, + OBJ_895 /* alts_record_protocol_crypter_common.cc */, + OBJ_896 /* alts_seal_privacy_integrity_crypter.cc */, + OBJ_897 /* alts_unseal_privacy_integrity_crypter.cc */, + OBJ_898 /* frame_handler.cc */, ); - name = rc4; - path = rc4; + name = frame_protector; + path = frame_protector; sourceTree = ""; }; - OBJ_844 /* rsa_extra */ = { + OBJ_899 /* handshaker */ = { isa = PBXGroup; children = ( - OBJ_845 /* rsa_asn1.c */, + OBJ_900 /* alts_handshaker_client.cc */, + OBJ_901 /* alts_handshaker_service_api.cc */, + OBJ_902 /* alts_handshaker_service_api_util.cc */, + OBJ_903 /* alts_shared_resource.cc */, + OBJ_904 /* alts_tsi_handshaker.cc */, + OBJ_905 /* alts_tsi_utils.cc */, + OBJ_906 /* altscontext.pb.c */, + OBJ_907 /* handshaker.pb.c */, + OBJ_908 /* transport_security_common.pb.c */, + OBJ_909 /* transport_security_common_api.cc */, ); - name = rsa_extra; - path = rsa_extra; + name = handshaker; + path = handshaker; sourceTree = ""; }; - OBJ_846 /* stack */ = { + OBJ_91 /* curve25519 */ = { isa = PBXGroup; children = ( - OBJ_847 /* stack.c */, + OBJ_92 /* spake25519.c */, ); - name = stack; - path = stack; + name = curve25519; + path = curve25519; sourceTree = ""; }; - OBJ_85 /* native */ = { + OBJ_910 /* zero_copy_frame_protector */ = { isa = PBXGroup; children = ( - OBJ_86 /* dns_resolver.cc */, + OBJ_911 /* alts_grpc_integrity_only_record_protocol.cc */, + OBJ_912 /* alts_grpc_privacy_integrity_record_protocol.cc */, + OBJ_913 /* alts_grpc_record_protocol_common.cc */, + OBJ_914 /* alts_iovec_record_protocol.cc */, + OBJ_915 /* alts_zero_copy_grpc_protector.cc */, ); - name = native; - path = native; + name = zero_copy_frame_protector; + path = zero_copy_frame_protector; sourceTree = ""; }; - OBJ_852 /* x509 */ = { - isa = PBXGroup; - children = ( - OBJ_853 /* a_digest.c */, - OBJ_854 /* a_sign.c */, - OBJ_855 /* a_strex.c */, - OBJ_856 /* a_verify.c */, - OBJ_857 /* algorithm.c */, - OBJ_858 /* asn1_gen.c */, - OBJ_859 /* by_dir.c */, - OBJ_860 /* by_file.c */, - OBJ_861 /* i2d_pr.c */, - OBJ_862 /* rsa_pss.c */, - OBJ_863 /* t_crl.c */, - OBJ_864 /* t_req.c */, - OBJ_865 /* t_x509.c */, - OBJ_866 /* t_x509a.c */, - OBJ_867 /* x509.c */, - OBJ_868 /* x509_att.c */, - OBJ_869 /* x509_cmp.c */, - OBJ_870 /* x509_d2.c */, - OBJ_871 /* x509_def.c */, - OBJ_872 /* x509_ext.c */, - OBJ_873 /* x509_lu.c */, - OBJ_874 /* x509_obj.c */, - OBJ_875 /* x509_r2x.c */, - OBJ_876 /* x509_req.c */, - OBJ_877 /* x509_set.c */, - OBJ_878 /* x509_trs.c */, - OBJ_879 /* x509_txt.c */, - OBJ_880 /* x509_v3.c */, - OBJ_881 /* x509_vfy.c */, - OBJ_882 /* x509_vpm.c */, - OBJ_883 /* x509cset.c */, - OBJ_884 /* x509name.c */, - OBJ_885 /* x509rset.c */, - OBJ_886 /* x509spki.c */, - OBJ_887 /* x_algor.c */, - OBJ_888 /* x_all.c */, - OBJ_889 /* x_attrib.c */, - OBJ_890 /* x_crl.c */, - OBJ_891 /* x_exten.c */, - OBJ_892 /* x_info.c */, - OBJ_893 /* x_name.c */, - OBJ_894 /* x_pkey.c */, - OBJ_895 /* x_pubkey.c */, - OBJ_896 /* x_req.c */, - OBJ_897 /* x_sig.c */, - OBJ_898 /* x_spki.c */, - OBJ_899 /* x_val.c */, - OBJ_900 /* x_x509.c */, - OBJ_901 /* x_x509a.c */, + OBJ_918 /* ssl */ = { + isa = PBXGroup; + children = ( + OBJ_919 /* session_cache */, ); - name = x509; - path = x509; + name = ssl; + path = ssl; sourceTree = ""; }; - OBJ_87 /* fake */ = { + OBJ_919 /* session_cache */ = { isa = PBXGroup; children = ( - OBJ_88 /* fake_resolver.cc */, + OBJ_920 /* ssl_session_boringssl.cc */, + OBJ_921 /* ssl_session_cache.cc */, + OBJ_922 /* ssl_session_openssl.cc */, ); - name = fake; - path = fake; + name = session_cache; + path = session_cache; sourceTree = ""; }; - OBJ_89 /* sockaddr */ = { + OBJ_926 /* third_party */ = { isa = PBXGroup; children = ( - OBJ_90 /* sockaddr_resolver.cc */, + OBJ_927 /* nanopb */, ); - name = sockaddr; - path = sockaddr; + name = third_party; + path = third_party; sourceTree = ""; }; - OBJ_902 /* x509v3 */ = { - isa = PBXGroup; - children = ( - OBJ_903 /* pcy_cache.c */, - OBJ_904 /* pcy_data.c */, - OBJ_905 /* pcy_lib.c */, - OBJ_906 /* pcy_map.c */, - OBJ_907 /* pcy_node.c */, - OBJ_908 /* pcy_tree.c */, - OBJ_909 /* v3_akey.c */, - OBJ_910 /* v3_akeya.c */, - OBJ_911 /* v3_alt.c */, - OBJ_912 /* v3_bcons.c */, - OBJ_913 /* v3_bitst.c */, - OBJ_914 /* v3_conf.c */, - OBJ_915 /* v3_cpols.c */, - OBJ_916 /* v3_crld.c */, - OBJ_917 /* v3_enum.c */, - OBJ_918 /* v3_extku.c */, - OBJ_919 /* v3_genn.c */, - OBJ_920 /* v3_ia5.c */, - OBJ_921 /* v3_info.c */, - OBJ_922 /* v3_int.c */, - OBJ_923 /* v3_lib.c */, - OBJ_924 /* v3_ncons.c */, - OBJ_925 /* v3_pci.c */, - OBJ_926 /* v3_pcia.c */, - OBJ_927 /* v3_pcons.c */, - OBJ_928 /* v3_pku.c */, - OBJ_929 /* v3_pmaps.c */, - OBJ_930 /* v3_prn.c */, - OBJ_931 /* v3_purp.c */, - OBJ_932 /* v3_skey.c */, - OBJ_933 /* v3_sxnet.c */, - OBJ_934 /* v3_utl.c */, + OBJ_927 /* nanopb */ = { + isa = PBXGroup; + children = ( + OBJ_928 /* pb_common.c */, + OBJ_929 /* pb_decode.c */, + OBJ_930 /* pb_encode.c */, ); - name = x509v3; - path = x509v3; + name = nanopb; + path = nanopb; sourceTree = ""; }; - OBJ_936 /* ssl */ = { - isa = PBXGroup; - children = ( - OBJ_937 /* bio_ssl.cc */, - OBJ_938 /* custom_extensions.cc */, - OBJ_939 /* d1_both.cc */, - OBJ_940 /* d1_lib.cc */, - OBJ_941 /* d1_pkt.cc */, - OBJ_942 /* d1_srtp.cc */, - OBJ_943 /* dtls_method.cc */, - OBJ_944 /* dtls_record.cc */, - OBJ_945 /* handshake.cc */, - OBJ_946 /* handshake_client.cc */, - OBJ_947 /* handshake_server.cc */, - OBJ_948 /* s3_both.cc */, - OBJ_949 /* s3_lib.cc */, - OBJ_950 /* s3_pkt.cc */, - OBJ_951 /* ssl_aead_ctx.cc */, - OBJ_952 /* ssl_asn1.cc */, - OBJ_953 /* ssl_buffer.cc */, - OBJ_954 /* ssl_cert.cc */, - OBJ_955 /* ssl_cipher.cc */, - OBJ_956 /* ssl_file.cc */, - OBJ_957 /* ssl_key_share.cc */, - OBJ_958 /* ssl_lib.cc */, - OBJ_959 /* ssl_privkey.cc */, - OBJ_960 /* ssl_session.cc */, - OBJ_961 /* ssl_stat.cc */, - OBJ_962 /* ssl_transcript.cc */, - OBJ_963 /* ssl_versions.cc */, - OBJ_964 /* ssl_x509.cc */, - OBJ_965 /* t1_enc.cc */, - OBJ_966 /* t1_lib.cc */, - OBJ_967 /* tls13_both.cc */, - OBJ_968 /* tls13_client.cc */, - OBJ_969 /* tls13_enc.cc */, - OBJ_970 /* tls13_server.cc */, - OBJ_971 /* tls_method.cc */, - OBJ_972 /* tls_record.cc */, + OBJ_93 /* dh */ = { + isa = PBXGroup; + children = ( + OBJ_94 /* check.c */, + OBJ_95 /* dh.c */, + OBJ_96 /* dh_asn1.c */, + OBJ_97 /* params.c */, ); - name = ssl; - path = ssl; + name = dh; + path = dh; sourceTree = ""; }; - OBJ_96 /* deadline */ = { + OBJ_931 /* include */ = { isa = PBXGroup; children = ( - OBJ_97 /* deadline_filter.cc */, + OBJ_932 /* pb_common.h */, + OBJ_933 /* cgrpc.h */, + OBJ_934 /* pb.h */, + OBJ_935 /* pb_encode.h */, + OBJ_936 /* pb_decode.h */, + OBJ_937 /* grpc */, + OBJ_994 /* module.modulemap */, ); - name = deadline; - path = deadline; + name = include; + path = include; sourceTree = ""; }; - OBJ_973 /* third_party */ = { + OBJ_937 /* grpc */ = { isa = PBXGroup; children = ( - OBJ_974 /* fiat */, + OBJ_938 /* grpc.h */, + OBJ_939 /* status.h */, + OBJ_940 /* census.h */, + OBJ_941 /* slice.h */, + OBJ_942 /* compression.h */, + OBJ_943 /* fork.h */, + OBJ_944 /* byte_buffer_reader.h */, + OBJ_945 /* grpc_security_constants.h */, + OBJ_946 /* byte_buffer.h */, + OBJ_947 /* slice_buffer.h */, + OBJ_948 /* grpc_posix.h */, + OBJ_949 /* grpc_security.h */, + OBJ_950 /* load_reporting.h */, + OBJ_951 /* support */, + OBJ_970 /* impl */, ); - name = third_party; - path = third_party; + name = grpc; + path = grpc; sourceTree = ""; }; - OBJ_974 /* fiat */ = { - isa = PBXGroup; - children = ( - OBJ_975 /* curve25519.c */, + OBJ_951 /* support */ = { + isa = PBXGroup; + children = ( + OBJ_952 /* time.h */, + OBJ_953 /* port_platform.h */, + OBJ_954 /* log_windows.h */, + OBJ_955 /* sync.h */, + OBJ_956 /* string_util.h */, + OBJ_957 /* sync_custom.h */, + OBJ_958 /* thd_id.h */, + OBJ_959 /* workaround_list.h */, + OBJ_960 /* atm_gcc_sync.h */, + OBJ_961 /* atm_gcc_atomic.h */, + OBJ_962 /* atm.h */, + OBJ_963 /* sync_generic.h */, + OBJ_964 /* log.h */, + OBJ_965 /* cpu.h */, + OBJ_966 /* sync_posix.h */, + OBJ_967 /* atm_windows.h */, + OBJ_968 /* sync_windows.h */, + OBJ_969 /* alloc.h */, ); - name = fiat; - path = fiat; + name = support; + path = support; sourceTree = ""; }; - OBJ_976 /* include */ = { + OBJ_970 /* impl */ = { isa = PBXGroup; children = ( - OBJ_977 /* openssl */, - OBJ_1051 /* module.modulemap */, + OBJ_971 /* codegen */, ); - name = include; - path = include; + name = impl; + path = impl; sourceTree = ""; }; - OBJ_977 /* openssl */ = { - isa = PBXGroup; - children = ( - OBJ_978 /* pem.h */, - OBJ_979 /* nid.h */, - OBJ_980 /* ssl3.h */, - OBJ_981 /* ossl_typ.h */, - OBJ_982 /* dtls1.h */, - OBJ_983 /* err.h */, - OBJ_984 /* bn.h */, - OBJ_985 /* blowfish.h */, - OBJ_986 /* engine.h */, - OBJ_987 /* bytestring.h */, - OBJ_988 /* x509.h */, - OBJ_989 /* asn1_mac.h */, - OBJ_990 /* pool.h */, - OBJ_991 /* ec_key.h */, - OBJ_992 /* base64.h */, - OBJ_993 /* is_boringssl.h */, - OBJ_994 /* sha.h */, - OBJ_995 /* asn1.h */, - OBJ_996 /* chacha.h */, - OBJ_997 /* opensslconf.h */, - OBJ_998 /* arm_arch.h */, - OBJ_999 /* bio.h */, - OBJ_1000 /* dh.h */, - OBJ_1001 /* digest.h */, - OBJ_1002 /* x509v3.h */, - OBJ_1003 /* conf.h */, - OBJ_1004 /* poly1305.h */, - OBJ_1005 /* hkdf.h */, - OBJ_1006 /* type_check.h */, - OBJ_1007 /* md5.h */, - OBJ_1008 /* x509_vfy.h */, - OBJ_1009 /* pkcs8.h */, - OBJ_1010 /* safestack.h */, - OBJ_1011 /* buf.h */, - OBJ_1012 /* obj.h */, - OBJ_1013 /* ecdsa.h */, - OBJ_1014 /* cipher.h */, - OBJ_1015 /* objects.h */, - OBJ_1016 /* pkcs12.h */, - OBJ_1017 /* crypto.h */, - OBJ_1018 /* opensslv.h */, - OBJ_1019 /* pkcs7.h */, - OBJ_1020 /* obj_mac.h */, - OBJ_1021 /* buffer.h */, - OBJ_1022 /* ssl.h */, - OBJ_1023 /* thread.h */, - OBJ_1024 /* evp.h */, - OBJ_1025 /* md4.h */, - OBJ_1026 /* hmac.h */, - OBJ_1027 /* aes.h */, - OBJ_1028 /* cast.h */, - OBJ_1029 /* rc4.h */, - OBJ_1030 /* cpu.h */, - OBJ_1031 /* stack.h */, - OBJ_1032 /* des.h */, - OBJ_1033 /* ec.h */, - OBJ_1034 /* ecdh.h */, - OBJ_1035 /* rand.h */, - OBJ_1036 /* aead.h */, - OBJ_1037 /* lhash_macros.h */, - OBJ_1038 /* span.h */, - OBJ_1039 /* rsa.h */, - OBJ_1040 /* mem.h */, - OBJ_1041 /* ripemd.h */, - OBJ_1042 /* curve25519.h */, - OBJ_1043 /* tls1.h */, - OBJ_1044 /* dsa.h */, - OBJ_1045 /* srtp.h */, - OBJ_1046 /* asn1t.h */, - OBJ_1047 /* cmac.h */, - OBJ_1048 /* lhash.h */, - OBJ_1049 /* ex_data.h */, - OBJ_1050 /* base.h */, + OBJ_971 /* codegen */ = { + isa = PBXGroup; + children = ( + OBJ_972 /* port_platform.h */, + OBJ_973 /* status.h */, + OBJ_974 /* gpr_types.h */, + OBJ_975 /* sync.h */, + OBJ_976 /* grpc_types.h */, + OBJ_977 /* sync_custom.h */, + OBJ_978 /* gpr_slice.h */, + OBJ_979 /* slice.h */, + OBJ_980 /* compression_types.h */, + OBJ_981 /* atm_gcc_sync.h */, + OBJ_982 /* atm_gcc_atomic.h */, + OBJ_983 /* atm.h */, + OBJ_984 /* sync_generic.h */, + OBJ_985 /* log.h */, + OBJ_986 /* fork.h */, + OBJ_987 /* byte_buffer_reader.h */, + OBJ_988 /* sync_posix.h */, + OBJ_989 /* atm_windows.h */, + OBJ_990 /* propagation_bits.h */, + OBJ_991 /* byte_buffer.h */, + OBJ_992 /* connectivity_state.h */, + OBJ_993 /* sync_windows.h */, ); - name = openssl; - path = openssl; + name = codegen; + path = codegen; sourceTree = ""; }; - OBJ_98 /* http */ = { + OBJ_98 /* digest_extra */ = { isa = PBXGroup; children = ( - OBJ_99 /* client */, - OBJ_101 /* client_authority_filter.cc */, - OBJ_102 /* http_filters_plugin.cc */, - OBJ_103 /* message_compress */, - OBJ_105 /* server */, + OBJ_99 /* digest_extra.c */, ); - name = http; - path = http; + name = digest_extra; + path = digest_extra; sourceTree = ""; }; - OBJ_99 /* client */ = { + OBJ_995 /* Echo */ = { isa = PBXGroup; children = ( - OBJ_100 /* http_client_filter.cc */, + OBJ_996 /* ssl.crt */, + OBJ_997 /* echo.proto */, + OBJ_998 /* Makefile */, + OBJ_999 /* RUNME */, + OBJ_1000 /* test.gold */, + OBJ_1001 /* README.md */, + OBJ_1002 /* ssl.key */, + OBJ_1003 /* EchoProvider.swift */, + OBJ_1004 /* Generated */, + OBJ_1007 /* main.swift */, ); - name = client; - path = client; - sourceTree = ""; + name = Echo; + path = Sources/Examples/Echo; + sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - F05C9863B4F72D3B3F9CC8AA /* Headers */ = { + 717BC585B88485C97A15AEA8 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 15DDE0819E918F1958E0892B /* cgrpc.h in Headers */, + 8C62FEC438C40E6C5D10918B /* cgrpc.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5440,10 +5696,10 @@ /* Begin PBXNativeTarget section */ SwiftGRPC::BoringSSL /* BoringSSL */ = { isa = PBXNativeTarget; - buildConfigurationList = OBJ_1402 /* Build configuration list for PBXNativeTarget "BoringSSL" */; + buildConfigurationList = OBJ_1474 /* Build configuration list for PBXNativeTarget "BoringSSL" */; buildPhases = ( - OBJ_1405 /* Sources */, - OBJ_1720 /* Frameworks */, + OBJ_1477 /* Sources */, + OBJ_1796 /* Frameworks */, ); buildRules = ( ); @@ -5456,16 +5712,16 @@ }; SwiftGRPC::CgRPC /* CgRPC */ = { isa = PBXNativeTarget; - buildConfigurationList = OBJ_1787 /* Build configuration list for PBXNativeTarget "CgRPC" */; + buildConfigurationList = OBJ_1863 /* Build configuration list for PBXNativeTarget "CgRPC" */; buildPhases = ( - OBJ_1790 /* Sources */, - OBJ_2145 /* Frameworks */, - F05C9863B4F72D3B3F9CC8AA /* Headers */, + OBJ_1866 /* Sources */, + OBJ_2245 /* Frameworks */, + 717BC585B88485C97A15AEA8 /* Headers */, ); buildRules = ( ); dependencies = ( - OBJ_2147 /* PBXTargetDependency */, + OBJ_2247 /* PBXTargetDependency */, ); name = CgRPC; productName = CgRPC; @@ -5474,17 +5730,17 @@ }; SwiftGRPC::SwiftGRPC /* SwiftGRPC */ = { isa = PBXNativeTarget; - buildConfigurationList = OBJ_2474 /* Build configuration list for PBXNativeTarget "SwiftGRPC" */; + buildConfigurationList = OBJ_2574 /* Build configuration list for PBXNativeTarget "SwiftGRPC" */; buildPhases = ( - OBJ_2477 /* Sources */, - OBJ_2514 /* Frameworks */, + OBJ_2577 /* Sources */, + OBJ_2614 /* Frameworks */, ); buildRules = ( ); dependencies = ( - OBJ_2518 /* PBXTargetDependency */, - OBJ_2519 /* PBXTargetDependency */, - OBJ_2520 /* PBXTargetDependency */, + OBJ_2618 /* PBXTargetDependency */, + OBJ_2619 /* PBXTargetDependency */, + OBJ_2620 /* PBXTargetDependency */, ); name = SwiftGRPC; productName = SwiftGRPC; @@ -5493,10 +5749,10 @@ }; SwiftProtobuf::SwiftProtobuf /* SwiftProtobuf */ = { isa = PBXNativeTarget; - buildConfigurationList = OBJ_2697 /* Build configuration list for PBXNativeTarget "SwiftProtobuf" */; + buildConfigurationList = OBJ_2797 /* Build configuration list for PBXNativeTarget "SwiftProtobuf" */; buildPhases = ( - OBJ_2700 /* Sources */, - OBJ_2778 /* Frameworks */, + OBJ_2800 /* Sources */, + OBJ_2878 /* Frameworks */, ); buildRules = ( ); @@ -5513,6 +5769,7 @@ OBJ_1 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftMigration = 9999; LastUpgradeCheck = 9999; }; buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "SwiftGRPC-Carthage" */; @@ -5523,7 +5780,7 @@ en, ); mainGroup = OBJ_5; - productRefGroup = OBJ_1371 /* Products */; + productRefGroup = OBJ_1426 /* Products */; projectDirPath = .; targets = ( SwiftGRPC::BoringSSL /* BoringSSL */, @@ -5535,830 +5792,858 @@ /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - OBJ_1405 /* Sources */ = { + OBJ_1477 /* Sources */ = { isa = PBXSourcesBuildPhase; files = ( - OBJ_1406 /* a_bitstr.c in Sources */, - OBJ_1407 /* a_bool.c in Sources */, - OBJ_1408 /* a_d2i_fp.c in Sources */, - OBJ_1409 /* a_dup.c in Sources */, - OBJ_1410 /* a_enum.c in Sources */, - OBJ_1411 /* a_gentm.c in Sources */, - OBJ_1412 /* a_i2d_fp.c in Sources */, - OBJ_1413 /* a_int.c in Sources */, - OBJ_1414 /* a_mbstr.c in Sources */, - OBJ_1415 /* a_object.c in Sources */, - OBJ_1416 /* a_octet.c in Sources */, - OBJ_1417 /* a_print.c in Sources */, - OBJ_1418 /* a_strnid.c in Sources */, - OBJ_1419 /* a_time.c in Sources */, - OBJ_1420 /* a_type.c in Sources */, - OBJ_1421 /* a_utctm.c in Sources */, - OBJ_1422 /* a_utf8.c in Sources */, - OBJ_1423 /* asn1_lib.c in Sources */, - OBJ_1424 /* asn1_par.c in Sources */, - OBJ_1425 /* asn_pack.c in Sources */, - OBJ_1426 /* f_enum.c in Sources */, - OBJ_1427 /* f_int.c in Sources */, - OBJ_1428 /* f_string.c in Sources */, - OBJ_1429 /* tasn_dec.c in Sources */, - OBJ_1430 /* tasn_enc.c in Sources */, - OBJ_1431 /* tasn_fre.c in Sources */, - OBJ_1432 /* tasn_new.c in Sources */, - OBJ_1433 /* tasn_typ.c in Sources */, - OBJ_1434 /* tasn_utl.c in Sources */, - OBJ_1435 /* time_support.c in Sources */, - OBJ_1436 /* base64.c in Sources */, - OBJ_1437 /* bio.c in Sources */, - OBJ_1438 /* bio_mem.c in Sources */, - OBJ_1439 /* connect.c in Sources */, - OBJ_1440 /* fd.c in Sources */, - OBJ_1441 /* file.c in Sources */, - OBJ_1442 /* hexdump.c in Sources */, - OBJ_1443 /* pair.c in Sources */, - OBJ_1444 /* printf.c in Sources */, - OBJ_1445 /* socket.c in Sources */, - OBJ_1446 /* socket_helper.c in Sources */, - OBJ_1447 /* bn_asn1.c in Sources */, - OBJ_1448 /* convert.c in Sources */, - OBJ_1449 /* buf.c in Sources */, - OBJ_1450 /* asn1_compat.c in Sources */, - OBJ_1451 /* ber.c in Sources */, - OBJ_1452 /* cbb.c in Sources */, - OBJ_1453 /* cbs.c in Sources */, - OBJ_1454 /* chacha.c in Sources */, - OBJ_1455 /* cipher_extra.c in Sources */, - OBJ_1456 /* derive_key.c in Sources */, - OBJ_1457 /* e_aesctrhmac.c in Sources */, - OBJ_1458 /* e_aesgcmsiv.c in Sources */, - OBJ_1459 /* e_chacha20poly1305.c in Sources */, - OBJ_1460 /* e_null.c in Sources */, - OBJ_1461 /* e_rc2.c in Sources */, - OBJ_1462 /* e_rc4.c in Sources */, - OBJ_1463 /* e_ssl3.c in Sources */, - OBJ_1464 /* e_tls.c in Sources */, - OBJ_1465 /* tls_cbc.c in Sources */, - OBJ_1466 /* cmac.c in Sources */, - OBJ_1467 /* conf.c in Sources */, - OBJ_1468 /* cpu-aarch64-linux.c in Sources */, - OBJ_1469 /* cpu-arm-linux.c in Sources */, - OBJ_1470 /* cpu-arm.c in Sources */, - OBJ_1471 /* cpu-intel.c in Sources */, - OBJ_1472 /* cpu-ppc64le.c in Sources */, - OBJ_1473 /* crypto.c in Sources */, - OBJ_1474 /* spake25519.c in Sources */, - OBJ_1475 /* x25519-x86_64.c in Sources */, - OBJ_1476 /* check.c in Sources */, - OBJ_1477 /* dh.c in Sources */, - OBJ_1478 /* dh_asn1.c in Sources */, - OBJ_1479 /* params.c in Sources */, - OBJ_1480 /* digest_extra.c in Sources */, - OBJ_1481 /* dsa.c in Sources */, - OBJ_1482 /* dsa_asn1.c in Sources */, - OBJ_1483 /* ec_asn1.c in Sources */, - OBJ_1484 /* ecdh.c in Sources */, - OBJ_1485 /* ecdsa_asn1.c in Sources */, - OBJ_1486 /* engine.c in Sources */, - OBJ_1487 /* err.c in Sources */, - OBJ_1488 /* err_data.c in Sources */, - OBJ_1489 /* digestsign.c in Sources */, - OBJ_1490 /* evp.c in Sources */, - OBJ_1491 /* evp_asn1.c in Sources */, - OBJ_1492 /* evp_ctx.c in Sources */, - OBJ_1493 /* p_dsa_asn1.c in Sources */, - OBJ_1494 /* p_ec.c in Sources */, - OBJ_1495 /* p_ec_asn1.c in Sources */, - OBJ_1496 /* p_ed25519.c in Sources */, - OBJ_1497 /* p_ed25519_asn1.c in Sources */, - OBJ_1498 /* p_rsa.c in Sources */, - OBJ_1499 /* p_rsa_asn1.c in Sources */, - OBJ_1500 /* pbkdf.c in Sources */, - OBJ_1501 /* print.c in Sources */, - OBJ_1502 /* scrypt.c in Sources */, - OBJ_1503 /* sign.c in Sources */, - OBJ_1504 /* ex_data.c in Sources */, - OBJ_1505 /* aes.c in Sources */, - OBJ_1506 /* key_wrap.c in Sources */, - OBJ_1507 /* mode_wrappers.c in Sources */, - OBJ_1508 /* add.c in Sources */, - OBJ_1509 /* bn.c in Sources */, - OBJ_1510 /* bytes.c in Sources */, - OBJ_1511 /* cmp.c in Sources */, - OBJ_1512 /* ctx.c in Sources */, - OBJ_1513 /* div.c in Sources */, - OBJ_1514 /* exponentiation.c in Sources */, - OBJ_1515 /* gcd.c in Sources */, - OBJ_1516 /* generic.c in Sources */, - OBJ_1517 /* jacobi.c in Sources */, - OBJ_1518 /* montgomery.c in Sources */, - OBJ_1519 /* montgomery_inv.c in Sources */, - OBJ_1520 /* mul.c in Sources */, - OBJ_1521 /* prime.c in Sources */, - OBJ_1522 /* random.c in Sources */, - OBJ_1523 /* rsaz_exp.c in Sources */, - OBJ_1524 /* shift.c in Sources */, - OBJ_1525 /* sqrt.c in Sources */, - OBJ_1526 /* aead.c in Sources */, - OBJ_1527 /* cipher.c in Sources */, - OBJ_1528 /* e_aes.c in Sources */, - OBJ_1529 /* e_des.c in Sources */, - OBJ_1530 /* des.c in Sources */, - OBJ_1531 /* digest.c in Sources */, - OBJ_1532 /* digests.c in Sources */, - OBJ_1533 /* ec.c in Sources */, - OBJ_1534 /* ec_key.c in Sources */, - OBJ_1535 /* ec_montgomery.c in Sources */, - OBJ_1536 /* oct.c in Sources */, - OBJ_1537 /* p224-64.c in Sources */, - OBJ_1538 /* p256-64.c in Sources */, - OBJ_1539 /* p256-x86_64.c in Sources */, - OBJ_1540 /* simple.c in Sources */, - OBJ_1541 /* util-64.c in Sources */, - OBJ_1542 /* wnaf.c in Sources */, - OBJ_1543 /* ecdsa.c in Sources */, - OBJ_1544 /* hmac.c in Sources */, - OBJ_1545 /* is_fips.c in Sources */, - OBJ_1546 /* md4.c in Sources */, - OBJ_1547 /* md5.c in Sources */, - OBJ_1548 /* cbc.c in Sources */, - OBJ_1549 /* cfb.c in Sources */, - OBJ_1550 /* ctr.c in Sources */, - OBJ_1551 /* gcm.c in Sources */, - OBJ_1552 /* ofb.c in Sources */, - OBJ_1553 /* polyval.c in Sources */, - OBJ_1554 /* ctrdrbg.c in Sources */, - OBJ_1555 /* rand.c in Sources */, - OBJ_1556 /* urandom.c in Sources */, - OBJ_1557 /* blinding.c in Sources */, - OBJ_1558 /* padding.c in Sources */, - OBJ_1559 /* rsa.c in Sources */, - OBJ_1560 /* rsa_impl.c in Sources */, - OBJ_1561 /* sha1-altivec.c in Sources */, - OBJ_1562 /* sha1.c in Sources */, - OBJ_1563 /* sha256.c in Sources */, - OBJ_1564 /* sha512.c in Sources */, - OBJ_1565 /* hkdf.c in Sources */, - OBJ_1566 /* lhash.c in Sources */, - OBJ_1567 /* mem.c in Sources */, - OBJ_1568 /* obj.c in Sources */, - OBJ_1569 /* obj_xref.c in Sources */, - OBJ_1570 /* pem_all.c in Sources */, - OBJ_1571 /* pem_info.c in Sources */, - OBJ_1572 /* pem_lib.c in Sources */, - OBJ_1573 /* pem_oth.c in Sources */, - OBJ_1574 /* pem_pk8.c in Sources */, - OBJ_1575 /* pem_pkey.c in Sources */, - OBJ_1576 /* pem_x509.c in Sources */, - OBJ_1577 /* pem_xaux.c in Sources */, - OBJ_1578 /* pkcs7.c in Sources */, - OBJ_1579 /* pkcs7_x509.c in Sources */, - OBJ_1580 /* p5_pbev2.c in Sources */, - OBJ_1581 /* pkcs8.c in Sources */, - OBJ_1582 /* pkcs8_x509.c in Sources */, - OBJ_1583 /* poly1305.c in Sources */, - OBJ_1584 /* poly1305_arm.c in Sources */, - OBJ_1585 /* poly1305_vec.c in Sources */, - OBJ_1586 /* pool.c in Sources */, - OBJ_1587 /* deterministic.c in Sources */, - OBJ_1588 /* forkunsafe.c in Sources */, - OBJ_1589 /* fuchsia.c in Sources */, - OBJ_1590 /* rand_extra.c in Sources */, - OBJ_1591 /* windows.c in Sources */, - OBJ_1592 /* rc4.c in Sources */, - OBJ_1593 /* refcount_c11.c in Sources */, - OBJ_1594 /* refcount_lock.c in Sources */, - OBJ_1595 /* rsa_asn1.c in Sources */, - OBJ_1596 /* stack.c in Sources */, - OBJ_1597 /* thread.c in Sources */, - OBJ_1598 /* thread_none.c in Sources */, - OBJ_1599 /* thread_pthread.c in Sources */, - OBJ_1600 /* thread_win.c in Sources */, - OBJ_1601 /* a_digest.c in Sources */, - OBJ_1602 /* a_sign.c in Sources */, - OBJ_1603 /* a_strex.c in Sources */, - OBJ_1604 /* a_verify.c in Sources */, - OBJ_1605 /* algorithm.c in Sources */, - OBJ_1606 /* asn1_gen.c in Sources */, - OBJ_1607 /* by_dir.c in Sources */, - OBJ_1608 /* by_file.c in Sources */, - OBJ_1609 /* i2d_pr.c in Sources */, - OBJ_1610 /* rsa_pss.c in Sources */, - OBJ_1611 /* t_crl.c in Sources */, - OBJ_1612 /* t_req.c in Sources */, - OBJ_1613 /* t_x509.c in Sources */, - OBJ_1614 /* t_x509a.c in Sources */, - OBJ_1615 /* x509.c in Sources */, - OBJ_1616 /* x509_att.c in Sources */, - OBJ_1617 /* x509_cmp.c in Sources */, - OBJ_1618 /* x509_d2.c in Sources */, - OBJ_1619 /* x509_def.c in Sources */, - OBJ_1620 /* x509_ext.c in Sources */, - OBJ_1621 /* x509_lu.c in Sources */, - OBJ_1622 /* x509_obj.c in Sources */, - OBJ_1623 /* x509_r2x.c in Sources */, - OBJ_1624 /* x509_req.c in Sources */, - OBJ_1625 /* x509_set.c in Sources */, - OBJ_1626 /* x509_trs.c in Sources */, - OBJ_1627 /* x509_txt.c in Sources */, - OBJ_1628 /* x509_v3.c in Sources */, - OBJ_1629 /* x509_vfy.c in Sources */, - OBJ_1630 /* x509_vpm.c in Sources */, - OBJ_1631 /* x509cset.c in Sources */, - OBJ_1632 /* x509name.c in Sources */, - OBJ_1633 /* x509rset.c in Sources */, - OBJ_1634 /* x509spki.c in Sources */, - OBJ_1635 /* x_algor.c in Sources */, - OBJ_1636 /* x_all.c in Sources */, - OBJ_1637 /* x_attrib.c in Sources */, - OBJ_1638 /* x_crl.c in Sources */, - OBJ_1639 /* x_exten.c in Sources */, - OBJ_1640 /* x_info.c in Sources */, - OBJ_1641 /* x_name.c in Sources */, - OBJ_1642 /* x_pkey.c in Sources */, - OBJ_1643 /* x_pubkey.c in Sources */, - OBJ_1644 /* x_req.c in Sources */, - OBJ_1645 /* x_sig.c in Sources */, - OBJ_1646 /* x_spki.c in Sources */, - OBJ_1647 /* x_val.c in Sources */, - OBJ_1648 /* x_x509.c in Sources */, - OBJ_1649 /* x_x509a.c in Sources */, - OBJ_1650 /* pcy_cache.c in Sources */, - OBJ_1651 /* pcy_data.c in Sources */, - OBJ_1652 /* pcy_lib.c in Sources */, - OBJ_1653 /* pcy_map.c in Sources */, - OBJ_1654 /* pcy_node.c in Sources */, - OBJ_1655 /* pcy_tree.c in Sources */, - OBJ_1656 /* v3_akey.c in Sources */, - OBJ_1657 /* v3_akeya.c in Sources */, - OBJ_1658 /* v3_alt.c in Sources */, - OBJ_1659 /* v3_bcons.c in Sources */, - OBJ_1660 /* v3_bitst.c in Sources */, - OBJ_1661 /* v3_conf.c in Sources */, - OBJ_1662 /* v3_cpols.c in Sources */, - OBJ_1663 /* v3_crld.c in Sources */, - OBJ_1664 /* v3_enum.c in Sources */, - OBJ_1665 /* v3_extku.c in Sources */, - OBJ_1666 /* v3_genn.c in Sources */, - OBJ_1667 /* v3_ia5.c in Sources */, - OBJ_1668 /* v3_info.c in Sources */, - OBJ_1669 /* v3_int.c in Sources */, - OBJ_1670 /* v3_lib.c in Sources */, - OBJ_1671 /* v3_ncons.c in Sources */, - OBJ_1672 /* v3_pci.c in Sources */, - OBJ_1673 /* v3_pcia.c in Sources */, - OBJ_1674 /* v3_pcons.c in Sources */, - OBJ_1675 /* v3_pku.c in Sources */, - OBJ_1676 /* v3_pmaps.c in Sources */, - OBJ_1677 /* v3_prn.c in Sources */, - OBJ_1678 /* v3_purp.c in Sources */, - OBJ_1679 /* v3_skey.c in Sources */, - OBJ_1680 /* v3_sxnet.c in Sources */, - OBJ_1681 /* v3_utl.c in Sources */, - OBJ_1682 /* err_data.c in Sources */, - OBJ_1683 /* bio_ssl.cc in Sources */, - OBJ_1684 /* custom_extensions.cc in Sources */, - OBJ_1685 /* d1_both.cc in Sources */, - OBJ_1686 /* d1_lib.cc in Sources */, - OBJ_1687 /* d1_pkt.cc in Sources */, - OBJ_1688 /* d1_srtp.cc in Sources */, - OBJ_1689 /* dtls_method.cc in Sources */, - OBJ_1690 /* dtls_record.cc in Sources */, - OBJ_1691 /* handshake.cc in Sources */, - OBJ_1692 /* handshake_client.cc in Sources */, - OBJ_1693 /* handshake_server.cc in Sources */, - OBJ_1694 /* s3_both.cc in Sources */, - OBJ_1695 /* s3_lib.cc in Sources */, - OBJ_1696 /* s3_pkt.cc in Sources */, - OBJ_1697 /* ssl_aead_ctx.cc in Sources */, - OBJ_1698 /* ssl_asn1.cc in Sources */, - OBJ_1699 /* ssl_buffer.cc in Sources */, - OBJ_1700 /* ssl_cert.cc in Sources */, - OBJ_1701 /* ssl_cipher.cc in Sources */, - OBJ_1702 /* ssl_file.cc in Sources */, - OBJ_1703 /* ssl_key_share.cc in Sources */, - OBJ_1704 /* ssl_lib.cc in Sources */, - OBJ_1705 /* ssl_privkey.cc in Sources */, - OBJ_1706 /* ssl_session.cc in Sources */, - OBJ_1707 /* ssl_stat.cc in Sources */, - OBJ_1708 /* ssl_transcript.cc in Sources */, - OBJ_1709 /* ssl_versions.cc in Sources */, - OBJ_1710 /* ssl_x509.cc in Sources */, - OBJ_1711 /* t1_enc.cc in Sources */, - OBJ_1712 /* t1_lib.cc in Sources */, - OBJ_1713 /* tls13_both.cc in Sources */, - OBJ_1714 /* tls13_client.cc in Sources */, - OBJ_1715 /* tls13_enc.cc in Sources */, - OBJ_1716 /* tls13_server.cc in Sources */, - OBJ_1717 /* tls_method.cc in Sources */, - OBJ_1718 /* tls_record.cc in Sources */, - OBJ_1719 /* curve25519.c in Sources */, - ); - }; - OBJ_1790 /* Sources */ = { + OBJ_1478 /* a_bitstr.c in Sources */, + OBJ_1479 /* a_bool.c in Sources */, + OBJ_1480 /* a_d2i_fp.c in Sources */, + OBJ_1481 /* a_dup.c in Sources */, + OBJ_1482 /* a_enum.c in Sources */, + OBJ_1483 /* a_gentm.c in Sources */, + OBJ_1484 /* a_i2d_fp.c in Sources */, + OBJ_1485 /* a_int.c in Sources */, + OBJ_1486 /* a_mbstr.c in Sources */, + OBJ_1487 /* a_object.c in Sources */, + OBJ_1488 /* a_octet.c in Sources */, + OBJ_1489 /* a_print.c in Sources */, + OBJ_1490 /* a_strnid.c in Sources */, + OBJ_1491 /* a_time.c in Sources */, + OBJ_1492 /* a_type.c in Sources */, + OBJ_1493 /* a_utctm.c in Sources */, + OBJ_1494 /* a_utf8.c in Sources */, + OBJ_1495 /* asn1_lib.c in Sources */, + OBJ_1496 /* asn1_par.c in Sources */, + OBJ_1497 /* asn_pack.c in Sources */, + OBJ_1498 /* f_enum.c in Sources */, + OBJ_1499 /* f_int.c in Sources */, + OBJ_1500 /* f_string.c in Sources */, + OBJ_1501 /* tasn_dec.c in Sources */, + OBJ_1502 /* tasn_enc.c in Sources */, + OBJ_1503 /* tasn_fre.c in Sources */, + OBJ_1504 /* tasn_new.c in Sources */, + OBJ_1505 /* tasn_typ.c in Sources */, + OBJ_1506 /* tasn_utl.c in Sources */, + OBJ_1507 /* time_support.c in Sources */, + OBJ_1508 /* base64.c in Sources */, + OBJ_1509 /* bio.c in Sources */, + OBJ_1510 /* bio_mem.c in Sources */, + OBJ_1511 /* connect.c in Sources */, + OBJ_1512 /* fd.c in Sources */, + OBJ_1513 /* file.c in Sources */, + OBJ_1514 /* hexdump.c in Sources */, + OBJ_1515 /* pair.c in Sources */, + OBJ_1516 /* printf.c in Sources */, + OBJ_1517 /* socket.c in Sources */, + OBJ_1518 /* socket_helper.c in Sources */, + OBJ_1519 /* bn_asn1.c in Sources */, + OBJ_1520 /* convert.c in Sources */, + OBJ_1521 /* buf.c in Sources */, + OBJ_1522 /* asn1_compat.c in Sources */, + OBJ_1523 /* ber.c in Sources */, + OBJ_1524 /* cbb.c in Sources */, + OBJ_1525 /* cbs.c in Sources */, + OBJ_1526 /* chacha.c in Sources */, + OBJ_1527 /* cipher_extra.c in Sources */, + OBJ_1528 /* derive_key.c in Sources */, + OBJ_1529 /* e_aesccm.c in Sources */, + OBJ_1530 /* e_aesctrhmac.c in Sources */, + OBJ_1531 /* e_aesgcmsiv.c in Sources */, + OBJ_1532 /* e_chacha20poly1305.c in Sources */, + OBJ_1533 /* e_null.c in Sources */, + OBJ_1534 /* e_rc2.c in Sources */, + OBJ_1535 /* e_rc4.c in Sources */, + OBJ_1536 /* e_ssl3.c in Sources */, + OBJ_1537 /* e_tls.c in Sources */, + OBJ_1538 /* tls_cbc.c in Sources */, + OBJ_1539 /* cmac.c in Sources */, + OBJ_1540 /* conf.c in Sources */, + OBJ_1541 /* cpu-aarch64-fuchsia.c in Sources */, + OBJ_1542 /* cpu-aarch64-linux.c in Sources */, + OBJ_1543 /* cpu-arm-linux.c in Sources */, + OBJ_1544 /* cpu-arm.c in Sources */, + OBJ_1545 /* cpu-intel.c in Sources */, + OBJ_1546 /* cpu-ppc64le.c in Sources */, + OBJ_1547 /* crypto.c in Sources */, + OBJ_1548 /* spake25519.c in Sources */, + OBJ_1549 /* check.c in Sources */, + OBJ_1550 /* dh.c in Sources */, + OBJ_1551 /* dh_asn1.c in Sources */, + OBJ_1552 /* params.c in Sources */, + OBJ_1553 /* digest_extra.c in Sources */, + OBJ_1554 /* dsa.c in Sources */, + OBJ_1555 /* dsa_asn1.c in Sources */, + OBJ_1556 /* ec_asn1.c in Sources */, + OBJ_1557 /* ecdh.c in Sources */, + OBJ_1558 /* ecdsa_asn1.c in Sources */, + OBJ_1559 /* engine.c in Sources */, + OBJ_1560 /* err.c in Sources */, + OBJ_1561 /* err_data.c in Sources */, + OBJ_1562 /* digestsign.c in Sources */, + OBJ_1563 /* evp.c in Sources */, + OBJ_1564 /* evp_asn1.c in Sources */, + OBJ_1565 /* evp_ctx.c in Sources */, + OBJ_1566 /* p_dsa_asn1.c in Sources */, + OBJ_1567 /* p_ec.c in Sources */, + OBJ_1568 /* p_ec_asn1.c in Sources */, + OBJ_1569 /* p_ed25519.c in Sources */, + OBJ_1570 /* p_ed25519_asn1.c in Sources */, + OBJ_1571 /* p_rsa.c in Sources */, + OBJ_1572 /* p_rsa_asn1.c in Sources */, + OBJ_1573 /* pbkdf.c in Sources */, + OBJ_1574 /* print.c in Sources */, + OBJ_1575 /* scrypt.c in Sources */, + OBJ_1576 /* sign.c in Sources */, + OBJ_1577 /* ex_data.c in Sources */, + OBJ_1578 /* aes.c in Sources */, + OBJ_1579 /* key_wrap.c in Sources */, + OBJ_1580 /* mode_wrappers.c in Sources */, + OBJ_1581 /* add.c in Sources */, + OBJ_1582 /* bn.c in Sources */, + OBJ_1583 /* bytes.c in Sources */, + OBJ_1584 /* cmp.c in Sources */, + OBJ_1585 /* ctx.c in Sources */, + OBJ_1586 /* div.c in Sources */, + OBJ_1587 /* exponentiation.c in Sources */, + OBJ_1588 /* gcd.c in Sources */, + OBJ_1589 /* generic.c in Sources */, + OBJ_1590 /* jacobi.c in Sources */, + OBJ_1591 /* montgomery.c in Sources */, + OBJ_1592 /* montgomery_inv.c in Sources */, + OBJ_1593 /* mul.c in Sources */, + OBJ_1594 /* prime.c in Sources */, + OBJ_1595 /* random.c in Sources */, + OBJ_1596 /* rsaz_exp.c in Sources */, + OBJ_1597 /* shift.c in Sources */, + OBJ_1598 /* sqrt.c in Sources */, + OBJ_1599 /* aead.c in Sources */, + OBJ_1600 /* cipher.c in Sources */, + OBJ_1601 /* e_aes.c in Sources */, + OBJ_1602 /* e_des.c in Sources */, + OBJ_1603 /* des.c in Sources */, + OBJ_1604 /* digest.c in Sources */, + OBJ_1605 /* digests.c in Sources */, + OBJ_1606 /* ec.c in Sources */, + OBJ_1607 /* ec_key.c in Sources */, + OBJ_1608 /* ec_montgomery.c in Sources */, + OBJ_1609 /* oct.c in Sources */, + OBJ_1610 /* p224-64.c in Sources */, + OBJ_1611 /* p256-x86_64.c in Sources */, + OBJ_1612 /* simple.c in Sources */, + OBJ_1613 /* util.c in Sources */, + OBJ_1614 /* wnaf.c in Sources */, + OBJ_1615 /* ecdsa.c in Sources */, + OBJ_1616 /* hmac.c in Sources */, + OBJ_1617 /* is_fips.c in Sources */, + OBJ_1618 /* md4.c in Sources */, + OBJ_1619 /* md5.c in Sources */, + OBJ_1620 /* cbc.c in Sources */, + OBJ_1621 /* ccm.c in Sources */, + OBJ_1622 /* cfb.c in Sources */, + OBJ_1623 /* ctr.c in Sources */, + OBJ_1624 /* gcm.c in Sources */, + OBJ_1625 /* ofb.c in Sources */, + OBJ_1626 /* polyval.c in Sources */, + OBJ_1627 /* ctrdrbg.c in Sources */, + OBJ_1628 /* rand.c in Sources */, + OBJ_1629 /* urandom.c in Sources */, + OBJ_1630 /* blinding.c in Sources */, + OBJ_1631 /* padding.c in Sources */, + OBJ_1632 /* rsa.c in Sources */, + OBJ_1633 /* rsa_impl.c in Sources */, + OBJ_1634 /* self_check.c in Sources */, + OBJ_1635 /* sha1-altivec.c in Sources */, + OBJ_1636 /* sha1.c in Sources */, + OBJ_1637 /* sha256.c in Sources */, + OBJ_1638 /* sha512.c in Sources */, + OBJ_1639 /* kdf.c in Sources */, + OBJ_1640 /* hkdf.c in Sources */, + OBJ_1641 /* lhash.c in Sources */, + OBJ_1642 /* mem.c in Sources */, + OBJ_1643 /* obj.c in Sources */, + OBJ_1644 /* obj_xref.c in Sources */, + OBJ_1645 /* pem_all.c in Sources */, + OBJ_1646 /* pem_info.c in Sources */, + OBJ_1647 /* pem_lib.c in Sources */, + OBJ_1648 /* pem_oth.c in Sources */, + OBJ_1649 /* pem_pk8.c in Sources */, + OBJ_1650 /* pem_pkey.c in Sources */, + OBJ_1651 /* pem_x509.c in Sources */, + OBJ_1652 /* pem_xaux.c in Sources */, + OBJ_1653 /* pkcs7.c in Sources */, + OBJ_1654 /* pkcs7_x509.c in Sources */, + OBJ_1655 /* p5_pbev2.c in Sources */, + OBJ_1656 /* pkcs8.c in Sources */, + OBJ_1657 /* pkcs8_x509.c in Sources */, + OBJ_1658 /* poly1305.c in Sources */, + OBJ_1659 /* poly1305_arm.c in Sources */, + OBJ_1660 /* poly1305_vec.c in Sources */, + OBJ_1661 /* pool.c in Sources */, + OBJ_1662 /* deterministic.c in Sources */, + OBJ_1663 /* forkunsafe.c in Sources */, + OBJ_1664 /* fuchsia.c in Sources */, + OBJ_1665 /* rand_extra.c in Sources */, + OBJ_1666 /* windows.c in Sources */, + OBJ_1667 /* rc4.c in Sources */, + OBJ_1668 /* refcount_c11.c in Sources */, + OBJ_1669 /* refcount_lock.c in Sources */, + OBJ_1670 /* rsa_asn1.c in Sources */, + OBJ_1671 /* stack.c in Sources */, + OBJ_1672 /* thread.c in Sources */, + OBJ_1673 /* thread_none.c in Sources */, + OBJ_1674 /* thread_pthread.c in Sources */, + OBJ_1675 /* thread_win.c in Sources */, + OBJ_1676 /* a_digest.c in Sources */, + OBJ_1677 /* a_sign.c in Sources */, + OBJ_1678 /* a_strex.c in Sources */, + OBJ_1679 /* a_verify.c in Sources */, + OBJ_1680 /* algorithm.c in Sources */, + OBJ_1681 /* asn1_gen.c in Sources */, + OBJ_1682 /* by_dir.c in Sources */, + OBJ_1683 /* by_file.c in Sources */, + OBJ_1684 /* i2d_pr.c in Sources */, + OBJ_1685 /* rsa_pss.c in Sources */, + OBJ_1686 /* t_crl.c in Sources */, + OBJ_1687 /* t_req.c in Sources */, + OBJ_1688 /* t_x509.c in Sources */, + OBJ_1689 /* t_x509a.c in Sources */, + OBJ_1690 /* x509.c in Sources */, + OBJ_1691 /* x509_att.c in Sources */, + OBJ_1692 /* x509_cmp.c in Sources */, + OBJ_1693 /* x509_d2.c in Sources */, + OBJ_1694 /* x509_def.c in Sources */, + OBJ_1695 /* x509_ext.c in Sources */, + OBJ_1696 /* x509_lu.c in Sources */, + OBJ_1697 /* x509_obj.c in Sources */, + OBJ_1698 /* x509_r2x.c in Sources */, + OBJ_1699 /* x509_req.c in Sources */, + OBJ_1700 /* x509_set.c in Sources */, + OBJ_1701 /* x509_trs.c in Sources */, + OBJ_1702 /* x509_txt.c in Sources */, + OBJ_1703 /* x509_v3.c in Sources */, + OBJ_1704 /* x509_vfy.c in Sources */, + OBJ_1705 /* x509_vpm.c in Sources */, + OBJ_1706 /* x509cset.c in Sources */, + OBJ_1707 /* x509name.c in Sources */, + OBJ_1708 /* x509rset.c in Sources */, + OBJ_1709 /* x509spki.c in Sources */, + OBJ_1710 /* x_algor.c in Sources */, + OBJ_1711 /* x_all.c in Sources */, + OBJ_1712 /* x_attrib.c in Sources */, + OBJ_1713 /* x_crl.c in Sources */, + OBJ_1714 /* x_exten.c in Sources */, + OBJ_1715 /* x_info.c in Sources */, + OBJ_1716 /* x_name.c in Sources */, + OBJ_1717 /* x_pkey.c in Sources */, + OBJ_1718 /* x_pubkey.c in Sources */, + OBJ_1719 /* x_req.c in Sources */, + OBJ_1720 /* x_sig.c in Sources */, + OBJ_1721 /* x_spki.c in Sources */, + OBJ_1722 /* x_val.c in Sources */, + OBJ_1723 /* x_x509.c in Sources */, + OBJ_1724 /* x_x509a.c in Sources */, + OBJ_1725 /* pcy_cache.c in Sources */, + OBJ_1726 /* pcy_data.c in Sources */, + OBJ_1727 /* pcy_lib.c in Sources */, + OBJ_1728 /* pcy_map.c in Sources */, + OBJ_1729 /* pcy_node.c in Sources */, + OBJ_1730 /* pcy_tree.c in Sources */, + OBJ_1731 /* v3_akey.c in Sources */, + OBJ_1732 /* v3_akeya.c in Sources */, + OBJ_1733 /* v3_alt.c in Sources */, + OBJ_1734 /* v3_bcons.c in Sources */, + OBJ_1735 /* v3_bitst.c in Sources */, + OBJ_1736 /* v3_conf.c in Sources */, + OBJ_1737 /* v3_cpols.c in Sources */, + OBJ_1738 /* v3_crld.c in Sources */, + OBJ_1739 /* v3_enum.c in Sources */, + OBJ_1740 /* v3_extku.c in Sources */, + OBJ_1741 /* v3_genn.c in Sources */, + OBJ_1742 /* v3_ia5.c in Sources */, + OBJ_1743 /* v3_info.c in Sources */, + OBJ_1744 /* v3_int.c in Sources */, + OBJ_1745 /* v3_lib.c in Sources */, + OBJ_1746 /* v3_ncons.c in Sources */, + OBJ_1747 /* v3_pci.c in Sources */, + OBJ_1748 /* v3_pcia.c in Sources */, + OBJ_1749 /* v3_pcons.c in Sources */, + OBJ_1750 /* v3_pku.c in Sources */, + OBJ_1751 /* v3_pmaps.c in Sources */, + OBJ_1752 /* v3_prn.c in Sources */, + OBJ_1753 /* v3_purp.c in Sources */, + OBJ_1754 /* v3_skey.c in Sources */, + OBJ_1755 /* v3_sxnet.c in Sources */, + OBJ_1756 /* v3_utl.c in Sources */, + OBJ_1757 /* bio_ssl.cc in Sources */, + OBJ_1758 /* custom_extensions.cc in Sources */, + OBJ_1759 /* d1_both.cc in Sources */, + OBJ_1760 /* d1_lib.cc in Sources */, + OBJ_1761 /* d1_pkt.cc in Sources */, + OBJ_1762 /* d1_srtp.cc in Sources */, + OBJ_1763 /* dtls_method.cc in Sources */, + OBJ_1764 /* dtls_record.cc in Sources */, + OBJ_1765 /* handoff.cc in Sources */, + OBJ_1766 /* handshake.cc in Sources */, + OBJ_1767 /* handshake_client.cc in Sources */, + OBJ_1768 /* handshake_server.cc in Sources */, + OBJ_1769 /* s3_both.cc in Sources */, + OBJ_1770 /* s3_lib.cc in Sources */, + OBJ_1771 /* s3_pkt.cc in Sources */, + OBJ_1772 /* ssl_aead_ctx.cc in Sources */, + OBJ_1773 /* ssl_asn1.cc in Sources */, + OBJ_1774 /* ssl_buffer.cc in Sources */, + OBJ_1775 /* ssl_cert.cc in Sources */, + OBJ_1776 /* ssl_cipher.cc in Sources */, + OBJ_1777 /* ssl_file.cc in Sources */, + OBJ_1778 /* ssl_key_share.cc in Sources */, + OBJ_1779 /* ssl_lib.cc in Sources */, + OBJ_1780 /* ssl_privkey.cc in Sources */, + OBJ_1781 /* ssl_session.cc in Sources */, + OBJ_1782 /* ssl_stat.cc in Sources */, + OBJ_1783 /* ssl_transcript.cc in Sources */, + OBJ_1784 /* ssl_versions.cc in Sources */, + OBJ_1785 /* ssl_x509.cc in Sources */, + OBJ_1786 /* t1_enc.cc in Sources */, + OBJ_1787 /* t1_lib.cc in Sources */, + OBJ_1788 /* tls13_both.cc in Sources */, + OBJ_1789 /* tls13_client.cc in Sources */, + OBJ_1790 /* tls13_enc.cc in Sources */, + OBJ_1791 /* tls13_server.cc in Sources */, + OBJ_1792 /* tls_method.cc in Sources */, + OBJ_1793 /* tls_record.cc in Sources */, + OBJ_1794 /* curve25519.c in Sources */, + OBJ_1795 /* p256.c in Sources */, + ); + }; + OBJ_1866 /* Sources */ = { isa = PBXSourcesBuildPhase; files = ( - OBJ_1791 /* byte_buffer.c in Sources */, - OBJ_1792 /* call.c in Sources */, - OBJ_1793 /* channel.c in Sources */, - OBJ_1794 /* completion_queue.c in Sources */, - OBJ_1795 /* event.c in Sources */, - OBJ_1796 /* handler.c in Sources */, - OBJ_1797 /* internal.c in Sources */, - OBJ_1798 /* metadata.c in Sources */, - OBJ_1799 /* mutex.c in Sources */, - OBJ_1800 /* observers.c in Sources */, - OBJ_1801 /* operations.c in Sources */, - OBJ_1802 /* server.c in Sources */, - OBJ_1803 /* grpc_context.cc in Sources */, - OBJ_1804 /* backup_poller.cc in Sources */, - OBJ_1805 /* channel_connectivity.cc in Sources */, - OBJ_1806 /* client_channel.cc in Sources */, - OBJ_1807 /* client_channel_factory.cc in Sources */, - OBJ_1808 /* client_channel_plugin.cc in Sources */, - OBJ_1809 /* connector.cc in Sources */, - OBJ_1810 /* http_connect_handshaker.cc in Sources */, - OBJ_1811 /* http_proxy.cc in Sources */, - OBJ_1812 /* lb_policy.cc in Sources */, - OBJ_1813 /* client_load_reporting_filter.cc in Sources */, - OBJ_1814 /* grpclb.cc in Sources */, - OBJ_1815 /* grpclb_channel_secure.cc in Sources */, - OBJ_1816 /* grpclb_client_stats.cc in Sources */, - OBJ_1817 /* load_balancer_api.cc in Sources */, - OBJ_1818 /* load_balancer.pb.c in Sources */, - OBJ_1819 /* pick_first.cc in Sources */, - OBJ_1820 /* round_robin.cc in Sources */, - OBJ_1821 /* lb_policy_factory.cc in Sources */, - OBJ_1822 /* lb_policy_registry.cc in Sources */, - OBJ_1823 /* method_params.cc in Sources */, - OBJ_1824 /* parse_address.cc in Sources */, - OBJ_1825 /* proxy_mapper.cc in Sources */, - OBJ_1826 /* proxy_mapper_registry.cc in Sources */, - OBJ_1827 /* resolver.cc in Sources */, - OBJ_1828 /* dns_resolver_ares.cc in Sources */, - OBJ_1829 /* grpc_ares_ev_driver_posix.cc in Sources */, - OBJ_1830 /* grpc_ares_wrapper.cc in Sources */, - OBJ_1831 /* grpc_ares_wrapper_fallback.cc in Sources */, - OBJ_1832 /* dns_resolver.cc in Sources */, - OBJ_1833 /* fake_resolver.cc in Sources */, - OBJ_1834 /* sockaddr_resolver.cc in Sources */, - OBJ_1835 /* resolver_registry.cc in Sources */, - OBJ_1836 /* retry_throttle.cc in Sources */, - OBJ_1837 /* subchannel.cc in Sources */, - OBJ_1838 /* subchannel_index.cc in Sources */, - OBJ_1839 /* uri_parser.cc in Sources */, - OBJ_1840 /* deadline_filter.cc in Sources */, - OBJ_1841 /* http_client_filter.cc in Sources */, - OBJ_1842 /* client_authority_filter.cc in Sources */, - OBJ_1843 /* http_filters_plugin.cc in Sources */, - OBJ_1844 /* message_compress_filter.cc in Sources */, - OBJ_1845 /* http_server_filter.cc in Sources */, - OBJ_1846 /* server_load_reporting_filter.cc in Sources */, - OBJ_1847 /* server_load_reporting_plugin.cc in Sources */, - OBJ_1848 /* max_age_filter.cc in Sources */, - OBJ_1849 /* message_size_filter.cc in Sources */, - OBJ_1850 /* workaround_cronet_compression_filter.cc in Sources */, - OBJ_1851 /* workaround_utils.cc in Sources */, - OBJ_1852 /* alpn.cc in Sources */, - OBJ_1853 /* authority.cc in Sources */, - OBJ_1854 /* chttp2_connector.cc in Sources */, - OBJ_1855 /* channel_create.cc in Sources */, - OBJ_1856 /* channel_create_posix.cc in Sources */, - OBJ_1857 /* secure_channel_create.cc in Sources */, - OBJ_1858 /* chttp2_server.cc in Sources */, - OBJ_1859 /* server_chttp2.cc in Sources */, - OBJ_1860 /* server_chttp2_posix.cc in Sources */, - OBJ_1861 /* server_secure_chttp2.cc in Sources */, - OBJ_1862 /* bin_decoder.cc in Sources */, - OBJ_1863 /* bin_encoder.cc in Sources */, - OBJ_1864 /* chttp2_plugin.cc in Sources */, - OBJ_1865 /* chttp2_transport.cc in Sources */, - OBJ_1866 /* flow_control.cc in Sources */, - OBJ_1867 /* frame_data.cc in Sources */, - OBJ_1868 /* frame_goaway.cc in Sources */, - OBJ_1869 /* frame_ping.cc in Sources */, - OBJ_1870 /* frame_rst_stream.cc in Sources */, - OBJ_1871 /* frame_settings.cc in Sources */, - OBJ_1872 /* frame_window_update.cc in Sources */, - OBJ_1873 /* hpack_encoder.cc in Sources */, - OBJ_1874 /* hpack_parser.cc in Sources */, - OBJ_1875 /* hpack_table.cc in Sources */, - OBJ_1876 /* http2_settings.cc in Sources */, - OBJ_1877 /* huffsyms.cc in Sources */, - OBJ_1878 /* incoming_metadata.cc in Sources */, - OBJ_1879 /* parsing.cc in Sources */, - OBJ_1880 /* stream_lists.cc in Sources */, - OBJ_1881 /* stream_map.cc in Sources */, - OBJ_1882 /* varint.cc in Sources */, - OBJ_1883 /* writing.cc in Sources */, - OBJ_1884 /* inproc_plugin.cc in Sources */, - OBJ_1885 /* inproc_transport.cc in Sources */, - OBJ_1886 /* avl.cc in Sources */, - OBJ_1887 /* backoff.cc in Sources */, - OBJ_1888 /* channel_args.cc in Sources */, - OBJ_1889 /* channel_stack.cc in Sources */, - OBJ_1890 /* channel_stack_builder.cc in Sources */, - OBJ_1891 /* channel_trace.cc in Sources */, - OBJ_1892 /* channel_trace_registry.cc in Sources */, - OBJ_1893 /* connected_channel.cc in Sources */, - OBJ_1894 /* handshaker.cc in Sources */, - OBJ_1895 /* handshaker_factory.cc in Sources */, - OBJ_1896 /* handshaker_registry.cc in Sources */, - OBJ_1897 /* status_util.cc in Sources */, - OBJ_1898 /* compression.cc in Sources */, - OBJ_1899 /* compression_internal.cc in Sources */, - OBJ_1900 /* message_compress.cc in Sources */, - OBJ_1901 /* stream_compression.cc in Sources */, - OBJ_1902 /* stream_compression_gzip.cc in Sources */, - OBJ_1903 /* stream_compression_identity.cc in Sources */, - OBJ_1904 /* stats.cc in Sources */, - OBJ_1905 /* stats_data.cc in Sources */, - OBJ_1906 /* trace.cc in Sources */, - OBJ_1907 /* alloc.cc in Sources */, - OBJ_1908 /* arena.cc in Sources */, - OBJ_1909 /* atm.cc in Sources */, - OBJ_1910 /* cpu_iphone.cc in Sources */, - OBJ_1911 /* cpu_linux.cc in Sources */, - OBJ_1912 /* cpu_posix.cc in Sources */, - OBJ_1913 /* cpu_windows.cc in Sources */, - OBJ_1914 /* env_linux.cc in Sources */, - OBJ_1915 /* env_posix.cc in Sources */, - OBJ_1916 /* env_windows.cc in Sources */, - OBJ_1917 /* fork.cc in Sources */, - OBJ_1918 /* host_port.cc in Sources */, - OBJ_1919 /* log.cc in Sources */, - OBJ_1920 /* log_android.cc in Sources */, - OBJ_1921 /* log_linux.cc in Sources */, - OBJ_1922 /* log_posix.cc in Sources */, - OBJ_1923 /* log_windows.cc in Sources */, - OBJ_1924 /* mpscq.cc in Sources */, - OBJ_1925 /* murmur_hash.cc in Sources */, - OBJ_1926 /* string.cc in Sources */, - OBJ_1927 /* string_posix.cc in Sources */, - OBJ_1928 /* string_util_windows.cc in Sources */, - OBJ_1929 /* string_windows.cc in Sources */, - OBJ_1930 /* sync.cc in Sources */, - OBJ_1931 /* sync_posix.cc in Sources */, - OBJ_1932 /* sync_windows.cc in Sources */, - OBJ_1933 /* time.cc in Sources */, - OBJ_1934 /* time_posix.cc in Sources */, - OBJ_1935 /* time_precise.cc in Sources */, - OBJ_1936 /* time_windows.cc in Sources */, - OBJ_1937 /* tls_pthread.cc in Sources */, - OBJ_1938 /* tmpfile_msys.cc in Sources */, - OBJ_1939 /* tmpfile_posix.cc in Sources */, - OBJ_1940 /* tmpfile_windows.cc in Sources */, - OBJ_1941 /* wrap_memcpy.cc in Sources */, - OBJ_1942 /* thd_posix.cc in Sources */, - OBJ_1943 /* thd_windows.cc in Sources */, - OBJ_1944 /* format_request.cc in Sources */, - OBJ_1945 /* httpcli.cc in Sources */, - OBJ_1946 /* httpcli_security_connector.cc in Sources */, - OBJ_1947 /* parser.cc in Sources */, - OBJ_1948 /* call_combiner.cc in Sources */, - OBJ_1949 /* combiner.cc in Sources */, - OBJ_1950 /* endpoint.cc in Sources */, - OBJ_1951 /* endpoint_pair_posix.cc in Sources */, - OBJ_1952 /* endpoint_pair_uv.cc in Sources */, - OBJ_1953 /* endpoint_pair_windows.cc in Sources */, - OBJ_1954 /* error.cc in Sources */, - OBJ_1955 /* ev_epoll1_linux.cc in Sources */, - OBJ_1956 /* ev_epollex_linux.cc in Sources */, - OBJ_1957 /* ev_epollsig_linux.cc in Sources */, - OBJ_1958 /* ev_poll_posix.cc in Sources */, - OBJ_1959 /* ev_posix.cc in Sources */, - OBJ_1960 /* ev_windows.cc in Sources */, - OBJ_1961 /* exec_ctx.cc in Sources */, - OBJ_1962 /* executor.cc in Sources */, - OBJ_1963 /* fork_posix.cc in Sources */, - OBJ_1964 /* fork_windows.cc in Sources */, - OBJ_1965 /* gethostname_fallback.cc in Sources */, - OBJ_1966 /* gethostname_host_name_max.cc in Sources */, - OBJ_1967 /* gethostname_sysconf.cc in Sources */, - OBJ_1968 /* iocp_windows.cc in Sources */, - OBJ_1969 /* iomgr.cc in Sources */, - OBJ_1970 /* iomgr_custom.cc in Sources */, - OBJ_1971 /* iomgr_internal.cc in Sources */, - OBJ_1972 /* iomgr_posix.cc in Sources */, - OBJ_1973 /* iomgr_uv.cc in Sources */, - OBJ_1974 /* iomgr_windows.cc in Sources */, - OBJ_1975 /* is_epollexclusive_available.cc in Sources */, - OBJ_1976 /* load_file.cc in Sources */, - OBJ_1977 /* lockfree_event.cc in Sources */, - OBJ_1978 /* network_status_tracker.cc in Sources */, - OBJ_1979 /* polling_entity.cc in Sources */, - OBJ_1980 /* pollset.cc in Sources */, - OBJ_1981 /* pollset_custom.cc in Sources */, - OBJ_1982 /* pollset_set.cc in Sources */, - OBJ_1983 /* pollset_set_custom.cc in Sources */, - OBJ_1984 /* pollset_set_windows.cc in Sources */, - OBJ_1985 /* pollset_uv.cc in Sources */, - OBJ_1986 /* pollset_windows.cc in Sources */, - OBJ_1987 /* resolve_address.cc in Sources */, - OBJ_1988 /* resolve_address_custom.cc in Sources */, - OBJ_1989 /* resolve_address_posix.cc in Sources */, - OBJ_1990 /* resolve_address_windows.cc in Sources */, - OBJ_1991 /* resource_quota.cc in Sources */, - OBJ_1992 /* sockaddr_utils.cc in Sources */, - OBJ_1993 /* socket_factory_posix.cc in Sources */, - OBJ_1994 /* socket_mutator.cc in Sources */, - OBJ_1995 /* socket_utils_common_posix.cc in Sources */, - OBJ_1996 /* socket_utils_linux.cc in Sources */, - OBJ_1997 /* socket_utils_posix.cc in Sources */, - OBJ_1998 /* socket_utils_uv.cc in Sources */, - OBJ_1999 /* socket_utils_windows.cc in Sources */, - OBJ_2000 /* socket_windows.cc in Sources */, - OBJ_2001 /* tcp_client.cc in Sources */, - OBJ_2002 /* tcp_client_custom.cc in Sources */, - OBJ_2003 /* tcp_client_posix.cc in Sources */, - OBJ_2004 /* tcp_client_windows.cc in Sources */, - OBJ_2005 /* tcp_custom.cc in Sources */, - OBJ_2006 /* tcp_posix.cc in Sources */, - OBJ_2007 /* tcp_server.cc in Sources */, - OBJ_2008 /* tcp_server_custom.cc in Sources */, - OBJ_2009 /* tcp_server_posix.cc in Sources */, - OBJ_2010 /* tcp_server_utils_posix_common.cc in Sources */, - OBJ_2011 /* tcp_server_utils_posix_ifaddrs.cc in Sources */, - OBJ_2012 /* tcp_server_utils_posix_noifaddrs.cc in Sources */, - OBJ_2013 /* tcp_server_windows.cc in Sources */, - OBJ_2014 /* tcp_uv.cc in Sources */, - OBJ_2015 /* tcp_windows.cc in Sources */, - OBJ_2016 /* time_averaged_stats.cc in Sources */, - OBJ_2017 /* timer.cc in Sources */, - OBJ_2018 /* timer_custom.cc in Sources */, - OBJ_2019 /* timer_generic.cc in Sources */, - OBJ_2020 /* timer_heap.cc in Sources */, - OBJ_2021 /* timer_manager.cc in Sources */, - OBJ_2022 /* timer_uv.cc in Sources */, - OBJ_2023 /* udp_server.cc in Sources */, - OBJ_2024 /* unix_sockets_posix.cc in Sources */, - OBJ_2025 /* unix_sockets_posix_noop.cc in Sources */, - OBJ_2026 /* wakeup_fd_cv.cc in Sources */, - OBJ_2027 /* wakeup_fd_eventfd.cc in Sources */, - OBJ_2028 /* wakeup_fd_nospecial.cc in Sources */, - OBJ_2029 /* wakeup_fd_pipe.cc in Sources */, - OBJ_2030 /* wakeup_fd_posix.cc in Sources */, - OBJ_2031 /* json.cc in Sources */, - OBJ_2032 /* json_reader.cc in Sources */, - OBJ_2033 /* json_string.cc in Sources */, - OBJ_2034 /* json_writer.cc in Sources */, - OBJ_2035 /* basic_timers.cc in Sources */, - OBJ_2036 /* stap_timers.cc in Sources */, - OBJ_2037 /* security_context.cc in Sources */, - OBJ_2038 /* alts_credentials.cc in Sources */, - OBJ_2039 /* check_gcp_environment.cc in Sources */, - OBJ_2040 /* check_gcp_environment_linux.cc in Sources */, - OBJ_2041 /* check_gcp_environment_no_op.cc in Sources */, - OBJ_2042 /* check_gcp_environment_windows.cc in Sources */, - OBJ_2043 /* grpc_alts_credentials_client_options.cc in Sources */, - OBJ_2044 /* grpc_alts_credentials_options.cc in Sources */, - OBJ_2045 /* grpc_alts_credentials_server_options.cc in Sources */, - OBJ_2046 /* composite_credentials.cc in Sources */, - OBJ_2047 /* credentials.cc in Sources */, - OBJ_2048 /* credentials_metadata.cc in Sources */, - OBJ_2049 /* fake_credentials.cc in Sources */, - OBJ_2050 /* credentials_generic.cc in Sources */, - OBJ_2051 /* google_default_credentials.cc in Sources */, - OBJ_2052 /* iam_credentials.cc in Sources */, - OBJ_2053 /* json_token.cc in Sources */, - OBJ_2054 /* jwt_credentials.cc in Sources */, - OBJ_2055 /* jwt_verifier.cc in Sources */, - OBJ_2056 /* oauth2_credentials.cc in Sources */, - OBJ_2057 /* plugin_credentials.cc in Sources */, - OBJ_2058 /* ssl_credentials.cc in Sources */, - OBJ_2059 /* alts_security_connector.cc in Sources */, - OBJ_2060 /* security_connector.cc in Sources */, - OBJ_2061 /* client_auth_filter.cc in Sources */, - OBJ_2062 /* secure_endpoint.cc in Sources */, - OBJ_2063 /* security_handshaker.cc in Sources */, - OBJ_2064 /* server_auth_filter.cc in Sources */, - OBJ_2065 /* target_authority_table.cc in Sources */, - OBJ_2066 /* tsi_error.cc in Sources */, - OBJ_2067 /* json_util.cc in Sources */, - OBJ_2068 /* b64.cc in Sources */, - OBJ_2069 /* percent_encoding.cc in Sources */, - OBJ_2070 /* slice.cc in Sources */, - OBJ_2071 /* slice_buffer.cc in Sources */, - OBJ_2072 /* slice_intern.cc in Sources */, - OBJ_2073 /* slice_string_helpers.cc in Sources */, - OBJ_2074 /* api_trace.cc in Sources */, - OBJ_2075 /* byte_buffer.cc in Sources */, - OBJ_2076 /* byte_buffer_reader.cc in Sources */, - OBJ_2077 /* call.cc in Sources */, - OBJ_2078 /* call_details.cc in Sources */, - OBJ_2079 /* call_log_batch.cc in Sources */, - OBJ_2080 /* channel.cc in Sources */, - OBJ_2081 /* channel_init.cc in Sources */, - OBJ_2082 /* channel_ping.cc in Sources */, - OBJ_2083 /* channel_stack_type.cc in Sources */, - OBJ_2084 /* completion_queue.cc in Sources */, - OBJ_2085 /* completion_queue_factory.cc in Sources */, - OBJ_2086 /* event_string.cc in Sources */, - OBJ_2087 /* init.cc in Sources */, - OBJ_2088 /* init_secure.cc in Sources */, - OBJ_2089 /* lame_client.cc in Sources */, - OBJ_2090 /* metadata_array.cc in Sources */, - OBJ_2091 /* server.cc in Sources */, - OBJ_2092 /* validate_metadata.cc in Sources */, - OBJ_2093 /* version.cc in Sources */, - OBJ_2094 /* bdp_estimator.cc in Sources */, - OBJ_2095 /* byte_stream.cc in Sources */, - OBJ_2096 /* connectivity_state.cc in Sources */, - OBJ_2097 /* error_utils.cc in Sources */, - OBJ_2098 /* metadata.cc in Sources */, - OBJ_2099 /* metadata_batch.cc in Sources */, - OBJ_2100 /* pid_controller.cc in Sources */, - OBJ_2101 /* service_config.cc in Sources */, - OBJ_2102 /* static_metadata.cc in Sources */, - OBJ_2103 /* status_conversion.cc in Sources */, - OBJ_2104 /* status_metadata.cc in Sources */, - OBJ_2105 /* timeout_encoding.cc in Sources */, - OBJ_2106 /* transport.cc in Sources */, - OBJ_2107 /* transport_op_string.cc in Sources */, - OBJ_2108 /* grpc_plugin_registry.cc in Sources */, - OBJ_2109 /* aes_gcm.cc in Sources */, - OBJ_2110 /* gsec.cc in Sources */, - OBJ_2111 /* alts_counter.cc in Sources */, - OBJ_2112 /* alts_crypter.cc in Sources */, - OBJ_2113 /* alts_frame_protector.cc in Sources */, - OBJ_2114 /* alts_record_protocol_crypter_common.cc in Sources */, - OBJ_2115 /* alts_seal_privacy_integrity_crypter.cc in Sources */, - OBJ_2116 /* alts_unseal_privacy_integrity_crypter.cc in Sources */, - OBJ_2117 /* frame_handler.cc in Sources */, - OBJ_2118 /* alts_handshaker_client.cc in Sources */, - OBJ_2119 /* alts_handshaker_service_api.cc in Sources */, - OBJ_2120 /* alts_handshaker_service_api_util.cc in Sources */, - OBJ_2121 /* alts_tsi_event.cc in Sources */, - OBJ_2122 /* alts_tsi_handshaker.cc in Sources */, - OBJ_2123 /* alts_tsi_utils.cc in Sources */, - OBJ_2124 /* altscontext.pb.c in Sources */, - OBJ_2125 /* handshaker.pb.c in Sources */, - OBJ_2126 /* transport_security_common.pb.c in Sources */, - OBJ_2127 /* transport_security_common_api.cc in Sources */, - OBJ_2128 /* alts_grpc_integrity_only_record_protocol.cc in Sources */, - OBJ_2129 /* alts_grpc_privacy_integrity_record_protocol.cc in Sources */, - OBJ_2130 /* alts_grpc_record_protocol_common.cc in Sources */, - OBJ_2131 /* alts_iovec_record_protocol.cc in Sources */, - OBJ_2132 /* alts_zero_copy_grpc_protector.cc in Sources */, - OBJ_2133 /* alts_transport_security.cc in Sources */, - OBJ_2134 /* fake_transport_security.cc in Sources */, - OBJ_2135 /* ssl_session_boringssl.cc in Sources */, - OBJ_2136 /* ssl_session_cache.cc in Sources */, - OBJ_2137 /* ssl_session_openssl.cc in Sources */, - OBJ_2138 /* ssl_transport_security.cc in Sources */, - OBJ_2139 /* transport_security.cc in Sources */, - OBJ_2140 /* transport_security_adapter.cc in Sources */, - OBJ_2141 /* transport_security_grpc.cc in Sources */, - OBJ_2142 /* pb_common.c in Sources */, - OBJ_2143 /* pb_decode.c in Sources */, - OBJ_2144 /* pb_encode.c in Sources */, - ); - }; - OBJ_2477 /* Sources */ = { + OBJ_1867 /* byte_buffer.c in Sources */, + OBJ_1868 /* call.c in Sources */, + OBJ_1869 /* channel.c in Sources */, + OBJ_1870 /* completion_queue.c in Sources */, + OBJ_1871 /* event.c in Sources */, + OBJ_1872 /* handler.c in Sources */, + OBJ_1873 /* internal.c in Sources */, + OBJ_1874 /* metadata.c in Sources */, + OBJ_1875 /* mutex.c in Sources */, + OBJ_1876 /* observers.c in Sources */, + OBJ_1877 /* operations.c in Sources */, + OBJ_1878 /* server.c in Sources */, + OBJ_1879 /* grpc_context.cc in Sources */, + OBJ_1880 /* backup_poller.cc in Sources */, + OBJ_1881 /* channel_connectivity.cc in Sources */, + OBJ_1882 /* client_channel.cc in Sources */, + OBJ_1883 /* client_channel_channelz.cc in Sources */, + OBJ_1884 /* client_channel_factory.cc in Sources */, + OBJ_1885 /* client_channel_plugin.cc in Sources */, + OBJ_1886 /* connector.cc in Sources */, + OBJ_1887 /* global_subchannel_pool.cc in Sources */, + OBJ_1888 /* health.pb.c in Sources */, + OBJ_1889 /* health_check_client.cc in Sources */, + OBJ_1890 /* http_connect_handshaker.cc in Sources */, + OBJ_1891 /* http_proxy.cc in Sources */, + OBJ_1892 /* lb_policy.cc in Sources */, + OBJ_1893 /* client_load_reporting_filter.cc in Sources */, + OBJ_1894 /* grpclb.cc in Sources */, + OBJ_1895 /* grpclb_channel_secure.cc in Sources */, + OBJ_1896 /* grpclb_client_stats.cc in Sources */, + OBJ_1897 /* load_balancer_api.cc in Sources */, + OBJ_1898 /* duration.pb.c in Sources */, + OBJ_1899 /* timestamp.pb.c in Sources */, + OBJ_1900 /* load_balancer.pb.c in Sources */, + OBJ_1901 /* pick_first.cc in Sources */, + OBJ_1902 /* round_robin.cc in Sources */, + OBJ_1903 /* xds.cc in Sources */, + OBJ_1904 /* xds_channel_secure.cc in Sources */, + OBJ_1905 /* xds_client_stats.cc in Sources */, + OBJ_1906 /* xds_load_balancer_api.cc in Sources */, + OBJ_1907 /* lb_policy_registry.cc in Sources */, + OBJ_1908 /* local_subchannel_pool.cc in Sources */, + OBJ_1909 /* parse_address.cc in Sources */, + OBJ_1910 /* proxy_mapper.cc in Sources */, + OBJ_1911 /* proxy_mapper_registry.cc in Sources */, + OBJ_1912 /* request_routing.cc in Sources */, + OBJ_1913 /* resolver.cc in Sources */, + OBJ_1914 /* dns_resolver_ares.cc in Sources */, + OBJ_1915 /* grpc_ares_ev_driver.cc in Sources */, + OBJ_1916 /* grpc_ares_ev_driver_posix.cc in Sources */, + OBJ_1917 /* grpc_ares_ev_driver_windows.cc in Sources */, + OBJ_1918 /* grpc_ares_wrapper.cc in Sources */, + OBJ_1919 /* grpc_ares_wrapper_fallback.cc in Sources */, + OBJ_1920 /* grpc_ares_wrapper_posix.cc in Sources */, + OBJ_1921 /* grpc_ares_wrapper_windows.cc in Sources */, + OBJ_1922 /* dns_resolver.cc in Sources */, + OBJ_1923 /* fake_resolver.cc in Sources */, + OBJ_1924 /* sockaddr_resolver.cc in Sources */, + OBJ_1925 /* resolver_registry.cc in Sources */, + OBJ_1926 /* resolver_result_parsing.cc in Sources */, + OBJ_1927 /* retry_throttle.cc in Sources */, + OBJ_1928 /* server_address.cc in Sources */, + OBJ_1929 /* subchannel.cc in Sources */, + OBJ_1930 /* subchannel_pool_interface.cc in Sources */, + OBJ_1931 /* deadline_filter.cc in Sources */, + OBJ_1932 /* http_client_filter.cc in Sources */, + OBJ_1933 /* client_authority_filter.cc in Sources */, + OBJ_1934 /* http_filters_plugin.cc in Sources */, + OBJ_1935 /* message_compress_filter.cc in Sources */, + OBJ_1936 /* http_server_filter.cc in Sources */, + OBJ_1937 /* max_age_filter.cc in Sources */, + OBJ_1938 /* message_size_filter.cc in Sources */, + OBJ_1939 /* workaround_cronet_compression_filter.cc in Sources */, + OBJ_1940 /* workaround_utils.cc in Sources */, + OBJ_1941 /* alpn.cc in Sources */, + OBJ_1942 /* authority.cc in Sources */, + OBJ_1943 /* chttp2_connector.cc in Sources */, + OBJ_1944 /* channel_create.cc in Sources */, + OBJ_1945 /* channel_create_posix.cc in Sources */, + OBJ_1946 /* secure_channel_create.cc in Sources */, + OBJ_1947 /* chttp2_server.cc in Sources */, + OBJ_1948 /* server_chttp2.cc in Sources */, + OBJ_1949 /* server_chttp2_posix.cc in Sources */, + OBJ_1950 /* server_secure_chttp2.cc in Sources */, + OBJ_1951 /* bin_decoder.cc in Sources */, + OBJ_1952 /* bin_encoder.cc in Sources */, + OBJ_1953 /* chttp2_plugin.cc in Sources */, + OBJ_1954 /* chttp2_transport.cc in Sources */, + OBJ_1955 /* context_list.cc in Sources */, + OBJ_1956 /* flow_control.cc in Sources */, + OBJ_1957 /* frame_data.cc in Sources */, + OBJ_1958 /* frame_goaway.cc in Sources */, + OBJ_1959 /* frame_ping.cc in Sources */, + OBJ_1960 /* frame_rst_stream.cc in Sources */, + OBJ_1961 /* frame_settings.cc in Sources */, + OBJ_1962 /* frame_window_update.cc in Sources */, + OBJ_1963 /* hpack_encoder.cc in Sources */, + OBJ_1964 /* hpack_parser.cc in Sources */, + OBJ_1965 /* hpack_table.cc in Sources */, + OBJ_1966 /* http2_settings.cc in Sources */, + OBJ_1967 /* huffsyms.cc in Sources */, + OBJ_1968 /* incoming_metadata.cc in Sources */, + OBJ_1969 /* parsing.cc in Sources */, + OBJ_1970 /* stream_lists.cc in Sources */, + OBJ_1971 /* stream_map.cc in Sources */, + OBJ_1972 /* varint.cc in Sources */, + OBJ_1973 /* writing.cc in Sources */, + OBJ_1974 /* inproc_plugin.cc in Sources */, + OBJ_1975 /* inproc_transport.cc in Sources */, + OBJ_1976 /* avl.cc in Sources */, + OBJ_1977 /* backoff.cc in Sources */, + OBJ_1978 /* channel_args.cc in Sources */, + OBJ_1979 /* channel_stack.cc in Sources */, + OBJ_1980 /* channel_stack_builder.cc in Sources */, + OBJ_1981 /* channel_trace.cc in Sources */, + OBJ_1982 /* channelz.cc in Sources */, + OBJ_1983 /* channelz_registry.cc in Sources */, + OBJ_1984 /* connected_channel.cc in Sources */, + OBJ_1985 /* handshaker.cc in Sources */, + OBJ_1986 /* handshaker_registry.cc in Sources */, + OBJ_1987 /* status_util.cc in Sources */, + OBJ_1988 /* compression.cc in Sources */, + OBJ_1989 /* compression_internal.cc in Sources */, + OBJ_1990 /* message_compress.cc in Sources */, + OBJ_1991 /* stream_compression.cc in Sources */, + OBJ_1992 /* stream_compression_gzip.cc in Sources */, + OBJ_1993 /* stream_compression_identity.cc in Sources */, + OBJ_1994 /* stats.cc in Sources */, + OBJ_1995 /* stats_data.cc in Sources */, + OBJ_1996 /* trace.cc in Sources */, + OBJ_1997 /* alloc.cc in Sources */, + OBJ_1998 /* arena.cc in Sources */, + OBJ_1999 /* atm.cc in Sources */, + OBJ_2000 /* cpu_iphone.cc in Sources */, + OBJ_2001 /* cpu_linux.cc in Sources */, + OBJ_2002 /* cpu_posix.cc in Sources */, + OBJ_2003 /* cpu_windows.cc in Sources */, + OBJ_2004 /* env_linux.cc in Sources */, + OBJ_2005 /* env_posix.cc in Sources */, + OBJ_2006 /* env_windows.cc in Sources */, + OBJ_2007 /* host_port.cc in Sources */, + OBJ_2008 /* log.cc in Sources */, + OBJ_2009 /* log_android.cc in Sources */, + OBJ_2010 /* log_linux.cc in Sources */, + OBJ_2011 /* log_posix.cc in Sources */, + OBJ_2012 /* log_windows.cc in Sources */, + OBJ_2013 /* mpscq.cc in Sources */, + OBJ_2014 /* murmur_hash.cc in Sources */, + OBJ_2015 /* string.cc in Sources */, + OBJ_2016 /* string_posix.cc in Sources */, + OBJ_2017 /* string_util_windows.cc in Sources */, + OBJ_2018 /* string_windows.cc in Sources */, + OBJ_2019 /* sync.cc in Sources */, + OBJ_2020 /* sync_posix.cc in Sources */, + OBJ_2021 /* sync_windows.cc in Sources */, + OBJ_2022 /* time.cc in Sources */, + OBJ_2023 /* time_posix.cc in Sources */, + OBJ_2024 /* time_precise.cc in Sources */, + OBJ_2025 /* time_windows.cc in Sources */, + OBJ_2026 /* tls_pthread.cc in Sources */, + OBJ_2027 /* tmpfile_msys.cc in Sources */, + OBJ_2028 /* tmpfile_posix.cc in Sources */, + OBJ_2029 /* tmpfile_windows.cc in Sources */, + OBJ_2030 /* wrap_memcpy.cc in Sources */, + OBJ_2031 /* fork.cc in Sources */, + OBJ_2032 /* thd_posix.cc in Sources */, + OBJ_2033 /* thd_windows.cc in Sources */, + OBJ_2034 /* format_request.cc in Sources */, + OBJ_2035 /* httpcli.cc in Sources */, + OBJ_2036 /* httpcli_security_connector.cc in Sources */, + OBJ_2037 /* parser.cc in Sources */, + OBJ_2038 /* buffer_list.cc in Sources */, + OBJ_2039 /* call_combiner.cc in Sources */, + OBJ_2040 /* combiner.cc in Sources */, + OBJ_2041 /* endpoint.cc in Sources */, + OBJ_2042 /* endpoint_pair_posix.cc in Sources */, + OBJ_2043 /* endpoint_pair_uv.cc in Sources */, + OBJ_2044 /* endpoint_pair_windows.cc in Sources */, + OBJ_2045 /* error.cc in Sources */, + OBJ_2046 /* ev_epoll1_linux.cc in Sources */, + OBJ_2047 /* ev_epollex_linux.cc in Sources */, + OBJ_2048 /* ev_poll_posix.cc in Sources */, + OBJ_2049 /* ev_posix.cc in Sources */, + OBJ_2050 /* ev_windows.cc in Sources */, + OBJ_2051 /* exec_ctx.cc in Sources */, + OBJ_2052 /* executor.cc in Sources */, + OBJ_2053 /* fork_posix.cc in Sources */, + OBJ_2054 /* fork_windows.cc in Sources */, + OBJ_2055 /* gethostname_fallback.cc in Sources */, + OBJ_2056 /* gethostname_host_name_max.cc in Sources */, + OBJ_2057 /* gethostname_sysconf.cc in Sources */, + OBJ_2058 /* grpc_if_nametoindex_posix.cc in Sources */, + OBJ_2059 /* grpc_if_nametoindex_unsupported.cc in Sources */, + OBJ_2060 /* internal_errqueue.cc in Sources */, + OBJ_2061 /* iocp_windows.cc in Sources */, + OBJ_2062 /* iomgr.cc in Sources */, + OBJ_2063 /* iomgr_custom.cc in Sources */, + OBJ_2064 /* iomgr_internal.cc in Sources */, + OBJ_2065 /* iomgr_posix.cc in Sources */, + OBJ_2066 /* iomgr_uv.cc in Sources */, + OBJ_2067 /* iomgr_windows.cc in Sources */, + OBJ_2068 /* is_epollexclusive_available.cc in Sources */, + OBJ_2069 /* load_file.cc in Sources */, + OBJ_2070 /* lockfree_event.cc in Sources */, + OBJ_2071 /* polling_entity.cc in Sources */, + OBJ_2072 /* pollset.cc in Sources */, + OBJ_2073 /* pollset_custom.cc in Sources */, + OBJ_2074 /* pollset_set.cc in Sources */, + OBJ_2075 /* pollset_set_custom.cc in Sources */, + OBJ_2076 /* pollset_set_windows.cc in Sources */, + OBJ_2077 /* pollset_uv.cc in Sources */, + OBJ_2078 /* pollset_windows.cc in Sources */, + OBJ_2079 /* resolve_address.cc in Sources */, + OBJ_2080 /* resolve_address_custom.cc in Sources */, + OBJ_2081 /* resolve_address_posix.cc in Sources */, + OBJ_2082 /* resolve_address_windows.cc in Sources */, + OBJ_2083 /* resource_quota.cc in Sources */, + OBJ_2084 /* sockaddr_utils.cc in Sources */, + OBJ_2085 /* socket_factory_posix.cc in Sources */, + OBJ_2086 /* socket_mutator.cc in Sources */, + OBJ_2087 /* socket_utils_common_posix.cc in Sources */, + OBJ_2088 /* socket_utils_linux.cc in Sources */, + OBJ_2089 /* socket_utils_posix.cc in Sources */, + OBJ_2090 /* socket_utils_uv.cc in Sources */, + OBJ_2091 /* socket_utils_windows.cc in Sources */, + OBJ_2092 /* socket_windows.cc in Sources */, + OBJ_2093 /* tcp_client.cc in Sources */, + OBJ_2094 /* tcp_client_custom.cc in Sources */, + OBJ_2095 /* tcp_client_posix.cc in Sources */, + OBJ_2096 /* tcp_client_windows.cc in Sources */, + OBJ_2097 /* tcp_custom.cc in Sources */, + OBJ_2098 /* tcp_posix.cc in Sources */, + OBJ_2099 /* tcp_server.cc in Sources */, + OBJ_2100 /* tcp_server_custom.cc in Sources */, + OBJ_2101 /* tcp_server_posix.cc in Sources */, + OBJ_2102 /* tcp_server_utils_posix_common.cc in Sources */, + OBJ_2103 /* tcp_server_utils_posix_ifaddrs.cc in Sources */, + OBJ_2104 /* tcp_server_utils_posix_noifaddrs.cc in Sources */, + OBJ_2105 /* tcp_server_windows.cc in Sources */, + OBJ_2106 /* tcp_uv.cc in Sources */, + OBJ_2107 /* tcp_windows.cc in Sources */, + OBJ_2108 /* time_averaged_stats.cc in Sources */, + OBJ_2109 /* timer.cc in Sources */, + OBJ_2110 /* timer_custom.cc in Sources */, + OBJ_2111 /* timer_generic.cc in Sources */, + OBJ_2112 /* timer_heap.cc in Sources */, + OBJ_2113 /* timer_manager.cc in Sources */, + OBJ_2114 /* timer_uv.cc in Sources */, + OBJ_2115 /* udp_server.cc in Sources */, + OBJ_2116 /* unix_sockets_posix.cc in Sources */, + OBJ_2117 /* unix_sockets_posix_noop.cc in Sources */, + OBJ_2118 /* wakeup_fd_cv.cc in Sources */, + OBJ_2119 /* wakeup_fd_eventfd.cc in Sources */, + OBJ_2120 /* wakeup_fd_nospecial.cc in Sources */, + OBJ_2121 /* wakeup_fd_pipe.cc in Sources */, + OBJ_2122 /* wakeup_fd_posix.cc in Sources */, + OBJ_2123 /* json.cc in Sources */, + OBJ_2124 /* json_reader.cc in Sources */, + OBJ_2125 /* json_string.cc in Sources */, + OBJ_2126 /* json_writer.cc in Sources */, + OBJ_2127 /* basic_timers.cc in Sources */, + OBJ_2128 /* stap_timers.cc in Sources */, + OBJ_2129 /* security_context.cc in Sources */, + OBJ_2130 /* alts_credentials.cc in Sources */, + OBJ_2131 /* check_gcp_environment.cc in Sources */, + OBJ_2132 /* check_gcp_environment_linux.cc in Sources */, + OBJ_2133 /* check_gcp_environment_no_op.cc in Sources */, + OBJ_2134 /* check_gcp_environment_windows.cc in Sources */, + OBJ_2135 /* grpc_alts_credentials_client_options.cc in Sources */, + OBJ_2136 /* grpc_alts_credentials_options.cc in Sources */, + OBJ_2137 /* grpc_alts_credentials_server_options.cc in Sources */, + OBJ_2138 /* composite_credentials.cc in Sources */, + OBJ_2139 /* credentials.cc in Sources */, + OBJ_2140 /* credentials_metadata.cc in Sources */, + OBJ_2141 /* fake_credentials.cc in Sources */, + OBJ_2142 /* credentials_generic.cc in Sources */, + OBJ_2143 /* google_default_credentials.cc in Sources */, + OBJ_2144 /* iam_credentials.cc in Sources */, + OBJ_2145 /* json_token.cc in Sources */, + OBJ_2146 /* jwt_credentials.cc in Sources */, + OBJ_2147 /* jwt_verifier.cc in Sources */, + OBJ_2148 /* local_credentials.cc in Sources */, + OBJ_2149 /* oauth2_credentials.cc in Sources */, + OBJ_2150 /* plugin_credentials.cc in Sources */, + OBJ_2151 /* ssl_credentials.cc in Sources */, + OBJ_2152 /* grpc_tls_credentials_options.cc in Sources */, + OBJ_2153 /* alts_security_connector.cc in Sources */, + OBJ_2154 /* fake_security_connector.cc in Sources */, + OBJ_2155 /* load_system_roots_fallback.cc in Sources */, + OBJ_2156 /* load_system_roots_linux.cc in Sources */, + OBJ_2157 /* local_security_connector.cc in Sources */, + OBJ_2158 /* security_connector.cc in Sources */, + OBJ_2159 /* ssl_security_connector.cc in Sources */, + OBJ_2160 /* ssl_utils.cc in Sources */, + OBJ_2161 /* client_auth_filter.cc in Sources */, + OBJ_2162 /* secure_endpoint.cc in Sources */, + OBJ_2163 /* security_handshaker.cc in Sources */, + OBJ_2164 /* server_auth_filter.cc in Sources */, + OBJ_2165 /* target_authority_table.cc in Sources */, + OBJ_2166 /* tsi_error.cc in Sources */, + OBJ_2167 /* json_util.cc in Sources */, + OBJ_2168 /* b64.cc in Sources */, + OBJ_2169 /* percent_encoding.cc in Sources */, + OBJ_2170 /* slice.cc in Sources */, + OBJ_2171 /* slice_buffer.cc in Sources */, + OBJ_2172 /* slice_intern.cc in Sources */, + OBJ_2173 /* slice_string_helpers.cc in Sources */, + OBJ_2174 /* api_trace.cc in Sources */, + OBJ_2175 /* byte_buffer.cc in Sources */, + OBJ_2176 /* byte_buffer_reader.cc in Sources */, + OBJ_2177 /* call.cc in Sources */, + OBJ_2178 /* call_details.cc in Sources */, + OBJ_2179 /* call_log_batch.cc in Sources */, + OBJ_2180 /* channel.cc in Sources */, + OBJ_2181 /* channel_init.cc in Sources */, + OBJ_2182 /* channel_ping.cc in Sources */, + OBJ_2183 /* channel_stack_type.cc in Sources */, + OBJ_2184 /* completion_queue.cc in Sources */, + OBJ_2185 /* completion_queue_factory.cc in Sources */, + OBJ_2186 /* event_string.cc in Sources */, + OBJ_2187 /* init.cc in Sources */, + OBJ_2188 /* init_secure.cc in Sources */, + OBJ_2189 /* lame_client.cc in Sources */, + OBJ_2190 /* metadata_array.cc in Sources */, + OBJ_2191 /* server.cc in Sources */, + OBJ_2192 /* validate_metadata.cc in Sources */, + OBJ_2193 /* version.cc in Sources */, + OBJ_2194 /* bdp_estimator.cc in Sources */, + OBJ_2195 /* byte_stream.cc in Sources */, + OBJ_2196 /* connectivity_state.cc in Sources */, + OBJ_2197 /* error_utils.cc in Sources */, + OBJ_2198 /* metadata.cc in Sources */, + OBJ_2199 /* metadata_batch.cc in Sources */, + OBJ_2200 /* pid_controller.cc in Sources */, + OBJ_2201 /* service_config.cc in Sources */, + OBJ_2202 /* static_metadata.cc in Sources */, + OBJ_2203 /* status_conversion.cc in Sources */, + OBJ_2204 /* status_metadata.cc in Sources */, + OBJ_2205 /* timeout_encoding.cc in Sources */, + OBJ_2206 /* transport.cc in Sources */, + OBJ_2207 /* transport_op_string.cc in Sources */, + OBJ_2208 /* uri_parser.cc in Sources */, + OBJ_2209 /* grpc_plugin_registry.cc in Sources */, + OBJ_2210 /* aes_gcm.cc in Sources */, + OBJ_2211 /* gsec.cc in Sources */, + OBJ_2212 /* alts_counter.cc in Sources */, + OBJ_2213 /* alts_crypter.cc in Sources */, + OBJ_2214 /* alts_frame_protector.cc in Sources */, + OBJ_2215 /* alts_record_protocol_crypter_common.cc in Sources */, + OBJ_2216 /* alts_seal_privacy_integrity_crypter.cc in Sources */, + OBJ_2217 /* alts_unseal_privacy_integrity_crypter.cc in Sources */, + OBJ_2218 /* frame_handler.cc in Sources */, + OBJ_2219 /* alts_handshaker_client.cc in Sources */, + OBJ_2220 /* alts_handshaker_service_api.cc in Sources */, + OBJ_2221 /* alts_handshaker_service_api_util.cc in Sources */, + OBJ_2222 /* alts_shared_resource.cc in Sources */, + OBJ_2223 /* alts_tsi_handshaker.cc in Sources */, + OBJ_2224 /* alts_tsi_utils.cc in Sources */, + OBJ_2225 /* altscontext.pb.c in Sources */, + OBJ_2226 /* handshaker.pb.c in Sources */, + OBJ_2227 /* transport_security_common.pb.c in Sources */, + OBJ_2228 /* transport_security_common_api.cc in Sources */, + OBJ_2229 /* alts_grpc_integrity_only_record_protocol.cc in Sources */, + OBJ_2230 /* alts_grpc_privacy_integrity_record_protocol.cc in Sources */, + OBJ_2231 /* alts_grpc_record_protocol_common.cc in Sources */, + OBJ_2232 /* alts_iovec_record_protocol.cc in Sources */, + OBJ_2233 /* alts_zero_copy_grpc_protector.cc in Sources */, + OBJ_2234 /* fake_transport_security.cc in Sources */, + OBJ_2235 /* local_transport_security.cc in Sources */, + OBJ_2236 /* ssl_session_boringssl.cc in Sources */, + OBJ_2237 /* ssl_session_cache.cc in Sources */, + OBJ_2238 /* ssl_session_openssl.cc in Sources */, + OBJ_2239 /* ssl_transport_security.cc in Sources */, + OBJ_2240 /* transport_security.cc in Sources */, + OBJ_2241 /* transport_security_grpc.cc in Sources */, + OBJ_2242 /* pb_common.c in Sources */, + OBJ_2243 /* pb_decode.c in Sources */, + OBJ_2244 /* pb_encode.c in Sources */, + ); + }; + OBJ_2577 /* Sources */ = { isa = PBXSourcesBuildPhase; files = ( - OBJ_2478 /* ByteBuffer.swift in Sources */, - OBJ_2479 /* Call.swift in Sources */, - OBJ_2480 /* CallError.swift in Sources */, - OBJ_2481 /* CallResult.swift in Sources */, - OBJ_2482 /* Channel.swift in Sources */, - OBJ_2483 /* ChannelArgument.swift in Sources */, - OBJ_2484 /* ChannelConnectivityObserver.swift in Sources */, - OBJ_2485 /* ChannelConnectivityState.swift in Sources */, - OBJ_2486 /* ClientNetworkMonitor.swift in Sources */, - OBJ_2487 /* CompletionQueue.swift in Sources */, - OBJ_2488 /* Handler.swift in Sources */, - OBJ_2489 /* Metadata.swift in Sources */, - OBJ_2490 /* Mutex.swift in Sources */, - OBJ_2491 /* Operation.swift in Sources */, - OBJ_2492 /* OperationGroup.swift in Sources */, - OBJ_2493 /* Roots.swift in Sources */, - OBJ_2494 /* Server.swift in Sources */, - OBJ_2495 /* ServerStatus.swift in Sources */, - OBJ_2496 /* StatusCode.swift in Sources */, - OBJ_2497 /* gRPC.swift in Sources */, - OBJ_2498 /* ClientCall.swift in Sources */, - OBJ_2499 /* ClientCallBidirectionalStreaming.swift in Sources */, - OBJ_2500 /* ClientCallClientStreaming.swift in Sources */, - OBJ_2501 /* ClientCallServerStreaming.swift in Sources */, - OBJ_2502 /* ClientCallUnary.swift in Sources */, - OBJ_2503 /* RPCError.swift in Sources */, - OBJ_2504 /* ServerSession.swift in Sources */, - OBJ_2505 /* ServerSessionBidirectionalStreaming.swift in Sources */, - OBJ_2506 /* ServerSessionClientStreaming.swift in Sources */, - OBJ_2507 /* ServerSessionServerStreaming.swift in Sources */, - OBJ_2508 /* ServerSessionUnary.swift in Sources */, - OBJ_2509 /* ServiceClient.swift in Sources */, - OBJ_2510 /* ServiceProvider.swift in Sources */, - OBJ_2511 /* ServiceServer.swift in Sources */, - OBJ_2512 /* StreamReceiving.swift in Sources */, - OBJ_2513 /* StreamSending.swift in Sources */, - ); - }; - OBJ_2700 /* Sources */ = { + OBJ_2578 /* ByteBuffer.swift in Sources */, + OBJ_2579 /* Call.swift in Sources */, + OBJ_2580 /* CallError.swift in Sources */, + OBJ_2581 /* CallResult.swift in Sources */, + OBJ_2582 /* Channel.swift in Sources */, + OBJ_2583 /* ChannelArgument.swift in Sources */, + OBJ_2584 /* ChannelConnectivityObserver.swift in Sources */, + OBJ_2585 /* ChannelConnectivityState.swift in Sources */, + OBJ_2586 /* ClientNetworkMonitor.swift in Sources */, + OBJ_2587 /* CompletionQueue.swift in Sources */, + OBJ_2588 /* Handler.swift in Sources */, + OBJ_2589 /* Metadata.swift in Sources */, + OBJ_2590 /* Mutex.swift in Sources */, + OBJ_2591 /* Operation.swift in Sources */, + OBJ_2592 /* OperationGroup.swift in Sources */, + OBJ_2593 /* Roots.swift in Sources */, + OBJ_2594 /* Server.swift in Sources */, + OBJ_2595 /* ServerStatus.swift in Sources */, + OBJ_2596 /* StatusCode.swift in Sources */, + OBJ_2597 /* gRPC.swift in Sources */, + OBJ_2598 /* ClientCall.swift in Sources */, + OBJ_2599 /* ClientCallBidirectionalStreaming.swift in Sources */, + OBJ_2600 /* ClientCallClientStreaming.swift in Sources */, + OBJ_2601 /* ClientCallServerStreaming.swift in Sources */, + OBJ_2602 /* ClientCallUnary.swift in Sources */, + OBJ_2603 /* RPCError.swift in Sources */, + OBJ_2604 /* ServerSession.swift in Sources */, + OBJ_2605 /* ServerSessionBidirectionalStreaming.swift in Sources */, + OBJ_2606 /* ServerSessionClientStreaming.swift in Sources */, + OBJ_2607 /* ServerSessionServerStreaming.swift in Sources */, + OBJ_2608 /* ServerSessionUnary.swift in Sources */, + OBJ_2609 /* ServiceClient.swift in Sources */, + OBJ_2610 /* ServiceProvider.swift in Sources */, + OBJ_2611 /* ServiceServer.swift in Sources */, + OBJ_2612 /* StreamReceiving.swift in Sources */, + OBJ_2613 /* StreamSending.swift in Sources */, + ); + }; + OBJ_2800 /* Sources */ = { isa = PBXSourcesBuildPhase; files = ( - OBJ_2701 /* AnyMessageStorage.swift in Sources */, - OBJ_2702 /* AnyUnpackError.swift in Sources */, - OBJ_2703 /* BinaryDecoder.swift in Sources */, - OBJ_2704 /* BinaryDecodingError.swift in Sources */, - OBJ_2705 /* BinaryDecodingOptions.swift in Sources */, - OBJ_2706 /* BinaryDelimited.swift in Sources */, - OBJ_2707 /* BinaryEncoder.swift in Sources */, - OBJ_2708 /* BinaryEncodingError.swift in Sources */, - OBJ_2709 /* BinaryEncodingSizeVisitor.swift in Sources */, - OBJ_2710 /* BinaryEncodingVisitor.swift in Sources */, - OBJ_2711 /* CustomJSONCodable.swift in Sources */, - OBJ_2712 /* Decoder.swift in Sources */, - OBJ_2713 /* DoubleFormatter.swift in Sources */, - OBJ_2714 /* Enum.swift in Sources */, - OBJ_2715 /* ExtensibleMessage.swift in Sources */, - OBJ_2716 /* ExtensionFieldValueSet.swift in Sources */, - OBJ_2717 /* ExtensionFields.swift in Sources */, - OBJ_2718 /* ExtensionMap.swift in Sources */, - OBJ_2719 /* FieldTag.swift in Sources */, - OBJ_2720 /* FieldTypes.swift in Sources */, - OBJ_2721 /* Google_Protobuf_Any+Extensions.swift in Sources */, - OBJ_2722 /* Google_Protobuf_Any+Registry.swift in Sources */, - OBJ_2723 /* Google_Protobuf_Duration+Extensions.swift in Sources */, - OBJ_2724 /* Google_Protobuf_FieldMask+Extensions.swift in Sources */, - OBJ_2725 /* Google_Protobuf_ListValue+Extensions.swift in Sources */, - OBJ_2726 /* Google_Protobuf_Struct+Extensions.swift in Sources */, - OBJ_2727 /* Google_Protobuf_Timestamp+Extensions.swift in Sources */, - OBJ_2728 /* Google_Protobuf_Value+Extensions.swift in Sources */, - OBJ_2729 /* Google_Protobuf_Wrappers+Extensions.swift in Sources */, - OBJ_2730 /* HashVisitor.swift in Sources */, - OBJ_2731 /* Internal.swift in Sources */, - OBJ_2732 /* JSONDecoder.swift in Sources */, - OBJ_2733 /* JSONDecodingError.swift in Sources */, - OBJ_2734 /* JSONDecodingOptions.swift in Sources */, - OBJ_2735 /* JSONEncoder.swift in Sources */, - OBJ_2736 /* JSONEncodingError.swift in Sources */, - OBJ_2737 /* JSONEncodingOptions.swift in Sources */, - OBJ_2738 /* JSONEncodingVisitor.swift in Sources */, - OBJ_2739 /* JSONMapEncodingVisitor.swift in Sources */, - OBJ_2740 /* JSONScanner.swift in Sources */, - OBJ_2741 /* MathUtils.swift in Sources */, - OBJ_2742 /* Message+AnyAdditions.swift in Sources */, - OBJ_2743 /* Message+BinaryAdditions.swift in Sources */, - OBJ_2744 /* Message+JSONAdditions.swift in Sources */, - OBJ_2745 /* Message+JSONArrayAdditions.swift in Sources */, - OBJ_2746 /* Message+TextFormatAdditions.swift in Sources */, - OBJ_2747 /* Message.swift in Sources */, - OBJ_2748 /* MessageExtension.swift in Sources */, - OBJ_2749 /* NameMap.swift in Sources */, - OBJ_2750 /* ProtoNameProviding.swift in Sources */, - OBJ_2751 /* ProtobufAPIVersionCheck.swift in Sources */, - OBJ_2752 /* ProtobufMap.swift in Sources */, - OBJ_2753 /* SelectiveVisitor.swift in Sources */, - OBJ_2754 /* SimpleExtensionMap.swift in Sources */, - OBJ_2755 /* StringUtils.swift in Sources */, - OBJ_2756 /* TextFormatDecoder.swift in Sources */, - OBJ_2757 /* TextFormatDecodingError.swift in Sources */, - OBJ_2758 /* TextFormatEncoder.swift in Sources */, - OBJ_2759 /* TextFormatEncodingVisitor.swift in Sources */, - OBJ_2760 /* TextFormatScanner.swift in Sources */, - OBJ_2761 /* TimeUtils.swift in Sources */, - OBJ_2762 /* UnknownStorage.swift in Sources */, - OBJ_2763 /* Varint.swift in Sources */, - OBJ_2764 /* Version.swift in Sources */, - OBJ_2765 /* Visitor.swift in Sources */, - OBJ_2766 /* WireFormat.swift in Sources */, - OBJ_2767 /* ZigZag.swift in Sources */, - OBJ_2768 /* any.pb.swift in Sources */, - OBJ_2769 /* api.pb.swift in Sources */, - OBJ_2770 /* duration.pb.swift in Sources */, - OBJ_2771 /* empty.pb.swift in Sources */, - OBJ_2772 /* field_mask.pb.swift in Sources */, - OBJ_2773 /* source_context.pb.swift in Sources */, - OBJ_2774 /* struct.pb.swift in Sources */, - OBJ_2775 /* timestamp.pb.swift in Sources */, - OBJ_2776 /* type.pb.swift in Sources */, - OBJ_2777 /* wrappers.pb.swift in Sources */, + OBJ_2801 /* AnyMessageStorage.swift in Sources */, + OBJ_2802 /* AnyUnpackError.swift in Sources */, + OBJ_2803 /* BinaryDecoder.swift in Sources */, + OBJ_2804 /* BinaryDecodingError.swift in Sources */, + OBJ_2805 /* BinaryDecodingOptions.swift in Sources */, + OBJ_2806 /* BinaryDelimited.swift in Sources */, + OBJ_2807 /* BinaryEncoder.swift in Sources */, + OBJ_2808 /* BinaryEncodingError.swift in Sources */, + OBJ_2809 /* BinaryEncodingSizeVisitor.swift in Sources */, + OBJ_2810 /* BinaryEncodingVisitor.swift in Sources */, + OBJ_2811 /* CustomJSONCodable.swift in Sources */, + OBJ_2812 /* Decoder.swift in Sources */, + OBJ_2813 /* DoubleFormatter.swift in Sources */, + OBJ_2814 /* Enum.swift in Sources */, + OBJ_2815 /* ExtensibleMessage.swift in Sources */, + OBJ_2816 /* ExtensionFieldValueSet.swift in Sources */, + OBJ_2817 /* ExtensionFields.swift in Sources */, + OBJ_2818 /* ExtensionMap.swift in Sources */, + OBJ_2819 /* FieldTag.swift in Sources */, + OBJ_2820 /* FieldTypes.swift in Sources */, + OBJ_2821 /* Google_Protobuf_Any+Extensions.swift in Sources */, + OBJ_2822 /* Google_Protobuf_Any+Registry.swift in Sources */, + OBJ_2823 /* Google_Protobuf_Duration+Extensions.swift in Sources */, + OBJ_2824 /* Google_Protobuf_FieldMask+Extensions.swift in Sources */, + OBJ_2825 /* Google_Protobuf_ListValue+Extensions.swift in Sources */, + OBJ_2826 /* Google_Protobuf_Struct+Extensions.swift in Sources */, + OBJ_2827 /* Google_Protobuf_Timestamp+Extensions.swift in Sources */, + OBJ_2828 /* Google_Protobuf_Value+Extensions.swift in Sources */, + OBJ_2829 /* Google_Protobuf_Wrappers+Extensions.swift in Sources */, + OBJ_2830 /* HashVisitor.swift in Sources */, + OBJ_2831 /* Internal.swift in Sources */, + OBJ_2832 /* JSONDecoder.swift in Sources */, + OBJ_2833 /* JSONDecodingError.swift in Sources */, + OBJ_2834 /* JSONDecodingOptions.swift in Sources */, + OBJ_2835 /* JSONEncoder.swift in Sources */, + OBJ_2836 /* JSONEncodingError.swift in Sources */, + OBJ_2837 /* JSONEncodingOptions.swift in Sources */, + OBJ_2838 /* JSONEncodingVisitor.swift in Sources */, + OBJ_2839 /* JSONMapEncodingVisitor.swift in Sources */, + OBJ_2840 /* JSONScanner.swift in Sources */, + OBJ_2841 /* MathUtils.swift in Sources */, + OBJ_2842 /* Message+AnyAdditions.swift in Sources */, + OBJ_2843 /* Message+BinaryAdditions.swift in Sources */, + OBJ_2844 /* Message+JSONAdditions.swift in Sources */, + OBJ_2845 /* Message+JSONArrayAdditions.swift in Sources */, + OBJ_2846 /* Message+TextFormatAdditions.swift in Sources */, + OBJ_2847 /* Message.swift in Sources */, + OBJ_2848 /* MessageExtension.swift in Sources */, + OBJ_2849 /* NameMap.swift in Sources */, + OBJ_2850 /* ProtoNameProviding.swift in Sources */, + OBJ_2851 /* ProtobufAPIVersionCheck.swift in Sources */, + OBJ_2852 /* ProtobufMap.swift in Sources */, + OBJ_2853 /* SelectiveVisitor.swift in Sources */, + OBJ_2854 /* SimpleExtensionMap.swift in Sources */, + OBJ_2855 /* StringUtils.swift in Sources */, + OBJ_2856 /* TextFormatDecoder.swift in Sources */, + OBJ_2857 /* TextFormatDecodingError.swift in Sources */, + OBJ_2858 /* TextFormatEncoder.swift in Sources */, + OBJ_2859 /* TextFormatEncodingVisitor.swift in Sources */, + OBJ_2860 /* TextFormatScanner.swift in Sources */, + OBJ_2861 /* TimeUtils.swift in Sources */, + OBJ_2862 /* UnknownStorage.swift in Sources */, + OBJ_2863 /* Varint.swift in Sources */, + OBJ_2864 /* Version.swift in Sources */, + OBJ_2865 /* Visitor.swift in Sources */, + OBJ_2866 /* WireFormat.swift in Sources */, + OBJ_2867 /* ZigZag.swift in Sources */, + OBJ_2868 /* any.pb.swift in Sources */, + OBJ_2869 /* api.pb.swift in Sources */, + OBJ_2870 /* duration.pb.swift in Sources */, + OBJ_2871 /* empty.pb.swift in Sources */, + OBJ_2872 /* field_mask.pb.swift in Sources */, + OBJ_2873 /* source_context.pb.swift in Sources */, + OBJ_2874 /* struct.pb.swift in Sources */, + OBJ_2875 /* timestamp.pb.swift in Sources */, + OBJ_2876 /* type.pb.swift in Sources */, + OBJ_2877 /* wrappers.pb.swift in Sources */, ); }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - OBJ_2147 /* PBXTargetDependency */ = { + OBJ_2247 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = SwiftGRPC::BoringSSL /* BoringSSL */; }; - OBJ_2518 /* PBXTargetDependency */ = { + OBJ_2618 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = SwiftProtobuf::SwiftProtobuf /* SwiftProtobuf */; }; - OBJ_2519 /* PBXTargetDependency */ = { + OBJ_2619 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = SwiftGRPC::CgRPC /* CgRPC */; }; - OBJ_2520 /* PBXTargetDependency */ = { + OBJ_2620 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = SwiftGRPC::BoringSSL /* BoringSSL */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - OBJ_1403 /* Debug */ = { + OBJ_1475 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++11"; @@ -6372,18 +6657,23 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/BoringSSL_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.BoringSSL; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -6393,7 +6683,7 @@ }; name = Debug; }; - OBJ_1404 /* Release */ = { + OBJ_1476 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++11"; @@ -6407,18 +6697,23 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/BoringSSL_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.BoringSSL; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -6428,7 +6723,7 @@ }; name = Release; }; - OBJ_1723 /* Debug */ = { + OBJ_1799 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6440,8 +6735,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOAtomics_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6461,7 +6756,7 @@ }; name = Debug; }; - OBJ_1724 /* Release */ = { + OBJ_1800 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6473,8 +6768,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOAtomics_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6494,7 +6789,7 @@ }; name = Release; }; - OBJ_1733 /* Debug */ = { + OBJ_1809 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6506,8 +6801,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIODarwin_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6527,7 +6822,7 @@ }; name = Debug; }; - OBJ_1734 /* Release */ = { + OBJ_1810 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6539,8 +6834,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIODarwin_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6560,7 +6855,7 @@ }; name = Release; }; - OBJ_1742 /* Debug */ = { + OBJ_1818 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6572,8 +6867,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOHTTPParser_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6593,7 +6888,7 @@ }; name = Debug; }; - OBJ_1743 /* Release */ = { + OBJ_1819 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6605,8 +6900,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOHTTPParser_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6626,7 +6921,7 @@ }; name = Release; }; - OBJ_1752 /* Debug */ = { + OBJ_1828 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6638,8 +6933,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOLinux_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6659,7 +6954,7 @@ }; name = Debug; }; - OBJ_1753 /* Release */ = { + OBJ_1829 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6671,8 +6966,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOLinux_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6692,7 +6987,7 @@ }; name = Release; }; - OBJ_1763 /* Debug */ = { + OBJ_1839 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { DEFINES_MODULE = NO; @@ -6703,15 +6998,22 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIONghttp2_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", + ); + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CNIONghttp2; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -6721,7 +7023,7 @@ }; name = Debug; }; - OBJ_1764 /* Release */ = { + OBJ_1840 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { DEFINES_MODULE = NO; @@ -6732,15 +7034,22 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIONghttp2_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", + ); + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CNIONghttp2; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -6750,7 +7059,7 @@ }; name = Release; }; - OBJ_1770 /* Debug */ = { + OBJ_1846 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6762,8 +7071,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOSHA1_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6783,7 +7092,7 @@ }; name = Debug; }; - OBJ_1771 /* Release */ = { + OBJ_1847 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6795,8 +7104,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOSHA1_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6816,7 +7125,7 @@ }; name = Release; }; - OBJ_1779 /* Debug */ = { + OBJ_1855 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6828,8 +7137,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOZlib_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6849,7 +7158,7 @@ }; name = Debug; }; - OBJ_1780 /* Release */ = { + OBJ_1856 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -6861,8 +7170,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CNIOZlib_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -6882,7 +7191,7 @@ }; name = Release; }; - OBJ_1788 /* Debug */ = { + OBJ_1864 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++11"; @@ -6897,18 +7206,23 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CgRPC_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CgRPC; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -6918,7 +7232,7 @@ }; name = Debug; }; - OBJ_1789 /* Release */ = { + OBJ_1865 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++11"; @@ -6933,18 +7247,23 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/CgRPC_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CgRPC; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -6954,7 +7273,7 @@ }; name = Release; }; - OBJ_2150 /* Debug */ = { + OBJ_2250 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -6979,7 +7298,7 @@ }; name = Debug; }; - OBJ_2151 /* Release */ = { + OBJ_2251 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7004,7 +7323,7 @@ }; name = Release; }; - OBJ_2165 /* Debug */ = { + OBJ_2265 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7014,7 +7333,7 @@ }; name = Debug; }; - OBJ_2166 /* Release */ = { + OBJ_2266 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7024,7 +7343,7 @@ }; name = Release; }; - OBJ_2171 /* Debug */ = { + OBJ_2271 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7035,19 +7354,24 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/Echo_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7056,7 +7380,7 @@ }; name = Debug; }; - OBJ_2172 /* Release */ = { + OBJ_2272 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7067,19 +7391,24 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/Echo_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7088,7 +7417,7 @@ }; name = Release; }; - OBJ_2193 /* Debug */ = { + OBJ_2293 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7097,26 +7426,31 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/EchoNIO_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7125,7 +7459,7 @@ }; name = Debug; }; - OBJ_2194 /* Release */ = { + OBJ_2294 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7134,26 +7468,31 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/EchoNIO_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7162,7 +7501,7 @@ }; name = Release; }; - OBJ_2244 /* Debug */ = { + OBJ_2344 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7172,11 +7511,11 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIO_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7197,7 +7536,7 @@ }; name = Debug; }; - OBJ_2245 /* Release */ = { + OBJ_2345 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7207,11 +7546,11 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIO_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7232,7 +7571,7 @@ }; name = Release; }; - OBJ_2316 /* Debug */ = { + OBJ_2416 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7242,8 +7581,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOConcurrencyHelpers_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7264,7 +7603,7 @@ }; name = Debug; }; - OBJ_2317 /* Release */ = { + OBJ_2417 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7274,8 +7613,8 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOConcurrencyHelpers_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7296,7 +7635,7 @@ }; name = Release; }; - OBJ_2325 /* Debug */ = { + OBJ_2425 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7306,11 +7645,11 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOFoundationCompat_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7331,7 +7670,7 @@ }; name = Debug; }; - OBJ_2326 /* Release */ = { + OBJ_2426 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7341,11 +7680,11 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOFoundationCompat_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7366,7 +7705,7 @@ }; name = Release; }; - OBJ_2345 /* Debug */ = { + OBJ_2445 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7376,13 +7715,13 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOHTTP1_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7403,7 +7742,7 @@ }; name = Debug; }; - OBJ_2346 /* Release */ = { + OBJ_2446 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7413,13 +7752,13 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOHTTP1_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7440,7 +7779,7 @@ }; name = Release; }; - OBJ_2377 /* Debug */ = { + OBJ_2477 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7450,26 +7789,31 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOHTTP2_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", "-lz", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.NIOHTTP2; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -7480,7 +7824,7 @@ }; name = Debug; }; - OBJ_2378 /* Release */ = { + OBJ_2478 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7490,26 +7834,31 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOHTTP2_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", "-lz", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.NIOHTTP2; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -7520,7 +7869,7 @@ }; name = Release; }; - OBJ_2422 /* Debug */ = { + OBJ_2522 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7530,7 +7879,7 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOPriorityQueue_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7551,7 +7900,7 @@ }; name = Debug; }; - OBJ_2423 /* Release */ = { + OBJ_2523 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7561,7 +7910,7 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOPriorityQueue_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7582,7 +7931,7 @@ }; name = Release; }; - OBJ_2429 /* Debug */ = { + OBJ_2529 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7592,11 +7941,11 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOTLS_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7617,7 +7966,7 @@ }; name = Debug; }; - OBJ_2430 /* Release */ = { + OBJ_2530 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7627,11 +7976,11 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/NIOTLS_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -7652,7 +8001,7 @@ }; name = Release; }; - OBJ_2452 /* Debug */ = { + OBJ_2552 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7661,18 +8010,23 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/RootsEncoder_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7681,7 +8035,7 @@ }; name = Debug; }; - OBJ_2453 /* Release */ = { + OBJ_2553 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7690,18 +8044,23 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/RootsEncoder_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7710,7 +8069,7 @@ }; name = Release; }; - OBJ_2459 /* Debug */ = { + OBJ_2559 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7721,19 +8080,24 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/Simple_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7742,7 +8106,7 @@ }; name = Debug; }; - OBJ_2460 /* Release */ = { + OBJ_2560 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -7753,19 +8117,24 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/Simple_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -7774,7 +8143,7 @@ }; name = Release; }; - OBJ_2475 /* Debug */ = { + OBJ_2575 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7786,19 +8155,24 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPC_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.SwiftGRPC; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -7809,7 +8183,7 @@ }; name = Debug; }; - OBJ_2476 /* Release */ = { + OBJ_2576 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7821,19 +8195,24 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPC_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.SwiftGRPC; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -7844,7 +8223,7 @@ }; name = Release; }; - OBJ_2522 /* Debug */ = { + OBJ_2622 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7854,26 +8233,31 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPCNIO_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.SwiftGRPCNIO; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -7884,7 +8268,7 @@ }; name = Debug; }; - OBJ_2523 /* Release */ = { + OBJ_2623 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -7894,26 +8278,31 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPCNIO_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.SwiftGRPCNIO; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -7924,7 +8313,7 @@ }; name = Release; }; - OBJ_2594 /* Debug */ = { + OBJ_2694 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -7935,36 +8324,41 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPCNIOTests_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_VERSION = 4.0; TARGET_NAME = SwiftGRPCNIOTests; }; name = Debug; }; - OBJ_2595 /* Release */ = { + OBJ_2695 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -7975,36 +8369,41 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-http2.git-1684232237084789971/Sources/CNIONghttp2/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOZlib/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOHTTPParser/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOSHA1/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOAtomics/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIODarwin/include", - "$(SRCROOT)/.build/checkouts/swift-nio.git--5531377063216196022/Sources/CNIOLinux/include", + "$(SRCROOT)/.build/checkouts/swift-nio-http2/Sources/CNIONghttp2/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOZlib/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOSHA1/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOAtomics/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIODarwin/include", + "$(SRCROOT)/.build/checkouts/swift-nio/Sources/CNIOLinux/include", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPCNIOTests_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/CNIONghttp2/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_VERSION = 4.0; TARGET_NAME = SwiftGRPCNIOTests; }; name = Release; }; - OBJ_2652 /* Debug */ = { + OBJ_2752 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8014,7 +8413,7 @@ }; name = Debug; }; - OBJ_2653 /* Release */ = { + OBJ_2753 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8024,21 +8423,21 @@ }; name = Release; }; - OBJ_2658 /* Debug */ = { + OBJ_2758 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; }; name = Debug; }; - OBJ_2659 /* Release */ = { + OBJ_2759 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; }; name = Release; }; - OBJ_2664 /* Debug */ = { + OBJ_2764 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -8051,26 +8450,31 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPCTests_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_VERSION = 4.0; TARGET_NAME = SwiftGRPCTests; }; name = Debug; }; - OBJ_2665 /* Release */ = { + OBJ_2765 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -8083,26 +8487,31 @@ "$(inherited)", "$(SRCROOT)/Sources/CgRPC/include", "$(SRCROOT)/Sources/BoringSSL/include", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", "$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/SwiftGRPCTests_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include -Xcc -fmodule-map-file=$(SRCROOT)/Sources/CgRPC/include/module.modulemap -Xcc -fmodule-map-file=$(SRCROOT)/SwiftGRPC-Carthage.xcodeproj/GeneratedModuleMap/BoringSSL/module.modulemap"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_VERSION = 4.0; TARGET_NAME = SwiftGRPCTests; }; name = Release; }; - OBJ_2698 /* Debug */ = { + OBJ_2798 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -8122,12 +8531,12 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGET_NAME = SwiftProtobuf; }; name = Debug; }; - OBJ_2699 /* Release */ = { + OBJ_2799 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -8147,12 +8556,12 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGET_NAME = SwiftProtobuf; }; name = Release; }; - OBJ_2781 /* Debug */ = { + OBJ_2881 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8162,7 +8571,7 @@ }; name = Debug; }; - OBJ_2782 /* Release */ = { + OBJ_2882 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8172,7 +8581,7 @@ }; name = Release; }; - OBJ_2787 /* Debug */ = { + OBJ_2887 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -8192,12 +8601,12 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGET_NAME = SwiftProtobufPluginLibrary; }; name = Debug; }; - OBJ_2788 /* Release */ = { + OBJ_2888 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ENABLE_TESTABILITY = YES; @@ -8217,12 +8626,12 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGET_NAME = SwiftProtobufPluginLibrary; }; name = Release; }; - OBJ_2813 /* Debug */ = { + OBJ_2913 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -8239,12 +8648,12 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGET_NAME = "protoc-gen-swift"; }; name = Debug; }; - OBJ_2814 /* Release */ = { + OBJ_2914 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -8261,12 +8670,12 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGET_NAME = "protoc-gen-swift"; }; name = Release; }; - OBJ_2841 /* Debug */ = { + OBJ_2941 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -8275,18 +8684,23 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/protoc_gen_swiftgrpc_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -8295,7 +8709,7 @@ }; name = Debug; }; - OBJ_2842 /* Release */ = { + OBJ_2942 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( @@ -8304,18 +8718,23 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support.git--6355023976830560477", - "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support.git--1829432960581026853", + "$(SRCROOT)/.build/checkouts/swift-nio-nghttp2-support", + "$(SRCROOT)/.build/checkouts/swift-nio-zlib-support", ); INFOPLIST_FILE = "SwiftGRPC-Carthage.xcodeproj/protoc_gen_swiftgrpc_Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; - OTHER_CFLAGS = "$(inherited)"; + OTHER_CFLAGS = ( + "$(inherited)", + "-I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include", + ); OTHER_LDFLAGS = ( "$(inherited)", + "-L/usr/local/homebrew/Cellar/nghttp2/1.35.1/lib", + "-lnghttp2", "-lz", ); - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -I/usr/local/homebrew/Cellar/nghttp2/1.35.1/include"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; @@ -8324,7 +8743,7 @@ }; name = Release; }; - OBJ_2860 /* Debug */ = { + OBJ_2960 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8334,7 +8753,7 @@ }; name = Debug; }; - OBJ_2861 /* Release */ = { + OBJ_2961 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8344,7 +8763,7 @@ }; name = Release; }; - OBJ_2866 /* Debug */ = { + OBJ_2966 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8354,7 +8773,7 @@ }; name = Debug; }; - OBJ_2867 /* Release */ = { + OBJ_2967 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -8376,8 +8795,9 @@ ENABLE_NS_ASSERTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", "$(inherited)", + "SWIFT_PACKAGE=1", + "DEBUG=1", ); MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; @@ -8385,7 +8805,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SWIFT_PACKAGE DEBUG"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE DEBUG"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; USE_HEADERMAP = NO; }; @@ -8401,12 +8821,16 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_OPTIMIZATION_LEVEL = s; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE=1", + ); MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_SWIFT_FLAGS = "-DXcode"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; USE_HEADERMAP = NO; }; @@ -8415,20 +8839,20 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - OBJ_1402 /* Build configuration list for PBXNativeTarget "BoringSSL" */ = { + OBJ_1474 /* Build configuration list for PBXNativeTarget "BoringSSL" */ = { isa = XCConfigurationList; buildConfigurations = ( - OBJ_1403 /* Debug */, - OBJ_1404 /* Release */, + OBJ_1475 /* Debug */, + OBJ_1476 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - OBJ_1787 /* Build configuration list for PBXNativeTarget "CgRPC" */ = { + OBJ_1863 /* Build configuration list for PBXNativeTarget "CgRPC" */ = { isa = XCConfigurationList; buildConfigurations = ( - OBJ_1788 /* Debug */, - OBJ_1789 /* Release */, + OBJ_1864 /* Debug */, + OBJ_1865 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -8442,20 +8866,20 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - OBJ_2474 /* Build configuration list for PBXNativeTarget "SwiftGRPC" */ = { + OBJ_2574 /* Build configuration list for PBXNativeTarget "SwiftGRPC" */ = { isa = XCConfigurationList; buildConfigurations = ( - OBJ_2475 /* Debug */, - OBJ_2476 /* Release */, + OBJ_2575 /* Debug */, + OBJ_2576 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - OBJ_2697 /* Build configuration list for PBXNativeTarget "SwiftProtobuf" */ = { + OBJ_2797 /* Build configuration list for PBXNativeTarget "SwiftProtobuf" */ = { isa = XCConfigurationList; buildConfigurations = ( - OBJ_2698 /* Debug */, - OBJ_2699 /* Release */, + OBJ_2798 /* Debug */, + OBJ_2799 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/EchoNIO.xcscheme b/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/EchoNIO.xcscheme index cb94fc823..8fc083668 100644 --- a/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/EchoNIO.xcscheme +++ b/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/EchoNIO.xcscheme @@ -24,7 +24,7 @@ @@ -33,7 +33,7 @@ diff --git a/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/RootsEncoder.xcscheme b/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/RootsEncoder.xcscheme index 170bbc470..fe267be86 100644 --- a/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/RootsEncoder.xcscheme +++ b/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/RootsEncoder.xcscheme @@ -24,7 +24,7 @@ @@ -33,7 +33,7 @@ diff --git a/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/SwiftGRPC-Package.xcscheme b/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/SwiftGRPC-Package.xcscheme index 072a18082..9a851eec5 100644 --- a/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/SwiftGRPC-Package.xcscheme +++ b/SwiftGRPC-Carthage.xcodeproj/xcshareddata/xcschemes/SwiftGRPC-Package.xcscheme @@ -33,7 +33,7 @@ @@ -45,8 +45,8 @@ buildForAnalyzing = "YES"> @@ -58,8 +58,8 @@ buildForAnalyzing = "YES"> @@ -71,8 +71,8 @@ buildForAnalyzing = "YES"> @@ -85,7 +85,7 @@ @@ -98,7 +98,7 @@ @@ -110,8 +110,8 @@ buildForAnalyzing = "YES"> @@ -123,8 +123,8 @@ buildForAnalyzing = "YES"> @@ -136,8 +136,8 @@ buildForAnalyzing = "YES"> @@ -150,9 +150,9 @@ + ReferencedContainer = "container:SwiftGRPC-Carthage.xcodeproj" + BuildableName = "SwiftProtobuf.framework"> diff --git a/SwiftGRPC.podspec b/SwiftGRPC.podspec index 896002f65..a374a0ea8 100644 --- a/SwiftGRPC.podspec +++ b/SwiftGRPC.podspec @@ -11,7 +11,7 @@ Pod::Spec.new do |s| s.name = 'SwiftGRPC' - s.version = '0.8.1' + s.version = '0.8.2' s.license = { :type => 'Apache License, Version 2.0', :text => <<-LICENSE Copyright 2018, gRPC Authors. All rights reserved. @@ -39,7 +39,7 @@ Pod::Spec.new do |s| s.source_files = 'Sources/SwiftGRPC/*.swift', 'Sources/SwiftGRPC/**/*.swift', 'Sources/CgRPC/shim/*.[ch]' s.public_header_files = 'Sources/CgRPC/shim/cgrpc.h' - s.dependency 'gRPC-Core', '~> 1.12.0' + s.dependency 'gRPC-Core', '~> 1.19.0' s.dependency 'BoringSSL', '~> 10.0' s.dependency 'SwiftProtobuf', '~> 1.3.1' end diff --git a/Tests/SwiftGRPCTests/ClientCancellingTests.swift b/Tests/SwiftGRPCTests/ClientCancellingTests.swift index 68591f432..24fe47756 100644 --- a/Tests/SwiftGRPCTests/ClientCancellingTests.swift +++ b/Tests/SwiftGRPCTests/ClientCancellingTests.swift @@ -18,6 +18,64 @@ import Foundation @testable import SwiftGRPC import XCTest +// Waits 10ms before each send operation and does not log sending errors, +// as these are expected when the call times out. +private class SleepingEchoProvider: Echo_EchoProvider { + func get(request: Echo_EchoRequest, session _: Echo_EchoGetSession) throws -> Echo_EchoResponse { + Thread.sleep(forTimeInterval: 0.1) + var response = Echo_EchoResponse() + response.text = "Swift echo get: " + request.text + return response + } + + func expand(request: Echo_EchoRequest, session: Echo_EchoExpandSession) throws -> ServerStatus? { + let parts = request.text.components(separatedBy: " ") + for (i, part) in parts.enumerated() { + Thread.sleep(forTimeInterval: 0.1) + var response = Echo_EchoResponse() + response.text = "Swift echo expand (\(i)): \(part)" + try session.send(response) + } + return .ok + } + + func collect(session: Echo_EchoCollectSession) throws -> Echo_EchoResponse? { + Thread.sleep(forTimeInterval: 0.1) + var parts: [String] = [] + while true { + do { + guard let request = try session.receive() + else { break } // End of stream + parts.append(request.text) + } catch { + break + } + } + var response = Echo_EchoResponse() + response.text = "Swift echo collect: " + parts.joined(separator: " ") + return response + } + + func update(session: Echo_EchoUpdateSession) throws -> ServerStatus? { + var count = 0 + while true { + do { + Thread.sleep(forTimeInterval: 0.1) + guard let request = try session.receive() + else { break } // End of stream + var response = Echo_EchoResponse() + response.text = "Swift echo update (\(count)): \(request.text)" + count += 1 + try session.send(response) + } catch { + break + } + } + return .ok + } +} + + class ClientCancellingTests: BasicEchoTestCase { static var allTests: [(String, (ClientCancellingTests) -> () throws -> Void)] { return [ @@ -27,12 +85,18 @@ class ClientCancellingTests: BasicEchoTestCase { ("testBidirectionalStreaming", testBidirectionalStreaming), ] } + + override func makeProvider() -> Echo_EchoProvider { return SleepingEchoProvider() } +} + +private func manyWords(_ count: Int) -> String { + return (0..&2 + exit 1 +fi set -euxo pipefail diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index 948defe07..afecc161f 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -78,4 +78,4 @@ rm -f $DSTROOT/crypto/fipsmodule/bcm.c # # edit the BoringSSL headers to disable dependency on assembly language helpers. # -perl -pi -e '$_ .= qq(\n#define OPENSSL_NO_ASM\n) if /#define OPENSSL_HEADER_BASE_H/' Sources/BoringSSL/include/openssl/base.h +perl -pi -e '$_ .= qq(\n#define OPENSSL_NO_ASM\n) if /#define OPENSSL_HEADER_BASE_H/' $DSTROOT/include/openssl/base.h diff --git a/scripts/vendor-grpc.sh b/scripts/vendor-grpc.sh index a30885700..f9fa30e8d 100755 --- a/scripts/vendor-grpc.sh +++ b/scripts/vendor-grpc.sh @@ -65,12 +65,12 @@ do cp $TMP_DIR/grpc/$src $dest done -echo "COPYING additional nanopb headers" -cp $TMP_DIR/grpc/third_party/nanopb/*.h $DSTROOT/CgRPC/third_party/nanopb/ - echo "ADDING additional compiler flags to nanopb/pb.h" perl -pi -e 's/\/\* #define PB_FIELD_16BIT 1 \*\//#define PB_FIELD_16BIT 1/' $DSTROOT/CgRPC/third_party/nanopb/pb.h +echo "MOVING nanopb headers to CgRPC/include" +mv $DSTROOT/CgRPC/third_party/nanopb/*.h $DSTROOT/CgRPC/include/ + echo "ADDING additional compiler flags to tsi/ssl_transport_security.cc" perl -pi -e 's/#define TSI_OPENSSL_ALPN_SUPPORT 1/#define TSI_OPENSSL_ALPN_SUPPORT 0/' $DSTROOT/CgRPC/src/core/tsi/ssl_transport_security.cc @@ -78,4 +78,5 @@ echo "DISABLING ARES" perl -pi -e 's/#define GRPC_ARES 1/#define GRPC_ARES 0/' $DSTROOT/CgRPC/include/grpc/impl/codegen/port_platform.h echo "COPYING roots.pem" +echo "Please run 'swift run RootsEncoder > Sources/SwiftGRPC/Core/Roots.swift' to import the updated certificates." cp $TMP_DIR/grpc/etc/roots.pem $DSTASSETS/roots.pem