diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 4056a45..a94bed2 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -25,7 +25,6 @@ export default defineConfig({ { text: 'Roadmap', link: '/roadmap/' }, { text: 'Guides', link: '/guides/' }, { text: 'About', link: '/about' }, - // { text: 'Feedback', link: '/feedback' }, ], sidebar: { @@ -49,10 +48,7 @@ export default defineConfig({ text: 'Introduction to Linux epoll', link: '/guides/resources/introduction-to-linux-epoll', }, - // { - // text: 'Linux epoll tutorial', - // link: '/guides/resources/linux-epoll-tutorial', - // }, + { text: 'Linux epoll', link: '/guides/resources/linux-epoll', @@ -62,7 +58,7 @@ export default defineConfig({ link: '/guides/resources/blocking-and-non-blocking-sockets', }, { text: 'HTTP', link: '/guides/resources/http' }, - + // { text: 'Internet Protocol (IP)', link: '/guides/resources/ip' }, // { text: 'File descriptors', link: '/guides/resources/file-descriptors' }, @@ -111,7 +107,7 @@ export default defineConfig({ { text: 'Stage 4: Linux epoll', link: '/roadmap/phase-0/stage-4', - + }, { text: 'Stage 5 a): TCP Proxy', @@ -187,9 +183,9 @@ export default defineConfig({ }, { text: 'Stage 17: Directory Browsing', - link: '/roadmap/phase-3/stage-17', + link: '/roadmap/phase-2/stage-17', }, - + ], }, { @@ -239,9 +235,10 @@ export default defineConfig({ ], }, ], + }, - socialLinks: [{ icon: 'github', link: 'https://github.com/eXpServer' }], + socialLinks: [{ icon: 'github', link: 'https://github.com/eXpServer' }], }, sitemap: { hostname: 'https://expserver.github.io', diff --git a/docs/assets/stage-12/mime_types.txt b/docs/assets/stage-12/mime_types.txt new file mode 100644 index 0000000..a868e3e --- /dev/null +++ b/docs/assets/stage-12/mime_types.txt @@ -0,0 +1,928 @@ +{".123", "application/vnd.lotus-1-2-3"}, +{".3dml", "text/vnd.in3d.3dml"}, +{".3g2", "video/3gpp2"}, +{".avif", "image/avif"}, +{".avifs", "image/avif"}, +{".kra", "application/x-krita"}, +{".krz", "application/x-krita"}, +{".heif", "image/heic"}, +{".heic", "image/heic"}, +{".3gp", "video/3gpp"}, +{".3g2", "audio/3gpp2"}, +{".3gp", "audio/3gpp"}, +{".7z", "application/x-7z-compressed"}, +{".a", "application/octet-stream"}, +{".bin", "application/octet-stream"}, +{".bpk", "application/octet-stream"}, +{".deploy", "application/octet-stream"}, +{".dist", "application/octet-stream"}, +{".distz", "application/octet-stream"}, +{".dmg", "application/octet-stream"}, +{".dms", "application/octet-stream"}, +{".dump", "application/octet-stream"}, +{".elc", "application/octet-stream"}, +{".iso", "application/octet-stream"}, +{".lha", "application/octet-stream"}, +{".lrf", "application/octet-stream"}, +{".lzh", "application/octet-stream"}, +{".o", "application/octet-stream"}, +{".obj", "application/octet-stream"}, +{".pkg", "application/octet-stream"}, +{".so", "application/octet-stream"}, +{".aab", "application/x-authorware-bin"}, +{".u32", "application/x-authorware-bin"}, +{".vox", "application/x-authorware-bin"}, +{".x32", "application/x-authorware-bin"}, +{".icns", "image/x-icns"}, +{".aac", "audio/aac"}, +{".mp4", "audio/aac"}, +{".m4a", "audio/aac"}, +{".aam", "application/x-authorware-map"}, +{".aas", "application/x-authorware-seg"}, +{".abw", "application/x-abiword"}, +{".acc", "application/vnd.americandynamics.acc"}, +{".ace", "application/x-ace-compressed"}, +{".acu", "application/vnd.acucobol"}, +{".acutc", "application/vnd.acucorp"}, +{".atc", "application/vnd.acucorp"}, +{".adp", "audio/adpcm"}, +{".aep", "application/vnd.audiograph"}, +{".afm", "application/x-font-type1"}, +{".pfa", "application/x-font-type1"}, +{".pfb", "application/x-font-type1"}, +{".pfm", "application/x-font-type1"}, +{".afp", "application/vnd.ibm.modcap"}, +{".list3820", "application/vnd.ibm.modcap"}, +{".listafp", "application/vnd.ibm.modcap"}, +{".ai", "application/postscript"}, +{".eps", "application/postscript"}, +{".ps", "application/postscript"}, +{".aif", "audio/x-aiff"}, +{".aifc", "audio/x-aiff"}, +{".aiff", "audio/x-aiff"}, +{".air", "application/vnd.adobe.air-application-installer-package+zip"}, +{".ami", "application/vnd.amiga.ami"}, +{".apk", "application/vnd.android.package-archive"}, +{".application", "application/x-ms-application"}, +{".apr", "application/vnd.lotus-approach"}, +{".asc", "application/pgp-signature"}, +{".sig", "application/pgp-signature"}, +{".asf", "video/x-ms-asf"}, +{".asx", "video/x-ms-asf"}, +{".asm", "text/x-asm"}, +{".s", "text/x-asm"}, +{".aso", "application/vnd.accpac.simply.aso"}, +{".atom", "application/atom+xml"}, +{".atomcat", "application/atomcat+xml"}, +{".atomsvc", "application/atomsvc+xml"}, +{".atx", "application/vnd.antix.game-component"}, +{".au", "audio/basic"}, +{".snd", "audio/basic"}, +{".avi", "video/x-msvideo"}, +{".aw", "application/applixware"}, +{".azf", "application/vnd.airzip.filesecure.azf"}, +{".azs", "application/vnd.airzip.filesecure.azs"}, +{".azw", "application/vnd.amazon.ebook"}, +{".bat", "application/x-msdownload"}, +{".com", "application/x-msdownload"}, +{".dll", "application/x-msdownload"}, +{".exe", "application/x-msdownload"}, +{".msi", "application/x-msdownload"}, +{".bcpio", "application/x-bcpio"}, +{".bdf", "application/x-font-bdf"}, +{".bdm", "application/vnd.syncml.dm+wbxml"}, +{".bh2", "application/vnd.fujitsu.oasysprs"}, +{".bmi", "application/vnd.bmi"}, +{".bmp", "image/bmp"}, +{".book", "application/vnd.framemaker"}, +{".fm", "application/vnd.framemaker"}, +{".frame", "application/vnd.framemaker"}, +{".maker", "application/vnd.framemaker"}, +{".box", "application/vnd.previewsystems.box"}, +{".boz", "application/x-bzip2"}, +{".bz2", "application/x-bzip2"}, +{".btif", "image/prs.btif"}, +{".bz", "application/x-bzip"}, +{".c", "text/x-c"}, +{".cc", "text/x-c"}, +{".cpp", "text/x-c"}, +{".cxx", "text/x-c"}, +{".dic", "text/x-c"}, +{".h", "text/x-c"}, +{".hh", "text/x-c"}, +{".c4d", "application/vnd.clonk.c4group"}, +{".c4f", "application/vnd.clonk.c4group"}, +{".c4g", "application/vnd.clonk.c4group"}, +{".c4p", "application/vnd.clonk.c4group"}, +{".c4u", "application/vnd.clonk.c4group"}, +{".cab", "application/vnd.ms-cab-compressed"}, +{".car", "application/vnd.curl.car"}, +{".cat", "application/vnd.ms-pki.seccat"}, +{".cct", "application/x-director"}, +{".cst", "application/x-director"}, +{".cxt", "application/x-director"}, +{".dcr", "application/x-director"}, +{".dir", "application/x-director"}, +{".dxr", "application/x-director"}, +{".fgd", "application/x-director"}, +{".swa", "application/x-director"}, +{".w3d", "application/x-director"}, +{".ccxml", "application/ccxml+xml"}, +{".cdbcmsg", "application/vnd.contact.cmsg"}, +{".cdf", "application/x-netcdf"}, +{".nc", "application/x-netcdf"}, +{".cdkey", "application/vnd.mediastation.cdkey"}, +{".cdx", "chemical/x-cdx"}, +{".cdxml", "application/vnd.chemdraw+xml"}, +{".cdy", "application/vnd.cinderella"}, +{".cer", "application/pkix-cert"}, +{".cgm", "image/cgm"}, +{".chat", "application/x-chat"}, +{".chm", "application/vnd.ms-htmlhelp"}, +{".chrt", "application/vnd.kde.kchart"}, +{".cif", "chemical/x-cif"}, +{".cii", "application/vnd.anser-web-certificate-issue-initiation"}, +{".cil", "application/vnd.ms-artgalry"}, +{".cla", "application/vnd.claymore"}, +{".class", "application/java-vm"}, +{".clkk", "application/vnd.crick.clicker.keyboard"}, +{".clkp", "application/vnd.crick.clicker.palette"}, +{".clkt", "application/vnd.crick.clicker.template"}, +{".clkw", "application/vnd.crick.clicker.wordbank"}, +{".clkx", "application/vnd.crick.clicker"}, +{".clp", "application/x-msclip"}, +{".cmc", "application/vnd.cosmocaller"}, +{".cmdf", "chemical/x-cmdf"}, +{".cml", "chemical/x-cml"}, +{".cmp", "application/vnd.yellowriver-custom-menu"}, +{".cmx", "image/x-cmx"}, +{".cod", "application/vnd.rim.cod"}, +{".conf", "text/plain"}, +{".def", "text/plain"}, +{".diff", "text/plain"}, +{".in", "text/plain"}, +{".ksh", "text/plain"}, +{".list", "text/plain"}, +{".log", "text/plain"}, +{".pl", "text/plain"}, +{".text", "text/plain"}, +{".txt", "text/plain"}, +{".deb", "application/vnd.debian.binary-package"}, +{".udeb", "application/vnd.debian.binary-package"}, +{".md", "text/markdown"}, +{".markdown", "text/markdown"}, +{".mdown", "text/markdown"}, +{".markdn", "text/markdown"}, +{".md", "text/x-markdown"}, +{".markdown", "text/x-markdown"}, +{".mdown", "text/x-markdown"}, +{".markdn", "text/x-markdown"}, +{".wasm", "application/wasm"}, +{".cpio", "application/x-cpio"}, +{".cpt", "application/mac-compactpro"}, +{".crd", "application/x-mscardfile"}, +{".crl", "application/pkix-crl"}, +{".crt", "application/x-x509-ca-cert"}, +{".der", "application/x-x509-ca-cert"}, +{".csh", "application/x-csh"}, +{".csml", "chemical/x-csml"}, +{".csp", "application/vnd.commonspace"}, +{".css", "text/css"}, +{".csv", "text/csv"}, +{".cu", "application/cu-seeme"}, +{".curl", "text/vnd.curl"}, +{".cww", "application/prs.cww"}, +{".daf", "application/vnd.mobius.daf"}, +{".dataless", "application/vnd.fdsn.seed"}, +{".seed", "application/vnd.fdsn.seed"}, +{".davmount", "application/davmount+xml"}, +{".dcurl", "text/vnd.curl.dcurl"}, +{".dd2", "application/vnd.oma.dd2+xml"}, +{".ddd", "application/vnd.fujixerox.ddd"}, +{".deb", "application/x-debian-package"}, +{".udeb", "application/x-debian-package"}, +{".dfac", "application/vnd.dreamfactory"}, +{".dis", "application/vnd.mobius.dis"}, +{".djv", "image/vnd.djvu"}, +{".djvu", "image/vnd.djvu"}, +{".dna", "application/vnd.dna"}, +{".doc", "application/msword"}, +{".dot", "application/msword"}, +{".wiz", "application/msword"}, +{".docm", "application/vnd.ms-word.document.macroenabled.12"}, +{".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, +{".dotm", "application/vnd.ms-word.template.macroenabled.12"}, +{".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, +{".dp", "application/vnd.osgi.dp"}, +{".dpg", "application/vnd.dpgraph"}, +{".dsc", "text/prs.lines.tag"}, +{".dtb", "application/x-dtbook+xml"}, +{".dtd", "application/xml-dtd"}, +{".dts", "audio/vnd.dts"}, +{".dtshd", "audio/vnd.dts.hd"}, +{".dvi", "application/x-dvi"}, +{".dwf", "model/vnd.dwf"}, +{".dwg", "image/vnd.dwg"}, +{".dxf", "image/vnd.dxf"}, +{".dxp", "application/vnd.spotfire.dxp"}, +{".ecelp4800", "audio/vnd.nuera.ecelp4800"}, +{".ecelp7470", "audio/vnd.nuera.ecelp7470"}, +{".ecelp9600", "audio/vnd.nuera.ecelp9600"}, +{".ecma", "application/ecmascript"}, +{".edm", "application/vnd.novadigm.edm"}, +{".edx", "application/vnd.novadigm.edx"}, +{".efif", "application/vnd.picsel"}, +{".ei6", "application/vnd.pg.osasli"}, +{".eml", "message/rfc822"}, +{".mht", "message/rfc822"}, +{".mhtml", "message/rfc822"}, +{".mime", "message/rfc822"}, +{".nws", "message/rfc822"}, +{".emma", "application/emma+xml"}, +{".eol", "audio/vnd.digital-winds"}, +{".eot", "application/vnd.ms-fontobject"}, +{".epub", "application/epub+zip"}, +{".es3", "application/vnd.eszigno3+xml"}, +{".et3", "application/vnd.eszigno3+xml"}, +{".esf", "application/vnd.epson.esf"}, +{".etx", "text/x-setext"}, +{".ext", "application/vnd.novadigm.ext"}, +{".ez", "application/andrew-inset"}, +{".ez2", "application/vnd.ezpix-album"}, +{".ez3", "application/vnd.ezpix-package"}, +{".f", "text/x-fortran"}, +{".f77", "text/x-fortran"}, +{".f90", "text/x-fortran"}, +{".for", "text/x-fortran"}, +{".f4v", "video/x-f4v"}, +{".fbs", "image/vnd.fastbidsheet"}, +{".fdf", "application/vnd.fdf"}, +{".fe_launch", "application/vnd.denovo.fcselayout-link"}, +{".fg5", "application/vnd.fujitsu.oasysgp"}, +{".fh", "image/x-freehand"}, +{".fh4", "image/x-freehand"}, +{".fh5", "image/x-freehand"}, +{".fh7", "image/x-freehand"}, +{".fhc", "image/x-freehand"}, +{".fig", "application/x-xfig"}, +{".fli", "video/x-fli"}, +{".flo", "application/vnd.micrografx.flo"}, +{".flv", "video/x-flv"}, +{".flw", "application/vnd.kde.kivio"}, +{".flx", "text/vnd.fmi.flexstor"}, +{".fly", "text/vnd.fly"}, +{".fnc", "application/vnd.frogans.fnc"}, +{".fpx", "image/vnd.fpx"}, +{".fsc", "application/vnd.fsc.weblaunch"}, +{".fst", "image/vnd.fst"}, +{".ftc", "application/vnd.fluxtime.clip"}, +{".fti", "application/vnd.anser-web-funds-transfer-initiation"}, +{".fvt", "video/vnd.fvt"}, +{".fzs", "application/vnd.fuzzysheet"}, +{".g3", "image/g3fax"}, +{".gac", "application/vnd.groove-account"}, +{".gdl", "model/vnd.gdl"}, +{".geo", "application/vnd.dynageo"}, +{".gex", "application/vnd.geometry-explorer"}, +{".gre", "application/vnd.geometry-explorer"}, +{".ggb", "application/vnd.geogebra.file"}, +{".ggt", "application/vnd.geogebra.tool"}, +{".ghf", "application/vnd.groove-help"}, +{".gif", "image/gif"}, +{".gim", "application/vnd.groove-identity-message"}, +{".gmx", "application/vnd.gmx"}, +{".gnumeric", "application/x-gnumeric"}, +{".gph", "application/vnd.flographit"}, +{".gqf", "application/vnd.grafeq"}, +{".gqs", "application/vnd.grafeq"}, +{".gram", "application/srgs"}, +{".grv", "application/vnd.groove-injector"}, +{".grxml", "application/srgs+xml"}, +{".gsf", "application/x-font-ghostscript"}, +{".gtar", "application/x-gtar"}, +{".gtm", "application/vnd.groove-tool-message"}, +{".gtw", "model/vnd.gtw"}, +{".gv", "text/vnd.graphviz"}, +{".gz", "application/x-gzip"}, +{".tgz", "application/x-gzip"}, +{".gz", "application/gzip"}, +{".tgz", "application/gzip"}, +{".h261", "video/h261"}, +{".gcode", "gcode"}, +{".h263", "video/h263"}, +{".h264", "video/h264"}, +{".hbci", "application/vnd.hbci"}, +{".gbr", "application/vnd.gerber"}, +{".hdf", "application/x-hdf"}, +{".hlp", "application/winhlp"}, +{".hpgl", "application/vnd.hp-hpgl"}, +{".hpid", "application/vnd.hp-hpid"}, +{".hps", "application/vnd.hp-hps"}, +{".hqx", "application/mac-binhex40"}, +{".htke", "application/vnd.kenameaapp"}, +{".htm", "text/html"}, +{".html", "text/html"}, +{".hvd", "application/vnd.yamaha.hv-dic"}, +{".hvp", "application/vnd.yamaha.hv-voice"}, +{".hvs", "application/vnd.yamaha.hv-script"}, +{".icc", "application/vnd.iccprofile"}, +{".icm", "application/vnd.iccprofile"}, +{".ice", "x-conference/x-cooltalk"}, +{".ico", "image/x-icon"}, +{".ics", "text/calendar"}, +{".ifb", "text/calendar"}, +{".ief", "image/ief"}, +{".ifm", "application/vnd.shana.informed.formdata"}, +{".iges", "model/iges"}, +{".igs", "model/iges"}, +{".igl", "application/vnd.igloader"}, +{".igx", "application/vnd.micrografx.igx"}, +{".iif", "application/vnd.shana.informed.interchange"}, +{".imp", "application/vnd.accpac.simply.imp"}, +{".ims", "application/vnd.ms-ims"}, +{".ipk", "application/vnd.shana.informed.package"}, +{".irm", "application/vnd.ibm.rights-management"}, +{".irp", "application/vnd.irepository.package+xml"}, +{".itp", "application/vnd.shana.informed.formtemplate"}, +{".ivp", "application/vnd.immervision-ivp"}, +{".ivu", "application/vnd.immervision-ivu"}, +{".jad", "text/vnd.sun.j2me.app-descriptor"}, +{".jam", "application/vnd.jam"}, +{".jar", "application/java-archive"}, +{".java", "text/x-java-source"}, +{".jisp", "application/vnd.jisp"}, +{".jlt", "application/vnd.hp-jlyt"}, +{".jnlp", "application/x-java-jnlp-file"}, +{".joda", "application/vnd.joost.joda-archive"}, +{".jpe", "image/jpeg"}, +{".jpeg", "image/jpeg"}, +{".jpg", "image/jpeg"}, +{".pjpg", "image/jpeg"}, +{".jfif", "image/jpeg"}, +{".jfif-tbnl", "image/jpeg"}, +{".jif", "image/jpeg"}, +{".jpe", "image/pjpeg"}, +{".jpeg", "image/pjpeg"}, +{".jpg", "image/pjpeg"}, +{".pjpg", "image/pjpeg"}, +{".jfi", "image/pjpeg"}, +{".jfif", "image/pjpeg"}, +{".jfif-tbnl", "image/pjpeg"}, +{".jif", "image/pjpeg"}, +{".jpgm", "video/jpm"}, +{".jpm", "video/jpm"}, +{".jpgv", "video/jpeg"}, +{".sh", "application/x-shellscript"}, +{".js", "text/javascript"}, +{".json", "application/json"}, +{".json", "text/json"}, +{".kar", "audio/midi"}, +{".mid", "audio/midi"}, +{".midi", "audio/midi"}, +{".rmi", "audio/midi"}, +{".aiff", "audio/aiff"}, +{".aif", "audio/aiff"}, +{".aff", "audio/aiff"}, +{".opus", "audio/opus"}, +{".karbon", "application/vnd.kde.karbon"}, +{".kfo", "application/vnd.kde.kformula"}, +{".kia", "application/vnd.kidspiration"}, +{".kil", "application/x-killustrator"}, +{".kml", "application/vnd.google-earth.kml+xml"}, +{".kmz", "application/vnd.google-earth.kmz"}, +{".kne", "application/vnd.kinar"}, +{".knp", "application/vnd.kinar"}, +{".kon", "application/vnd.kde.kontour"}, +{".kpr", "application/vnd.kde.kpresenter"}, +{".kpt", "application/vnd.kde.kpresenter"}, +{".ksp", "application/vnd.kde.kspread"}, +{".ktr", "application/vnd.kahootz"}, +{".ktz", "application/vnd.kahootz"}, +{".kwd", "application/vnd.kde.kword"}, +{".kwt", "application/vnd.kde.kword"}, +{".latex", "application/x-latex"}, +{".lbd", "application/vnd.llamagraphics.life-balance.desktop"}, +{".lbe", "application/vnd.llamagraphics.life-balance.exchange+xml"}, +{".les", "application/vnd.hhe.lesson-player"}, +{".link66", "application/vnd.route66.link66+xml"}, +{".lostxml", "application/lost+xml"}, +{".lrm", "application/vnd.ms-lrm"}, +{".ltf", "application/vnd.frogans.ltf"}, +{".lvp", "audio/vnd.lucent.voice"}, +{".lwp", "application/vnd.lotus-wordpro"}, +{".m13", "application/x-msmediaview"}, +{".m14", "application/x-msmediaview"}, +{".mvb", "application/x-msmediaview"}, +{".m1v", "video/mpeg"}, +{".m2v", "video/mpeg"}, +{".mpa", "video/mpeg"}, +{".mpe", "video/mpeg"}, +{".mpeg", "video/mpeg"}, +{".mpg", "video/mpeg"}, +{".m2a", "audio/mpeg"}, +{".m3a", "audio/mpeg"}, +{".mp2", "audio/mpeg"}, +{".mp2a", "audio/mpeg"}, +{".mp3", "audio/mpeg"}, +{".mpga", "audio/mpeg"}, +{".m3u", "audio/x-mpegurl"}, +{".m4u", "video/vnd.mpegurl"}, +{".mxu", "video/vnd.mpegurl"}, +{".m4v", "video/x-m4v"}, +{".ma", "application/mathematica"}, +{".mb", "application/mathematica"}, +{".nb", "application/mathematica"}, +{".mag", "application/vnd.ecowin.chart"}, +{".man", "text/troff"}, +{".me", "text/troff"}, +{".ms", "text/troff"}, +{".roff", "text/troff"}, +{".t", "text/troff"}, +{".tr", "text/troff"}, +{".mathml", "application/mathml+xml"}, +{".mml", "application/mathml+xml"}, +{".mathml", "text/mathml"}, +{".mml", "text/mathml"}, +{".db", "application/vnd.sqlite3"}, +{".sqlite", "application/vnd.sqlite3"}, +{".sqlite3", "application/vnd.sqlite3"}, +{".db-wal", "application/vnd.sqlite3"}, +{".sqlite-wal", "application/vnd.sqlite3"}, +{".db-shm", "application/vnd.sqlite3"}, +{".sqlite-shm", "application/vnd.sqlite3"}, +{".db", "application/x-sqlite3"}, +{".sqlite", "application/x-sqlite3"}, +{".sqlite3", "application/x-sqlite3"}, +{".db-wal", "application/x-sqlite3"}, +{".sqlite-wal", "application/x-sqlite3"}, +{".db-shm", "application/x-sqlite3"}, +{".sqlite-shm", "application/x-sqlite3"}, +{".mbk", "application/vnd.mobius.mbk"}, +{".mbox", "application/mbox"}, +{".mc1", "application/vnd.medcalcdata"}, +{".mcd", "application/vnd.mcd"}, +{".mcurl", "text/vnd.curl.mcurl"}, +{".mdb", "application/x-msaccess"}, +{".mdi", "image/vnd.ms-modi"}, +{".mesh", "model/mesh"}, +{".msh", "model/mesh"}, +{".silo", "model/mesh"}, +{".mfm", "application/vnd.mfmp"}, +{".mgz", "application/vnd.proteus.magazine"}, +{".mif", "application/vnd.mif"}, +{".mj2", "video/mj2"}, +{".mjp2", "video/mj2"}, +{".mlp", "application/vnd.dolby.mlp"}, +{".mmd", "application/vnd.chipnuts.karaoke-mmd"}, +{".mmf", "application/vnd.smaf"}, +{".mmr", "image/vnd.fujixerox.edmics-mmr"}, +{".mny", "application/x-msmoney"}, +{".mobi", "application/x-mobipocket-ebook"}, +{".prc", "application/x-mobipocket-ebook"}, +{".mov", "video/quicktime"}, +{".qt", "video/quicktime"}, +{".movie", "video/x-sgi-movie"}, +{".mp4", "video/mp4"}, +{".mp4v", "video/mp4"}, +{".mpg4", "video/mp4"}, +{".mp4a", "audio/mp4"}, +{".yaml", "application/yaml"}, +{".yml", "application/yaml"}, +{".mp4s", "application/mp4"}, +{".mpc", "application/vnd.mophun.certificate"}, +{".mpkg", "application/vnd.apple.installer+xml"}, +{".mpm", "application/vnd.blueice.multipass"}, +{".mpn", "application/vnd.mophun.application"}, +{".mpp", "application/vnd.ms-project"}, +{".mpt", "application/vnd.ms-project"}, +{".mpy", "application/vnd.ibm.minipay"}, +{".mqy", "application/vnd.mobius.mqy"}, +{".mrc", "application/marc"}, +{".mscml", "application/mediaservercontrol+xml"}, +{".mseed", "application/vnd.fdsn.mseed"}, +{".mseq", "application/vnd.mseq"}, +{".msf", "application/vnd.epson.msf"}, +{".msl", "application/vnd.mobius.msl"}, +{".msty", "application/vnd.muvee.style"}, +{".mts", "model/vnd.mts"}, +{".mus", "application/vnd.musician"}, +{".musicxml", "application/vnd.recordare.musicxml+xml"}, +{".mwf", "application/vnd.mfer"}, +{".mxf", "application/mxf"}, +{".mxl", "application/vnd.recordare.musicxml"}, +{".mxml", "application/xv+xml"}, +{".xhvml", "application/xv+xml"}, +{".xvm", "application/xv+xml"}, +{".xvml", "application/xv+xml"}, +{".mxs", "application/vnd.triscape.mxs"}, +{".n-gage", "application/vnd.nokia.n-gage.symbian.install"}, +{".ncx", "application/x-dtbncx+xml"}, +{".ngdat", "application/vnd.nokia.n-gage.data"}, +{".nlu", "application/vnd.neurolanguage.nlu"}, +{".nml", "application/vnd.enliven"}, +{".nnd", "application/vnd.noblenet-directory"}, +{".nns", "application/vnd.noblenet-sealer"}, +{".nnw", "application/vnd.noblenet-web"}, +{".npx", "image/vnd.net-fpx"}, +{".nsf", "application/vnd.lotus-notes"}, +{".oa2", "application/vnd.fujitsu.oasys2"}, +{".oa3", "application/vnd.fujitsu.oasys3"}, +{".oas", "application/vnd.fujitsu.oasys"}, +{".obd", "application/x-msbinder"}, +{".oda", "application/oda"}, +{".odb", "application/vnd.oasis.opendocument.database"}, +{".odc", "application/vnd.oasis.opendocument.chart"}, +{".odf", "application/vnd.oasis.opendocument.formula"}, +{".odft", "application/vnd.oasis.opendocument.formula-template"}, +{".odg", "application/vnd.oasis.opendocument.graphics"}, +{".odi", "application/vnd.oasis.opendocument.image"}, +{".odp", "application/vnd.oasis.opendocument.presentation"}, +{".ods", "application/vnd.oasis.opendocument.spreadsheet"}, +{".odt", "application/vnd.oasis.opendocument.text"}, +{".oga", "audio/ogg"}, +{".ogg", "audio/ogg"}, +{".spx", "audio/ogg"}, +{".mkv", "video/x-matroska"}, +{".mka", "audio/x-matroska"}, +{".ogv", "video/ogg"}, +{".ogx", "application/ogg"}, +{".onepkg", "application/onenote"}, +{".onetmp", "application/onenote"}, +{".onetoc", "application/onenote"}, +{".onetoc2", "application/onenote"}, +{".opf", "application/oebps-package+xml"}, +{".oprc", "application/vnd.palm"}, +{".pdb", "application/vnd.palm"}, +{".pqa", "application/vnd.palm"}, +{".org", "application/vnd.lotus-organizer"}, +{".osf", "application/vnd.yamaha.openscoreformat"}, +{".osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml"}, +{".otc", "application/vnd.oasis.opendocument.chart-template"}, +{".woff", "font/woff"}, +{".woff2", "font/woff2"}, +{".rpa", "application/x-redhat-package-manager"}, +{".pm", "application/x-perl"}, +{".pl", "application/x-perl"}, +{".weba", "audio/webm"}, +{".webm", "video/webm"}, +{".webp", "image/webp"}, +{".otf", "application/x-font-otf"}, +{".otf", "font/otf"}, +{".otg", "application/vnd.oasis.opendocument.graphics-template"}, +{".oth", "application/vnd.oasis.opendocument.text-web"}, +{".oti", "application/vnd.oasis.opendocument.image-template"}, +{".otm", "application/vnd.oasis.opendocument.text-master"}, +{".otp", "application/vnd.oasis.opendocument.presentation-template"}, +{".ots", "application/vnd.oasis.opendocument.spreadsheet-template"}, +{".ott", "application/vnd.oasis.opendocument.text-template"}, +{".oxt", "application/vnd.openofficeorg.extension"}, +{".p", "text/x-pascal"}, +{".pas", "text/x-pascal"}, +{".pp", "text/x-pascal"}, +{".inc", "text/x-pascal"}, +{".p10", "application/pkcs10"}, +{".p12", "application/x-pkcs12"}, +{".pfx", "application/x-pkcs12"}, +{".p7b", "application/x-pkcs7-certificates"}, +{".spc", "application/x-pkcs7-certificates"}, +{".p7c", "application/pkcs7-mime"}, +{".p7m", "application/pkcs7-mime"}, +{".p7r", "application/x-pkcs7-certreqresp"}, +{".p7s", "application/pkcs7-signature"}, +{".pbd", "application/vnd.powerbuilder6"}, +{".pbm", "image/x-portable-bitmap"}, +{".pcf", "application/x-font-pcf"}, +{".pcl", "application/vnd.hp-pcl"}, +{".pclxl", "application/vnd.hp-pclxl"}, +{".pct", "image/x-pict"}, +{".pic", "image/x-pict"}, +{".pcurl", "application/vnd.curl.pcurl"}, +{".pcx", "image/x-pcx"}, +{".pdf", "application/pdf"}, +{".pfr", "application/font-tdpfr"}, +{".pgm", "image/x-portable-graymap"}, +{".pgn", "application/x-chess-pgn"}, +{".pgp", "application/pgp-encrypted"}, +{".pki", "application/pkixcmp"}, +{".pkipath", "application/pkix-pkipath"}, +{".plb", "application/vnd.3gpp.pic-bw-large"}, +{".plc", "application/vnd.mobius.plc"}, +{".plf", "application/vnd.pocketlearn"}, +{".pls", "application/pls+xml"}, +{".pml", "application/vnd.ctc-posml"}, +{".png", "image/png"}, +{".png", "image/x-png"}, +{".png", "image/vnd.mozilla.apng"}, +{".pnm", "image/x-portable-anymap"}, +{".portpkg", "application/vnd.macports.portpkg"}, +{".pot", "application/vnd.ms-powerpoint"}, +{".ppa", "application/vnd.ms-powerpoint"}, +{".pps", "application/vnd.ms-powerpoint"}, +{".ppt", "application/vnd.ms-powerpoint"}, +{".pwz", "application/vnd.ms-powerpoint"}, +{".potm", "application/vnd.ms-powerpoint.template.macroenabled.12"}, +{".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, +{".ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12"}, +{".ppd", "application/vnd.cups-ppd"}, +{".ppm", "image/x-portable-pixmap"}, +{".ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12"}, +{".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, +{".pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12"}, +{".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, +{".pre", "application/vnd.lotus-freelance"}, +{".prf", "application/pics-rules"}, +{".prql", "application/prql"}, +{".psb", "application/vnd.3gpp.pic-bw-small"}, +{".psd", "image/vnd.adobe.photoshop"}, +{".psf", "application/x-font-linux-psf"}, +{".ptid", "application/vnd.pvi.ptid1"}, +{".pub", "application/x-mspublisher"}, +{".pvb", "application/vnd.3gpp.pic-bw-var"}, +{".pwn", "application/vnd.3m.post-it-notes"}, +{".py", "text/x-python"}, +{".pya", "audio/vnd.ms-playready.media.pya"}, +{".pyc", "application/x-python-code"}, +{".pyo", "application/x-python-code"}, +{".pyv", "video/vnd.ms-playready.media.pyv"}, +{".qam", "application/vnd.epson.quickanime"}, +{".qbo", "application/vnd.intu.qbo"}, +{".qfx", "application/vnd.intu.qfx"}, +{".qps", "application/vnd.publishare-delta-tree"}, +{".qwd", "application/vnd.quark.quarkxpress"}, +{".qwt", "application/vnd.quark.quarkxpress"}, +{".qxb", "application/vnd.quark.quarkxpress"}, +{".qxd", "application/vnd.quark.quarkxpress"}, +{".qxl", "application/vnd.quark.quarkxpress"}, +{".qxt", "application/vnd.quark.quarkxpress"}, +{".ra", "audio/x-pn-realaudio"}, +{".ram", "audio/x-pn-realaudio"}, +{".rar", "application/vnd.rar"}, +{".rar", "application/x-rar-compressed"}, +{".ras", "image/x-cmu-raster"}, +{".rcprofile", "application/vnd.ipunplugged.rcprofile"}, +{".rdf", "application/rdf+xml"}, +{".rdz", "application/vnd.data-vision.rdz"}, +{".rep", "application/vnd.businessobjects"}, +{".res", "application/x-dtbresource+xml"}, +{".rgb", "image/x-rgb"}, +{".rif", "application/reginfo+xml"}, +{".rl", "application/resource-lists+xml"}, +{".rlc", "image/vnd.fujixerox.edmics-rlc"}, +{".rld", "application/resource-lists-diff+xml"}, +{".rm", "application/vnd.rn-realmedia"}, +{".rmp", "audio/x-pn-realaudio-plugin"}, +{".rms", "application/vnd.jcp.javame.midlet-rms"}, +{".rnc", "application/relax-ng-compact-syntax"}, +{".rpm", "application/x-rpm"}, +{".rpss", "application/vnd.nokia.radio-presets"}, +{".rpst", "application/vnd.nokia.radio-preset"}, +{".rq", "application/sparql-query"}, +{".rs", "application/rls-services+xml"}, +{".rsd", "application/rsd+xml"}, +{".rss", "application/rss+xml"}, +{".xml", "application/rss+xml"}, +{".rtf", "application/rtf"}, +{".rtx", "text/richtext"}, +{".saf", "application/vnd.yamaha.smaf-audio"}, +{".sbml", "application/sbml+xml"}, +{".sc", "application/vnd.ibm.secure-container"}, +{".scd", "application/x-msschedule"}, +{".scm", "application/vnd.lotus-screencam"}, +{".scq", "application/scvp-cv-request"}, +{".scs", "application/scvp-cv-response"}, +{".scurl", "text/vnd.curl.scurl"}, +{".sda", "application/vnd.stardivision.draw"}, +{".sdc", "application/vnd.stardivision.calc"}, +{".sdd", "application/vnd.stardivision.impress"}, +{".sdkd", "application/vnd.solent.sdkm+xml"}, +{".sdkm", "application/vnd.solent.sdkm+xml"}, +{".sdp", "application/sdp"}, +{".sdw", "application/vnd.stardivision.writer"}, +{".vor", "application/vnd.stardivision.writer"}, +{".see", "application/vnd.seemail"}, +{".sema", "application/vnd.sema"}, +{".semd", "application/vnd.semd"}, +{".semf", "application/vnd.semf"}, +{".ser", "application/java-serialized-object"}, +{".setpay", "application/set-payment-initiation"}, +{".setreg", "application/set-registration-initiation"}, +{".sfd-hdstx", "application/vnd.hydrostatix.sof-data"}, +{".sfs", "application/vnd.spotfire.sfs"}, +{".sgl", "application/vnd.stardivision.writer-global"}, +{".sgm", "text/sgml"}, +{".sgml", "text/sgml"}, +{".sh", "application/x-sh"}, +{".shar", "application/x-shar"}, +{".shf", "application/shf+xml"}, +{".si", "text/vnd.wap.si"}, +{".sic", "application/vnd.wap.sic"}, +{".sis", "application/vnd.symbian.install"}, +{".sisx", "application/vnd.symbian.install"}, +{".sit", "application/x-stuffit"}, +{".sitx", "application/x-stuffitx"}, +{".skd", "application/vnd.koan"}, +{".skm", "application/vnd.koan"}, +{".skp", "application/vnd.koan"}, +{".skt", "application/vnd.koan"}, +{".sl", "text/vnd.wap.sl"}, +{".slc", "application/vnd.wap.slc"}, +{".sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12"}, +{".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"}, +{".slt", "application/vnd.epson.salt"}, +{".smf", "application/vnd.stardivision.math"}, +{".smi", "application/smil+xml"}, +{".smil", "application/smil+xml"}, +{".snf", "application/x-font-snf"}, +{".spf", "application/vnd.yamaha.smaf-phrase"}, +{".spl", "application/x-futuresplash"}, +{".spot", "text/vnd.in3d.spot"}, +{".spp", "application/scvp-vp-response"}, +{".spq", "application/scvp-vp-request"}, +{".src", "application/x-wais-source"}, +{".srx", "application/sparql-results+xml"}, +{".sse", "application/vnd.kodak-descriptor"}, +{".ssf", "application/vnd.epson.ssf"}, +{".ssml", "application/ssml+xml"}, +{".stc", "application/vnd.sun.xml.calc.template"}, +{".std", "application/vnd.sun.xml.draw.template"}, +{".stf", "application/vnd.wt.stf"}, +{".sti", "application/vnd.sun.xml.impress.template"}, +{".stk", "application/hyperstudio"}, +{".stl", "application/vnd.ms-pki.stl"}, +{".str", "application/vnd.pg.format"}, +{".stw", "application/vnd.sun.xml.writer.template"}, +{".sus", "application/vnd.sus-calendar"}, +{".susp", "application/vnd.sus-calendar"}, +{".sv4cpio", "application/x-sv4cpio"}, +{".sv4crc", "application/x-sv4crc"}, +{".svd", "application/vnd.svd"}, +{".svg", "image/svg+xml"}, +{".svgz", "image/svg+xml"}, +{".swf", "application/x-shockwave-flash"}, +{".swi", "application/vnd.arastra.swi"}, +{".sxc", "application/vnd.sun.xml.calc"}, +{".sxd", "application/vnd.sun.xml.draw"}, +{".sxg", "application/vnd.sun.xml.writer.global"}, +{".sxi", "application/vnd.sun.xml.impress"}, +{".sxm", "application/vnd.sun.xml.math"}, +{".sxw", "application/vnd.sun.xml.writer"}, +{".tao", "application/vnd.tao.intent-module-archive"}, +{".tar", "application/x-tar"}, +{".tcap", "application/vnd.3gpp2.tcap"}, +{".tcl", "application/x-tcl"}, +{".teacher", "application/vnd.smart.teacher"}, +{".tex", "application/x-tex"}, +{".texi", "application/x-texinfo"}, +{".texinfo", "application/x-texinfo"}, +{".tfm", "application/x-tex-tfm"}, +{".tif", "image/tiff"}, +{".tiff", "image/tiff"}, +{".tmo", "application/vnd.tmobile-livetv"}, +{".torrent", "application/x-bittorrent"}, +{".tpl", "application/vnd.groove-tool-template"}, +{".tpt", "application/vnd.trid.tpt"}, +{".tra", "application/vnd.trueapp"}, +{".trm", "application/x-msterminal"}, +{".tsv", "text/tab-separated-values"}, +{".ttc", "application/x-font-ttf"}, +{".ttf", "application/x-font-ttf"}, +{".twd", "application/vnd.simtech-mindmapper"}, +{".twds", "application/vnd.simtech-mindmapper"}, +{".txd", "application/vnd.genomatix.tuxedo"}, +{".txf", "application/vnd.mobius.txf"}, +{".ufd", "application/vnd.ufdl"}, +{".ufdl", "application/vnd.ufdl"}, +{".umj", "application/vnd.umajin"}, +{".unityweb", "application/vnd.unity"}, +{".uoml", "application/vnd.uoml+xml"}, +{".uri", "text/uri-list"}, +{".uris", "text/uri-list"}, +{".urls", "text/uri-list"}, +{".ustar", "application/x-ustar"}, +{".utz", "application/vnd.uiq.theme"}, +{".uu", "text/x-uuencode"}, +{".vcd", "application/x-cdlink"}, +{".vcf", "text/x-vcard"}, +{".vcg", "application/vnd.groove-vcard"}, +{".vcs", "text/x-vcalendar"}, +{".vcx", "application/vnd.vcx"}, +{".vis", "application/vnd.visionary"}, +{".viv", "video/vnd.vivo"}, +{".vrml", "model/vrml"}, +{".wrl", "model/vrml"}, +{".vsd", "application/vnd.visio"}, +{".vss", "application/vnd.visio"}, +{".vst", "application/vnd.visio"}, +{".vsw", "application/vnd.visio"}, +{".vsdx", "application/vnd.visio"}, +{".vssx", "application/vnd.visio"}, +{".vstx", "application/vnd.visio"}, +{".vssm", "application/vnd.visio"}, +{".vstm", "application/vnd.visio"}, +{".vsf", "application/vnd.vsf"}, +{".vtu", "model/vnd.vtu"}, +{".vxml", "application/voicexml+xml"}, +{".wad", "application/x-doom"}, +{".ts", "video/mp2t"}, +{".wav", "audio/wav"}, +{".wax", "audio/x-ms-wax"}, +{".wbmp", "image/vnd.wap.wbmp"}, +{".wbs", "application/vnd.criticaltools.wbs+xml"}, +{".wbxml", "application/vnd.wap.wbxml"}, +{".wcm", "application/vnd.ms-works"}, +{".wdb", "application/vnd.ms-works"}, +{".wks", "application/vnd.ms-works"}, +{".wps", "application/vnd.ms-works"}, +{".wm", "video/x-ms-wm"}, +{".wma", "audio/x-ms-wma"}, +{".wmd", "application/x-ms-wmd"}, +{".wmf", "application/x-msmetafile"}, +{".wml", "text/vnd.wap.wml"}, +{".wmlc", "application/vnd.wap.wmlc"}, +{".wmls", "text/vnd.wap.wmlscript"}, +{".wmlsc", "application/vnd.wap.wmlscriptc"}, +{".wmv", "video/x-ms-wmv"}, +{".wmx", "video/x-ms-wmx"}, +{".wmz", "application/x-ms-wmz"}, +{".wpd", "application/vnd.wordperfect"}, +{".wpl", "application/vnd.ms-wpl"}, +{".wqd", "application/vnd.wqd"}, +{".wri", "application/x-mswrite"}, +{".wsdl", "application/wsdl+xml"}, +{".wspolicy", "application/wspolicy+xml"}, +{".wtb", "application/vnd.webturbo"}, +{".wvx", "video/x-ms-wvx"}, +{".x3d", "application/vnd.hzn-3d-crossword"}, +{".xap", "application/x-silverlight-app"}, +{".xar", "application/vnd.xara"}, +{".xbap", "application/x-ms-xbap"}, +{".xbd", "application/vnd.fujixerox.docuworks.binder"}, +{".xbm", "image/x-xbitmap"}, +{".xdm", "application/vnd.syncml.dm+xml"}, +{".xdp", "application/vnd.adobe.xdp+xml"}, +{".xdw", "application/vnd.fujixerox.docuworks"}, +{".xenc", "application/xenc+xml"}, +{".xer", "application/patch-ops-error+xml"}, +{".xfdf", "application/vnd.adobe.xfdf"}, +{".xfdl", "application/vnd.xfdl"}, +{".xht", "application/xhtml+xml"}, +{".xhtml", "application/xhtml+xml"}, +{".xif", "image/vnd.xiff"}, +{".xla", "application/vnd.ms-excel"}, +{".xlb", "application/vnd.ms-excel"}, +{".xlc", "application/vnd.ms-excel"}, +{".xlm", "application/vnd.ms-excel"}, +{".xls", "application/vnd.ms-excel"}, +{".xlt", "application/vnd.ms-excel"}, +{".xlw", "application/vnd.ms-excel"}, +{".xlam", "application/vnd.ms-excel.addin.macroenabled.12"}, +{".xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12"}, +{".xlsm", "application/vnd.ms-excel.sheet.macroenabled.12"}, +{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, +{".xltm", "application/vnd.ms-excel.template.macroenabled.12"}, +{".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, +{".xml", "application/xml"}, +{".xpdl", "application/xml"}, +{".xsl", "application/xml"}, +{".xo", "application/vnd.olpc-sugar"}, +{".xop", "application/xop+xml"}, +{".xpi", "application/x-xpinstall"}, +{".xpm", "image/x-xpixmap"}, +{".xpr", "application/vnd.is-xpr"}, +{".xps", "application/vnd.ms-xpsdocument"}, +{".xpw", "application/vnd.intercon.formnet"}, +{".xpx", "application/vnd.intercon.formnet"}, +{".xslt", "application/xslt+xml"}, +{".xsm", "application/vnd.syncml+xml"}, +{".xspf", "application/xspf+xml"}, +{".xul", "application/vnd.mozilla.xul+xml"}, +{".xwd", "image/x-xwindowdump"}, +{".xyz", "chemical/x-xyz"}, +{".zaz", "application/vnd.zzazz.deck+xml"}, +{".zip", "application/zip"}, +{".zip", "application/x-zip-compressed"}, +{".zip", "application/zip-compressed"}, +{".zir", "application/vnd.zul"}, +{".zirz", "application/vnd.zul"}, +{".zmm", "application/vnd.handheld-entertainment+xml"}, +{".dng", "image/x-adobe-dng"}, +{".arw", "image/x-sony-arw"}, +{".cr2", "image/x-canon-cr2"}, +{".crw", "image/x-canon-crw"}, +{".dcr", "image/x-kodak-dcr"}, +{".erf", "image/x-epson-erf"}, +{".k25", "image/x-kodak-k25"}, +{".kdc", "image/x-kodak-kdc"}, +{".mrw", "image/x-minolta-mrw"}, +{".nef", "image/x-nikon-nef"}, +{".orf", "image/x-olympus-orf"}, +{".pef", "image/x-pentax-pef"}, +{".ptx", "image/x-pentax-pef"}, +{".raf", "image/x-fuji-raf"}, +{".raw", "image/x-panasonic-raw"}, +{".rw2", "image/x-panasonic-raw"}, +{".rwl", "image/x-panasonic-raw"}, +{".flac", "audio/flac"}, +{".sr2", "image/x-sony-sr2"}, +{".srf", "image/x-sony-srf"}, +{".x3f", "image/x-sigma-x3f"} \ No newline at end of file diff --git a/docs/assets/stage-17/directory.png b/docs/assets/stage-17/directory.png new file mode 100644 index 0000000..f31e69f Binary files /dev/null and b/docs/assets/stage-17/directory.png differ diff --git a/docs/guides/resources/linux-epoll.md b/docs/guides/resources/linux-epoll.md index 81e00f4..35da17c 100644 --- a/docs/guides/resources/linux-epoll.md +++ b/docs/guides/resources/linux-epoll.md @@ -362,7 +362,7 @@ In edge-triggered mode, epoll reports events only when the readiness state chang Because **ET does not repeat events**, the application must read or write until the operation returns `EAGAIN`; otherwise, data may remain unread with no further notifications. -ET reduces unnecessary wakeups and is useful for high-performance servers, but requires more careful programming. This mode is enabled by passing the `EPOLLET` flag when registering the file descriptor with `epoll_ctl()`. +ET reduces unnecessary wakeups and is useful for high-performance servers, but requires more careful programming. This mode is enabled by passing the `EPOLLET` flag when registering the file descriptor with `epoll_ctl()`. ::: tip NOTE `EAGAIN` is a common error code returned by non-blocking I/O operations (e.g., `read`, `write`, `recv`, `send`) when the operation cannot be completed immediately without blocking the calling process. In the context of `epoll` with non-blocking sockets, especially in Edge-Triggered mode, receiving `EAGAIN` indicates that there is no more data to read or the write buffer is full, and you should stop attempting the operation until a new event is reported by `epoll_wait()`. @@ -391,13 +391,13 @@ When a socket receives new data: ## Summary Table -| Component | Data Structure | Purpose | -| :---- | :---- | :---- | -| Interest list | Red-black tree (`rbr`) | Store registered FDs | -| Ready list | Linked list (`rdlist`) | Store active events | -| Wait queue | `wait_queue_head_t` | Put sleeping processes | -| FD node | `epitem` | Connects file to eventpoll | -| Callback | `ep_poll_callback()` | Moves item to ready list + wakeup | +| Component | Data Structure | Purpose | +| :------------ | :--------------------- | :-------------------------------- | +| Interest list | Red-black tree (`rbr`) | Store registered FDs | +| Ready list | Linked list (`rdlist`) | Store active events | +| Wait queue | `wait_queue_head_t` | Put sleeping processes | +| FD node | `epitem` | Connects file to eventpoll | +| Callback | `ep_poll_callback()` | Moves item to ready list + wakeup | ### Summary of chain of events: @@ -407,10 +407,10 @@ Workflow of `epoll_wait()` : ![epoll_wait.png](/assets/resources/linux-epoll-wait.png) -# Glossary +## Glossary -## Callback +### Callback A callback is a function inside the kernel that is registered to be run automatically when a certain kernel condition occurs. In epoll, the callback is used to inform the epoll subsystem that the state of a monitored file descriptor has changed. @@ -418,7 +418,7 @@ When a file descriptor is added to epoll using epoll_ctl(EPOLL_CTL_ADD), epoll r The callback runs entirely inside the kernel and is not called by user code. Its job is only to record that the file descriptor is ready and to wake up any threads waiting in epoll_wait(). It does not decide which events occurred and does not return data to user space. Because it may run in interrupt or softirq context, the callback is not allowed to sleep. -## Spinlock +### Spinlock A spinlock is a low-level kernel synchronization primitive used to protect shared data structures from concurrent access. When a CPU attempts to acquire a spinlock, it repeatedly checks the lock until it becomes available, without putting the current execution context to sleep. @@ -426,7 +426,7 @@ Spinlocks are used in epoll because parts of the epoll subsystem, including call -## Interrupt Context (Hard Interrupt Context) +#### Interrupt Context (Hard Interrupt Context) Interrupt context is a kernel execution context entered when the CPU receives a hardware interrupt from a device such as a network card, disk controller, or timer. When an interrupt occurs, the CPU immediately suspends the currently running code, switches to kernel mode if necessary, and begins executing the registered interrupt handler. @@ -436,7 +436,7 @@ In the context of epoll, interrupt handlers do not directly invoke epoll logic. ---------- -## Softirq Context +#### Softirq Context Softirq context is a kernel execution context used to perform deferred work that was triggered by a hardware interrupt but could not be completed safely or efficiently within the interrupt handler itself. Softirqs allow the kernel to defer processing while still executing soon after the interrupt and without sleeping. diff --git a/docs/roadmap/phase-1/stage-12.md b/docs/roadmap/phase-1/stage-12.md index 1b42057..43b523a 100644 --- a/docs/roadmap/phase-1/stage-12.md +++ b/docs/roadmap/phase-1/stage-12.md @@ -58,6 +58,7 @@ The function `xps_get_mime()` returns the MIME type of a file based on its exten #include "../xps.h" //here, some extension-mime types pairs are given, you can add as required xps_keyval_t mime_types[] = { + {".h", "text/x-c"}, {".c", "text/x-c"}, {".cc", "text/x-c"}, {".cpp", "text/x-c"}, @@ -86,7 +87,11 @@ const char *xps_get_mime(const char *file_path) { return NULL; } ``` -::: +::: + +:::tip NOTE +If you want to add more **MIME** types, you can refer to this [link](/assets/stage-12/mime_types.txt). +::: As we are mapping the MIME type based on the file extension, a function for finding the file extension is added in `xps_utils.h`. Add the below given function in `xps_utils.c` @@ -386,8 +391,6 @@ In the expserver folder, create a new folder public. Inside this create a file s Now start the server as mentioned in previous stages. Connect a client on port 8002 using `netcat localhost 8002`. Verify that the contents in file sample.txt is received by the client in terminal. Thus we have successfully implemented a basic file server which can send files in local disk to the client. - - ## Conclusion Now all the clients connected to port 8002, would be served the specified file. Thus we have implemented a basic file server. The file server is implemented along with the pipe mechanism itself with the only difference being source reading the file attached to its `ptr` field and writing it to pipe. \ No newline at end of file diff --git a/docs/roadmap/phase-2/stage-16.md b/docs/roadmap/phase-2/stage-16.md index b5edfc9..a1bca68 100644 --- a/docs/roadmap/phase-2/stage-16.md +++ b/docs/roadmap/phase-2/stage-16.md @@ -369,7 +369,7 @@ if (lookup->type == REQ_FILE_SERVE) { /*implementation already given*/ } else if (lookup->type == REQ_REVERSE_PROXY) { - + ... sscanf(lookup->upstream, "%[^:]:%u", host, &port); /*create upstream connection*/ /*handle errors*/ @@ -584,34 +584,37 @@ void sigint_handler(int signum) { First we have to run the server by giving the JSON file containing the configuration information as command line argument. ![exp1-img1.png](/assets/stage-16/exp1-img1.png) + Three port would be created as given: ![exp1-img2.png](/assets/stage-16/exp1-img2.png) -- First, we would be verifying the file server functionality. An `index.html` file as mentioned in the xps_config.json is created in the public folder. Add some standard html code in this file. The contents can be viewed on `[localhost:8001](http://localhost:8001)` on the browser. +- First, we would be verifying the file server functionality. An `index.html` file as mentioned in the xps_config.json is created in the public folder. Add some standard html code in this file. The contents can be viewed on [localhost:8001](http://localhost:8001) on the browser. Try by replacing files of different format. You have to update JSON configuration file accordingly. - Now, run a python file server as done earlier in Phase 0. - ![exp1-img3.png](/assets/stage-16/exp1-img3.png) - - This will create the upstream server mentioned in xps_config.json. + ![exp1-img3.png](/assets/stage-16/exp1-img3.png) + + This will create the upstream server mentioned in xps_config.json. - The files in the directory in which the python server is running can be viewed from the urls [`localhost:8001/hello`] and [`localhost:8002`] . In this case, the url is redirected to the second one. +The files in the directory in which the python server is running can be viewed from the urls [`localhost:8001/hello`](http://localhost:800/hello) and [`localhost:8002`](http://localhost:8002) . In this case, the url is redirected to the second one. - `localhost:8003` would be redirecting to the `redirect_url` mentioned in the JSON configuration file. Try adding more ports and redirect to different urls. -## Experiment #1 +## Experiments + +### Experiment #1 eXpServer uses a **Longest Prefix Match** strategy to decide which route to use when multiple routes match a request path. To see this in action, open your `xps_config.json` and add two overlapping routes for the same server: Route A with `req_path: "/"` (Type: `file_serve`) and Route B with `req_path: "/api"` (Type: `redirect` to `http://localhost:8002`). Now, try requesting `http://localhost:8001/api/data`. You will notice that Route B is chosen because `/api` is a longer match than `/`. If you request `/ap`, where do you think it will be routed to? -## Experiment #2 +### Experiment #2 In this experiment, we will explore how the server behaves when an index file is missing. Open `xps_config.json` and change the `dir_path` for the root route of port `8001` from `../public/` to `../../` (your project root). diff --git a/docs/roadmap/phase-2/stage-17.md b/docs/roadmap/phase-2/stage-17.md index 2ab8576..33c85c0 100644 --- a/docs/roadmap/phase-2/stage-17.md +++ b/docs/roadmap/phase-2/stage-17.md @@ -1 +1,277 @@ # Stage 17: Directory Browsing + +## Recap + +In the previous stages, we updated the server to handle HTTP messages. Stage 14 focused on implementing HTTP request parsing, while Stage 15 covered the construction of HTTP response messages. And in stage 16 we have implemented multiple cores, used a JSON file to set-up server configuration and implemented reverse proxy and URL redirecting in our webserver. + +## Learning Objectives + +- Implement directory browsing as a fallback when no index file is present +- Create a new `xps_directory` module to handle directory listing + +## Introduction + +Directory browsing is a feature in web servers that allows us to see the files and folders in a directory when a default index file (typically, index.html) is missing or not present in the directory. The web server dynamically generates an index.html file with a list of files and subdirectories within the request directory and serves it. To achieve directory browsing, we will use inbuilt functions like `opendir(),readdir(),closedir()` but remember that directory browsing can expose sensitive files and directories that were not intended to be publicly accessible. This can include configuration files, source code, database backups, and other sensitive data, so be careful when you configure the path to be displayed under directory browsing + +## Implementation + +Recall, during config lookup, when we were unable to find the index file, we set the `dir_path` to resource path. + +```c +lookup_object->dir_path = resource_path; +``` + +If this is the case, we initiate the directory browsing function which takes in the `dir_path` and generates an `index.html` file. So when `lookup->type==REQ_FILE_SEREVE` and if `lookup->dir_path` is not `NULL`, `xps_directory_browsing()` will generate HTML file then set the body of `http_res` + +To open a directory stream we use `opendir()` with `dir_path` and assigned to `DIR` data type + +:::tip NOTE +Before going to the implementation, we have to look into some system calls that will help you to implement directory browsing from **``** + +- [`opendir(dir_path)`](https://man7.org/linux/man-pages/man3/opendir.3.html) function opens a directory stream corresponding to the directory name, and returns a pointer to the directory stream. The stream is positioned at the first entry in the directory.on success, it will return a pointer to the a directory stream on error will return `NULL` pointer +- [`readdir(dirp)`](https://man7.org/linux/man-pages/man3/readdir.3.html) function returns a pointer to a `dirent` structure representing the next directory entry in the directory stream pointed to by `dirp`. It returns `NULL` on reaching the end of the directory stream or if an error occurred. +In the `glibc` implementation, the `dirent` structure is defined as follows: + +```c +struct dirent{ + ino_t d_ino; /* Inode number */ + off_t d_off; /* Not an offset; see below */ + unsigned short d_reclen; /* Length of this record */ + unsigned char d_type; /* Type of file; not supported + by all filesystem types */ + char d_name[256]; /* Null-terminated filename */ +}; +``` + +The only fields in the `dirent` structure that are mandated by POSIX.1 are `d_name` and `d_ino` . + +The other fields are unstandardized and not present on all systems. + +::: + +### **xps_directory** + +#### `xps_directory.h` + +The code below has the contents of the header file for `xps_directory.h`. Have a look at it and make a copy of it in your codebase + +```c +#ifndef XPS_DIRECTORY +#define XPS_DIRECTORY + +#include "../xps.h" + +/** + * @brief Generates a directory listing HTML page for directory browsing. + * + * This function generates an HTML page displaying the contents of a directory + * for browsing. + * + * @param dir_path The path to the directory to be browsed. + * @param pathname The pathname to be displayed in the HTML page. + * @return An xps_buffer_t pointer containing the HTML page, or NULL on failure. + */ +xps_buffer_t *xps_directory_browsing(const char *dir_path, const char *pathname); + +#endif +``` + +#### `xps_directory.c` + +When the `xps_directory_browsing()` called from the `sesssion_process_request()` a buffer will be created with HTML tags and the heading of the page, then all the data will be added in the formatted pattern to the buffer + +:::tip NOTE +Before proceeding to `xps_session`, please go through some system calls and functions that will help us to implement directory browsing + +- [`stat`](https://man7.org/linux/man-pages/man3/stat.3type.html) file status - Describe the information about a file +- [`fstat`](https://man7.org/linux/man-pages/man2/stat.2.html) retrieve the information about the file pointed to the pathname +- [`S_ISREG, S_ISDIR`](https://www.gnu.org/software/libc/manual/html_node/Testing-File-Type.html) for testing the type of a file +::: + +:::details expserver/src/disk/xps_directory.c + +```c +#include "../xps.h" + +xps_buffer_t *xps_directory_browsing(const char *dir_path,const char *pathname){ + /* validate parameters */ + + // Buffer for HTTP message + char *buff= /* fill this */ + if (buff == NULL) { + logger(LOG_ERROR, "xps_directory_browsing()", "malloc() failed for 'buff'"); + return + } + + //Here we will append the html file into this buff starting from the heading and basic styling + spintf(buff,"Directory: " + "%s

eXpServer

Index " + "of %s


", + pathname, pathname); + + // Open a directory stream using opendir function + DIR *dir = opendir(dir_path); + if(dir == NULL){ + logger(LOG_ERROR, "xps_directory_browsing()", "opendir() failed"); + free(buff); + return NULL; + } + + struct dirent *dir_entry; + + while((dir_entry == readdir(dir)) != NULL){ + //skip the first two entries such as . and .. in list directory from dir_entry->d_dname + if (strcmp(dir_entry->d_name, ".") == || strcmp(dir_entry->d_name, "..") == 0)) + continue; + + char full_path[1024]; + /* copy the dir_path and dir_entry->d_name with formatted with a / into full_path */ + //HINT: you can use snprintf + + //open the file in the full_path + int file_fd = /*fill this*/ + if(file_fd == -1){ + logger(LOG_ERROR, "xps_directory_browsing()", "failed to open file"); + continue; + } + + struct stat file_stat; + + //get information about the file + if(fstat(file_fd, &file_stat) ==-1){ + logger(LOG_ERROR, "xps_directory_browsing()", "fstat()"); + close(file_fd); + continue; + } + //check if file is regular file or if the file is a direcory + if(S_ISREG(file_stat.st_mode) || S_ISDIR(file_stat.st_mode)){ + char *is_dir = S_ISDIR(file_stat.st_mode) ? "/" : ""; + + char *temp_pathname = str_create(pathname); + if (temp_pathname[strlen(temp_pathname) - 1] == '/') + temp_pathname[strlen(temp_pathname) - 1] = '\0'; + + // char time_buff[20]; + // strftime(time_buff, sizeof(time_buff), "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_mtime)); + + if (S_ISREG(file_stat.st_mode)) // IS_FILE + sprintf(buff + strlen(buff), + "\n", + temp_pathname, dir_entry->d_name, dir_entry->d_name, is_dir,); + else + sprintf( + buff + strlen(buff), + "\n", + temp_pathname, dir_entry->d_name, dir_entry->d_name, is_dir); + free(temp_pathname); + } + + /*close the file*/ + + } + + closedir(file_fd); + sprintf(buff + strlen(buff), "
%s%s
%s%s
"); + xps_buffer_t *directory_browsing = /*fill this*/ + + if (directory_browsing == NULL) { + logger(LOG_ERROR, "xps_directory_browsing()","xps_buffer_create() returned NULL"); + free(buff); + return NULL; + } + + return directory_browsing; + +} + +``` +::: + +### `xps_config.c` + +In this part we have to set `lookup->dir_path = resource_path` if the index file not found , Remember that in the last stage, we iterate through the route index and set the `index_file_flound=true` if the `index_fille_path` is a file + +```c +xps_config_lookup_t *xps_config_lookup(xps_config_t *config, xps_http_req_t *http_req, xps_connection_t *client, int *error) { + //* no change from the last stage + + if(is_file(resource_path)){ + lookup->file_path = resource_path; + }else if( is_dir(resource_path)){ + //from stage 16 + + //if the index file not found set the dir_path in lookup to resource_path + }else{ + free(resource_path); + } + + //* no change from the last stage + +} +``` + +### `xps_session.c` + +So far, when the lookup type is `REQ_FILE_SERVE`, we only handled file serving if the `file_path` in the `lookup` is not empty.Now onwards, we are going first to check if `dir_path` in the lookup is there; then it will go for directory browsing by creating an HTML file using the `xps_directory_browsing` function and add the HTML file in the HTTP response body + +```c +void session_process_request(xps_session_t *session) { + + /* no change from the last stage*/ + + if(lookup->type == REQ_FILE_SERVE){ + + xps_buffer_t *dir_html= /*generate the html content*/ + /*verify the dir_html is not NULL*/ + + /*no change from the last stage*/ + + /*create http_res with status code HTTP_OK dir html is not NULL or HTTP_INTERNAL_SERVER_ERROR*/ + + /*if dir_html is not null set the body and header of http_res*/ + + xps_buffer_t *http_res_buff= /*fill this*/ + + /*serialize and set to_client_buff*/ + /*destroy response object after use*/ + return; + } + +} +``` + +## Milestone #1 + +Build the server and run it with `xps_config.json`. Ensure that the `dir_path` is set to a directory without an index file (as configured in Stage 16's Experiment #2). Navigate to [localhost:8001](http://localhost:8001) in your browser. If the implementation is correct, you should see an HTML page listing all files and subdirectories in the configured directory. + +## Experiments + +### Experiment #1 + +For all directories and files, display the last modified date in the following format: + +```c +"%Y-%m-%d %H:%M:%S" +``` +Extend the directory listing to display file sizes in KB for each file. You can retrieve the file size in **bytes** using `file_stat.st_size` and convert it to kilobytes. + +![directory image](/assets/stage-17/directory.png) + +After completing this experiment, your directory listing should display the last modified date and file size for each entry, as shown above. + +## Conclusion + +In this stage, we implemented the `xps_directory` module to handle directory browsing. When a requested directory lacks an index file, the server now dynamically generates an HTML page listing all files and subdirectories, solving the 404 issue we encountered in Stage 16. + +This also marks the end of Phase 2. Throughout this phase, we transformed eXpServer from a basic TCP server into a fully functional HTTP server with dynamic configuration, multiple worker cores, file serving, reverse proxying, and URL redirection. + +However, our server currently accepts connections from any client on the network. What if you want to restrict access to only trusted IP addresses within your organization or block known malicious IPs? Think about how you might solve this problem. \ No newline at end of file