[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/ca.crt b/src/lynq/lib/liblynq-protcl/http/cert/ca.crt
new file mode 100644
index 0000000..a9007d2
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/ca.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDfzCCAmegAwIBAgIJAODN6ztlacOjMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV
+BAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5nMRAwDgYD
+VQQKDAdUZWFtc3VuMRAwDgYDVQQLDAdUZWFtc3VuMCAXDTIwMDkyODEwMTUwNVoY
+DzIxMjAwOTA0MTAxNTA1WjBVMQswCQYDVQQGEwJDTjEQMA4GA1UECAwHQmVpamlu
+ZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVhbXN1bjEQMA4GA1UECwwH
+VGVhbXN1bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqVvba2fnHk
+gayq5P0kLQIV+xu1yND/LPOuuCTwnVHHqp0VHxtIP8TvYhxXT7oaqsMNQlPKm+SH
+1wDVpe+mrbrv3G9vVsfjPdHf772fP3gLb/+MbnADfD9cq9rIFWKfXNw5F9GYetA2
+gEo/oA0jD2t6Z69hJqsnmhw4LAJhVJxTefyAcOLm59PHB3FRLPOfWOZIX4m16yXn
+C+Pgi3t7fAZDt2ty3VGxg63rLGEoCh0J1AlQhU4QfF7wu1eqxWbMIukkpOzex88k
+C3chj4aWYOscUNCoiPtV2EtR1gqyoyqMIGUtMPtw703oY8A8fNcAjLtqUsObr1JD
+vay+VBVG7V0CAwEAAaNQME4wHQYDVR0OBBYEFOHWjOIKOO7OKH1/+0PjMs8eYK2t
+MB8GA1UdIwQYMBaAFOHWjOIKOO7OKH1/+0PjMs8eYK2tMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggEBAFUK/09WXsFVHhOzfFYquHqNcDyYeld9XVQ7NrZp
+vzI/+rxeHswvQ8+iQF9pV0aOMo27ccE7AjuHwdFwQQHal9y892tzFXSUxfhATT/I
+ZAySC3Gvsf8AQYkcu+fWDLB0FZmRbxvO3+tSTnL+4jkI+IJbSsDvDB6VG9ugWTwd
+O14X+gOalwO1TcsZuMV1d4a1nB8X6pkG78KcQfMwkrb/KPWhZKaxcksBLxBkKHt8
+sZY+FERnWZf3sNaCpm0Uwvd3Ua+IU+f/FpiShBZnSk5mqXB/C6sx2PbXyXNh6fv/
+5rTIpv3nlxAVHNVJo0LFAE5wPpCMCNj082WuT25OkVxKIyY=
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/ca.key b/src/lynq/lib/liblynq-protcl/http/cert/ca.key
new file mode 100644
index 0000000..4758736
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAupW9trZ+ceSBrKrk/SQtAhX7G7XI0P8s8664JPCdUceqnRUf
+G0g/xO9iHFdPuhqqww1CU8qb5IfXANWl76atuu/cb29Wx+M90d/vvZ8/eAtv/4xu
+cAN8P1yr2sgVYp9c3DkX0Zh60DaASj+gDSMPa3pnr2EmqyeaHDgsAmFUnFN5/IBw
+4ubn08cHcVEs859Y5khfibXrJecL4+CLe3t8BkO3a3LdUbGDressYSgKHQnUCVCF
+ThB8XvC7V6rFZswi6SSk7N7HzyQLdyGPhpZg6xxQ0KiI+1XYS1HWCrKjKowgZS0w
++3DvTehjwDx81wCMu2pSw5uvUkO9rL5UFUbtXQIDAQABAoIBAH/D+/X6v1kkHTvs
+hgNl20AbZykRcOLUaaawFL6O2Vtfu0/3X6ah8bDcLzWzABAzJI2OLcYM7nUuI6cZ
+pZgWbc6dYzgXaLhVvkZR7uvM+XwtcNLwCcvARztoLPISoro24DKZEdtfa3HacDzn
+lqSIRo3VctygTQdUhe4e9NvoZDTqtOvjdu2NDYPTKawBe0KHWNFTsp8eUS+5rwcb
+IWWnfjcq9Z6HHobY5wf274izlloG1wNtxgqX4PTVRKlK6gAnZVaFFaRBLypBj4IC
+XmqmWrxtitGnIXTaSZjlkRo6SkFGiz+ovnjs0qbfBKu+0C83qZVS93aK9lVLvoum
+JKsLUe0CgYEA5T7s16uow0AG6UBmvjjlEtb6F0mXCqaGij9cO1ClZ4tBBzVxohRW
+ZCo4mGOSBToUnPTby3B/ZiN0+Pwz7nmOploIv9X65V6798MA6v5juWwThI7lQmu+
+S7rxpxkolDqTdyochqseqcIHv8ZuxRI0JtapjXNDQ1H+rd7iozm7btcCgYEA0FxB
+gxaIilQkQdw4byDv41tlGbbgeVCOKp86VxxkpDTz6MMs0yIRp+F9p58rostkPcIh
+ToWtoneeaT6P4WwuA2ETvI6g03H4nN1X1MTdx+M0FniYNMe20Ye0N1GhCILLXsTb
+XKNB0/u7nBIbjNkZ/0mCFGjGd71JjVQ5KaSpgusCgYEAiveKO3Mj6rh1eBBCOC3l
+L3aCRHunxB0Okd+22X4Zxprz4JrVN5t8g1vU0wwJCIIc3MjSNJENqaz0y7qXAIlP
+oCgUBbaBUWoMKDVd6RYs/co2SrUU5R7LTL0WoGTv5Gtd2W79u+UfwWiNqgNwQqa2
+VpTqU4T70WNzL5Ndb/UfWiECgYEAguNBYCi6kzLyJ9FAPkcRiuAx7WpdLrg05n9p
+9ajna+O7yN86fFMthil3duHdVoGwMb+OjrYY8jN0dqaPWctMSGEmNc/fJZS12UyO
+TSFyNIv8f5U4AAfpR0yZIBsOLruDJ8BAELyZsKG1JACX/+2tkBnMNifvbO6ikr5y
+vj8rIQsCgYEAhO/0Ky4A3jOvMK4f1NAVWBcuOt3UzmF06cRU6rCF6Roi1WNoDHsd
+XR2qZfVgozhqj0YzXQ4J83HuyeCLWynKLptJkgqEdZDoBJ6vGVg9GZmyYoQD0wRH
+l8q/xQvrdMhlJvZX7zKDv2h7QS/i2DODFAeYtnYN/aBzGfPSgpV1N+o=
+-----END RSA PRIVATE KEY-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/ca.p12 b/src/lynq/lib/liblynq-protcl/http/cert/ca.p12
new file mode 100644
index 0000000..85eafa4
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/ca.p12
Binary files differ
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.crt b/src/lynq/lib/liblynq-protcl/http/cert/client.crt
new file mode 100644
index 0000000..7eb321f
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.crt
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:16:35 2020 GMT
+ Not After : Sep 28 10:16:35 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guog, CN=guog
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:99:5f:72:71:bc:e4:08:76:43:77:32:9d:17:61:
+ 74:f7:44:49:33:ef:3c:7f:89:0e:97:0e:ce:d9:39:
+ 32:ca:10:34:af:6c:8c:39:19:58:38:16:9f:11:1e:
+ 55:9f:95:89:ac:fb:e2:cb:5f:ee:1a:bd:3d:25:79:
+ cd:18:20:36:83:ef:df:93:2e:7a:9e:1f:2f:98:05:
+ b0:65:c9:4f:93:c2:00:0b:70:84:2b:fb:44:01:d1:
+ 36:22:a6:5a:43:f7:c6:54:f4:81:cc:a6:26:47:e4:
+ 92:f5:e6:97:41:34:3e:c5:37:89:13:64:c6:cc:93:
+ 6c:a2:b0:0e:64:e0:3b:7d:a2:2e:b1:e4:42:79:cf:
+ a7:06:5e:89:53:4b:56:46:f5:07:54:99:5e:0f:80:
+ 1b:28:2f:19:63:c2:cd:e9:97:8f:09:cd:38:f4:05:
+ d4:83:00:4a:3b:14:00:51:d9:fe:b9:d4:82:52:c3:
+ a3:2f:2a:2d:f4:98:b1:44:0f:8c:ca:ee:0c:94:7e:
+ af:8b:b8:ab:8c:21:9d:16:1e:72:ee:9b:3d:04:70:
+ 1c:c6:46:06:d3:df:12:59:97:b6:af:3c:97:8d:b9:
+ 2e:88:d0:c9:c5:42:14:bb:c2:dd:ac:a3:3a:80:8a:
+ af:34:d2:e4:85:26:92:da:0e:99:20:3b:e8:78:11:
+ ba:e3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 27:96:0E:38:74:AA:00:98:D8:8C:54:5F:09:98:D9:03:C8:3D:D7:9C
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ a8:89:a9:9c:48:86:04:10:bf:5a:83:60:78:44:eb:42:59:af:
+ 9b:58:33:2c:68:33:f5:e1:c0:a9:d2:07:87:55:07:dc:95:68:
+ 18:20:9d:d2:3a:ad:3c:fc:d7:03:ec:f1:d4:91:26:09:d5:dd:
+ cd:90:74:0a:2a:c6:5a:98:6a:f7:e8:4f:04:e7:35:23:70:5e:
+ ea:20:83:b6:b7:6f:8b:2c:80:3e:0e:c5:f0:a1:30:4a:5e:df:
+ 6a:bc:60:43:2f:91:c8:e2:14:ca:47:af:9c:6b:ad:8d:c5:a6:
+ cd:1f:f8:1a:82:d8:02:b0:e7:d4:06:a2:47:bc:f7:b7:0e:dc:
+ 89:8d:3e:c9:50:55:8a:a1:04:5e:e6:a6:23:d8:54:37:57:c5:
+ 1e:57:0d:ed:1b:45:2a:1a:e3:10:ba:17:95:cf:c3:7d:a3:ec:
+ 08:d2:57:db:24:32:a0:9f:8e:30:95:81:20:00:fb:97:eb:c9:
+ 0c:e9:82:0f:62:a5:16:fa:ed:ae:7c:59:2c:f1:f2:b5:fd:8d:
+ c0:fe:20:ba:d2:f8:40:ef:2f:2e:ec:98:c3:55:b1:dd:83:4d:
+ 2a:9a:a3:f2:fc:4a:29:71:70:5f:3f:44:47:07:af:8f:ad:57:
+ 2c:1a:d9:68:19:c4:e8:c0:6b:2e:50:f9:d6:5c:97:ec:5a:8a:
+ cd:ac:8c:0f
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE2MzVaFw0yMTA5Mjgx
+MDE2MzVaME8xCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ0wCwYDVQQLDARndW9nMQ0wCwYDVQQDDARndW9nMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV9ycbzkCHZDdzKdF2F090RJM+88f4kO
+lw7O2TkyyhA0r2yMORlYOBafER5Vn5WJrPviy1/uGr09JXnNGCA2g+/fky56nh8v
+mAWwZclPk8IAC3CEK/tEAdE2IqZaQ/fGVPSBzKYmR+SS9eaXQTQ+xTeJE2TGzJNs
+orAOZOA7faIuseRCec+nBl6JU0tWRvUHVJleD4AbKC8ZY8LN6ZePCc049AXUgwBK
+OxQAUdn+udSCUsOjLyot9JixRA+Myu4MlH6vi7irjCGdFh5y7ps9BHAcxkYG098S
+WZe2rzyXjbkuiNDJxUIUu8LdrKM6gIqvNNLkhSaS2g6ZIDvoeBG64wIDAQABo3sw
+eTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUJ5YOOHSqAJjYjFRfCZjZA8g915wwHwYDVR0j
+BBgwFoAU4daM4go47s4ofX/7Q+Myzx5gra0wDQYJKoZIhvcNAQELBQADggEBAKiJ
+qZxIhgQQv1qDYHhE60JZr5tYMyxoM/XhwKnSB4dVB9yVaBggndI6rTz81wPs8dSR
+JgnV3c2QdAoqxlqYavfoTwTnNSNwXuogg7a3b4ssgD4OxfChMEpe32q8YEMvkcji
+FMpHr5xrrY3Fps0f+BqC2AKw59QGoke897cO3ImNPslQVYqhBF7mpiPYVDdXxR5X
+De0bRSoa4xC6F5XPw32j7AjSV9skMqCfjjCVgSAA+5fryQzpgg9ipRb67a58WSzx
+8rX9jcD+ILrS+EDvLy7smMNVsd2DTSqao/L8SilxcF8/REcHr4+tVywa2WgZxOjA
+ay5Q+dZcl+xais2sjA8=
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.csr b/src/lynq/lib/liblynq-protcl/http/cert/client.csr
new file mode 100644
index 0000000..f6b6207
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAO
+BgNVBAcMB0JlaWppbmcxEDAOBgNVBAoMB1RlYW1zdW4xDTALBgNVBAsMBGd1b2cx
+DTALBgNVBAMMBGd1b2cwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ
+X3JxvOQIdkN3Mp0XYXT3REkz7zx/iQ6XDs7ZOTLKEDSvbIw5GVg4Fp8RHlWflYms
+++LLX+4avT0lec0YIDaD79+TLnqeHy+YBbBlyU+TwgALcIQr+0QB0TYiplpD98ZU
+9IHMpiZH5JL15pdBND7FN4kTZMbMk2yisA5k4Dt9oi6x5EJ5z6cGXolTS1ZG9QdU
+mV4PgBsoLxljws3pl48JzTj0BdSDAEo7FABR2f651IJSw6MvKi30mLFED4zK7gyU
+fq+LuKuMIZ0WHnLumz0EcBzGRgbT3xJZl7avPJeNuS6I0MnFQhS7wt2sozqAiq80
+0uSFJpLaDpkgO+h4EbrjAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAdntI2cu7
+H+N3BURFIfq+Zjzd2djO6SthHJ3h5KaUkxvGfuL3gVau+7w/RO6hgkPeQ0/E7dSy
+ZHxURkLNlbVgZz/zVH/rxPPlkwDP+HqOLMRrSkckvNjuuinxWizM1wKASOS4Yefp
+CS/1AtAKBePdmxqTmgFO3yciIs0I/IEf6Gw1XuW8iVfCcR2aTRLI/SQfPgXOp/FK
+YSpIs0WbVDp8SZd8994rVOyujqbfjcjc+zHEqyb24pUoEMstXK51QWZOjixoLHH3
+CdmxKwNk6GlAEXELhC1FjvwZLJR5emEoqsu4NdEPopfsZ0kLRDbJo0KdeErbh1e9
+6ixDUYO5TkWU5w==
+-----END CERTIFICATE REQUEST-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.key b/src/lynq/lib/liblynq-protcl/http/cert/client.key
new file mode 100644
index 0000000..3d63cca
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAmV9ycbzkCHZDdzKdF2F090RJM+88f4kOlw7O2TkyyhA0r2yM
+ORlYOBafER5Vn5WJrPviy1/uGr09JXnNGCA2g+/fky56nh8vmAWwZclPk8IAC3CE
+K/tEAdE2IqZaQ/fGVPSBzKYmR+SS9eaXQTQ+xTeJE2TGzJNsorAOZOA7faIuseRC
+ec+nBl6JU0tWRvUHVJleD4AbKC8ZY8LN6ZePCc049AXUgwBKOxQAUdn+udSCUsOj
+Lyot9JixRA+Myu4MlH6vi7irjCGdFh5y7ps9BHAcxkYG098SWZe2rzyXjbkuiNDJ
+xUIUu8LdrKM6gIqvNNLkhSaS2g6ZIDvoeBG64wIDAQABAoIBAGQ7moF2Xtig4Wpu
+63cyO8y1FdoZCUKYAa77AHe6B9VCTgwvNlzCkYLmVcJMPszyX21rmEYtRWC4N9Pc
+DAsuUjJbe5Omln/sBaCmZye+LoF0Ea9oMxjDNyiw3145tVgh/73ZpVJnazEk0l5d
++o+kYzlkF/NSsxFTb3XK9T07xeVOK3dpher/YKJIFTicGIp+PUenIuVBMVWjiUM3
+ku/xHedoCCjURMMaoBXolA7L5YNw6dapV4BYBTFZ5H/eTdtEmIRpBypStHSuxrKC
+qsEPLPD0/vFgRoD6fzGoYsa/is4kX56vB/LISslaazY1D57c6hC1o/OwBt7/MzAk
+0rMeoiECgYEAy/lr72yHpeG2+6LXxSRixKd20x1Z4mZbtAKy+9XHyjof8I45QqDp
+sIAdj1VbVacGibb71BjYxrkSDQXpK94padlfpGcyxnRtg+wZaIne5HVJShqUjcRH
+G/aKXxjnGkyRmP7eJgvEkKrgLXoC8n/86PFPehP6QgjAgNh+XYq/qBkCgYEAwH37
+5ZJlWrTUjVzDjszqIB4ELPu2UId1wMnoTIocQ89XsWwk7RLmrknV8y8DfnwF8fbp
+nVLVTBB11bX5cbwu8iw8J5XvBAu3zs0UTHE6c4DUsqq92KO2a7qSVJeHB8IZErei
+DWCSv8qcfVc3ZVOMg4N1VGoYqNq8jQd8fqBgClsCgYEAsF4jeOtTwxgPGzfr7/eN
+O1M9yD+Zx8wPwO+QiXaJARAPK/YeBsGSLt4oMRZyGfaJDazdxMATOIkv1Xjl69t1
+3aNqMoJVAgoL48TTF3QW+V18mImxJ3+uqLwdWyryMOhCAJNnzGfid+B4ZHoacEpA
+ib6VpQ3/FvfwU7heU020eIkCgYBKBCeH7vLqHf5dHP5VOpYMI36XjXJdJLkymHCq
+fbDAokml/19ziYEKI3oROFKvoCDpGXha9i7uQKYOtxpjkWi71iaLUivF8nuLGXBk
+tGU1ZKRkzyKQ2uKaKfN6c4mIgioB+HpnimrjNJVX3OGAJNAzAalr/B/fTbySvf4w
+8pn7YQKBgE4c1e2Xr67DqvGbpJx42fKlYYT0eW5ZxbzHkGj0Q5CZet61/S3lF9g8
+Bjm9TVhDBR2UJJbaaMuWed4Xp1UXZ9qWTeHtn3bX2BHr5HDY4ba+0sebVkdOmvre
+/p+sfKCBGkkIBgGjNld/UFErkbat/FfG0AWJZtX+5ulSEo7CodD4
+-----END RSA PRIVATE KEY-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.p12 b/src/lynq/lib/liblynq-protcl/http/cert/client.p12
new file mode 100644
index 0000000..4de6ab8
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.p12
Binary files differ
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt b/src/lynq/lib/liblynq-protcl/http/cert/index.txt
new file mode 100644
index 0000000..4c34e96
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt
@@ -0,0 +1,2 @@
+V 210928101551Z 01 unknown /C=CN/ST=Beijing/O=Teamsun/OU=guoxu/CN=guoxu
+V 210928101635Z 02 unknown /C=CN/ST=Beijing/O=Teamsun/OU=guog/CN=guog
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr.old b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr.old
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr.old
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt.old b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.old
new file mode 100644
index 0000000..2037566
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.old
@@ -0,0 +1 @@
+V 210928101551Z 01 unknown /C=CN/ST=Beijing/O=Teamsun/OU=guoxu/CN=guoxu
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/newcerts/01.pem b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/01.pem
new file mode 100644
index 0000000..e92b642
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/01.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:15:51 2020 GMT
+ Not After : Sep 28 10:15:51 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guoxu, CN=guoxu
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a5:10:f2:43:40:a8:83:25:07:17:61:3e:8e:90:
+ 88:d1:b2:3d:5a:51:55:5e:fb:5f:c8:ee:3b:57:8a:
+ 13:64:4e:af:d9:74:0a:e5:db:42:1f:a8:3c:04:4f:
+ 2b:ed:08:fd:47:98:1c:4f:10:d3:2b:48:7a:3e:6a:
+ ec:4d:bf:9d:6a:a6:5b:78:b6:22:28:12:1c:36:b6:
+ 84:de:b9:d4:60:dd:f3:b2:9d:c2:07:db:1c:f5:e8:
+ 02:6a:64:99:44:fe:4f:86:a4:d9:14:6a:cd:d2:9d:
+ 4f:e3:01:54:f8:06:d5:7a:0c:14:f0:61:93:a7:1f:
+ f0:8b:44:f2:16:37:81:9d:3a:9b:f2:75:d0:fb:68:
+ 36:5d:59:23:38:bd:75:4e:e8:4d:6a:56:6c:a3:95:
+ c4:71:1e:3b:2a:29:e4:d6:01:83:c9:a2:75:82:c6:
+ 42:d3:cd:3b:0f:2e:2f:09:57:9b:ed:b8:76:84:85:
+ 5d:49:95:d0:9e:de:cb:8a:2a:bc:d0:7d:29:b1:fe:
+ 92:02:65:a9:24:28:b8:24:8b:68:69:e0:2b:14:f3:
+ 62:e1:91:12:2d:89:5f:02:10:78:48:76:49:9e:82:
+ 8a:94:ff:f0:bb:6f:0d:82:10:e0:7f:78:58:f3:53:
+ 4a:dc:54:ee:f3:7d:fc:15:40:8d:48:c3:bc:a3:5d:
+ df:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 5C:7C:6F:02:4F:B5:EB:F7:74:88:2F:2A:05:4C:D9:6A:4C:17:A2:ED
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 61:1d:fb:07:16:a2:33:7b:bd:d0:fe:3f:f8:73:06:ea:26:1b:
+ 28:2e:de:f9:90:8d:ee:62:a4:97:f6:d4:04:05:a1:8e:11:93:
+ af:3b:3e:de:24:eb:68:ff:32:9a:d3:16:86:61:68:27:9e:2b:
+ d3:ff:50:e7:f7:f6:c4:81:e4:c3:87:41:f7:bb:3b:85:00:ee:
+ f7:5f:86:7c:b9:2a:d6:4f:1a:60:f6:55:77:cc:e7:84:2b:6c:
+ f4:d3:58:8f:ed:df:af:d3:f8:b6:f5:46:de:1b:19:91:a5:93:
+ 31:db:5b:14:07:0f:8e:d9:db:ab:00:ea:6c:58:2c:67:24:bf:
+ b2:f7:a5:5c:d2:e1:cd:8b:42:0c:a5:b1:a3:03:aa:79:bc:10:
+ 4f:79:4f:9b:7e:8b:28:09:3e:70:68:fa:a3:c5:ec:3b:33:80:
+ 91:5b:1d:65:86:a3:9f:f4:25:48:d4:cf:9f:31:ce:54:a9:ce:
+ 3e:7b:bb:00:21:27:b7:5c:44:bf:67:63:23:1b:c8:8d:b5:f4:
+ bd:5b:fa:ae:7d:fa:21:a0:0d:6e:8d:23:af:23:aa:e9:69:ef:
+ d7:64:37:5b:13:be:ea:c7:40:dd:8e:7d:e6:e2:1f:e2:7c:08:
+ 57:27:0f:16:05:a1:e3:d0:ea:99:6b:d8:41:60:80:58:29:72:
+ 80:d5:22:91
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE1NTFaFw0yMTA5Mjgx
+MDE1NTFaMFExCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ4wDAYDVQQLDAVndW94dTEOMAwGA1UEAwwFZ3VveHUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClEPJDQKiDJQcXYT6OkIjRsj1aUVVe
++1/I7jtXihNkTq/ZdArl20IfqDwETyvtCP1HmBxPENMrSHo+auxNv51qplt4tiIo
+Ehw2toTeudRg3fOyncIH2xz16AJqZJlE/k+GpNkUas3SnU/jAVT4BtV6DBTwYZOn
+H/CLRPIWN4GdOpvyddD7aDZdWSM4vXVO6E1qVmyjlcRxHjsqKeTWAYPJonWCxkLT
+zTsPLi8JV5vtuHaEhV1JldCe3suKKrzQfSmx/pICZakkKLgki2hp4CsU82LhkRIt
+iV8CEHhIdkmegoqU//C7bw2CEOB/eFjzU0rcVO7zffwVQI1Iw7yjXd9vAgMBAAGj
+ezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBRcfG8CT7Xr93SILyoFTNlqTBei7TAfBgNV
+HSMEGDAWgBTh1oziCjjuzih9f/tD4zLPHmCtrTANBgkqhkiG9w0BAQsFAAOCAQEA
+YR37BxaiM3u90P4/+HMG6iYbKC7e+ZCN7mKkl/bUBAWhjhGTrzs+3iTraP8ymtMW
+hmFoJ54r0/9Q5/f2xIHkw4dB97s7hQDu91+GfLkq1k8aYPZVd8znhCts9NNYj+3f
+r9P4tvVG3hsZkaWTMdtbFAcPjtnbqwDqbFgsZyS/svelXNLhzYtCDKWxowOqebwQ
+T3lPm36LKAk+cGj6o8XsOzOAkVsdZYajn/QlSNTPnzHOVKnOPnu7ACEnt1xEv2dj
+IxvIjbX0vVv6rn36IaANbo0jryOq6Wnv12Q3WxO+6sdA3Y595uIf4nwIVycPFgWh
+49DqmWvYQWCAWClygNUikQ==
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/newcerts/02.pem b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/02.pem
new file mode 100644
index 0000000..7eb321f
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/02.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:16:35 2020 GMT
+ Not After : Sep 28 10:16:35 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guog, CN=guog
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:99:5f:72:71:bc:e4:08:76:43:77:32:9d:17:61:
+ 74:f7:44:49:33:ef:3c:7f:89:0e:97:0e:ce:d9:39:
+ 32:ca:10:34:af:6c:8c:39:19:58:38:16:9f:11:1e:
+ 55:9f:95:89:ac:fb:e2:cb:5f:ee:1a:bd:3d:25:79:
+ cd:18:20:36:83:ef:df:93:2e:7a:9e:1f:2f:98:05:
+ b0:65:c9:4f:93:c2:00:0b:70:84:2b:fb:44:01:d1:
+ 36:22:a6:5a:43:f7:c6:54:f4:81:cc:a6:26:47:e4:
+ 92:f5:e6:97:41:34:3e:c5:37:89:13:64:c6:cc:93:
+ 6c:a2:b0:0e:64:e0:3b:7d:a2:2e:b1:e4:42:79:cf:
+ a7:06:5e:89:53:4b:56:46:f5:07:54:99:5e:0f:80:
+ 1b:28:2f:19:63:c2:cd:e9:97:8f:09:cd:38:f4:05:
+ d4:83:00:4a:3b:14:00:51:d9:fe:b9:d4:82:52:c3:
+ a3:2f:2a:2d:f4:98:b1:44:0f:8c:ca:ee:0c:94:7e:
+ af:8b:b8:ab:8c:21:9d:16:1e:72:ee:9b:3d:04:70:
+ 1c:c6:46:06:d3:df:12:59:97:b6:af:3c:97:8d:b9:
+ 2e:88:d0:c9:c5:42:14:bb:c2:dd:ac:a3:3a:80:8a:
+ af:34:d2:e4:85:26:92:da:0e:99:20:3b:e8:78:11:
+ ba:e3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 27:96:0E:38:74:AA:00:98:D8:8C:54:5F:09:98:D9:03:C8:3D:D7:9C
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ a8:89:a9:9c:48:86:04:10:bf:5a:83:60:78:44:eb:42:59:af:
+ 9b:58:33:2c:68:33:f5:e1:c0:a9:d2:07:87:55:07:dc:95:68:
+ 18:20:9d:d2:3a:ad:3c:fc:d7:03:ec:f1:d4:91:26:09:d5:dd:
+ cd:90:74:0a:2a:c6:5a:98:6a:f7:e8:4f:04:e7:35:23:70:5e:
+ ea:20:83:b6:b7:6f:8b:2c:80:3e:0e:c5:f0:a1:30:4a:5e:df:
+ 6a:bc:60:43:2f:91:c8:e2:14:ca:47:af:9c:6b:ad:8d:c5:a6:
+ cd:1f:f8:1a:82:d8:02:b0:e7:d4:06:a2:47:bc:f7:b7:0e:dc:
+ 89:8d:3e:c9:50:55:8a:a1:04:5e:e6:a6:23:d8:54:37:57:c5:
+ 1e:57:0d:ed:1b:45:2a:1a:e3:10:ba:17:95:cf:c3:7d:a3:ec:
+ 08:d2:57:db:24:32:a0:9f:8e:30:95:81:20:00:fb:97:eb:c9:
+ 0c:e9:82:0f:62:a5:16:fa:ed:ae:7c:59:2c:f1:f2:b5:fd:8d:
+ c0:fe:20:ba:d2:f8:40:ef:2f:2e:ec:98:c3:55:b1:dd:83:4d:
+ 2a:9a:a3:f2:fc:4a:29:71:70:5f:3f:44:47:07:af:8f:ad:57:
+ 2c:1a:d9:68:19:c4:e8:c0:6b:2e:50:f9:d6:5c:97:ec:5a:8a:
+ cd:ac:8c:0f
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE2MzVaFw0yMTA5Mjgx
+MDE2MzVaME8xCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ0wCwYDVQQLDARndW9nMQ0wCwYDVQQDDARndW9nMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV9ycbzkCHZDdzKdF2F090RJM+88f4kO
+lw7O2TkyyhA0r2yMORlYOBafER5Vn5WJrPviy1/uGr09JXnNGCA2g+/fky56nh8v
+mAWwZclPk8IAC3CEK/tEAdE2IqZaQ/fGVPSBzKYmR+SS9eaXQTQ+xTeJE2TGzJNs
+orAOZOA7faIuseRCec+nBl6JU0tWRvUHVJleD4AbKC8ZY8LN6ZePCc049AXUgwBK
+OxQAUdn+udSCUsOjLyot9JixRA+Myu4MlH6vi7irjCGdFh5y7ps9BHAcxkYG098S
+WZe2rzyXjbkuiNDJxUIUu8LdrKM6gIqvNNLkhSaS2g6ZIDvoeBG64wIDAQABo3sw
+eTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUJ5YOOHSqAJjYjFRfCZjZA8g915wwHwYDVR0j
+BBgwFoAU4daM4go47s4ofX/7Q+Myzx5gra0wDQYJKoZIhvcNAQELBQADggEBAKiJ
+qZxIhgQQv1qDYHhE60JZr5tYMyxoM/XhwKnSB4dVB9yVaBggndI6rTz81wPs8dSR
+JgnV3c2QdAoqxlqYavfoTwTnNSNwXuogg7a3b4ssgD4OxfChMEpe32q8YEMvkcji
+FMpHr5xrrY3Fps0f+BqC2AKw59QGoke897cO3ImNPslQVYqhBF7mpiPYVDdXxR5X
+De0bRSoa4xC6F5XPw32j7AjSV9skMqCfjjCVgSAA+5fryQzpgg9ipRb67a58WSzx
+8rX9jcD+ILrS+EDvLy7smMNVsd2DTSqao/L8SilxcF8/REcHr4+tVywa2WgZxOjA
+ay5Q+dZcl+xais2sjA8=
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/serial b/src/lynq/lib/liblynq-protcl/http/cert/serial
new file mode 100644
index 0000000..75016ea
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/serial
@@ -0,0 +1 @@
+03
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/serial.old b/src/lynq/lib/liblynq-protcl/http/cert/serial.old
new file mode 100644
index 0000000..9e22bcb
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/serial.old
@@ -0,0 +1 @@
+02
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.crt b/src/lynq/lib/liblynq-protcl/http/cert/server.crt
new file mode 100644
index 0000000..e92b642
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.crt
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:15:51 2020 GMT
+ Not After : Sep 28 10:15:51 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guoxu, CN=guoxu
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a5:10:f2:43:40:a8:83:25:07:17:61:3e:8e:90:
+ 88:d1:b2:3d:5a:51:55:5e:fb:5f:c8:ee:3b:57:8a:
+ 13:64:4e:af:d9:74:0a:e5:db:42:1f:a8:3c:04:4f:
+ 2b:ed:08:fd:47:98:1c:4f:10:d3:2b:48:7a:3e:6a:
+ ec:4d:bf:9d:6a:a6:5b:78:b6:22:28:12:1c:36:b6:
+ 84:de:b9:d4:60:dd:f3:b2:9d:c2:07:db:1c:f5:e8:
+ 02:6a:64:99:44:fe:4f:86:a4:d9:14:6a:cd:d2:9d:
+ 4f:e3:01:54:f8:06:d5:7a:0c:14:f0:61:93:a7:1f:
+ f0:8b:44:f2:16:37:81:9d:3a:9b:f2:75:d0:fb:68:
+ 36:5d:59:23:38:bd:75:4e:e8:4d:6a:56:6c:a3:95:
+ c4:71:1e:3b:2a:29:e4:d6:01:83:c9:a2:75:82:c6:
+ 42:d3:cd:3b:0f:2e:2f:09:57:9b:ed:b8:76:84:85:
+ 5d:49:95:d0:9e:de:cb:8a:2a:bc:d0:7d:29:b1:fe:
+ 92:02:65:a9:24:28:b8:24:8b:68:69:e0:2b:14:f3:
+ 62:e1:91:12:2d:89:5f:02:10:78:48:76:49:9e:82:
+ 8a:94:ff:f0:bb:6f:0d:82:10:e0:7f:78:58:f3:53:
+ 4a:dc:54:ee:f3:7d:fc:15:40:8d:48:c3:bc:a3:5d:
+ df:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 5C:7C:6F:02:4F:B5:EB:F7:74:88:2F:2A:05:4C:D9:6A:4C:17:A2:ED
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 61:1d:fb:07:16:a2:33:7b:bd:d0:fe:3f:f8:73:06:ea:26:1b:
+ 28:2e:de:f9:90:8d:ee:62:a4:97:f6:d4:04:05:a1:8e:11:93:
+ af:3b:3e:de:24:eb:68:ff:32:9a:d3:16:86:61:68:27:9e:2b:
+ d3:ff:50:e7:f7:f6:c4:81:e4:c3:87:41:f7:bb:3b:85:00:ee:
+ f7:5f:86:7c:b9:2a:d6:4f:1a:60:f6:55:77:cc:e7:84:2b:6c:
+ f4:d3:58:8f:ed:df:af:d3:f8:b6:f5:46:de:1b:19:91:a5:93:
+ 31:db:5b:14:07:0f:8e:d9:db:ab:00:ea:6c:58:2c:67:24:bf:
+ b2:f7:a5:5c:d2:e1:cd:8b:42:0c:a5:b1:a3:03:aa:79:bc:10:
+ 4f:79:4f:9b:7e:8b:28:09:3e:70:68:fa:a3:c5:ec:3b:33:80:
+ 91:5b:1d:65:86:a3:9f:f4:25:48:d4:cf:9f:31:ce:54:a9:ce:
+ 3e:7b:bb:00:21:27:b7:5c:44:bf:67:63:23:1b:c8:8d:b5:f4:
+ bd:5b:fa:ae:7d:fa:21:a0:0d:6e:8d:23:af:23:aa:e9:69:ef:
+ d7:64:37:5b:13:be:ea:c7:40:dd:8e:7d:e6:e2:1f:e2:7c:08:
+ 57:27:0f:16:05:a1:e3:d0:ea:99:6b:d8:41:60:80:58:29:72:
+ 80:d5:22:91
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE1NTFaFw0yMTA5Mjgx
+MDE1NTFaMFExCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ4wDAYDVQQLDAVndW94dTEOMAwGA1UEAwwFZ3VveHUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClEPJDQKiDJQcXYT6OkIjRsj1aUVVe
++1/I7jtXihNkTq/ZdArl20IfqDwETyvtCP1HmBxPENMrSHo+auxNv51qplt4tiIo
+Ehw2toTeudRg3fOyncIH2xz16AJqZJlE/k+GpNkUas3SnU/jAVT4BtV6DBTwYZOn
+H/CLRPIWN4GdOpvyddD7aDZdWSM4vXVO6E1qVmyjlcRxHjsqKeTWAYPJonWCxkLT
+zTsPLi8JV5vtuHaEhV1JldCe3suKKrzQfSmx/pICZakkKLgki2hp4CsU82LhkRIt
+iV8CEHhIdkmegoqU//C7bw2CEOB/eFjzU0rcVO7zffwVQI1Iw7yjXd9vAgMBAAGj
+ezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBRcfG8CT7Xr93SILyoFTNlqTBei7TAfBgNV
+HSMEGDAWgBTh1oziCjjuzih9f/tD4zLPHmCtrTANBgkqhkiG9w0BAQsFAAOCAQEA
+YR37BxaiM3u90P4/+HMG6iYbKC7e+ZCN7mKkl/bUBAWhjhGTrzs+3iTraP8ymtMW
+hmFoJ54r0/9Q5/f2xIHkw4dB97s7hQDu91+GfLkq1k8aYPZVd8znhCts9NNYj+3f
+r9P4tvVG3hsZkaWTMdtbFAcPjtnbqwDqbFgsZyS/svelXNLhzYtCDKWxowOqebwQ
+T3lPm36LKAk+cGj6o8XsOzOAkVsdZYajn/QlSNTPnzHOVKnOPnu7ACEnt1xEv2dj
+IxvIjbX0vVv6rn36IaANbo0jryOq6Wnv12Q3WxO+6sdA3Y595uIf4nwIVycPFgWh
+49DqmWvYQWCAWClygNUikQ==
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.csr b/src/lynq/lib/liblynq-protcl/http/cert/server.csr
new file mode 100644
index 0000000..853b893
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICqDCCAZACAQAwYzELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAO
+BgNVBAcMB0JlaWppbmcxEDAOBgNVBAoMB1RlYW1zdW4xDjAMBgNVBAsMBWd1b3h1
+MQ4wDAYDVQQDDAVndW94dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKUQ8kNAqIMlBxdhPo6QiNGyPVpRVV77X8juO1eKE2ROr9l0CuXbQh+oPARPK+0I
+/UeYHE8Q0ytIej5q7E2/nWqmW3i2IigSHDa2hN651GDd87KdwgfbHPXoAmpkmUT+
+T4ak2RRqzdKdT+MBVPgG1XoMFPBhk6cf8ItE8hY3gZ06m/J10PtoNl1ZIzi9dU7o
+TWpWbKOVxHEeOyop5NYBg8midYLGQtPNOw8uLwlXm+24doSFXUmV0J7ey4oqvNB9
+KbH+kgJlqSQouCSLaGngKxTzYuGREi2JXwIQeEh2SZ6CipT/8LtvDYIQ4H94WPNT
+StxU7vN9/BVAjUjDvKNd328CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQApPn/s
+nVyEdO6QOK/c1ThZ8t8A+CVdllgsJrP2qZsnWnwKyAHcYSC2nuv4qvw20MNFdprd
+z/kIQz79o4lOCO9OHkpP5h6WaQ0z2u3kqCkIdkntkfkIKo1xq9MCO2ETKIkKEJcI
+HL9zLLiqL7tyHhv87celbqdiyvKfDKtH1/n7zT3nuU/PNzzUK6rLrlMASO5DQ5TI
+u/B+gfSem4aVyfgk4FqtpMnVhGlkdst+ajMJiFRNrB9nK8VhQZ7zdydt1TIT5E2H
+GSVFBi7TrC7lN1WHTPCRJXWlP4gaXO7imJ26IydSUaLi/X7DhDMXVAlOw38yvlUE
+MSJfg2BZDDSn7jVH
+-----END CERTIFICATE REQUEST-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.key b/src/lynq/lib/liblynq-protcl/http/cert/server.key
new file mode 100644
index 0000000..995401a
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEApRDyQ0CogyUHF2E+jpCI0bI9WlFVXvtfyO47V4oTZE6v2XQK
+5dtCH6g8BE8r7Qj9R5gcTxDTK0h6PmrsTb+daqZbeLYiKBIcNraE3rnUYN3zsp3C
+B9sc9egCamSZRP5PhqTZFGrN0p1P4wFU+AbVegwU8GGTpx/wi0TyFjeBnTqb8nXQ
++2g2XVkjOL11TuhNalZso5XEcR47Kink1gGDyaJ1gsZC0807Dy4vCVeb7bh2hIVd
+SZXQnt7Liiq80H0psf6SAmWpJCi4JItoaeArFPNi4ZESLYlfAhB4SHZJnoKKlP/w
+u28NghDgf3hY81NK3FTu8338FUCNSMO8o13fbwIDAQABAoIBAC5t39bu3vdUePQo
+lDIBkZp6Kiu3aO34gu6/o81xtxal02y06UPSMn05EvibVF2uA6AZtwy+TMeF8WyR
+IrqTxTF0bZI8mMrwnSL+n80ONCCzDZMWMLeI+FJq2hMXDM2NQs06nRzTFeXB/fB6
+NW42beGQeGtM5v1BTKW/1OBO6JRSrkODUwKluuTDZOwErfGZyuaJsZdghQ1Fh6jw
+WEpb9OzyqzRu5BQjk0xRyPSSDDNWi2jRCTYlk3hDCqeBvzqMHXMLh2biSIdUsEEG
+88STOFHGXR57Szpj+zl3P3AnH/c5ZLIHwq6b8gwC02TUb9cPK7setmXHrliWvVYT
+WXxsFuECgYEA1cPxmEqsZ9QW1j7rm1zMop+R0ft23zuKD93nskNreKinaPyOKyDG
+7+WQjCrdglIuuMnMmPJyhLx1taDMvOpzN1LbFWjxTwG1S6dp0tkTHAVaoKH58rxq
+XwDgWe3o9Txtt4dk9NuvJztxblT7qU7wIFXr3w5z13Y9GnqQvvfpTykCgYEAxa3X
+e6DAurK5A6+44eKrQXcvesjBJknYphVnQoFq+YjrYb/vCa/AgOFi5xQ1Co/q+F7r
+gtTAj/2KEbzdzxED+akIn0/pSsCxz8mbK85O8vBlaymrmMtRFVDIrDxMKxrgMT7Q
+4oKyB+JJy/6Muwlq/NTeMel0aFUP3WTI0GZpxNcCgYEArEajIVolAfSChx3kYaxz
+WyiAq5senR/tz4XGIfuF1JMPgGPx674ZteLsEJrHNC0pbFFuK2FRe7oqnzs9ZY8J
+Ve/XkrSlrUeyJYuBlKTPasjB1i1UNBU3IOOi67b6BRIzVjKu4UtfKJ4Wd5XT0ApH
+Kbg1ROnv4BhxfDKFDvLbO6kCgYBQyRW5+V0qL2X7ArI85iR00Z9+v1JoMl+uqCqV
+/EvahMElJooq3D+ArBt+Mjzm/x/YtvnqcsXrUoM9coD3YY3NVu4mJUNDAHLqZwra
+ISsUj3fzDomJHPYbDvOjp9S8/PPITFKTbzQQksLz8ihTO6sUfm372dtv0+ty4ABN
+Yr0w6wKBgGwfvkITtbYU0gFOC8G7XX8liT23HOegvTXraBm38IWXHMVqOwk0lCEQ
+crk54pXDzJd3yXqwFIq5g1w/enjeGq+ly6C/XWuSAepkQjecHxzkYTcrCdyWWifx
+zZD9xKOvXNqU26ZdoZQHNaAktCoXYEC3BA6jSJtfinLzzwS4olV1
+-----END RSA PRIVATE KEY-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.p12 b/src/lynq/lib/liblynq-protcl/http/cert/server.p12
new file mode 100644
index 0000000..eb0ceea
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.p12
Binary files differ
diff --git a/src/lynq/lib/liblynq-protcl/http/src/lynq_http.c b/src/lynq/lib/liblynq-protcl/http/src/lynq_http.c
new file mode 100644
index 0000000..94b8ef1
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/src/lynq_http.c
@@ -0,0 +1,1289 @@
+#include "http/lynq_http.h"
+
+
+
+#define _stricmp strcasecmp
+#define _strnicmp strncasecmp
+
+
+const int kSelectRead = 1 << 0;
+const int kSelectWrite = 1 << 1;
+const int kSelectError = 1 << 2;
+
+#define DEFAULT_USER_AGENT_STR "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n"
+#define CONNECT_KEEP_STR "Connection: keep-alive\r\n"
+#define CONNECT_CLOSE_STR "Connection: close\r\n"
+#define ACCEPT_STR "Accept: */*\r\n"
+#define CONTENT_LENGTH_STR "Content-Length"
+#define CONTENT_TYPE_STR "Content-Type:application/x-www-form-urlencoded\r\n"
+#define CONTENT_DISPOSITION_STR "Content-Disposition"
+#define CRLF "\r\n"
+
+#define CA_ROOT "cert/ca.crt"
+#define CA_CLICRT "cert/client.crt"
+#define CA_CLIKEY "cert/client.key"
+
+
+static char* _strdup(const char* src)
+{
+ char* dst = NULL;
+ int len = 0;
+ if(src == NULL)
+ {
+ return NULL;
+ }
+ len = strlen(src);
+ dst = (char*)malloc(len + 1);
+ if(dst == NULL)
+ {
+ return NULL;
+ }
+ strcpy(dst, src);
+ return dst;
+}
+
+static void http_ssl_free(lynq_http_client_t* http)
+{
+ if(http->ssl != NULL)
+ {
+ SSL_shutdown(http->ssl);
+ SSL_free(http->ssl);
+ http->ssl = NULL;
+ }
+ if(http->ctx != NULL)
+ {
+ SSL_CTX_free(http->ctx);
+ http->ctx = NULL;
+ }
+}
+
+int lynq_http_init()
+{
+ OpenSSL_add_all_algorithms();
+ ERR_load_BIO_strings();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+
+ if(SSL_library_init() < 0)
+ {
+ LYVERBLOG("+[http][init]: error num = %d\n", ERR_SSL_CREATE_SSL);
+ return ERR_SSL_CREATE_SSL;
+ }
+ return 0;
+}
+
+lynq_http_client_t* lynq_http_new()
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)calloc(1, sizeof(lynq_http_client_t));
+
+ return http;
+}
+
+void lynq_http_destroy(lynq_http_client_t* http)
+{
+ if(http == NULL) return;
+
+ free_member(http->body);
+ free_member(http->header_field);
+ free_member(http->header_value);
+ free_member(http->redirect_url);
+ free_member(http->filename);
+ close_socket(http->fd);
+ close_file(http->pf);
+
+ http_ssl_free(http);
+
+ free(http);
+}
+
+int lynq_http_get_error_code(lynq_http_client_t* http)
+{
+ if(http == NULL)
+ {
+ return -1;
+ }
+ return http->error_code;
+}
+
+static int socket_noblocking(socket_t fd, int noblocking)
+{
+
+ int flags;
+ if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
+ {
+ return -1;
+ }
+ if(noblocking)
+ {
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ }
+ else
+ {
+ return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ return 0;
+}
+
+static int last_error()
+{
+ return errno;
+}
+
+static int socket_select(lynq_http_client_t* http, int mode, int timeout)
+{
+ fd_set rfd, wfd, efd;
+ int r = 0;
+ int error = 0;
+ int remaind = timeout;
+ socklen_t len = sizeof(error);
+
+ struct timeval tv, start, elapsed;
+
+ gettimeofday(&start, 0);
+
+ while(remaind > 0)
+ {
+ if(mode & kSelectRead) { FD_ZERO(&rfd); FD_SET(http->fd, &rfd); }
+ if(mode & kSelectWrite){ FD_ZERO(&wfd); FD_SET(http->fd, &wfd); }
+ if(mode & kSelectError){ FD_ZERO(&efd); FD_SET(http->fd, &efd); }
+
+ tv.tv_sec = remaind / 1000;
+ tv.tv_usec = remaind % 1000 * 1000;
+
+ r = select(http->fd+1,
+ (mode & kSelectRead) ? &rfd : NULL,
+ (mode & kSelectWrite) ? &wfd : NULL,
+ (mode & kSelectError) ? &efd : NULL,
+ &tv);
+
+ if( r == 0)
+ {
+ return -1;
+ }
+
+ if( r > 0)
+ {
+ if(getsockopt(http->fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) == 0 && error == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ if( r < 0 )
+ {
+ if(last_error() == HTTP_EINTR)
+ {
+ gettimeofday(&elapsed, 0);
+ remaind = timeout - ((int)(elapsed.tv_sec - start.tv_sec) * 1000 + (int)(elapsed.tv_usec - start.tv_usec) / 1000);
+
+ continue;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ };
+
+ return -1;
+}
+
+static int _field_value_malloc(char** str, unsigned short* cur_size, unsigned short* size, const char* at, size_t length)
+{
+ if(*str == NULL)
+ {
+#define DEFAULT_HEADER_SIZE 128
+ *size = length > DEFAULT_HEADER_SIZE ? length: DEFAULT_HEADER_SIZE;
+ *str = (char*)calloc(1, *size + 1);
+ if(*str == NULL)
+ {
+ return -1;
+ }
+ *cur_size = 0;
+ }
+ else if(*cur_size + length > *size)
+ {
+ *size = *cur_size + length;
+ *str = (char*)realloc(*str, *size + 1);
+ if(*str == NULL)
+ {
+ return -1;
+ }
+ }
+ memcpy(*str + *cur_size, at, length);
+ *cur_size += length;
+ (*str)[*cur_size] = '\0';
+ return 0;
+}
+
+static int parser_field_value(lynq_http_client_t* http)
+{
+ if(http->cur_value_size > 0 &&
+ http->cur_field_size > 0 &&
+ http->header_field && http->header_value)
+ {
+ if(_stricmp(http->header_field, "Location") == 0)
+ {
+ free_member(http->redirect_url);
+ http->redirect_url = _strdup(http->header_value);
+
+ http->redirect = 1;
+ return -1;
+ }
+ else if(_stricmp(http->header_field, CONTENT_LENGTH_STR) == 0)
+ {
+ http->content_length = atol(http->header_value);
+ }
+ else
+ {
+ /* extract other header field value */
+ }
+ http->cur_field_size = 0;
+ http->cur_value_size = 0;
+ }
+
+ return 0;
+}
+
+static int on_header_field_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->parser_statue == PARSERD_VALUE)
+ {
+ if( parser_field_value(http) != 0)
+ {
+ return -1;
+ }
+ }
+ http->parser_statue = PARSERD_FIELD;
+ return _field_value_malloc(&http->header_field, &http->cur_field_size, &http->field_size, at, length);
+}
+
+static int on_header_value_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->parser_statue == PARSERD_FIELD || http->parser_statue == PARSERD_VALUE)
+ {
+ http->parser_statue = PARSERD_VALUE;
+ return _field_value_malloc(&http->header_value, &http->cur_value_size, &http->value_size, at, length);
+ }
+ return 0;
+}
+
+static int on_status_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+ http->status_code = parser->status_code;
+ return 0;
+}
+
+static int on_headers_complete_cb(http_parser* parser)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+ if(parser_field_value(http) != 0)
+ {
+ return -1;
+ }
+ free_member(http->header_field);
+ free_member(http->header_value);
+ http->parser_statue = PARSERD_BODY;
+ http->cur_field_size = http->cur_value_size = 0;
+ return 0;
+}
+
+static int on_download_file_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->status_code >= 200 && http->status_code <= 299)
+ {
+ if(http->pf == NULL)
+ {
+ if(http->filename != NULL)
+ {
+ http->pf = fopen(http->filename, "wb");
+ }
+ }
+
+ if(http->pf == NULL)
+ {
+ return -1;
+ }
+ if( http->recv_cb && (http->recv_cb)(http, at, length, http->content_length, http->user) != 0)
+ {
+ return -1;
+ }
+
+ fwrite(at, 1, length, http->pf);
+ }
+
+ return 0;
+}
+
+static int on_body_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->body == NULL)
+ {
+
+ if(http->content_length > 0)
+ {
+ http->body = (char*)calloc(1, http->content_length + 1);
+ }
+ else
+ {
+ http->body = (char*)calloc(1, length + 1);
+ }
+ }
+ else
+ {
+ if(http->content_length <= 0)
+ {
+ http->body = (char*)realloc(http->body, http->body_len + length + 1);
+ }
+ }
+ if(http->body == NULL)
+ {
+ return -1;
+ }
+ memcpy(http->body + http->body_len, at, length);
+ http->body_len += length;
+
+ return 0;
+}
+
+static int on_message_complete_cb(http_parser* parser)
+{
+ return 0;
+}
+
+static int http_check_error(lynq_http_client_t* http, int mode, int ret)
+{
+ int error_code;
+ if(http->proto_type == PROTO_HTTPS)
+ {
+ int error = SSL_get_error(http->ssl, ret);
+ if(SSL_ERROR_ZERO_RETURN == error)
+ {
+ return -1;
+ }
+ else if(error == SSL_ERROR_WANT_WRITE ||
+ error == SSL_ERROR_WANT_READ)
+ {
+ return 0;
+ }
+ else if(SSL_ERROR_SYSCALL == error)
+ {
+ goto check_select;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+check_select:
+ error_code = last_error();
+ if(error_code == HTTP_EINTR)
+ {
+ return 0;
+ }
+ else if(error_code == HTTP_EINPROGRESS || error_code == HTTP_EWOULDBLOCK)
+ {
+ if(socket_select(http, mode, http->timeout) == 0)
+ {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int http_read_write(lynq_http_client_t* http, const char* data, int len, int read)
+{
+ int n = 0, r = 0;
+
+ do
+ {
+ if(http->exit == 1)
+ {
+ return -1;
+ }
+
+ if(http->proto_type == PROTO_HTTPS)
+ {
+
+ r = read ? SSL_read(http->ssl, (char*)data + n, len - n) : SSL_write(http->ssl, data + n, len - n);
+ }
+ else
+ {
+ r = read ? recv(http->fd, (char*)data + n, len - n, 0) : send(http->fd, data + n, len - n, 0);
+ }
+
+ if(r > 0)
+ {
+ n += r;
+ }
+ else if(r == 0)
+ {
+ return n;
+ }
+ else
+ {
+ if(http_check_error(http, read ? kSelectRead : kSelectWrite, r) == 0)
+ {
+ continue;
+ }
+ return -1;
+ }
+
+ http->data = data;
+ LYDBGLOG("[%s-%d] +http%s, session = %d, data = %s \n", __FUNCTION__, __LINE__, http->action, http->session, data);
+ LYVERBLOG("+[http][%s][session%d]: data = %s\n", http->action, http->session, data);
+ LYVERBLOG("+[http][%s][session%d]: ok!!\n", http->action, http->session);
+ }while(n < len);
+ http->data = NULL;
+
+ return n;
+}
+
+#define HTTP_KEY "self.key"
+#define HTTP_CERTIFICATE "self.crt"
+
+static int sslSetCertFile(SSL_CTX *sslctx, char *certFile)
+{
+ if (sslctx == NULL)
+ {
+ return -1;
+ }
+
+ if (SSL_CTX_use_certificate_file(sslctx, certFile, SSL_FILETYPE_PEM) <= 0) {
+ if (SSL_CTX_use_certificate_file(sslctx, certFile, SSL_FILETYPE_ASN1) <= 0) {
+ return -1;
+ }
+ }
+
+ if(!SSL_CTX_check_private_key(sslctx)){
+ return -1;
+ }
+ return 0;
+}
+
+
+static int sslSetKeyFile(SSL_CTX *sslctx, char *keyFile)
+{
+ if (sslctx == NULL)
+ {
+ return -1;
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
+ if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_ASN1) <= 0) {
+ return -1;
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+#define VERIFY_DEPTH 10
+static int verify_X509Certificate(int ok, X509_STORE_CTX *xContext)
+{
+ X509 *cert;
+ char subject[260], issuer[260], peer[260];
+ int error, depth;
+ subject[0] = issuer[0] = '\0';
+ cert = X509_STORE_CTX_get_current_cert(xContext);
+ error = X509_STORE_CTX_get_error(xContext);
+ depth = X509_STORE_CTX_get_error_depth(xContext);
+ ok = 1;
+
+ if (X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject) - 1) < 0) {
+ ok = 0;
+ }
+
+ if (X509_NAME_oneline(X509_get_issuer_name(cert), issuer, sizeof(issuer) - 1) < 0) {
+ ok = 0;
+ }
+
+ if (ok && VERIFY_DEPTH < depth) {
+ if (error == 0) {
+ error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+ switch (error) {
+ case X509_V_OK:
+ break ;
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_OUT_OF_MEM:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_REVOKED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_CA:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_PURPOSE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_UNTRUSTED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_REJECTED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_AKID_SKID_MISMATCH:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_EXTENSION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_POLICY_EXTENSION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_DIFFERENT_CRL_SCOPE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_PERMITTED_VIOLATION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_EXCLUDED_VIOLATION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_SUBTREE_MINMAX:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_APPLICATION_VERIFICATION:
+ ok = 0;
+ break;
+
+ default:
+ ok = 0;
+ break;
+ }
+
+ return ok;
+}
+
+void https_certificate_validation(SSL * ssl)
+{
+ X509 *cert;
+ char *line;
+
+ cert = SSL_get_peer_certificate(ssl);
+ if(SSL_get_verify_result(ssl) == X509_V_OK){
+ LYDBGLOG("Certificate verification passed\n");
+ }
+ if (cert != NULL) {
+ line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ free(line);
+ line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ free(line);
+ X509_free(cert);
+ } else
+ LYDBGLOG("[%s %d] No certificate information\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_NOCERT);
+}
+
+static int http_ssl_connect(lynq_http_client_t* http)
+{
+ int ssl_ret = 0;
+ int remaind = http->timeout;
+ struct timeval start, elapsed;
+
+ http->ctx = SSL_CTX_new(SSLv23_client_method());
+ if(http->ctx == NULL)
+ {
+ return -1;
+ }
+ SSL_CTX_set_verify(http->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_X509Certificate);
+ SSL_CTX_set_verify_depth(http->ctx, VERIFY_DEPTH);
+
+ if (SSL_CTX_load_verify_locations(http->ctx, CA_ROOT, NULL) <= 0){
+ LYVERBLOG("+[http][%s][session%d]: error num = %d\n", http->action, http->session, ERR_SSL_CREATE_CTX);
+ return ERR_SSL_CREATE_CTX;
+ }
+
+ sslSetCertFile(http->ctx, CA_CLICRT);
+
+ sslSetKeyFile(http->ctx, CA_CLIKEY);
+
+ http->ssl = SSL_new(http->ctx);
+ if(http->ssl == NULL)
+ {
+ return -1;
+ }
+ if(SSL_set_fd(http->ssl, http->fd) == 0)
+ {
+ return -1;
+ }
+
+ gettimeofday(&start, 0);
+
+ do
+ {
+ ssl_ret = SSL_connect(http->ssl);
+
+ if (ssl_ret == -1) {
+ ERR_print_errors_fp(stderr);
+ }
+
+ else {
+ LYDBGLOG("[%s %d] Connected with %s encryption\n", __FUNCTION__, __LINE__, SSL_get_cipher(http->ssl));
+ //Show certificate information
+ //https_certificate_validation(http->ssl);
+ }
+
+ gettimeofday(&elapsed, 0);
+ remaind = http->timeout - ((int)(elapsed.tv_sec - start.tv_sec) * 1000 + (int)(elapsed.tv_usec - start.tv_usec) / 1000);
+
+ if(ssl_ret > 0)
+ {
+ return 0;
+ }
+ else
+ {
+ if(remaind <= 0)
+ {
+ return -1;
+ }
+ else if(http_check_error(http, kSelectRead+kSelectWrite, ssl_ret) == 0)
+ {
+ continue;
+ }
+ return -1;
+ }
+ }while(1);
+
+ return -1;
+}
+
+static int http_connect_host(lynq_http_client_t* http, const char* url, struct http_parser_url* u)
+{
+ struct sockaddr_in sin;
+ char host[256] = {0};
+ int r;
+ unsigned short port = 80;
+
+ if(u->field_set & (1 << UF_SCHEMA))
+ {
+ if(_strnicmp("http://", url + u->field_data[UF_SCHEMA].off, 7) == 0)
+ {
+ port = 80; http->proto_type = PROTO_HTTP;
+ }
+
+ else if(_strnicmp("https://", url + u->field_data[UF_SCHEMA].off, 8) == 0)
+ {
+ port = 443; http->proto_type = PROTO_HTTPS;
+ }
+
+ else
+ {
+ return ERR_URL_INVALID_PROTO;
+ }
+ }
+
+ if(!(u->field_set & (1 << UF_HOST)))
+ {
+ return ERR_URL_INVALID_HOST;
+ }
+
+ if(u->field_set & (1 << UF_PORT))
+ {
+ port = (unsigned short)atoi(url + u->field_data[UF_PORT].off);
+ }
+
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ memcpy(host, url + u->field_data[UF_HOST].off, u->field_data[UF_HOST].len);
+ if(host[0] >= '0' && host[0] <= '9')
+ {
+ sin.sin_addr.s_addr = (unsigned long)inet_addr(host);
+ }
+ else
+ {
+ struct hostent* he = gethostbyname(host);
+ if(he == NULL || he->h_addrtype != AF_INET)
+ {
+ return ERR_URL_RESOLVED_HOST;
+ }
+ sin.sin_addr = *((struct in_addr *)he->h_addr_list[0]);
+ }
+
+ if(sin.sin_addr.s_addr == INADDR_NONE)
+ {
+ return ERR_URL_RESOLVED_HOST;
+ }
+
+ sin.sin_port = htons(port);
+ sin.sin_family = AF_INET;
+
+
+ http->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if(http->fd == HTTP_INVALID_SOCKET)
+ {
+ return ERR_SOCKET_CREATE;
+ }
+
+ {
+ struct linger linger;
+ linger.l_onoff = 1;
+ linger.l_linger = 0;
+
+ if(setsockopt(http->fd,SOL_SOCKET, SO_LINGER,(const char *) &linger,sizeof(linger)) != 0)
+ {
+ return ERR_SOCKET_SET_OPT;
+ }
+ if(socket_noblocking(http->fd, 1) != 0)
+ {
+ return ERR_SOCKET_NOBLOCKING;
+ }
+ }
+
+ do
+ {
+ r = connect(http->fd, (struct sockaddr*)&sin, sizeof(sin));
+ if(r < 0)
+ {
+ int error = last_error();
+ if(error == HTTP_EINTR)
+ {
+ continue;
+ }
+ else if( error == HTTP_EINPROGRESS || error == HTTP_EWOULDBLOCK || error == HTTP_EALREADY)
+ {
+ if(socket_select(http, kSelectWrite, http->timeout) == 0)
+ {
+ break;
+ }
+ else
+ {
+ return ERR_SOCKET_CONNECT_TIMEOUT;
+ }
+ }
+ return ERR_SOCKET_CONNECT;
+ }
+ }while(1);
+
+ if(http->proto_type == PROTO_HTTPS)
+ {
+ if(http_ssl_connect(http) != 0)
+ {
+ return ERR_SSL_CONNECT;
+ }
+ }
+
+ return ERR_OK;
+}
+
+void http_init(lynq_http_client_t* http)
+{
+
+ http->redirect = 0;
+ http->body_len = 0;
+ http->content_length = 0;
+ http->cur_field_size = 0;
+ http->cur_value_size = 0;
+ http->field_size = 0;
+ http->value_size = 0;
+ http->parser_statue = 0;
+ http->error_code = 0;
+ http->user_header = 0;
+ http->user_header_len = 0;
+
+ if(http->timeout == 0) http->timeout = 1500000;
+}
+
+int http_connect(lynq_http_client_t* http)
+{
+ int r = 0;
+ if( http_parser_parse_url(http->url, strlen(http->url), 0, &http->u) != 0 )
+ {
+ LYDBGLOG("[%s-%d] ==============\n", __FUNCTION__, __LINE__);
+ return (http->error_code = ERR_URL_INVALID);
+ }
+
+ r = http_connect_host(http, http->url, &http->u);
+ if(r != ERR_OK)
+ {
+ LYDBGLOG("[%s-%d] ==============\n", __FUNCTION__, __LINE__);
+ return (http->error_code = r);
+ }
+
+ return 0;
+}
+
+int CHECK(int ret, lynq_http_client_t* http)
+{
+ if(ret <= 0)
+ return (http->error_code = ERR_SOCKET_WRITE);
+
+ return 0;
+}
+
+void http_write_headers(lynq_http_client_t* http)
+{
+ char *url = NULL;
+ if(http->redirect == 1)
+ url = http->redirect_url;
+ else
+ url = http->url;
+
+ if(http->method == M_GET)
+ {
+ CHECK(http_read_write(http, "GET ", 4, 0), http);
+ }
+ else if(http->method == M_POST)
+ {
+ CHECK(http_read_write(http, "POST ", 5, 0), http);
+ }
+
+ if(http->u.field_set & (1 << UF_PATH))
+ {
+ CHECK(http_read_write(http, url + http->u.field_data[UF_PATH].off, http->u.field_data[UF_PATH].len, 0), http);
+ }
+ else
+ {
+ CHECK(http_read_write(http, "/", 1, 0), http);
+ }
+
+ if(http->u.field_set & (1 << UF_QUERY))
+ {
+ CHECK(http_read_write(http, "?", 1, 0), http);
+ CHECK(http_read_write(http, url + http->u.field_data[UF_QUERY].off, http->u.field_data[UF_QUERY].len, 0), http);
+ }
+
+ CHECK(http_read_write(http, " HTTP/1.1\r\nHost:", 16, 0), http);
+ CHECK(http_read_write(http, url + http->u.field_data[UF_HOST].off, http->u.field_data[UF_HOST].len, 0), http);
+
+ if(http->conn_method == M_KEEP) {
+ CHECK(http_read_write(http, CRLF CONNECT_KEEP_STR ACCEPT_STR DEFAULT_USER_AGENT_STR ,
+ 2 + strlen(CONNECT_KEEP_STR) + strlen(ACCEPT_STR) + strlen(DEFAULT_USER_AGENT_STR), 0), http);
+ }
+ else {
+ CHECK(http_read_write(http, CRLF CONNECT_CLOSE_STR ACCEPT_STR DEFAULT_USER_AGENT_STR ,
+ 2 + strlen(CONNECT_CLOSE_STR) + strlen(ACCEPT_STR) + strlen(DEFAULT_USER_AGENT_STR), 0), http);
+ }
+
+ if(http->user_header != NULL)
+ {
+ CHECK(http_read_write(http, http->user_header, http->user_header_len, 0), http);
+ }
+
+ if(http->post_data && http->post_data_len > 0)
+ {
+ char len_data[256] = {0};
+ int n = sprintf(len_data, "%s:%d\r\n", CONTENT_TYPE_STR CONTENT_LENGTH_STR, http->post_data_len);
+ CHECK(http_read_write(http, len_data, n, 0), http);
+ }
+
+ CHECK(http_read_write(http, CRLF, 2, 0), http);
+
+
+}
+
+void http_write_data(lynq_http_client_t* http)
+{
+ CHECK(http_read_write(http, http->post_data, http->post_data_len, 0), http);
+}
+
+int lynq_http_data_send(char *data)
+{
+ struct mymesg ckxmsg;
+ ckxmsg.mtype = 1;
+ strcpy(ckxmsg.mtext, data);
+ int id = lynq_msgq_init("/tmp", 0666);
+ lynq_msgq_send(id, &ckxmsg);
+}
+
+void *lynq_http_write_head_data(lynq_http_client_t* http)
+{
+
+ http_write_headers(http);
+
+ if(http->post_data && http->post_data_len > 0)
+ {
+ http_write_data(http);
+ }
+ http->post_data = "";
+}
+
+void *http_write_head_data_thread(void* arg)
+{
+ int id = 0;
+ int runing = 1 ;
+ struct mymesg ckxmsg;
+
+ lynq_http_client_t* http = (lynq_http_client_t*)arg;
+
+ id = lynq_msgq_init("/tmp", 0666);
+
+ while(runing)
+ {
+#if 1
+ if(!strcmp(http->post_data, "") && http->conn_method == M_KEEP)
+ {
+ if(msgrcv(id, (void *)&ckxmsg, 512, 1, 0) < 0)
+ {
+ LYDBGLOG("[%s-%d] receive msg error \n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_MSG);
+ return ERR_MSG;
+ }
+ LYDBGLOG("[%s-%d] mtext :%s\n", __FUNCTION__, __LINE__, ckxmsg.mtext);
+
+ if (!strcmp(ckxmsg.mtext,"close"))
+ return NULL;
+
+ http->post_data = ckxmsg.mtext;
+ }
+#endif
+ lynq_http_write_head_data(http);
+
+ }
+}
+
+
+void *http_read_data_thread(void* arg)
+{
+ int parsed = 0;
+ lynq_http_client_t* http = (lynq_http_client_t*)arg;
+ do
+ {
+ int nread = 0;
+
+ if(http->download == 0 && http->parser_statue == PARSERD_BODY && http->body && http->content_length > 0)
+ {
+ nread = http_read_write(http, http->body+http->body_len, http->content_length - http->body_len, 1);
+ if(nread > 0)
+ {
+ http->body_len += nread;
+ break;
+ }
+ }
+ else
+ {
+ char buf[RECV_BUF_SIZE + 1] = {0};
+
+ nread = http_read_write(http, buf, RECV_BUF_SIZE, 1);
+
+ if(nread > 0)
+ {
+ parsed = http_parser_execute(&http->parser, &http->parser_setting, buf, nread);
+
+ if(http->redirect)
+ {
+ break;
+ }
+
+ if(parsed != nread)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if(nread == 0)
+ {
+ break;
+ }
+ else if(nread < 0)
+ {
+ return NULL;
+ }
+
+ } while (1);
+
+ return NULL;
+}
+
+
+
+static int http_internal_sync_request(lynq_http_client_t* http)
+{
+ int ret = 0;
+ http_init(http);
+
+ ret = http_connect(http);
+ if(ret != ERR_OK)
+ {
+ LYDBGLOG("[%s %d] return error\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http][%s][session%d]: error num = %d\n", http->action, http->session, http->error_code);
+ return (http->error_code);
+ }
+
+ if(http->conn_method == M_CLOSE)
+ lynq_http_write_head_data(http);
+ else {
+ pthread_t tid;
+ pthread_create(&tid, NULL, http_write_head_data_thread, http);
+ }
+ memset(&http->parser_setting, 0, sizeof(http->parser_setting));
+ http->parser_setting.on_body = http->download ? on_download_file_cb : on_body_cb;
+ http->parser_setting.on_message_complete = on_message_complete_cb;
+ http->parser_setting.on_header_field = on_header_field_cb;
+ http->parser_setting.on_header_value = on_header_value_cb;
+ http->parser_setting.on_headers_complete = on_headers_complete_cb;
+ http->parser_setting.on_status = on_status_cb;
+
+ http_parser_init(&http->parser, HTTP_RESPONSE);
+ http->parser.data = http;
+
+ if(http->conn_method == M_CLOSE)
+ http_read_data_thread(http);
+ else {
+ pthread_t read_tid;
+ pthread_create(&read_tid, NULL, http_read_data_thread, http);
+ }
+
+ if(http->redirect == 1)
+ {
+ return http_internal_sync_request(http);
+ }
+ else
+ {
+ if(http->download)
+ {
+ if(http->pf)
+ {
+ fclose(http->pf);
+ http->pf = NULL;
+ }
+ }
+ if(http->body && http->body_len > 0)
+ {
+ http->body[http->body_len] = '\0';
+ }
+ }
+ return http->error_code;
+}
+
+const char* lynq_http_sync_request(lynq_http_client_t* http, const char* url, http_request_method_e m, http_connent_method_e c_m)
+{
+ if(http == NULL)
+ {
+ return NULL;
+ }
+
+ http->method = m;
+ http->conn_method = c_m;
+ http->download = 0;
+ http->url = (char *)url;
+ http->error_code = http_internal_sync_request(http);
+
+ return http->body;
+}
+
+const char* lynq_http_sync_post_request(lynq_http_client_t* http, char* url, char* post_data, http_request_method_e m, http_connent_method_e c_m)
+{
+ if(http == NULL)
+ {
+ return NULL;
+ }
+
+ http->method = m;
+ http->conn_method = c_m;
+ http->download = 0;
+ free_member(http->post_data);
+ http->post_data = post_data;
+ http->url = url;
+ http->post_data_len = strlen(http->post_data);
+
+ http->error_code = http_internal_sync_request(http);
+
+ return http->body;
+}
+
+ int lynq_http_sync_download_file(lynq_http_client_t* http, char* url, char* filepath, http_request_method_e m, http_connent_method_e c_m)
+{
+ if(http == NULL)
+ {
+ return -1;
+ }
+
+ http->method = m;
+ http->conn_method = c_m;
+ http->download = 1;
+
+ http->post_data = "";
+
+ free_member(http->url);
+
+ http->url = url;
+
+ free_member(http->filename);
+
+ if(filepath == NULL || !strcmp(filepath, ""))
+ {
+ filepath = strrchr(http->url, '/') + 1 ;
+ }
+
+ if(filepath != NULL)
+ {
+ http->filename = _strdup(filepath);
+
+ if(http->filename == NULL)
+ {
+ return http->error_code = ERR_OUT_MEMORY;
+ }
+ }
+
+ if(http_internal_sync_request(http) == ERR_OK)
+ {
+ return ERR_OK;
+ }
+
+ return http->error_code;
+}
+
+int lynq_http_exit(lynq_http_client_t* http)
+{
+ if(http) http->exit = 1;
+
+ return 0;
+}
+
+int ft_http_set_data_recv_cb(lynq_http_client_t* http, data_recv_cb_t cb, void* user)
+{
+ if(http)
+ {
+ http->user = user;
+ http->recv_cb = cb;
+ }
+ return 0;
+}
diff --git a/src/lynq/lib/liblynq-protcl/http/src/lynq_http_parser.c b/src/lynq/lib/liblynq-protcl/http/src/lynq_http_parser.c
new file mode 100644
index 0000000..306e6db
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/src/lynq_http_parser.c
@@ -0,0 +1,2267 @@
+#include "http/lynq_http_parser.h"
+#include <assert.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifndef ULLONG_MAX
+# define ULLONG_MAX ((uint64_t) -1)
+#endif
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#ifndef BIT_AT
+# define BIT_AT(a, i) \
+ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
+ (1 << ((unsigned int) (i) & 7))))
+#endif
+
+#ifndef ELEM_AT
+# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
+#endif
+
+#define SET_ERRNO(e) \
+ do { \
+ parser->http_errno = (e); \
+ } while(0)
+
+#define CURRENT_STATE() p_state
+#define UPDATE_STATE(V) p_state = (enum state) (V);
+#define RETURN(V) \
+ do { \
+ parser->state = CURRENT_STATE(); \
+ return (V); \
+ } while (0);
+#define REEXECUTE() \
+ goto reexecute; \
+
+# define LIKELY(X) __builtin_expect(!!(X), 1)
+# define UNLIKELY(X) __builtin_expect(!!(X), 0)
+
+
+
+/* Run the notify callback FOR, returning ER if it fails */
+#define CALLBACK_NOTIFY_(FOR, ER) \
+ do { \
+ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
+ \
+ if (LIKELY(settings->on_##FOR)) { \
+ parser->state = CURRENT_STATE(); \
+ if (UNLIKELY(0 != settings->on_##FOR(parser))) { \
+ SET_ERRNO(HPE_CB_##FOR); \
+ } \
+ UPDATE_STATE(parser->state); \
+ \
+ /* We either errored above or got paused; get out */ \
+ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
+ return (ER); \
+ } \
+ } \
+ } while (0)
+
+#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
+#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
+#define CALLBACK_DATA_(FOR, LEN, ER) \
+ do { \
+ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
+ \
+ if (FOR##_mark) { \
+ if (LIKELY(settings->on_##FOR)) { \
+ parser->state = CURRENT_STATE(); \
+ if (UNLIKELY(0 != \
+ settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
+ SET_ERRNO(HPE_CB_##FOR); \
+ } \
+ UPDATE_STATE(parser->state); \
+ \
+ /* We either errored above or got paused; get out */ \
+ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
+ return (ER); \
+ } \
+ } \
+ FOR##_mark = NULL; \
+ } \
+ } while (0)
+
+#define CALLBACK_DATA(FOR) \
+ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
+
+#define CALLBACK_DATA_NOADVANCE(FOR) \
+ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
+
+#define MARK(FOR) \
+ do { \
+ if (!FOR##_mark) { \
+ FOR##_mark = p; \
+ } \
+ } while (0)
+
+#define COUNT_HEADER_SIZE(V) \
+ do { \
+ parser->nread += (V); \
+ if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \
+ SET_ERRNO(HPE_HEADER_OVERFLOW); \
+ goto error; \
+ } \
+ } while (0)
+
+
+#define PROXY_CONNECTION "proxy-connection"
+#define CONNECTION "connection"
+#define CONTENT_LENGTH "content-length"
+#define TRANSFER_ENCODING "transfer-encoding"
+#define UPGRADE "upgrade"
+#define CHUNKED "chunked"
+#define KEEP_ALIVE "keep-alive"
+#define CLOSE "close"
+
+
+static const char *method_strings[] =
+{
+#define XX(num, name, string) #string,
+ HTTP_METHOD_MAP(XX)
+#undef XX
+};
+
+static const char tokens[256] = {
+ /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+ 0, '!', 0, '#', '$', '%', '&', '\'',
+ /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+ 0, 0, '*', '+', 0, '-', '.', 0,
+ /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+ '8', '9', 0, 0, 0, 0, 0, 0,
+ /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+ 'x', 'y', 'z', 0, 0, 0, '^', '_',
+ /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+ 'x', 'y', 'z', 0, '|', 0, '~', 0 };
+
+
+static const int8_t unhex[256] =
+{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+};
+
+
+#if HTTP_PARSER_STRICT
+# define T(v) 0
+#else
+# define T(v) v
+#endif
+
+
+static const uint8_t normal_url_char[32] = {
+ /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+ /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+ 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
+ /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+ /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+ /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+ 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
+ /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
+ /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
+
+#undef T
+
+enum state
+{
+ s_dead = 1,
+ s_start_req_or_res,
+ s_res_or_resp_H,
+ s_start_res,
+ s_res_H,
+ s_res_HT,
+ s_res_HTT,
+ s_res_HTTP,
+ s_res_first_http_major,
+ s_res_http_major,
+ s_res_first_http_minor,
+ s_res_http_minor,
+ s_res_first_status_code,
+ s_res_status_code,
+ s_res_status_start,
+ s_res_status,
+ s_res_line_almost_done,
+ s_start_req,
+ s_req_method,
+ s_req_spaces_before_url,
+ s_req_schema,
+ s_req_schema_slash,
+ s_req_schema_slash_slash,
+ s_req_server_start,
+ s_req_server,
+ s_req_server_with_at,
+ s_req_path,
+ s_req_query_string_start,
+ s_req_query_string,
+ s_req_fragment_start,
+ s_req_fragment,
+ s_req_http_start,
+ s_req_http_H,
+ s_req_http_HT,
+ s_req_http_HTT,
+ s_req_http_HTTP,
+ s_req_first_http_major,
+ s_req_http_major,
+ s_req_first_http_minor,
+ s_req_http_minor,
+ s_req_line_almost_done,
+ s_header_field_start,
+ s_header_field,
+ s_header_value_discard_ws,
+ s_header_value_discard_ws_almost_done,
+ s_header_value_discard_lws,
+ s_header_value_start,
+ s_header_value,
+ s_header_value_lws,
+ s_header_almost_done,
+ s_chunk_size_start,
+ s_chunk_size,
+ s_chunk_parameters,
+ s_chunk_size_almost_done,
+ s_headers_almost_done,
+ s_headers_done,
+ s_chunk_data,
+ s_chunk_data_almost_done,
+ s_chunk_data_done,
+ s_body_identity,
+ s_body_identity_eof,
+ s_message_done,
+};
+
+
+#define PARSING_HEADER(state) (state <= s_headers_done)
+
+
+enum header_states
+{
+ h_general = 0,
+ h_C,
+ h_CO,
+ h_CON,
+ h_matching_connection,
+ h_matching_proxy_connection,
+ h_matching_content_length,
+ h_matching_transfer_encoding,
+ h_matching_upgrade,
+
+ h_connection,
+ h_content_length,
+ h_transfer_encoding,
+ h_upgrade,
+
+ h_matching_transfer_encoding_chunked,
+ h_matching_connection_token_start,
+ h_matching_connection_keep_alive,
+ h_matching_connection_close,
+ h_matching_connection_upgrade,
+ h_matching_connection_token,
+
+ h_transfer_encoding_chunked,
+ h_connection_keep_alive,
+ h_connection_close,
+ h_connection_upgrade,
+};
+
+enum http_host_state
+{
+ s_http_host_dead = 1,
+ s_http_userinfo_start,
+ s_http_userinfo,
+ s_http_host_start,
+ s_http_host_v6_start,
+ s_http_host,
+ s_http_host_v6,
+ s_http_host_v6_end,
+ s_http_host_v6_zone_start,
+ s_http_host_v6_zone,
+ s_http_host_port_start,
+ s_http_host_port,
+};
+
+/* Macros for character classes; depends on strict-mode */
+#define CR '\r'
+#define LF '\n'
+#define LOWER(c) (unsigned char)(c | 0x20)
+#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
+#define IS_NUM(c) ((c) >= '0' && (c) <= '9')
+#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
+#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
+#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
+ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
+ (c) == ')')
+#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
+ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
+ (c) == '$' || (c) == ',')
+
+#define STRICT_TOKEN(c) (tokens[(unsigned char)c])
+
+#if HTTP_PARSER_STRICT
+#define TOKEN(c) (tokens[(unsigned char)c])
+#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
+#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
+#else
+#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
+#define IS_URL_CHAR(c) \
+ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
+#define IS_HOST_CHAR(c) \
+ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
+#endif
+
+
+#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
+
+
+#if HTTP_PARSER_STRICT
+# define STRICT_CHECK(cond) \
+ do { \
+ if (cond) { \
+ SET_ERRNO(HPE_STRICT); \
+ goto error; \
+ } \
+ } while (0)
+# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
+#else
+# define STRICT_CHECK(cond)
+# define NEW_MESSAGE() start_state
+#endif
+
+
+/* Map errno values to strings for human-readable output */
+#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
+static struct {
+ const char *name;
+ const char *description;
+} http_strerror_tab[] = {
+ HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
+};
+#undef HTTP_STRERROR_GEN
+
+int http_message_needs_eof(const http_parser *parser);
+
+static enum state
+parse_url_char(enum state s, const char ch)
+{
+ if (ch == ' ' || ch == '\r' || ch == '\n') {
+ return s_dead;
+ }
+
+#if HTTP_PARSER_STRICT
+ if (ch == '\t' || ch == '\f') {
+ return s_dead;
+ }
+#endif
+
+ switch (s) {
+ case s_req_spaces_before_url:
+ if (ch == '/' || ch == '*') {
+ return s_req_path;
+ }
+
+ if (IS_ALPHA(ch)) {
+ return s_req_schema;
+ }
+
+ break;
+
+ case s_req_schema:
+ if (IS_ALPHA(ch)) {
+ return s;
+ }
+
+ if (ch == ':') {
+ return s_req_schema_slash;
+ }
+
+ break;
+
+ case s_req_schema_slash:
+ if (ch == '/') {
+ return s_req_schema_slash_slash;
+ }
+
+ break;
+
+ case s_req_schema_slash_slash:
+ if (ch == '/') {
+ return s_req_server_start;
+ }
+
+ break;
+
+ case s_req_server_with_at:
+ if (ch == '@') {
+ return s_dead;
+ }
+ case s_req_server_start:
+ case s_req_server:
+ if (ch == '/') {
+ return s_req_path;
+ }
+
+ if (ch == '?') {
+ return s_req_query_string_start;
+ }
+
+ if (ch == '@') {
+ return s_req_server_with_at;
+ }
+
+ if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
+ return s_req_server;
+ }
+
+ break;
+
+ case s_req_path:
+ if (IS_URL_CHAR(ch)) {
+ return s;
+ }
+
+ switch (ch) {
+ case '?':
+ return s_req_query_string_start;
+
+ case '#':
+ return s_req_fragment_start;
+ }
+
+ break;
+
+ case s_req_query_string_start:
+ case s_req_query_string:
+ if (IS_URL_CHAR(ch)) {
+ return s_req_query_string;
+ }
+
+ switch (ch) {
+ case '?':
+ /* allow extra '?' in query string */
+ return s_req_query_string;
+
+ case '#':
+ return s_req_fragment_start;
+ }
+
+ break;
+
+ case s_req_fragment_start:
+ if (IS_URL_CHAR(ch)) {
+ return s_req_fragment;
+ }
+
+ switch (ch) {
+ case '?':
+ return s_req_fragment;
+
+ case '#':
+ return s;
+ }
+
+ break;
+
+ case s_req_fragment:
+ if (IS_URL_CHAR(ch)) {
+ return s;
+ }
+
+ switch (ch) {
+ case '?':
+ case '#':
+ return s;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return s_dead;
+}
+
+size_t http_parser_execute (http_parser *parser,
+ const http_parser_settings *settings,
+ const char *data,
+ size_t len)
+{
+ char c, ch;
+ int8_t unhex_val;
+ const char *p = data;
+ const char *header_field_mark = 0;
+ const char *header_value_mark = 0;
+ const char *url_mark = 0;
+ const char *body_mark = 0;
+ const char *status_mark = 0;
+ enum state p_state = (enum state) parser->state;
+
+ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+ return 0;
+ }
+
+ if (len == 0) {
+ switch (CURRENT_STATE()) {
+ case s_body_identity_eof:
+ CALLBACK_NOTIFY_NOADVANCE(message_complete);
+ return 0;
+
+ case s_dead:
+ case s_start_req_or_res:
+ case s_start_res:
+ case s_start_req:
+ return 0;
+
+ default:
+ SET_ERRNO(HPE_INVALID_EOF_STATE);
+ return 1;
+ }
+ }
+
+ if (CURRENT_STATE() == s_header_field)
+ header_field_mark = data;
+ if (CURRENT_STATE() == s_header_value)
+ header_value_mark = data;
+ switch (CURRENT_STATE()) {
+ case s_req_path:
+ case s_req_schema:
+ case s_req_schema_slash:
+ case s_req_schema_slash_slash:
+ case s_req_server_start:
+ case s_req_server:
+ case s_req_server_with_at:
+ case s_req_query_string_start:
+ case s_req_query_string:
+ case s_req_fragment_start:
+ case s_req_fragment:
+ url_mark = data;
+ break;
+ case s_res_status:
+ status_mark = data;
+ break;
+ default:
+ break;
+ }
+
+ for (p=data; p != data + len; p++) {
+ ch = *p;
+
+ if (PARSING_HEADER(CURRENT_STATE()))
+ COUNT_HEADER_SIZE(1);
+
+reexecute:
+ switch (CURRENT_STATE()) {
+
+ case s_dead:
+ if (LIKELY(ch == CR || ch == LF))
+ break;
+
+ SET_ERRNO(HPE_CLOSED_CONNECTION);
+ goto error;
+
+ case s_start_req_or_res:
+ {
+ if (ch == CR || ch == LF)
+ break;
+ parser->flags = 0;
+ parser->content_length = ULLONG_MAX;
+
+ if (ch == 'H') {
+ UPDATE_STATE(s_res_or_resp_H);
+
+ CALLBACK_NOTIFY(message_begin);
+ } else {
+ parser->type = HTTP_REQUEST;
+ UPDATE_STATE(s_start_req);
+ REEXECUTE();
+ }
+
+ break;
+ }
+
+ case s_res_or_resp_H:
+ if (ch == 'T') {
+ parser->type = HTTP_RESPONSE;
+ UPDATE_STATE(s_res_HT);
+ } else {
+ if (UNLIKELY(ch != 'E')) {
+ SET_ERRNO(HPE_INVALID_CONSTANT);
+ goto error;
+ }
+
+ parser->type = HTTP_REQUEST;
+ parser->method = HTTP_HEAD;
+ parser->index = 2;
+ UPDATE_STATE(s_req_method);
+ }
+ break;
+
+ case s_start_res:
+ {
+ parser->flags = 0;
+ parser->content_length = ULLONG_MAX;
+
+ switch (ch) {
+ case 'H':
+ UPDATE_STATE(s_res_H);
+ break;
+
+ case CR:
+ case LF:
+ break;
+
+ default:
+ SET_ERRNO(HPE_INVALID_CONSTANT);
+ goto error;
+ }
+
+ CALLBACK_NOTIFY(message_begin);
+ break;
+ }
+
+ case s_res_H:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_res_HT);
+ break;
+
+ case s_res_HT:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_res_HTT);
+ break;
+
+ case s_res_HTT:
+ STRICT_CHECK(ch != 'P');
+ UPDATE_STATE(s_res_HTTP);
+ break;
+
+ case s_res_HTTP:
+ STRICT_CHECK(ch != '/');
+ UPDATE_STATE(s_res_first_http_major);
+ break;
+
+ case s_res_first_http_major:
+ if (UNLIKELY(ch < '0' || ch > '9')) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major = ch - '0';
+ UPDATE_STATE(s_res_http_major);
+ break;
+
+ case s_res_http_major:
+ {
+ if (ch == '.') {
+ UPDATE_STATE(s_res_first_http_minor);
+ break;
+ }
+
+ if (!IS_NUM(ch)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major *= 10;
+ parser->http_major += ch - '0';
+
+ if (UNLIKELY(parser->http_major > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_res_first_http_minor:
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor = ch - '0';
+ UPDATE_STATE(s_res_http_minor);
+ break;
+
+ /* minor HTTP version or end of request line */
+ case s_res_http_minor:
+ {
+ if (ch == ' ') {
+ UPDATE_STATE(s_res_first_status_code);
+ break;
+ }
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor *= 10;
+ parser->http_minor += ch - '0';
+
+ if (UNLIKELY(parser->http_minor > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_res_first_status_code:
+ {
+ if (!IS_NUM(ch)) {
+ if (ch == ' ') {
+ break;
+ }
+
+ SET_ERRNO(HPE_INVALID_STATUS);
+ goto error;
+ }
+ parser->status_code = ch - '0';
+ UPDATE_STATE(s_res_status_code);
+ break;
+ }
+
+ case s_res_status_code:
+ {
+ if (!IS_NUM(ch)) {
+ switch (ch) {
+ case ' ':
+ UPDATE_STATE(s_res_status_start);
+ break;
+ case CR:
+ UPDATE_STATE(s_res_line_almost_done);
+ break;
+ case LF:
+ UPDATE_STATE(s_header_field_start);
+ break;
+ default:
+ SET_ERRNO(HPE_INVALID_STATUS);
+ goto error;
+ }
+ break;
+ }
+
+ parser->status_code *= 10;
+ parser->status_code += ch - '0';
+
+ if (UNLIKELY(parser->status_code > 999)) {
+ SET_ERRNO(HPE_INVALID_STATUS);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_res_status_start:
+ {
+ if (ch == CR) {
+ UPDATE_STATE(s_res_line_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_field_start);
+ break;
+ }
+
+ MARK(status);
+ UPDATE_STATE(s_res_status);
+ parser->index = 0;
+ break;
+ }
+
+ case s_res_status:
+ if (ch == CR) {
+ UPDATE_STATE(s_res_line_almost_done);
+ CALLBACK_DATA(status);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_field_start);
+ CALLBACK_DATA(status);
+ break;
+ }
+
+ break;
+
+ case s_res_line_almost_done:
+ STRICT_CHECK(ch != LF);
+ UPDATE_STATE(s_header_field_start);
+ break;
+
+ case s_start_req:
+ {
+ if (ch == CR || ch == LF)
+ break;
+ parser->flags = 0;
+ parser->content_length = ULLONG_MAX;
+
+ if (UNLIKELY(!IS_ALPHA(ch))) {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+
+ parser->method = (enum http_method) 0;
+ parser->index = 1;
+ switch (ch) {
+ case 'A': parser->method = HTTP_ACL; break;
+ case 'B': parser->method = HTTP_BIND; break;
+ case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
+ case 'D': parser->method = HTTP_DELETE; break;
+ case 'G': parser->method = HTTP_GET; break;
+ case 'H': parser->method = HTTP_HEAD; break;
+ case 'L': parser->method = HTTP_LOCK; break;
+ case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
+ case 'N': parser->method = HTTP_NOTIFY; break;
+ case 'O': parser->method = HTTP_OPTIONS; break;
+ case 'P': parser->method = HTTP_POST;
+ /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
+ break;
+ case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
+ case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
+ case 'T': parser->method = HTTP_TRACE; break;
+ case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND */ break;
+ default:
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ UPDATE_STATE(s_req_method);
+
+ CALLBACK_NOTIFY(message_begin);
+
+ break;
+ }
+
+ case s_req_method:
+ {
+ const char *matcher;
+ if (UNLIKELY(ch == '\0')) {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+
+ matcher = method_strings[parser->method];
+ if (ch == ' ' && matcher[parser->index] == '\0') {
+ UPDATE_STATE(s_req_spaces_before_url);
+ } else if (ch == matcher[parser->index]) {
+ ; /* nada */
+ } else if (parser->method == HTTP_CONNECT) {
+ if (parser->index == 1 && ch == 'H') {
+ parser->method = HTTP_CHECKOUT;
+ } else if (parser->index == 2 && ch == 'P') {
+ parser->method = HTTP_COPY;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_MKCOL) {
+ if (parser->index == 1 && ch == 'O') {
+ parser->method = HTTP_MOVE;
+ } else if (parser->index == 1 && ch == 'E') {
+ parser->method = HTTP_MERGE;
+ } else if (parser->index == 1 && ch == '-') {
+ parser->method = HTTP_MSEARCH;
+ } else if (parser->index == 2 && ch == 'A') {
+ parser->method = HTTP_MKACTIVITY;
+ } else if (parser->index == 3 && ch == 'A') {
+ parser->method = HTTP_MKCALENDAR;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_SUBSCRIBE) {
+ if (parser->index == 1 && ch == 'E') {
+ parser->method = HTTP_SEARCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_REPORT) {
+ if (parser->index == 2 && ch == 'B') {
+ parser->method = HTTP_REBIND;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->index == 1 && parser->method == HTTP_POST) {
+ if (ch == 'R') {
+ parser->method = HTTP_PROPFIND;
+ } else if (ch == 'U') {
+ parser->method = HTTP_PUT;
+ } else if (ch == 'A') {
+ parser->method = HTTP_PATCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->index == 2) {
+ if (parser->method == HTTP_PUT) {
+ if (ch == 'R') {
+ parser->method = HTTP_PURGE;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_UNLOCK) {
+ if (ch == 'S') {
+ parser->method = HTTP_UNSUBSCRIBE;
+ } else if(ch == 'B') {
+ parser->method = HTTP_UNBIND;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
+ parser->method = HTTP_PROPPATCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+
+ ++parser->index;
+ break;
+ }
+
+ case s_req_spaces_before_url:
+ {
+ if (ch == ' ') break;
+
+ MARK(url);
+ if (parser->method == HTTP_CONNECT) {
+ UPDATE_STATE(s_req_server_start);
+ }
+
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_req_schema:
+ case s_req_schema_slash:
+ case s_req_schema_slash_slash:
+ case s_req_server_start:
+ {
+ switch (ch) {
+ case ' ':
+ case CR:
+ case LF:
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ default:
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ }
+ }
+
+ break;
+ }
+
+ case s_req_server:
+ case s_req_server_with_at:
+ case s_req_path:
+ case s_req_query_string_start:
+ case s_req_query_string:
+ case s_req_fragment_start:
+ case s_req_fragment:
+ {
+ switch (ch) {
+ case ' ':
+ UPDATE_STATE(s_req_http_start);
+ CALLBACK_DATA(url);
+ break;
+ case CR:
+ case LF:
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ UPDATE_STATE((ch == CR) ?
+ s_req_line_almost_done :
+ s_header_field_start);
+ CALLBACK_DATA(url);
+ break;
+ default:
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ }
+ }
+ break;
+ }
+
+ case s_req_http_start:
+ switch (ch) {
+ case 'H':
+ UPDATE_STATE(s_req_http_H);
+ break;
+ case ' ':
+ break;
+ default:
+ SET_ERRNO(HPE_INVALID_CONSTANT);
+ goto error;
+ }
+ break;
+
+ case s_req_http_H:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_req_http_HT);
+ break;
+
+ case s_req_http_HT:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_req_http_HTT);
+ break;
+
+ case s_req_http_HTT:
+ STRICT_CHECK(ch != 'P');
+ UPDATE_STATE(s_req_http_HTTP);
+ break;
+
+ case s_req_http_HTTP:
+ STRICT_CHECK(ch != '/');
+ UPDATE_STATE(s_req_first_http_major);
+ break;
+
+ case s_req_first_http_major:
+ if (UNLIKELY(ch < '1' || ch > '9')) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major = ch - '0';
+ UPDATE_STATE(s_req_http_major);
+ break;
+
+ case s_req_http_major:
+ {
+ if (ch == '.') {
+ UPDATE_STATE(s_req_first_http_minor);
+ break;
+ }
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major *= 10;
+ parser->http_major += ch - '0';
+
+ if (UNLIKELY(parser->http_major > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_req_first_http_minor:
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor = ch - '0';
+ UPDATE_STATE(s_req_http_minor);
+ break;
+
+ case s_req_http_minor:
+ {
+ if (ch == CR) {
+ UPDATE_STATE(s_req_line_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_field_start);
+ break;
+ }
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor *= 10;
+ parser->http_minor += ch - '0';
+
+ if (UNLIKELY(parser->http_minor > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_req_line_almost_done:
+ {
+ if (UNLIKELY(ch != LF)) {
+ SET_ERRNO(HPE_LF_EXPECTED);
+ goto error;
+ }
+
+ UPDATE_STATE(s_header_field_start);
+ break;
+ }
+
+ case s_header_field_start:
+ {
+ if (ch == CR) {
+ UPDATE_STATE(s_headers_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_headers_almost_done);
+ REEXECUTE();
+ }
+
+ c = TOKEN(ch);
+
+ if (UNLIKELY(!c)) {
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+ goto error;
+ }
+
+ MARK(header_field);
+
+ parser->index = 0;
+ UPDATE_STATE(s_header_field);
+
+ switch (c) {
+ case 'c':
+ parser->header_state = h_C;
+ break;
+
+ case 'p':
+ parser->header_state = h_matching_proxy_connection;
+ break;
+
+ case 't':
+ parser->header_state = h_matching_transfer_encoding;
+ break;
+
+ case 'u':
+ parser->header_state = h_matching_upgrade;
+ break;
+
+ default:
+ parser->header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_field:
+ {
+ const char* start = p;
+ for (; p != data + len; p++) {
+ ch = *p;
+ c = TOKEN(ch);
+
+ if (!c)
+ break;
+
+ switch (parser->header_state) {
+ case h_general:
+ break;
+
+ case h_C:
+ parser->index++;
+ parser->header_state = (c == 'o' ? h_CO : h_general);
+ break;
+
+ case h_CO:
+ parser->index++;
+ parser->header_state = (c == 'n' ? h_CON : h_general);
+ break;
+
+ case h_CON:
+ parser->index++;
+ switch (c) {
+ case 'n':
+ parser->header_state = h_matching_connection;
+ break;
+ case 't':
+ parser->header_state = h_matching_content_length;
+ break;
+ default:
+ parser->header_state = h_general;
+ break;
+ }
+ break;
+
+ case h_matching_connection:
+ parser->index++;
+ if (parser->index > sizeof(CONNECTION)-1
+ || c != CONNECTION[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(CONNECTION)-2) {
+ parser->header_state = h_connection;
+ }
+ break;
+
+ case h_matching_proxy_connection:
+ parser->index++;
+ if (parser->index > sizeof(PROXY_CONNECTION)-1
+ || c != PROXY_CONNECTION[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
+ parser->header_state = h_connection;
+ }
+ break;
+
+ case h_matching_content_length:
+ parser->index++;
+ if (parser->index > sizeof(CONTENT_LENGTH)-1
+ || c != CONTENT_LENGTH[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
+ parser->header_state = h_content_length;
+ }
+ break;
+
+ case h_matching_transfer_encoding:
+ parser->index++;
+ if (parser->index > sizeof(TRANSFER_ENCODING)-1
+ || c != TRANSFER_ENCODING[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
+ parser->header_state = h_transfer_encoding;
+ }
+ break;
+
+ case h_matching_upgrade:
+ parser->index++;
+ if (parser->index > sizeof(UPGRADE)-1
+ || c != UPGRADE[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(UPGRADE)-2) {
+ parser->header_state = h_upgrade;
+ }
+ break;
+
+ case h_connection:
+ case h_content_length:
+ case h_transfer_encoding:
+ case h_upgrade:
+ if (ch != ' ') parser->header_state = h_general;
+ break;
+
+ default:
+ assert(0 && "Unknown header_state");
+ break;
+ }
+ }
+
+ COUNT_HEADER_SIZE(p - start);
+
+ if (p == data + len) {
+ --p;
+ break;
+ }
+
+ if (ch == ':') {
+ UPDATE_STATE(s_header_value_discard_ws);
+ CALLBACK_DATA(header_field);
+ break;
+ }
+
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+ goto error;
+ }
+
+ case s_header_value_discard_ws:
+ if (ch == ' ' || ch == '\t') break;
+
+ if (ch == CR) {
+ UPDATE_STATE(s_header_value_discard_ws_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_value_discard_lws);
+ break;
+ }
+
+ case s_header_value_start:
+ {
+ MARK(header_value);
+
+ UPDATE_STATE(s_header_value);
+ parser->index = 0;
+
+ c = LOWER(ch);
+
+ switch (parser->header_state) {
+ case h_upgrade:
+ parser->flags |= F_UPGRADE;
+ parser->header_state = h_general;
+ break;
+
+ case h_transfer_encoding:
+ if ('c' == c) {
+ parser->header_state = h_matching_transfer_encoding_chunked;
+ } else {
+ parser->header_state = h_general;
+ }
+ break;
+
+ case h_content_length:
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ goto error;
+ }
+
+ parser->content_length = ch - '0';
+ break;
+
+ case h_connection:
+ if (c == 'k') {
+ parser->header_state = h_matching_connection_keep_alive;
+ } else if (c == 'c') {
+ parser->header_state = h_matching_connection_close;
+ } else if (c == 'u') {
+ parser->header_state = h_matching_connection_upgrade;
+ } else {
+ parser->header_state = h_matching_connection_token;
+ }
+ break;
+
+ case h_matching_connection_token_start:
+ break;
+
+ default:
+ parser->header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_value:
+ {
+ const char* start = p;
+ enum header_states h_state = (enum header_states) parser->header_state;
+ for (; p != data + len; p++) {
+ ch = *p;
+ if (ch == CR) {
+ UPDATE_STATE(s_header_almost_done);
+ parser->header_state = h_state;
+ CALLBACK_DATA(header_value);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_almost_done);
+ COUNT_HEADER_SIZE(p - start);
+ parser->header_state = h_state;
+ CALLBACK_DATA_NOADVANCE(header_value);
+ REEXECUTE();
+ }
+
+ c = LOWER(ch);
+
+ switch (h_state) {
+ case h_general:
+ {
+ const char* p_cr;
+ const char* p_lf;
+ size_t limit = data + len - p;
+
+ limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
+
+ p_cr = (const char*) memchr(p, CR, limit);
+ p_lf = (const char*) memchr(p, LF, limit);
+ if (p_cr != NULL) {
+ if (p_lf != NULL && p_cr >= p_lf)
+ p = p_lf;
+ else
+ p = p_cr;
+ } else if (UNLIKELY(p_lf != NULL)) {
+ p = p_lf;
+ } else {
+ p = data + len;
+ }
+ --p;
+
+ break;
+ }
+
+ case h_connection:
+ case h_transfer_encoding:
+ assert(0 && "Shouldn't get here.");
+ break;
+
+ case h_content_length:
+ {
+ uint64_t t;
+
+ if (ch == ' ') break;
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ parser->header_state = h_state;
+ goto error;
+ }
+
+ t = parser->content_length;
+ t *= 10;
+ t += ch - '0';
+
+ if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ parser->header_state = h_state;
+ goto error;
+ }
+
+ parser->content_length = t;
+ break;
+ }
+
+ case h_matching_transfer_encoding_chunked:
+ parser->index++;
+ if (parser->index > sizeof(CHUNKED)-1
+ || c != CHUNKED[parser->index]) {
+ h_state = h_general;
+ } else if (parser->index == sizeof(CHUNKED)-2) {
+ h_state = h_transfer_encoding_chunked;
+ }
+ break;
+
+ case h_matching_connection_token_start:
+ if (c == 'k') {
+ h_state = h_matching_connection_keep_alive;
+ } else if (c == 'c') {
+ h_state = h_matching_connection_close;
+ } else if (c == 'u') {
+ h_state = h_matching_connection_upgrade;
+ } else if (STRICT_TOKEN(c)) {
+ h_state = h_matching_connection_token;
+ } else if (c == ' ' || c == '\t') {
+ /* Skip lws */
+ } else {
+ h_state = h_general;
+ }
+ break;
+
+ case h_matching_connection_keep_alive:
+ parser->index++;
+ if (parser->index > sizeof(KEEP_ALIVE)-1
+ || c != KEEP_ALIVE[parser->index]) {
+ h_state = h_matching_connection_token;
+ } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
+ h_state = h_connection_keep_alive;
+ }
+ break;
+
+ case h_matching_connection_close:
+ parser->index++;
+ if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
+ h_state = h_matching_connection_token;
+ } else if (parser->index == sizeof(CLOSE)-2) {
+ h_state = h_connection_close;
+ }
+ break;
+
+ case h_matching_connection_upgrade:
+ parser->index++;
+ if (parser->index > sizeof(UPGRADE) - 1 ||
+ c != UPGRADE[parser->index]) {
+ h_state = h_matching_connection_token;
+ } else if (parser->index == sizeof(UPGRADE)-2) {
+ h_state = h_connection_upgrade;
+ }
+ break;
+
+ case h_matching_connection_token:
+ if (ch == ',') {
+ h_state = h_matching_connection_token_start;
+ parser->index = 0;
+ }
+ break;
+
+ case h_transfer_encoding_chunked:
+ if (ch != ' ') h_state = h_general;
+ break;
+
+ case h_connection_keep_alive:
+ case h_connection_close:
+ case h_connection_upgrade:
+ if (ch == ',') {
+ if (h_state == h_connection_keep_alive) {
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ } else if (h_state == h_connection_close) {
+ parser->flags |= F_CONNECTION_CLOSE;
+ } else if (h_state == h_connection_upgrade) {
+ parser->flags |= F_CONNECTION_UPGRADE;
+ }
+ h_state = h_matching_connection_token_start;
+ parser->index = 0;
+ } else if (ch != ' ') {
+ h_state = h_matching_connection_token;
+ }
+ break;
+
+ default:
+ UPDATE_STATE(s_header_value);
+ h_state = h_general;
+ break;
+ }
+ }
+ parser->header_state = h_state;
+
+ COUNT_HEADER_SIZE(p - start);
+
+ if (p == data + len)
+ --p;
+ break;
+ }
+
+ case s_header_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+
+ UPDATE_STATE(s_header_value_lws);
+ break;
+ }
+
+ case s_header_value_lws:
+ {
+ if (ch == ' ' || ch == '\t') {
+ UPDATE_STATE(s_header_value_start);
+ REEXECUTE();
+ }
+
+ /* finished the header */
+ switch (parser->header_state) {
+ case h_connection_keep_alive:
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ break;
+ case h_connection_close:
+ parser->flags |= F_CONNECTION_CLOSE;
+ break;
+ case h_transfer_encoding_chunked:
+ parser->flags |= F_CHUNKED;
+ break;
+ case h_connection_upgrade:
+ parser->flags |= F_CONNECTION_UPGRADE;
+ break;
+ default:
+ break;
+ }
+
+ UPDATE_STATE(s_header_field_start);
+ REEXECUTE();
+ }
+
+ case s_header_value_discard_ws_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+ UPDATE_STATE(s_header_value_discard_lws);
+ break;
+ }
+
+ case s_header_value_discard_lws:
+ {
+ if (ch == ' ' || ch == '\t') {
+ UPDATE_STATE(s_header_value_discard_ws);
+ break;
+ } else {
+ switch (parser->header_state) {
+ case h_connection_keep_alive:
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ break;
+ case h_connection_close:
+ parser->flags |= F_CONNECTION_CLOSE;
+ break;
+ case h_connection_upgrade:
+ parser->flags |= F_CONNECTION_UPGRADE;
+ break;
+ case h_transfer_encoding_chunked:
+ parser->flags |= F_CHUNKED;
+ break;
+ default:
+ break;
+ }
+ MARK(header_value);
+ UPDATE_STATE(s_header_field_start);
+ CALLBACK_DATA_NOADVANCE(header_value);
+ REEXECUTE();
+ }
+ }
+
+ case s_headers_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+
+ if (parser->flags & F_TRAILING) {
+ /* End of a chunked request */
+ UPDATE_STATE(s_message_done);
+ CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
+ REEXECUTE();
+ }
+
+ UPDATE_STATE(s_headers_done);
+
+ parser->upgrade =
+ ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) ==
+ (F_UPGRADE | F_CONNECTION_UPGRADE) ||
+ parser->method == HTTP_CONNECT);
+
+ if (settings->on_headers_complete) {
+ switch (settings->on_headers_complete(parser)) {
+ case 0:
+ break;
+
+ case 1:
+ parser->flags |= F_SKIPBODY;
+ break;
+
+ default:
+ SET_ERRNO(HPE_CB_headers_complete);
+ RETURN(p - data); /* Error */
+ }
+ }
+
+ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+ RETURN(p - data);
+ }
+
+ REEXECUTE();
+ }
+
+ case s_headers_done:
+ {
+ int hasBody;
+ STRICT_CHECK(ch != LF);
+
+ parser->nread = 0;
+
+ hasBody = parser->flags & F_CHUNKED ||
+ (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
+ if (parser->upgrade && (parser->method == HTTP_CONNECT ||
+ (parser->flags & F_SKIPBODY) || !hasBody)) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ RETURN((p - data) + 1);
+ }
+
+ if (parser->flags & F_SKIPBODY) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ } else if (parser->flags & F_CHUNKED) {
+ UPDATE_STATE(s_chunk_size_start);
+ } else {
+ if (parser->content_length == 0) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ } else if (parser->content_length != ULLONG_MAX) {
+ UPDATE_STATE(s_body_identity);
+ } else {
+ if (!http_message_needs_eof(parser)) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ } else {
+ UPDATE_STATE(s_body_identity_eof);
+ }
+ }
+ }
+
+ break;
+ }
+
+ case s_body_identity:
+ {
+ uint64_t to_read = MIN(parser->content_length,
+ (uint64_t) ((data + len) - p));
+
+ assert(parser->content_length != 0
+ && parser->content_length != ULLONG_MAX);
+ MARK(body);
+ parser->content_length -= to_read;
+ p += to_read - 1;
+
+ if (parser->content_length == 0) {
+ UPDATE_STATE(s_message_done);
+ CALLBACK_DATA_(body, p - body_mark + 1, p - data);
+ REEXECUTE();
+ }
+
+ break;
+ }
+ case s_body_identity_eof:
+ MARK(body);
+ p = data + len - 1;
+
+ break;
+
+ case s_message_done:
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ if (parser->upgrade) {
+ RETURN((p - data) + 1);
+ }
+ break;
+
+ case s_chunk_size_start:
+ {
+ assert(parser->nread == 1);
+ assert(parser->flags & F_CHUNKED);
+
+ unhex_val = unhex[(unsigned char)ch];
+ if (UNLIKELY(unhex_val == -1)) {
+ SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+ goto error;
+ }
+
+ parser->content_length = unhex_val;
+ UPDATE_STATE(s_chunk_size);
+ break;
+ }
+
+ case s_chunk_size:
+ {
+ uint64_t t;
+
+ assert(parser->flags & F_CHUNKED);
+
+ if (ch == CR) {
+ UPDATE_STATE(s_chunk_size_almost_done);
+ break;
+ }
+
+ unhex_val = unhex[(unsigned char)ch];
+
+ if (unhex_val == -1) {
+ if (ch == ';' || ch == ' ') {
+ UPDATE_STATE(s_chunk_parameters);
+ break;
+ }
+
+ SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+ goto error;
+ }
+
+ t = parser->content_length;
+ t *= 16;
+ t += unhex_val;
+
+ if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ goto error;
+ }
+
+ parser->content_length = t;
+ break;
+ }
+
+ case s_chunk_parameters:
+ {
+ assert(parser->flags & F_CHUNKED);
+ if (ch == CR) {
+ UPDATE_STATE(s_chunk_size_almost_done);
+ break;
+ }
+ break;
+ }
+
+ case s_chunk_size_almost_done:
+ {
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != LF);
+
+ parser->nread = 0;
+
+ if (parser->content_length == 0) {
+ parser->flags |= F_TRAILING;
+ UPDATE_STATE(s_header_field_start);
+ } else {
+ UPDATE_STATE(s_chunk_data);
+ }
+ CALLBACK_NOTIFY(chunk_header);
+ break;
+ }
+
+ case s_chunk_data:
+ {
+ uint64_t to_read = MIN(parser->content_length,
+ (uint64_t) ((data + len) - p));
+
+ assert(parser->flags & F_CHUNKED);
+ assert(parser->content_length != 0
+ && parser->content_length != ULLONG_MAX);
+
+ MARK(body);
+ parser->content_length -= to_read;
+ p += to_read - 1;
+
+ if (parser->content_length == 0) {
+ UPDATE_STATE(s_chunk_data_almost_done);
+ }
+
+ break;
+ }
+
+ case s_chunk_data_almost_done:
+ assert(parser->flags & F_CHUNKED);
+ assert(parser->content_length == 0);
+ STRICT_CHECK(ch != CR);
+ UPDATE_STATE(s_chunk_data_done);
+ CALLBACK_DATA(body);
+ break;
+
+ case s_chunk_data_done:
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != LF);
+ parser->nread = 0;
+ UPDATE_STATE(s_chunk_size_start);
+ CALLBACK_NOTIFY(chunk_complete);
+ break;
+
+ default:
+ assert(0 && "unhandled state");
+ SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
+ goto error;
+ }
+ }
+
+ assert(((header_field_mark ? 1 : 0) +
+ (header_value_mark ? 1 : 0) +
+ (url_mark ? 1 : 0) +
+ (body_mark ? 1 : 0) +
+ (status_mark ? 1 : 0)) <= 1);
+
+ CALLBACK_DATA_NOADVANCE(header_field);
+ CALLBACK_DATA_NOADVANCE(header_value);
+ CALLBACK_DATA_NOADVANCE(url);
+ CALLBACK_DATA_NOADVANCE(body);
+ CALLBACK_DATA_NOADVANCE(status);
+
+ RETURN(len);
+
+error:
+ if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
+ SET_ERRNO(HPE_UNKNOWN);
+ }
+
+ RETURN(p - data);
+}
+
+int http_message_needs_eof (const http_parser *parser)
+{
+ if (parser->type == HTTP_REQUEST) {
+ return 0;
+ }
+
+ if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
+ parser->status_code == 204 || /* No Content */
+ parser->status_code == 304 || /* Not Modified */
+ parser->flags & F_SKIPBODY) { /* response to a HEAD request */
+ return 0;
+ }
+
+ if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int http_should_keep_alive (const http_parser *parser)
+{
+ if (parser->http_major > 0 && parser->http_minor > 0) {
+ if (parser->flags & F_CONNECTION_CLOSE) {
+ return 0;
+ }
+ } else {
+ if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
+ return 0;
+ }
+ }
+
+ return !http_message_needs_eof(parser);
+}
+
+
+ const char *
+http_method_str (enum http_method m)
+{
+ return ELEM_AT(method_strings, m, "<unknown>");
+}
+
+
+ void
+http_parser_init (http_parser *parser, enum http_parser_type t)
+{
+ void *data = parser->data; /* preserve application data */
+ memset(parser, 0, sizeof(*parser));
+ parser->data = data;
+ parser->type = t;
+ parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
+ parser->http_errno = HPE_OK;
+}
+
+ void
+http_parser_settings_init(http_parser_settings *settings)
+{
+ memset(settings, 0, sizeof(*settings));
+}
+
+const char *
+http_errno_name(enum http_errno err) {
+ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+ return http_strerror_tab[err].name;
+}
+
+const char *
+http_errno_description(enum http_errno err) {
+ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+ return http_strerror_tab[err].description;
+}
+
+static enum http_host_state
+http_parse_host_char(enum http_host_state s, const char ch) {
+ switch(s) {
+ case s_http_userinfo:
+ case s_http_userinfo_start:
+ if (ch == '@') {
+ return s_http_host_start;
+ }
+
+ if (IS_USERINFO_CHAR(ch)) {
+ return s_http_userinfo;
+ }
+ break;
+
+ case s_http_host_start:
+ if (ch == '[') {
+ return s_http_host_v6_start;
+ }
+
+ if (IS_HOST_CHAR(ch)) {
+ return s_http_host;
+ }
+
+ break;
+
+ case s_http_host:
+ if (IS_HOST_CHAR(ch)) {
+ return s_http_host;
+ }
+
+ /* FALLTHROUGH */
+ case s_http_host_v6_end:
+ if (ch == ':') {
+ return s_http_host_port_start;
+ }
+
+ break;
+
+ case s_http_host_v6:
+ if (ch == ']') {
+ return s_http_host_v6_end;
+ }
+
+ /* FALLTHROUGH */
+ case s_http_host_v6_start:
+ if (IS_HEX(ch) || ch == ':' || ch == '.') {
+ return s_http_host_v6;
+ }
+
+ if (s == s_http_host_v6 && ch == '%') {
+ return s_http_host_v6_zone_start;
+ }
+ break;
+
+ case s_http_host_v6_zone:
+ if (ch == ']') {
+ return s_http_host_v6_end;
+ }
+
+ /* FALLTHROUGH */
+ case s_http_host_v6_zone_start:
+ if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
+ ch == '~') {
+ return s_http_host_v6_zone;
+ }
+ break;
+
+ case s_http_host_port:
+ case s_http_host_port_start:
+ if (IS_NUM(ch)) {
+ return s_http_host_port;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ return s_http_host_dead;
+}
+
+static int
+http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
+ enum http_host_state s;
+ size_t buflen = 0;
+ const char *p;
+
+ assert(u->field_set & (1 << UF_HOST));
+
+ buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
+
+ u->field_data[UF_HOST].len = 0;
+
+ s = found_at ? s_http_userinfo_start : s_http_host_start;
+
+ for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
+ enum http_host_state new_s = http_parse_host_char(s, *p);
+
+ if (new_s == s_http_host_dead) {
+ return 1;
+ }
+
+ switch(new_s) {
+ case s_http_host:
+ if (s != s_http_host) {
+ u->field_data[UF_HOST].off = p - buf;
+ }
+ u->field_data[UF_HOST].len++;
+ break;
+
+ case s_http_host_v6:
+ if (s != s_http_host_v6) {
+ u->field_data[UF_HOST].off = p - buf;
+ }
+ u->field_data[UF_HOST].len++;
+ break;
+
+ case s_http_host_v6_zone_start:
+ case s_http_host_v6_zone:
+ u->field_data[UF_HOST].len++;
+ break;
+
+ case s_http_host_port:
+ if (s != s_http_host_port) {
+ u->field_data[UF_PORT].off = p - buf;
+ u->field_data[UF_PORT].len = 0;
+ u->field_set |= (1 << UF_PORT);
+ }
+ u->field_data[UF_PORT].len++;
+ break;
+
+ case s_http_userinfo:
+ if (s != s_http_userinfo) {
+ u->field_data[UF_USERINFO].off = p - buf ;
+ u->field_data[UF_USERINFO].len = 0;
+ u->field_set |= (1 << UF_USERINFO);
+ }
+ u->field_data[UF_USERINFO].len++;
+ break;
+
+ default:
+ break;
+ }
+ s = new_s;
+ }
+
+ switch (s) {
+ case s_http_host_start:
+ case s_http_host_v6_start:
+ case s_http_host_v6:
+ case s_http_host_v6_zone_start:
+ case s_http_host_v6_zone:
+ case s_http_host_port_start:
+ case s_http_userinfo:
+ case s_http_userinfo_start:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
+ struct http_parser_url *u)
+{
+ enum state s;
+ const char *p;
+ enum http_parser_url_fields uf, old_uf;
+ int found_at = 0;
+
+ u->port = u->field_set = 0;
+ s = is_connect ? s_req_server_start : s_req_spaces_before_url;
+ old_uf = UF_MAX;
+
+ for (p = buf; p < buf + buflen; p++) {
+ s = parse_url_char(s, *p);
+
+ /* Figure out the next field that we're operating on */
+ switch (s) {
+ case s_dead:
+ return 1;
+ case s_req_schema_slash:
+ case s_req_schema_slash_slash:
+ case s_req_server_start:
+ case s_req_query_string_start:
+ case s_req_fragment_start:
+ continue;
+
+ case s_req_schema:
+ uf = UF_SCHEMA;
+ break;
+
+ case s_req_server_with_at:
+ found_at = 1;
+
+ case s_req_server:
+ uf = UF_HOST;
+ break;
+
+ case s_req_path:
+ uf = UF_PATH;
+ break;
+
+ case s_req_query_string:
+ uf = UF_QUERY;
+ break;
+
+ case s_req_fragment:
+ uf = UF_FRAGMENT;
+ break;
+
+ default:
+ assert(!"Unexpected state");
+ return 1;
+ }
+
+ if (uf == old_uf) {
+ u->field_data[uf].len++;
+ continue;
+ }
+
+ u->field_data[uf].off = p - buf;
+ u->field_data[uf].len = 1;
+
+ u->field_set |= (1 << uf);
+ old_uf = uf;
+ }
+
+ if ((u->field_set & (1 << UF_SCHEMA)) &&
+ (u->field_set & (1 << UF_HOST)) == 0) {
+ return 1;
+ }
+
+ if (u->field_set & (1 << UF_HOST)) {
+ if (http_parse_host(buf, u, found_at) != 0) {
+ return 1;
+ }
+ }
+
+ if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
+ return 1;
+ }
+
+ if (u->field_set & (1 << UF_PORT)) {
+ unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
+
+ if (v > 0xffff) {
+ return 1;
+ }
+
+ u->port = (uint16_t) v;
+ }
+
+ return 0;
+}
+
+void
+http_parser_pause(http_parser *parser, int paused) {
+ if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
+ HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
+ SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
+ } else {
+ assert(0 && "Attempting to pause parser in error state");
+ }
+}
+
+int
+http_body_is_final(const struct http_parser *parser) {
+ return parser->state == s_message_done;
+}
+
+unsigned long
+http_parser_version(void) {
+ return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
+ HTTP_PARSER_VERSION_MINOR * 0x00100 |
+ HTTP_PARSER_VERSION_PATCH * 0x00001;
+}
diff --git a/src/lynq/lib/liblynq-protcl/http/src/lynq_msgq.c b/src/lynq/lib/liblynq-protcl/http/src/lynq_msgq.c
new file mode 100644
index 0000000..5005c18
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/src/lynq_msgq.c
@@ -0,0 +1,33 @@
+#include <sys/msg.h>
+#include <sys/ipc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "http/lynq_msgq.h"
+
+
+int lynq_msgq_init(char *pathname, int create)
+{
+ key_t key = ftok(pathname, 66);
+ int queueId = msgget(key, IPC_CREAT | create);
+ if(queueId == -1)
+ {
+ //LYDBGLOG("[%s %d] create msg error \n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_MSG);
+ return ERR_MSG;
+ }
+
+ return queueId ;
+}
+
+int lynq_msgq_send(int queueId, struct mymesg *ckxmsg)
+{
+ if(msgsnd(queueId, ckxmsg, 512, 0) < 0)
+ {
+ //LYDBGLOG("[%s %d] send msg error \n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_MSG);
+ return ERR_MSG;
+ }
+
+ return 0;
+}