1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00
Introduce an api for efficiently dealing with allocations for
large, unknown amounts of objects.
This commit is contained in:
Andy Green 2018-10-14 06:12:27 +08:00
parent ed00704566
commit a5b2248e72
14 changed files with 1036 additions and 0 deletions

View file

@ -110,6 +110,7 @@ option(LWS_WITH_GCOV "Build with gcc gcov coverage instrumentation" OFF)
option(LWS_WITH_EXPORT_LWSTARGETS "Export libwebsockets CMake targets. Disable if they conflict with an outer cmake project." ON)
option(LWS_REPRODUCIBLE "Build libwebsockets reproducible. It removes the build user and hostname from the build" ON)
option(LWS_WITH_MINIMAL_EXAMPLES "Also build the normally standalone minimal examples, for QA" OFF)
option(LWS_WITH_LWSAC "lwsac Chunk Allocation api" ON)
#
# End of user settings
#
@ -149,6 +150,10 @@ if (WIN32 OR LWS_WITH_ESP32)
set(LWS_UNIX_SOCK 0)
endif()
if (LWS_WITH_ESP32)
set(LWS_WITH_LWSAC 0)
endif()
project(libwebsockets C)
set(PACKAGE "libwebsockets")
@ -875,6 +880,12 @@ if (LWS_WITH_PEER_LIMITS)
lib/misc/peer-limits.c)
endif()
if (LWS_WITH_LWSAC)
list(APPEND SOURCES
lib/misc/lwsac/lwsac.c
lib/misc/lwsac/cached-file.c)
endif()
if (NOT LWS_WITHOUT_CLIENT)
list(APPEND SOURCES
lib/core/connect.c

View file

@ -15,6 +15,8 @@
#cmakedefine LWS_ROLE_CGI
#cmakedefine LWS_ROLE_DBUS
#cmakedefine LWS_WITH_LWSAC
/* Define to 1 to use wolfSSL/CyaSSL as a replacement for OpenSSL.
* LWS_OPENSSL_SUPPORT needs to be set also for this to work. */
#cmakedefine USE_WOLFSSL

131
doc-assets/lwsac.svg Normal file
View file

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="187.8mm" height="80.752mm" version="1.1" viewBox="0 0 187.79663 80.752144" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="a" x="-.014418" y="-.034864" width="1.0288" height="1.0697" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="1.5466839"/>
</filter>
</defs>
<g transform="translate(-161.61 156.88)">
<g>
<g stroke="#666" stroke-linejoin="round">
<rect transform="matrix(.709 0 0 .709 167.83 -486.38)" x="-5.0609" y="468.46" width="257.45" height="106.47" ry="0" filter="url(#a)" stroke-width=".24551"/>
<rect x="163.71" y="-154.85" width="182.53" height="75.489" ry="0" fill="#f2f2f2" stroke-width=".17406"/>
<rect x="171.7" y="-140.36" width="30.952" height="50.082" fill="#808080" stroke-width=".40058"/>
<rect x="172.68" y="-139.06" width="28.784" height="6.4996" fill="#a00" stroke-width=".11698"/>
<rect x="172.74" y="-131.83" width="28.784" height="40.39" fill="#c4c8b7" stroke-width=".11698"/>
</g>
<text x="181.33067" y="-136.13423" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="181.33067" y="-136.13423" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac</tspan></text>
<text x="184.53554" y="-92.850395" fill="#000000" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="184.53554" y="-92.850395" font-family="'Open Sans'" stroke-width=".39677">allocated area</tspan></text>
<path d="m206.96-138.6 1.5352 0.74171-1.4119 0.76078-0.0812-0.34638-6.239-0.0174c0.0635-0.40246-0.0214-0.51522 0.0725-0.82588l6.136 5e-3z" fill="#2a7fff"/>
<rect x="172" y="-150.67" width="26.156" height="4.4025" fill="#500" stroke="#666" stroke-linejoin="round" stroke-width=".091779"/>
<text x="185.17738" y="-147.67433" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="185.17738" y="-147.67433" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac *head</tspan></text>
<text x="198.1916" y="-137.38612" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="198.1916" y="-137.38612">next</tspan><tspan x="198.1916" y="-135.51024">head</tspan><tspan x="198.1916" y="-133.63435">curr</tspan></text>
<path d="m174.55-138.71-0.74171 2.0619-0.76078-1.8964 0.34638-0.10906 0.0174-8.3796c0.40246 0.0853 0.51522-0.0288 0.82587 0.0974l-5e-3 8.2413z" fill="#2a7fff"/>
<text x="188.84824" y="-135.46999" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="188.84824" y="-135.46999" text-align="start">ofs</tspan><tspan x="188.84824" y="-133.5941" text-align="start">alloc_size</tspan></text>
<path d="m195.91-144.71-0.7417-2.0619-0.76078 1.8964 0.34637 0.10906-0.0412 9.1651c0.24984 0.0323 0.88518-0.0192 1.5658-0.0156 0.0711-0.0968 0.0691-0.46205 0.015-0.82619-0.45397 2e-3 -0.78488-5e-3 -0.69634-0.0411l-5e-3 -8.2413z" fill="#2a7fff"/>
</g>
<path d="m201.26-131.89-2.3876 2.1223-0.13265 35.947 2.7855 2.255" fill="none" stroke="#000" stroke-dasharray="0.5627649, 0.1875883" stroke-width=".18759"/>
<path d="m191.97-133.09 6.8975 7.6934" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<path d="m174.12-132.51-1.5352 0.7417 1.4119 0.76078 0.0812-0.34638 2.127 0.0157c-0.0635-0.40245 0.0214-0.54838-0.0725-0.85903l-2.024 5e-3z"/>
<path d="m176.09-131.63 5.7037 0.0664 6.2343-3.913 0.66323-0.0995" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<g>
<rect x="220.5" y="-140.05" width="30.952" height="50.082" fill="#808080" stroke="#666" stroke-linejoin="round" stroke-width=".40058"/>
<rect x="221.48" y="-138.74" width="28.784" height="6.4996" fill="#a00" stroke="#666" stroke-linejoin="round" stroke-width=".11698"/>
<text x="226.27528" y="-118.77273" fill="#000000" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="226.27528" y="-118.77273" font-family="'Open Sans'" stroke-width=".18759">ptr aligned</tspan></text>
<rect x="221.54" y="-131.51" width="28.784" height="40.39" fill="#c4c8b7" stroke="#666" stroke-linejoin="round" stroke-width=".11698"/>
<text x="230.13133" y="-135.82219" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="230.13133" y="-135.82219" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac</tspan></text>
<text x="233.3362" y="-92.538383" fill="#000000" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="233.3362" y="-92.538383" font-family="'Open Sans'" stroke-width=".39677">allocated area</tspan></text>
<path d="m255.76-138.29 1.5352 0.74171-1.4119 0.76078-0.0812-0.34638-6.239-0.0174c0.0635-0.40246-0.0214-0.51522 0.0725-0.82588l6.136 5e-3z" fill="#2a7fff"/>
<rect x="220.8" y="-150.36" width="26.156" height="4.4025" fill="#500" stroke="#666" stroke-linejoin="round" stroke-width=".091779"/>
<text x="233.97806" y="-147.36229" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="233.97806" y="-147.36229" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac *head</tspan></text>
<text x="246.99228" y="-137.07408" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="246.99228" y="-137.07408">next</tspan><tspan x="246.99228" y="-135.1982">head</tspan><tspan x="246.99228" y="-133.32231">curr</tspan></text>
<path d="m223.35-138.4-0.74171 2.0619-0.76078-1.8964 0.34638-0.10905 0.0174-8.3796c0.40246 0.0853 0.51522-0.0288 0.82588 0.0974l-5e-3 8.2413z" fill="#2a7fff"/>
<text x="237.64891" y="-135.15791" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="237.64891" y="-135.15791" text-align="start">ofs</tspan><tspan x="237.64891" y="-133.28203" text-align="start">alloc_size</tspan></text>
<path d="m244.71-144.39-0.74171-2.0619-0.76078 1.8964 0.34638 0.10906-0.0412 9.1651c0.24984 0.0323 0.88518-0.0192 1.5658-0.0156 0.0711-0.0968 0.0691-0.46205 0.015-0.82618-0.45397 2e-3 -0.78488-5e-3 -0.69634-0.0411l-5e-3 -8.2413z" fill="#2a7fff"/>
<rect x="221.98" y="-130.85" width="27.712" height="7.4313" fill="#ff8080" stroke="#666" stroke-linejoin="round" stroke-width=".14463"/>
<rect x="221.97" y="-121.59" width="27.712" height="7.4313" fill="#ff8080" stroke="#666" stroke-linejoin="round" stroke-width=".14463"/>
</g>
<path d="m250.06-131.58-2.3876 2.1223-0.13265 35.947 2.7855 2.255" fill="none" stroke="#000" stroke-dasharray="0.56276491, 0.1875883" stroke-width=".18759"/>
<path d="m240.78-132.77 6.8975 7.6934" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<text x="235.9016" y="-126.22051" fill="#ffffff" font-family="'Open Sans'" font-size="2.5582px" letter-spacing="0px" stroke-width=".31977" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="235.9016" y="-126.22051" fill="#ffffff" font-family="'Open Sans'" stroke-width=".31977">lwsac_use area</tspan></text>
<path d="m223.49-112.72-1.5352 0.7417 1.4119 0.76079 0.0812-0.34638 2.127 0.0157c-0.0635-0.40245 0.0214-0.54838-0.0725-0.85903l-2.024 5e-3z"/>
<path d="m225.29-112.13 8.31 0.0664 3.0298-2.9076 0.20032-20.194 0.66323-0.0995" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<g>
<text x="177.42035" y="-129.76131" fill="#000000" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="177.42035" y="-129.76131" font-family="'Open Sans'" stroke-width=".18759">ptr aligned</tspan></text>
<text x="235.79298" y="-122.17254" fill="#000000" font-family="'Open Sans'" font-size="1.0364px" letter-spacing="0px" stroke-width=".12956" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="235.79298" y="-122.17254" font-family="'Open Sans'" stroke-width=".12956">alignment padding</tspan></text>
<path d="m220.64-131.26 1.5352 0.7417-1.4119 0.76079-0.0812-0.34638-2.127 0.0157c0.0635-0.40246-0.0214-0.54838 0.0725-0.85903l2.024 5e-3z"/>
<g font-family="'Open Sans'" letter-spacing="0px" text-anchor="middle" word-spacing="0px">
<text x="235.89856" y="-116.96035" fill="#ffffff" font-size="2.5582px" stroke-width=".31977" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="235.89856" y="-116.96035" fill="#ffffff" font-family="'Open Sans'" stroke-width=".31977">lwsac_use area</tspan></text>
<text x="226.27226" y="-109.51257" fill="#000000" font-size="1.5007px" stroke-width=".18759" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="226.27226" y="-109.51257" font-family="'Open Sans'" stroke-width=".18759">ptr aligned</tspan></text>
<text x="235.78995" y="-112.91241" fill="#000000" font-size="1.0364px" stroke-width=".12956" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="235.78995" y="-112.91241" font-family="'Open Sans'" stroke-width=".12956">alignment padding</tspan></text>
</g>
<path d="m220.64-122 1.5352 0.7417-1.4119 0.76079-0.0812-0.34638-2.127 0.0157c0.0635-0.40245-0.0214-0.54838 0.0725-0.85903l2.024 5e-3z"/>
<rect x="268.33" y="-140.45" width="30.952" height="50.082" fill="#808080" stroke="#666" stroke-linejoin="round" stroke-width=".40058"/>
<rect x="269.31" y="-139.14" width="28.784" height="6.4996" fill="#a00" stroke="#666" stroke-linejoin="round" stroke-width=".11698"/>
<text x="274.10483" y="-119.17068" fill="#000000" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="274.10483" y="-119.17068" font-family="'Open Sans'" stroke-width=".18759">ptr aligned</tspan></text>
<rect x="269.37" y="-131.91" width="28.784" height="40.39" fill="#c4c8b7" stroke="#666" stroke-linejoin="round" stroke-width=".11698"/>
<text x="277.96088" y="-136.22011" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="277.96088" y="-136.22011" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac</tspan></text>
<text x="281.16574" y="-92.936333" fill="#000000" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="281.16574" y="-92.936333" font-family="'Open Sans'" stroke-width=".39677">allocated area</tspan></text>
<rect x="302.47" y="-140.62" width="30.952" height="50.082" fill="#808080" stroke="#666" stroke-linejoin="round" stroke-width=".40058"/>
<rect x="303.45" y="-139.31" width="28.784" height="6.4996" fill="#a00" stroke="#666" stroke-linejoin="round" stroke-width=".11698"/>
<path d="m303.59-138.69 1.5352 0.7417-1.4119 0.76078-0.0812-0.34638-6.239-0.0174c0.0635-0.40245-0.0214-0.51522 0.0725-0.82587l6.136 5e-3z" fill="#2a7fff"/>
<rect x="268.63" y="-150.76" width="26.156" height="4.4025" fill="#500" stroke="#666" stroke-linejoin="round" stroke-width=".091779"/>
<text x="281.80762" y="-147.76024" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="281.80762" y="-147.76024" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac *head</tspan></text>
<text x="294.82181" y="-137.47203" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="294.82181" y="-137.47203">next</tspan><tspan x="294.82181" y="-135.59615">head</tspan><tspan x="294.82181" y="-133.72026">curr</tspan></text>
<path d="m271.18-138.8-0.74171 2.0619-0.76078-1.8964 0.34638-0.10906 0.0174-8.3796c0.40246 0.0853 0.51522-0.0288 0.82587 0.0974l-5e-3 8.2413z" fill="#2a7fff"/>
<text x="285.47845" y="-135.55586" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="285.47845" y="-135.55586" text-align="start">ofs</tspan><tspan x="285.47845" y="-133.67998" text-align="start">alloc_size</tspan></text>
<path d="m292.54-144.79-0.74171-2.0619-0.76078 1.8964 0.34638 0.10906-0.0412 9.1651c0.24984 0.0323 0.88517-0.0192 1.5658-0.0156 0.0711-0.0968 0.0691-0.46206 0.015-0.82619-0.45397 2e-3 -0.78487-5e-3 -0.69633-0.0411l-5e-3 -8.2413z" fill="#2a7fff"/>
<rect x="269.81" y="-131.25" width="27.712" height="7.4313" fill="#ff8080" stroke="#666" stroke-linejoin="round" stroke-width=".14463"/>
<rect x="269.8" y="-121.99" width="27.712" height="7.4313" fill="#ff8080" stroke="#666" stroke-linejoin="round" stroke-width=".14463"/>
</g>
<path d="m297.89-131.98-2.3876 2.1223-0.13264 35.947 2.7855 2.255" fill="none" stroke="#000" stroke-dasharray="0.56276492, 0.1875883" stroke-width=".18759"/>
<path d="m288.61-133.17 6.8975 7.6934" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<text x="283.73114" y="-126.61846" fill="#ffffff" font-family="'Open Sans'" font-size="2.5582px" letter-spacing="0px" stroke-width=".31977" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="283.73114" y="-126.61846" fill="#ffffff" font-family="'Open Sans'" stroke-width=".31977">lwsac_use area</tspan></text>
<path d="m271.31-113.11-1.5352 0.7417 1.4119 0.76079 0.0812-0.34638 2.127 0.0157c-0.0635-0.40246 0.0214-0.54838-0.0725-0.85904l-2.024 5e-3z"/>
<path d="m273.12-112.52 8.31 0.0664 3.0298-2.9076 0.20032-20.194 0.66323-0.0995" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<g>
<text x="283.62253" y="-122.57049" fill="#000000" font-family="'Open Sans'" font-size="1.0364px" letter-spacing="0px" stroke-width=".12956" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="283.62253" y="-122.57049" font-family="'Open Sans'" stroke-width=".12956">alignment padding</tspan></text>
<path d="m268.47-131.66 1.5352 0.74171-1.4119 0.76078-0.0812-0.34638-2.127 0.0157c0.0635-0.40245-0.0214-0.54838 0.0725-0.85903l2.024 5e-3z"/>
<g font-family="'Open Sans'" letter-spacing="0px" text-anchor="middle" word-spacing="0px">
<text x="283.72812" y="-117.3583" fill="#ffffff" font-size="2.5582px" stroke-width=".31977" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="283.72812" y="-117.3583" fill="#ffffff" font-family="'Open Sans'" stroke-width=".31977">lwsac_use area</tspan></text>
<text x="274.10181" y="-109.91051" fill="#000000" font-size="1.5007px" stroke-width=".18759" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="274.10181" y="-109.91051" font-family="'Open Sans'" stroke-width=".18759">ptr aligned</tspan></text>
<text x="283.61948" y="-113.31036" fill="#000000" font-size="1.0364px" stroke-width=".12956" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="283.61948" y="-113.31036" font-family="'Open Sans'" stroke-width=".12956">alignment padding</tspan></text>
</g>
<path d="m268.47-122.4 1.5352 0.7417-1.4119 0.76079-0.0812-0.34638-2.127 0.0157c0.0635-0.40246-0.0214-0.54838 0.0725-0.85904l2.024 5e-3z"/>
<rect x="303.52" y="-132.08" width="28.784" height="40.39" fill="#c4c8b7" stroke="#666" stroke-linejoin="round" stroke-width=".11698"/>
<text x="312.10593" y="-136.39232" fill="#ffffff" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="312.10593" y="-136.39232" fill="#ffffff" font-family="'Open Sans'" font-size="2.8222px" stroke-width=".39677">struct lwsac</tspan></text>
<text x="315.31079" y="-93.108513" fill="#000000" font-family="'Open Sans'" font-size="3.1742px" letter-spacing="0px" stroke-width=".39677" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="315.31079" y="-93.108513" font-family="'Open Sans'" stroke-width=".39677">allocated area</tspan></text>
<path d="m337.74-138.86 1.5352 0.74171-1.4119 0.76078-0.0812-0.34638-6.239-0.0174c0.0635-0.40245-0.0214-0.51522 0.0725-0.82587l6.136 5e-3z" fill="#2a7fff"/>
<text x="328.96686" y="-137.64424" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="328.96686" y="-137.64424">next</tspan><tspan x="328.96686" y="-135.76836">head</tspan><tspan x="328.96686" y="-133.89247">curr</tspan></text>
<text x="319.6235" y="-135.72807" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" stroke-width=".18759" text-align="center" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="319.6235" y="-135.72807" text-align="start">ofs</tspan><tspan x="319.6235" y="-133.85219" text-align="start">alloc_size</tspan></text>
<rect x="304.15" y="-131.34" width="27.572" height="28.913" fill="#ff8080" stroke="#666" stroke-linejoin="round" stroke-width=".28455"/>
</g>
<path d="m332.04-132.15-2.3876 2.1223-0.13264 35.947 2.7855 2.255" fill="none" stroke="#000" stroke-dasharray="0.56276491, 0.1875883" stroke-width=".18759"/>
<path d="m322.75-133.34 6.8975 7.6934" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<path d="m292.68-145.32 0.74171-1.5352 0.76078 1.4119-0.34638 0.0812 0.0259 2.071 28.542 0.041 2.225 2.8639 0.0875 2.9524 0.64641 0.65493 1.5316 2e-3 0.0488 0.76904-2.1195-0.0297-1.142-1.1761-0.0569-2.9726-2.1165-2.253c-0.40246-0.0635-28.205 0.0547-28.516-0.0391l5e-3 -2.8532z" fill="#2a7fff"/>
<path d="m303.21-134.9 1.5352 0.74171-1.4119 0.76078-0.0812-0.34638-6.239-0.0174c0.0635-0.40245-0.0214-0.51522 0.0725-0.82587l6.136 5e-3z" fill="#2a7fff"/>
<path d="m307.26-100.45 1.4591 0.0664 3.06-3.7843-9e-3 -23.607 7.6934-8.0582" fill="none" stroke="#000" stroke-dasharray="0.37517659, 0.1875883" stroke-width=".18759"/>
<g>
<path d="m305.59-100.91-1.5352 0.74171 1.4119 0.76078 0.0812-0.34638 2.127 0.01569c-0.0635-0.40245 0.0214-0.54838-0.0725-0.85903l-2.024 5e-3z"/>
<g font-family="'Open Sans'" letter-spacing="0px" text-anchor="middle" word-spacing="0px">
<text x="318.0058" y="-105.15496" fill="#ffffff" font-size="2.5582px" stroke-width=".31977" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="318.0058" y="-105.15496" fill="#ffffff" font-family="'Open Sans'" stroke-width=".31977">lwsac_use area</tspan></text>
<text x="308.37949" y="-97.707207" fill="#000000" font-size="1.5007px" stroke-width=".18759" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="308.37949" y="-97.707207" font-family="'Open Sans'" stroke-width=".18759">ptr aligned</tspan></text>
<text x="317.89719" y="-101.10705" fill="#000000" font-size="1.0364px" stroke-width=".12956" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="317.89719" y="-101.10705" font-family="'Open Sans'" stroke-width=".12956">alignment padding</tspan></text>
</g>
<path d="m302.48-132.08 1.5352 0.74171-1.4119 0.76078-0.0812-0.34638-2.127 0.0157c0.0635-0.40245-0.0214-0.54838 0.0725-0.85903l2.024 5e-3z"/>
<g stroke-width=".18759">
<rect x="204.83" y="-139.17" width="5.018" height="2.6731" ry="1.3366" fill="#808080" stroke="#666" stroke-linejoin="round"/>
<text x="207.36176" y="-137.33116" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="207.36176" y="-137.33116" fill="#ffffff" font-family="'Open Sans'" stroke-width=".18759">NULL</tspan></text>
<rect x="253.14" y="-139.13" width="5.018" height="2.6731" ry="1.3366" fill="#808080" stroke="#666" stroke-linejoin="round"/>
<text x="255.6705" y="-137.29219" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="255.6705" y="-137.29219" fill="#ffffff" font-family="'Open Sans'" stroke-width=".18759">NULL</tspan></text>
<rect x="336.04" y="-139.46" width="5.018" height="2.6731" ry="1.3366" fill="#808080" stroke="#666" stroke-linejoin="round"/>
<text x="338.57361" y="-137.62383" fill="#ffffff" font-family="'Open Sans'" font-size="1.5007px" letter-spacing="0px" text-align="center" text-anchor="middle" word-spacing="0px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="338.57361" y="-137.62383" fill="#ffffff" font-family="'Open Sans'" stroke-width=".18759">NULL</tspan></text>
</g>
</g>
<g fill="#0000ff" font-family="'Open Sans'" font-size="3.2649px" letter-spacing="0px" stroke-width=".40811" text-anchor="middle" word-spacing="0px">
<text x="187.11359" y="-84.657211" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="187.11359" y="-84.657211" fill="#0000ff" font-family="'Open Sans'" stroke-width=".40811">empty, generic lwsac</tspan></text>
<text x="235.71112" y="-84.353561" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="235.71112" y="-84.353561" fill="#0000ff" font-family="'Open Sans'" stroke-width=".40811">lwsac with 2 "uses"</tspan></text>
<text x="300.70877" y="-83.844711" text-align="center" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;line-height:1.25" xml:space="preserve"><tspan x="300.70877" y="-83.844711" fill="#0000ff" font-family="'Open Sans'" stroke-width=".40811">lwsac with 2 "uses", 3rd requires a new one</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -409,6 +409,7 @@ struct lws;
#include <libwebsockets/lws-stats.h>
#include <libwebsockets/lws-threadpool.h>
#include <libwebsockets/lws-tokenize.h>
#include <libwebsockets/lws-lwsac.h>
#if defined(LWS_WITH_TLS)

View file

@ -0,0 +1,191 @@
/*
* libwebsockets - lws alloc chunk
*
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* included from libwebsockets.h
*/
/** \defgroup log lwsac
*
* ##Allocated Chunks
*
* If you know you will be allocating a large, unknown number of same or
* differently sized objects, it's certainly possible to do it with libc
* malloc. However the allocation cost in time and memory overhead can
* add up, and deallocation means walking the structure of every object and
* freeing them in turn.
*
* lwsac (LWS Allocated Chunks) allocates chunks intended to be larger
* than your objects (4000 bytes by default) which you linearly allocate from
* using lwsac_use().
*
* If your next request won't fit in the current chunk, a new chunk is added
* to the chain of chunks and the allocaton done from there. If the request
* is larger than the chunk size, an oversize chunk is created to satisfy it.
*
* When you are finished with the allocations, you call lwsac_free() and
* free all the *chunks*. So you may have thousands of objects in the chunks,
* but they are all destroyed with the chunks without having to deallocate them
* one by one pointlessly.
*/
///@{
struct lwsac;
typedef unsigned char * lwsac_cached_file_t;
#define lws_list_ptr_container(P,T,M) ((T *)((char *)(P) - offsetof(T, M)))
/*
* linked-list helper that's commonly useful to manage lists of things
* allocated using lwsac.
*
* These lists point to their corresponding "next" member in the target, NOT
* the original containing struct. To get the containing struct, you must use
* lws_list_ptr_container() to convert.
*
* It's like that because it means we no longer have to have the next pointer
* at the start of the struct, and we can have the same struct on multiple
* linked-lists with everything held in the struct itself.
*/
typedef void * lws_list_ptr;
/*
* optional sorting callback called by lws_list_ptr_insert() to sort the right
* things inside the opqaue struct being sorted / inserted on the list.
*/
typedef int (*lws_list_ptr_sort_func_t)(lws_list_ptr a, lws_list_ptr b);
#define lws_list_ptr_advance(_lp) _lp = *((void **)_lp)
/* sort may be NULL if you don't care about order */
LWS_VISIBLE LWS_EXTERN void
lws_list_ptr_insert(lws_list_ptr *phead, lws_list_ptr *add,
lws_list_ptr_sort_func_t sort);
/**
* lwsac_use - allocate / use some memory from a lwsac
*
* \param head: pointer to the lwsac list object
* \param ensure: the number of bytes we want to use
* \param chunk_size: 0, or the size of the chunk to (over)allocate if
* what we want won't fit in the current tail chunk. If
* 0, the default value of 4000 is used. If ensure is
* larger, it is used instead.
*
* This also serves to init the lwsac if *head is NULL. Basically it does
* whatever is necessary to return you a pointer to ensure bytes of memory
* reserved for the caller.
*
* Returns NULL if OOM.
*/
LWS_VISIBLE LWS_EXTERN void *
lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size);
/**
* lwsac_free - deallocate all chunks in the lwsac and set head NULL
*
* \param head: pointer to the lwsac list object
*
* This deallocates all chunks in the lwsac, then sets *head to NULL. All
* lwsac_use() pointers are invalidated in one hit without individual frees.
*/
LWS_VISIBLE LWS_EXTERN void
lwsac_free(struct lwsac **head);
/*
* Optional helpers useful for where consumers may need to defer destruction
* until all consumers are finished with the lwsac
*/
/**
* lwsac_detach() - destroy an lwsac unless somebody else is referencing it
*
* \param head: pointer to the lwsac list object
*
* The creator of the lwsac can all this instead of lwsac_free() when it itself
* has finished with the lwsac, but other code may be consuming it.
*
* If there are no other references, the lwsac is destroyed, *head is set to
* NULL and that's the end; however if something else has called
* lwsac_reference() on the lwsac, it simply returns. When lws_unreference()
* is called and no references are left, it will be destroyed then.
*/
LWS_VISIBLE LWS_EXTERN void
lwsac_detach(struct lwsac **head);
/**
* lwsac_reference() - increase the lwsac reference count
*
* \param head: pointer to the lwsac list object
*
* Increment the reference count on the lwsac to defer destruction.
*/
LWS_VISIBLE LWS_EXTERN void
lwsac_reference(struct lwsac *head);
/**
* lwsac_reference() - increase the lwsac reference count
*
* \param head: pointer to the lwsac list object
*
* Decrement the reference count on the lwsac... if it reached 0 on a detached
* lwsac then the lwsac is immediately destroyed and *head set to NULL.
*/
LWS_VISIBLE LWS_EXTERN void
lwsac_unreference(struct lwsac **head);
/* helpers to keep a file cached in memory */
LWS_VISIBLE LWS_EXTERN void
lwsac_use_cached_file_start(lwsac_cached_file_t cache);
LWS_VISIBLE LWS_EXTERN void
lwsac_use_cached_file_end(lwsac_cached_file_t *cache);
LWS_VISIBLE LWS_EXTERN void
lwsac_use_cached_file_detach(lwsac_cached_file_t *cache);
LWS_VISIBLE LWS_EXTERN int
lwsac_cached_file(const char *filepath, lwsac_cached_file_t *cache,
size_t *len);
/* more advanced helpers */
LWS_VISIBLE LWS_EXTERN size_t
lwsac_sizeof(void);
LWS_VISIBLE LWS_EXTERN size_t
lwsac_get_tail_pos(struct lwsac *lac);
LWS_VISIBLE LWS_EXTERN struct lwsac *
lwsac_get_next(struct lwsac *lac);
LWS_VISIBLE LWS_EXTERN size_t
lwsac_align(size_t length);
LWS_VISIBLE LWS_EXTERN void
lwsac_info(struct lwsac *head);
LWS_VISIBLE LWS_EXTERN uint64_t
lwsac_total_alloc(struct lwsac *head);
///@}

63
lib/misc/lwsac/README.md Normal file
View file

@ -0,0 +1,63 @@
## LWS Allocated Chunks
![lwsac flow](/doc-assets/lwsac.svg)
These apis provide a way to manage a linked-list of allocated chunks...
[ HEAD alloc ] -> [ next alloc ] -> [ next alloc ] -> [ curr alloc ]
... and sub-allocate trivially inside the chunks. These sub-allocations are
not tracked by lwsac at all, there is a "used" high-water mark for each chunk
that's simply advanced by the amount sub-allocated. If the allocation size
matches the platform pointer alignment, there is zero overhead to sub-allocate
(otherwise the allocation is padded to the next platform pointer alignment
automatically).
If you have an unknown amount of relatively little things to allocate, including
strings or other unstructured data, lwsac is significantly more efficient than
individual allocations using malloc or so.
## lwsac_use() api
When you make an sub-allocation using `lwsac_use()`, you can either
set the `chunk_size` arg to zero, defaulting to 4000, or a specific chunk size.
In the event the requested sub-allocation exceeds the chunk size, the chunk
size is increated to match it automatically for this allocation only.
Subsequent `lwsac_use()` calls will advance internal pointers to use up the
remaining space inside the current chunk if possible; if not enough remaining
space it is skipped, a new allocation is chained on and the request pointed to
there.
Lwsac does not store information about sub-allocations. There is really zero
overhead for individual sub-allocations (unless their size is not
pointer-aligned, in which case the actual amount sub-allocated is rounded up to
the next pointer alignment automatically). For structs, which are pointer-
aligned naturally, and a chunk size relatively large for the sub-allocation
size, lwsac is extremely efficient even for huge numbers of small allocations.
This makes lwsac very effective when the total amount of allocation needed is
not known at the start and may be large... it will simply add on chunks to cope
with whatever happens.
## lwsac_free() api
When you are finished with the lwsac, you simply free the chain of allocated
chunks using lwsac_free() on the lwsac head. There's no tracking or individual
destruction of suballocations - the whole chain of chunks the suballocations
live in are freed and invalidated all together.
If the structs stored in the lwsac allocated things **outside** the lwsac, then the
user must unwind through them and perform the frees. But the idea of lwsac is
things stored in the lwsac also suballocate into the lwsac, and point into the
lwsac if they need to, avoiding any need to visit them during destroy. It's
like clearing up after a kids' party by gathering up a disposable tablecloth:
no matter what was left on the table, it's all gone in one step.
## lws_list_ptr helpers
A common pattern needed with sub-allocated structs is they are on one or more
linked-list. To make that simple to do cleanly, lws_list... apis are provided
along with a generic insertion function that can take a sort callback. These
allow a struct to participate on multiple linked-lists simultaneously.

View file

@ -0,0 +1,202 @@
/*
* libwebsockets - lws alloc chunk live file caching
*
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "core/private.h"
#include "misc/lwsac/private.h"
/*
* Helper for caching a file in memory in a lac, but also to check at intervals
* no less than 5s if the file is still fresh.
*
* Set *cache to NULL the first time before calling.
*
* You should call this each time before using the cache... if it's
*
* - less than 5s since the last freshness check, and
* - the file is already in memory
*
* it just returns with *cache left alone; this costs very little. You should
* call `lwsac_use_cached_file_start()` and `lwsac_use_cached_file_end()` to lock
* the cache against deletion while you are using it.
*
* If it's
*
* - at least 5s since the last freshness check, and
* - the file timestamp has changed
*
* then
*
* - the file is reloaded into a new lac and *cache set to that
*
* - the old cache lac, if any, is detached (so it will be freed when its
* reference count reaches zero, or immediately if nobody has it)
*
* Note the call can fail due to OOM or filesystem issue at any time.
*
*
* After the LAC header there is stored a `struct cached_file_info` and then
* the raw file contents. *
*
* [LAC header]
* [struct cached_file_info]
* [file contents] <--- *cache is set to here
*
* The api returns a lwsac_cached_file_t type offset to point to the file
* contents. Helpers for reference counting and freeing are also provided
* that take that type and know how to correct it back to operate on the LAC.
*/
#define cache_file_to_lac(c) ((struct lwsac *)((char *)c - \
sizeof(struct cached_file_info) - \
sizeof(struct lwsac)))
void
lwsac_use_cached_file_start(lwsac_cached_file_t cache)
{
struct lwsac *lac = cache_file_to_lac(cache);
lac->refcount++;
// lwsl_debug("%s: html refcount: %d\n", __func__, lac->refcount);
}
void
lwsac_use_cached_file_end(lwsac_cached_file_t *cache)
{
struct lwsac *lac;
if (!cache || !*cache)
return;
lac = cache_file_to_lac(*cache);
if (!lac->refcount)
lwsl_err("%s: html refcount zero on entry\n", __func__);
if (lac->refcount && !--lac->refcount && lac->detached) {
*cache = NULL; /* not usable any more */
lwsac_free(&lac);
}
}
void
lwsac_use_cached_file_detach(lwsac_cached_file_t *cache)
{
struct lwsac *lac = cache_file_to_lac(*cache);
lac->detached = 1;
if (lac->refcount)
return;
*cache = NULL;
lwsac_free(&lac);
}
int
lwsac_cached_file(const char *filepath, lwsac_cached_file_t *cache, size_t *len)
{
struct cached_file_info *info = NULL;
lwsac_cached_file_t old = *cache;
struct lwsac *lac = NULL;
time_t t = time(NULL);
unsigned char *a;
struct stat s;
size_t all;
ssize_t rd;
int fd;
if (old) { /* we already have a cached copy of it */
info = (struct cached_file_info *)((*cache) - sizeof(*info));
if (t - info->last_confirm < 5)
/* we checked it as fresh less than 5s ago, use old */
return 0;
}
/*
* ...it's been 5s, we should check again on the filesystem
* that the file hasn't changed
*/
fd = open(filepath, O_RDONLY);
if (fd < 0) {
lwsl_err("%s: cannot open %s\n", __func__, filepath);
return 1;
}
if (fstat(fd, &s)) {
lwsl_err("%s: cannot stat %s\n", __func__, filepath);
goto bail;
}
if (old && s.st_mtime == info->s.st_mtime) {
/* it still seems to be the same as our cached one */
info->last_confirm = t;
close(fd);
return 0;
}
/*
* we either didn't cache it yet, or it has changed since we cached
* it... reload in a new lac and then detach the old lac.
*/
all = sizeof(*info) + s.st_size + 1;
info = lwsac_use(&lac, all, all);
if (!info)
goto bail;
info->s = s;
info->last_confirm = t;
a = (unsigned char *)(info + 1);
*len = s.st_size;
a[s.st_size] = '\0';
rd = read(fd, a, s.st_size);
if (rd != s.st_size) {
lwsl_err("%s: cannot read %s (%d)\n", __func__, filepath,
(int)rd);
goto bail1;
}
close(fd);
*cache = (lwsac_cached_file_t)a;
if (old)
lwsac_use_cached_file_detach(&old);
return 0;
bail1:
lwsac_free(&lac);
bail:
close(fd);
return 1;
}

182
lib/misc/lwsac/lwsac.c Normal file
View file

@ -0,0 +1,182 @@
/*
* libwebsockets - lws alloc chunk
*
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "core/private.h"
#include "misc/lwsac/private.h"
void
lws_list_ptr_insert(lws_list_ptr *head, lws_list_ptr *add,
lws_list_ptr_sort_func_t sort_func)
{
while (sort_func && *head) {
if (sort_func(add, *head) <= 0)
break;
head = *head;
}
*add = *head;
*head = add;
}
size_t
lwsac_align(size_t length)
{
size_t align = sizeof(int *);
if (length & (align - 1))
length += align - (length & (align - 1));
return length;
}
size_t
lwsac_sizeof(void)
{
return sizeof(struct lwsac);
}
size_t
lwsac_get_tail_pos(struct lwsac *lac)
{
return lac->ofs;
}
struct lwsac *
lwsac_get_next(struct lwsac *lac)
{
return lac->next;
}
void *
lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size)
{
struct lwsac *chunk;
size_t ofs, alloc;
/* ensure there's a chunk and enough space in it for this name */
if (!*head || (*head)->curr->alloc_size - (*head)->curr->ofs < ensure) {
if (!chunk_size)
alloc = LWSAC_CHUNK_SIZE + sizeof(*chunk);
else
alloc = chunk_size + sizeof(*chunk);
/*
* If we get asked for something outside our expectation,
* allocate to meet it
*/
if (ensure >= alloc - sizeof(*chunk))
alloc = ensure + sizeof(*chunk);
chunk = malloc(alloc);
if (!chunk) {
lwsl_err("%s: OOM trying to alloc %llud\n", __func__,
(unsigned long long)alloc);
return NULL;
}
if (!*head) {
*head = chunk;
chunk->total_alloc_size = 0;
chunk->total_blocks = 0;
}
else
(*head)->curr->next = chunk;
(*head)->curr = chunk;
(*head)->curr->head = *head;
chunk->next = NULL;
chunk->alloc_size = alloc;
chunk->detached = 0;
chunk->refcount = 0;
(*head)->total_alloc_size += alloc;
(*head)->total_blocks++;
/*
* belabouring the point... ofs is aligned to the platform's
* generic struct alignment at the start then
*/
(*head)->curr->ofs = sizeof(*chunk);
}
ofs = (*head)->curr->ofs;
(*head)->curr->ofs += lwsac_align(ensure);
if ((*head)->curr->ofs >= (*head)->curr->alloc_size)
(*head)->curr->ofs = (*head)->curr->alloc_size;
return (char *)(*head)->curr + ofs;
}
void
lwsac_free(struct lwsac **head)
{
struct lwsac *it = *head;
while (it) {
struct lwsac *tmp = it->next;
free(it);
it = tmp;
}
*head = NULL;
}
void
lwsac_info(struct lwsac *head)
{
lwsl_notice("%s: lac %p: %dKiB in %d blocks\n", __func__, head,
(int)(head->total_alloc_size >> 10), head->total_blocks);
}
uint64_t
lwsac_total_alloc(struct lwsac *head)
{
return head->total_alloc_size;
}
void
lwsac_reference(struct lwsac *head)
{
head->refcount++;
}
void
lwsac_unreference(struct lwsac **head)
{
(*head)->refcount--;
if ((*head)->detached && !(*head)->refcount)
lwsac_free(head);
}
void
lwsac_detach(struct lwsac **head)
{
(*head)->detached = 1;
if (!(*head)->refcount)
lwsac_free(head);
}

48
lib/misc/lwsac/private.h Normal file
View file

@ -0,0 +1,48 @@
/*
* libwebsockets - lws alloc chunk
*
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include <sys/stat.h>
/* under page size of 4096 to allow overhead */
#define LWSAC_CHUNK_SIZE 4000
/*
* the chunk list members all point back to the head themselves so the list
* can be detached from the formal head and free itself when its reference
* count reaches zero.
*/
struct lwsac {
struct lwsac *next;
struct lwsac *head; /* pointer back to the first chunk */
struct lwsac *curr; /* applies to head chunk only */
size_t total_alloc_size; /* applies to head chunk only */
size_t alloc_size;
size_t ofs; /* next writeable position inside chunk */
int refcount; /* applies to head chunk only */
int total_blocks; /* applies to head chunk only */
char detached; /* if our refcount gets to zero, free the chunk list */
};
struct cached_file_info {
struct stat s;
time_t last_confirm;
};

View file

@ -0,0 +1,5 @@
|name|tests|
---|---
api-test-lwsac|LWS Allocated Chunks
api-test-lws_tokenize|Generic secure string tokenizer

View file

@ -0,0 +1,73 @@
cmake_minimum_required(VERSION 2.8)
include(CheckCSourceCompiles)
set(SAMP lws-api-test-lwsac)
set(SRCS main.c)
# If we are being built as part of lws, confirm current build config supports
# reqconfig, else skip building ourselves.
#
# If we are being built externally, confirm installed lws was configured to
# support reqconfig, else error out with a helpful message about the problem.
#
MACRO(require_lws_config reqconfig _val result)
if (DEFINED ${reqconfig})
if (${reqconfig})
set (rq 1)
else()
set (rq 0)
endif()
else()
set(rq 0)
endif()
if (${_val} EQUAL ${rq})
set(SAME 1)
else()
set(SAME 0)
endif()
if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})
if (${_val})
message("${SAMP}: skipping as lws being built without ${reqconfig}")
else()
message("${SAMP}: skipping as lws built with ${reqconfig}")
endif()
set(${result} 0)
else()
if (LWS_WITH_MINIMAL_EXAMPLES)
set(MET ${SAME})
else()
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig})
if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})
set(HAS_${reqconfig} 0)
else()
set(HAS_${reqconfig} 1)
endif()
if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))
set(MET 1)
else()
set(MET 0)
endif()
endif()
if (NOT MET)
if (${_val})
message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}")
else()
message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project")
endif()
endif()
endif()
ENDMACRO()
add_executable(${SAMP} ${SRCS})
if (websockets_shared)
target_link_libraries(${SAMP} websockets_shared)
add_dependencies(${SAMP} websockets_shared)
else()
target_link_libraries(${SAMP} websockets)
endif()

View file

@ -0,0 +1,22 @@
# lws api test lwsac
Demonstrates how to use and performs selftests for lwsac
## build
```
$ cmake . && make
```
## usage
Commandline option|Meaning
---|---
-d <loglevel>|Debug verbosity in decimal, eg, -d15
```
$ ./lws-api-test-lwsac
[2018/10/09 09:14:17:4834] USER: LWS API selftest: lwsac
[2018/10/09 09:14:17:4835] USER: Completed: PASS
```

View file

@ -0,0 +1,81 @@
/*
* lws-api-test-lwsac
*
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*/
#include <libwebsockets.h>
struct mytest {
int payload;
/* notice doesn't have to be at start of struct */
lws_list_ptr list_next;
/* a struct can appear on multiple lists too... */
};
/* converts a ptr to struct mytest .list_next to a ptr to struct mytest */
#define list_to_mytest(p) lws_list_ptr_container(p, struct mytest, list_next)
int main(int argc, const char **argv)
{
int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, acc;
lws_list_ptr list_head = NULL, iter;
struct lwsac *lwsac = NULL;
struct mytest *m;
const char *p;
if ((p = lws_cmdline_option(argc, argv, "-d")))
logs = atoi(p);
lws_set_log_level(logs, NULL);
lwsl_user("LWS API selftest: lwsac\n");
/*
* 1) allocate and create 1000 struct mytest in a linked-list
*/
for (n = 0; n < 1000; n++) {
m = lwsac_use(&lwsac, sizeof(*m), 0);
m->payload = n;
lws_list_ptr_insert(&list_head, &m->list_next, NULL);
}
/*
* 2) report some debug info about the lwsac state... those 1000
* allocations actually only required 4 mallocs
*/
lwsac_info(lwsac);
/* 3) iterate the list, accumulating the payloads */
acc = 0;
iter = list_head;
while (iter) {
m = list_to_mytest(iter);
acc += m->payload;
lws_list_ptr_advance(iter);
}
if (acc != 499500) {
lwsl_err("%s: FAIL acc %d\n", __func__, acc);
return 1;
}
/*
* 4) deallocate everything (lwsac is also set to NULL). It just
* deallocates the 4 mallocs, everything in there is gone accordingly
*/
lwsac_free(&lwsac);
lwsl_user("Completed: PASS\n");
return 0;
}

View file

@ -0,0 +1,24 @@
#!/bin/bash
#
# $1: path to minimal example binaries...
# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1
# that will be ./bin from your build dir
#
# $2: path for logs and results. The results will go
# in a subdir named after the directory this script
# is in
#
# $3: offset for test index count
#
# $4: total test count
#
# $5: path to ./minimal-examples dir in lws
#
# Test return code 0: OK, 254: timed out, other: error indication
. $5/selftests-library.sh
COUNT_TESTS=1
dotest $1 $2 apiselftest
exit $FAILS