├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── bss.asm ├── constants.asm ├── data.asm ├── debug.asm ├── dirent.asm ├── http.asm ├── macros.asm ├── main.asm ├── mutex.asm ├── string.asm ├── syscall.asm └── web_root └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | asmttpd 2 | *.o -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stable-slim AS build 2 | WORKDIR /opt 3 | RUN apt update -y && apt install make yasm binutils -y 4 | COPY . . 5 | RUN make release 6 | 7 | FROM scratch 8 | COPY --from=build /opt/asmttpd / 9 | COPY --from=build /opt/web_root /web_root 10 | ENTRYPOINT ["/asmttpd"] 11 | CMD ["/web_root", "80"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # asmttpd - Web server for Linux written in amd64 assembly. \ 2 | Copyright (C) 2014 nemasu \ 3 | \ 4 | This file is part of asmttpd. \ 5 | \ 6 | asmttpd is free software: you can redistribute it and/or modify \ 7 | it under the terms of the GNU General Public License as published by \ 8 | the Free Software Foundation, either version 2 of the License, or \ 9 | (at your option) any later version. \ 10 | \ 11 | asmttpd is distributed in the hope that it will be useful, \ 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of \ 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \ 14 | GNU General Public License for more details. \ 15 | \ 16 | You should have received a copy of the GNU General Public License \ 17 | along with asmttpd. If not, see . 18 | 19 | all: main 20 | 21 | release: http.asm constants.asm bss.asm data.asm macros.asm main.asm mutex.asm string.asm syscall.asm dirent.asm 22 | yasm -f elf64 -a x86 main.asm -o main.o 23 | ld main.o -o asmttpd 24 | strip -s asmttpd 25 | 26 | main.o: http.asm constants.asm bss.asm data.asm macros.asm main.asm mutex.asm string.asm syscall.asm dirent.asm 27 | yasm -g dwarf2 -f elf64 -a x86 main.asm -o main.o 28 | main: main.o 29 | ld main.o -o asmttpd 30 | clean: 31 | rm -rf main.o asmttpd 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | asmttpd 2 | ======= 3 | 4 | Web server for Linux written in amd64 assembly. 5 | 6 | Features: 7 | * Multi-threaded. 8 | * No libraries required ( only 64-bit Linux ). 9 | * Very small binary. 10 | * Quite fast. 11 | 12 | What works: 13 | * Serving files from specified document root. 14 | * HEAD requests. 15 | * 200, 206, 404, 400, 413, 416 16 | * Content-types: xml, html, xhtml, gif, png, jpeg, css, js, svg, txt, and octet-stream. 17 | 18 | Planned Features: 19 | * Directory listing. 20 | 21 | Current Limitations / Known Issues 22 | ======= 23 | * Sendfile can hang if GET is cancelled. 24 | 25 | Installation 26 | ======= 27 | 28 | Run `make` or `make release` for non-debug version. 29 | 30 | You will need `yasm` installed. 31 | 32 | Usage 33 | ======= 34 | 35 | `./asmttpd /path/to/web_root port_number` 36 | 37 | Example: `./asmttpd ./web_root 8080` 38 | 39 | Changes 40 | ======= 41 | 2025-03-01 : asmttpd - 0.4.7 42 | 43 | * Added txt type. 44 | 45 | 2023-04-13 : asmttpd - 0.4.6 46 | 47 | * Initial directory listing support. 48 | 49 | 2021-01-15 : asmttpd - 0.4.5 50 | 51 | * string_contains bugfix. 52 | 53 | 2019-04-22 : asmttpd - 0.4.4 54 | 55 | * Added SVG support. 56 | 57 | 2019-01-24 : asmttpd - 0.4.3 58 | 59 | * Added port number as parameter. 60 | 61 | 2017-10-18 : asmttpd - 0.4.2 62 | 63 | * Set REUSEADDR. 64 | 65 | 2017-10-17 : asmttpd - 0.4.1 66 | 67 | * Stack address bug fix. 68 | 69 | 2016-10-31 : asmttpd - 0.4 70 | 71 | * HEAD support. 72 | 73 | 2014-07-14 : asmttpd - 0.3 74 | 75 | * Added default document support. 76 | 77 | 2014-02-10 : asmttpd - 0.2 78 | 79 | * Added 400, 413, 416 responses. 80 | * Fixed header processing bug. 81 | 82 | 2014-02-07 : asmttpd - 0.1.1 83 | 84 | * Fixed 206 max length bug. 85 | * Commented out simple request logging, uncomment in main.asm to enable. 86 | 87 | 2014-02-06 : asmttpd - 0.1 88 | 89 | * Fixed SIGPIPE when transfer is cancelled. 90 | * Added a more useful error on bind failure. 91 | * Fixed 206 size calculation. 92 | * Combined seek & get file size system calls. 93 | 94 | 2014-02-05 : asmttpd - 0.09 95 | 96 | * Issue #8 fix. Crashes on long request paths. 97 | 98 | 2014-02-04 : asmttpd - 0.08 99 | 100 | * Added TCP corking. 101 | 102 | 2014-02-04 : asmttpd - 0.07 103 | 104 | * Removed thread pool after benchmarking, changed to an accept-per-thread model. 105 | 106 | 2014-02-04 : asmttpd - 0.06 107 | 108 | * Worker thread stack corruption bug fix. 109 | 110 | 2014-02-04 : asmttpd - 0.05 111 | 112 | * Changed 200 and 206 implementation to use sendfile system call. 113 | * Got rid of read/write buffer, changed request read buffer to standard 8KB. 114 | 115 | 2014-02-03 : asmttpd - 0.04 116 | 117 | * 200 now streams full amount 118 | 119 | 120 | 2014-02-01 : asmttpd - 0.03 121 | 122 | * Files are split if too large to fit into buffer. 123 | * Added 206 responses with Content-Range handling 124 | 125 | 126 | 2014-01-30 : asmttpd - 0.02 127 | 128 | * Added xml, xhtml, gif, png, jpeg, css, and javascript content types. 129 | * Changed thread memory size to something reasonable. You can tweak it according to available memory. See comments in main.asm 130 | * Added simple request logging. 131 | * Added removal of '../' in URL. 132 | -------------------------------------------------------------------------------- /bss.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | listen_socket: resq 1 19 | listen_port: resw 1 20 | one_constant: resq 1 21 | directory_path: resq 1 22 | -------------------------------------------------------------------------------- /constants.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | ;Constants 20 | %define FD_STDOUT 0x1 21 | %define THREAD_STACK_SIZE 16384 22 | %define SIGCHILD 0x11 ;SIGCHILD signal constant 23 | %define SIGHUP 1 ;Hangup (POSIX). 24 | %define SIGINT 2 ;Interrupt (ANSI). 25 | %define SIGQUIT 3 ;Quit (POSIX). 26 | %define SIGPIPE 13;broken pipe 27 | %define SIGTERM 15; Default kill signal 28 | %define SIGIGN 1;Ignore signal 29 | %define SA_RESTORER 0x04000000 ;Required for x86_64 sigaction 30 | %define QUEUE_SIZE 40960 ; in bytes, 40960 is about 5120 fds. 31 | %define THREAD_BUFFER_SIZE 8192 ; 8KB recv buffer 32 | %define URL_LENGTH_LIMIT 2000 33 | %define DIRECTORY_LENGTH_LIMIT 100 34 | %define DIRECTORY_LIST_BUFFER 1024 ; holds linux_dirents 35 | %define CUSTOM_CONTENT_BUFFER 1024 ; holds directory listing HTML formatted reply 36 | 37 | ;Request Types 38 | %define REQ_UNK 0 39 | %define REQ_GET 1 40 | %define REQ_HEAD 2 41 | 42 | ;Flags 43 | %define MMAP_PROT_READ 0x1 44 | %define MMAP_PROT_WRITE 0x2 45 | %define MMAP_MAP_PRIVATE 0x2 46 | %define MMAP_MAP_ANON 0x20 47 | %define MMAP_MAP_GROWSDOWN 0x100 48 | 49 | %define CLONE_VM 0x100 ;Same memory space 50 | %define CLONE_FS 0x200 ;Same file system information 51 | %define CLONE_FILES 0x400 ;Share file descriptors 52 | %define CLONE_SIGHAND 0x800 ;Share signal handlers 53 | %define CLONE_THREAD 0x10000 ;Same thread group ( same process ) 54 | 55 | %define OPEN_RDONLY 00 56 | %define OPEN_DIRECTORY 0x10000 ; Open will fail if path is not a directory 57 | 58 | %define AF_INET 2 59 | %define SOCK_STREAM 1 60 | %define PROTO_TCP 6 61 | 62 | %define LSEEK_SET 0 ; seek to offset bytes 63 | %define LSEEK_END 2 ; seek to end plus offset 64 | 65 | %define LEVEL_SOL_TCP 1 66 | %define LEVEL_IPPROTO_TCP 6 67 | %define SOCKOPT_TCP_REUSEADDR 2 68 | %define SOCKOPT_TCP_CORK 3 69 | 70 | ;Internal Constants 71 | %define CONTENT_TYPE_HTML 0 72 | %define CONTENT_TYPE_OCTET_STREAM 1 73 | %define CONTENT_TYPE_CSS 2 74 | %define CONTENT_TYPE_JAVASCRIPT 3 75 | %define CONTENT_TYPE_XHTML 4 76 | %define CONTENT_TYPE_XML 5 77 | %define CONTENT_TYPE_GIF 6 78 | %define CONTENT_TYPE_PNG 7 79 | %define CONTENT_TYPE_JPEG 8 80 | %define CONTENT_TYPE_SVG 9 81 | %define CONTENT_TYPE_TXT 10 82 | 83 | ;Dirent types 84 | %define DT_UNKNOWN 0 85 | %define DT_FIFO 1 86 | %define DT_CHR 2 87 | %define DT_DIR 4 88 | %define DT_BLK 6 89 | %define DT_REG 8 90 | %define DT_LNK 10 91 | %define DT_SOCK 12 92 | %define DT_WHT 14 93 | 94 | ;System Call Values 95 | %define SYS_WRITE 1 ;int fd, const void *buf, size_t count 96 | %define SYS_LSEEK 8 ;int fd, off_t offset, int whence 97 | %define SYS_MMAP 9 ;void *addr, size_t length, int prot, int flags, int fd, off_t offset 98 | %define SYS_CLONE 56 ;unsigned long clone_flags, unsigned long newsp, void ___user *parent_tid, void __user *child_tid, struct pt_regs *regs 99 | %define SYS_EXIT 60 ;int status 100 | %define SYS_EXIT_GROUP 231 ;int status 101 | %define SYS_NANOSLEEP 35 ;const struct timespec *req, struct timespec *rem 102 | %define SYS_RT_SIGACTION 13 ;int sig,const struct sigaction __user * act,struct sigaction __user * oact,size_t sigsetsize 103 | %define SYS_SOCKET 41 ;int domain, int type, int protocol 104 | %define SYS_ACCEPT 43 ;int sockfd, struct sockaddr *addr, socklen_t *addrlen 105 | %define SYS_SENDTO 44 ;int sockfd, const void *buf, size_t len, int flags, ... 106 | %define SYS_RECVFROM 45 ;int sockfd, void *buf, size_t len, int flags 107 | %define SYS_BIND 49 ;int sockfd, const struct sockaddr *addr, socklen_t addrlen 108 | %define SYS_LISTEN 50 ;int sockfd, int backlog 109 | %define SYS_SELECT 23 ;int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout 110 | %define SYS_GETDENTS 78 ;unsigned int fd, struct linux_dirent *dirp, unsigned int count 111 | %define SYS_OPEN 2 ;const char *pathname, int flags, mode_t mode 112 | %define SYS_CLOSE 3 ;unsigned int fd 113 | %define SYS_SENDFILE 40 ;int out_fd, int in_fd, off_t *offset, size_t count 114 | %define SYS_SETSOCKOPT 54; int sockfd, int level, int optname,const void *optval, socklen_t optlen 115 | -------------------------------------------------------------------------------- /data.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | struc sockaddr_in 20 | sin_family: resw 1 21 | sin_port: resw 1 22 | sin_addr: resd 1 23 | endstruc 24 | 25 | sa: istruc sockaddr_in 26 | at sin_family, dw AF_INET 27 | at sin_port, dw 0 28 | at sin_addr, dd 0 ;INADDR_ANY 29 | iend 30 | 31 | request_type dq 0 32 | request_offset dq 0 33 | 34 | timeval: ;struct 35 | tv_sec dq 0 36 | tv_usec dq 0 37 | sigaction: ;struct 38 | sa_handler dq 0 39 | sa_flags dq SA_RESTORER ; also dq, because padding 40 | sa_restorer dq 0 41 | sa_mask dq 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 42 | 43 | dir_ent_pointer dq 0 44 | dir_ent_size dq 0 45 | 46 | ;Strings 47 | in_enter db "In Enter:",0x00 48 | in_enter_len equ $ - in_enter 49 | in_exit db "In Exit:", 0x00 50 | in_exit_len equ $ - in_exit 51 | new_line db 0x0a 52 | start_text db "asmttpd - ",ASMTTPD_VERSION,0x0a,0x00 53 | start_text_len equ $ - start_text 54 | msg_bind_error db "Error - Bind() failed. Check if port is in use or you have sufficient privileges.",0x00 55 | msg_bind_error_len equ $ - msg_bind_error 56 | msg_error db "An error has occured, exiting",0x00 57 | msg_error_len equ $ - msg_error 58 | msg_help db "Usage: ./asmttpd /path/to/directory port",0x00 59 | msg_help_len equ $ - msg_help 60 | msg_not_a_directory dd "Error: Specified document root is not a directory",0x00 61 | msg_not_a_directory_len equ $ - msg_not_a_directory 62 | msg_request_log db 0x0a,"Request: ",0x00 63 | msg_request_log_len equ $ - msg_request_log 64 | 65 | header_range_search db "Range: ",0x00 66 | header_range_search_len equ $ - header_range_search 67 | 68 | location db "Location: ",0x00 69 | 70 | find_bytes_range db "bytes=",0x00 71 | find_bytes_range_len equ $ - find_bytes_range 72 | 73 | filter_prev_dir db "../",0x00 74 | filter_prev_dir_len equ $ - filter_prev_dir 75 | 76 | crlfx2 db 0x0d,0x0a,0x0d,0x0a,0x00 77 | crlfx2_len equ $ - crlfx2 78 | 79 | crlf db 0x0d,0x0a,0x00 80 | crlf_len equ $ - crlf 81 | 82 | char_slash db "/",0x00 83 | char_hyphen db "-",0x00 84 | 85 | ;HTTP 86 | http_200 db "HTTP/1.1 200 OK",0x0d,0x0a,0x00 87 | http_200_len equ $ - http_200 88 | http_206 db "HTTP/1.1 206 Partial Content",0x0d,0x0a,0x00 89 | http_206_len equ $ - http_206 90 | http_301 db "HTTP/1.1 301 Moved Permanently",0x0d,0x0a,0x00 91 | http_301_len equ $ - http_301 92 | http_404 db "HTTP/1.1 404 Not Found",0x0d,0x0a,0x00 93 | http_404_len equ $ - http_404 94 | http_404_text db "I'm sorry, Dave. I'm afraid I can't do that. 404 Not Found",0x00 95 | http_404_text_len equ $ - http_404_text 96 | http_400 db "HTTP/1.1 400 Bad Request",0x0d,0x0a,0x00 97 | http_400_len equ $ - http_400 98 | http_413 db "HTTP/1.1 413 Request Entity Too Large",0x0d,0x0a,0x00 99 | http_413_len equ $ - http_413 100 | http_416 db "HTTP/1.1 416 Requested Range Not Satisfiable",0x0d,0x0a,0x00 101 | http_416_len equ $ - http_416 102 | 103 | server_header db "Server: asmttpd/",ASMTTPD_VERSION,0x0d,0x0a,0x00 104 | server_header_len equ $ - server_header 105 | 106 | range_header db "Accept-Ranges: bytes",0x0d,0x0a,0x00 107 | range_header_len equ $ - range_header 108 | 109 | content_range db "Content-Range: bytes ",0x00 110 | content_range_len equ $ - content_range ;Content-Range: bytes 200-1000/3000 111 | 112 | content_length db "Content-Length: ",0x00 ;Content-Length: 800 113 | content_length_len equ $ - content_length 114 | 115 | connection_header db "Connection: close",0x0d,0x0a,0x00 116 | connection_header_len equ $ - connection_header 117 | 118 | content_type db "Content-Type: ",0x00 119 | content_type_len equ $ - content_type 120 | 121 | ;Content-Type 122 | content_type_html db "text/html",0x0d,0x0a,0x00 123 | content_type_html_len equ $ - content_type_html 124 | 125 | content_type_octet_stream db "application/octet-stream",0x0d,0x0a,0x00 126 | content_type_octet_stream_len equ $ - content_type_octet_stream 127 | 128 | content_type_xhtml db "application/xhtml+xml",0x0d,0x0a,0x00 129 | content_type_xhtml_len equ $ - content_type_xhtml 130 | 131 | content_type_xml db "text/xml",0x0d,0x0a,0x00 132 | content_type_xml_len equ $ - content_type_xml 133 | 134 | content_type_javascript db "application/javascript",0x0d,0x0a,0x00 135 | content_type_javascript_len equ $ - content_type_javascript 136 | 137 | content_type_css db "text/css",0x0d,0x0a,0x00 138 | content_type_css_len equ $ - content_type_css 139 | 140 | content_type_jpeg db "image/jpeg",0x0d,0x0a,0x00 141 | content_type_jpeg_len equ $ - content_type_jpeg 142 | 143 | content_type_png db "image/png",0x0d,0x0a,0x00 144 | content_type_png_len equ $ - content_type_png 145 | 146 | content_type_gif db "image/gif",0x0d,0x0a,0x00 147 | content_type_gif_len equ $ - content_type_gif 148 | 149 | content_type_svg db "image/svg+xml",0x0d,0x0a,0x00 150 | content_type_svg_len equ $ - content_type_svg 151 | 152 | content_type_txt db "text/plain",0x0d,0x0a,0x00 153 | content_type_txt_len equ $ - content_type_txt 154 | 155 | default_document db "/index.html",0x00 156 | default_document_len equ $ - default_document 157 | 158 | ;Content extension 159 | extension_html db ".html",0x00 160 | extension_htm db ".htm" ,0x00 161 | extension_javascript db ".js", 0x00 162 | extension_css db ".css", 0x00 163 | extension_xhtml db ".xhtml",0x00 164 | extension_xml db ".xml",0x00 165 | extension_gif db ".gif",0x00 166 | extension_jpg db ".jpg",0x00 167 | extension_jpeg db ".jpeg",0x00 168 | extension_png db ".png",0x00 169 | extension_svg db ".svg",0x00 170 | extension_txt db ".txt",0x00 171 | 172 | ; dir listing 173 | http_200_dir_list_open_h1_tag db "

Index of ",0x00 174 | http_200_dir_list_close_h1_tag db "

",0x00 175 | http_dir_entry_open_a_tag_pre db '

',0x00 177 | http_dir_entry_close_a_tag db '

',0x00 178 | -------------------------------------------------------------------------------- /debug.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | ;hint, use these with GDB 20 | ;set follow-fork-mode child 21 | 22 | section .bss 23 | printbuffer: resb 1024;debug 24 | 25 | section .text 26 | print_rdi: 27 | 28 | stackpush 29 | push rax 30 | push rbx 31 | push rcx 32 | 33 | 34 | call get_number_of_digits 35 | mov rcx, rax ; 36 | 37 | inc rax ;include NL char in length 38 | push rax; save length for syscall 39 | 40 | ;add lf 41 | mov rdx, 0xa 42 | mov [printbuffer+rcx], dl 43 | dec rcx 44 | 45 | mov rax, rdi ; value to print 46 | xor rdx, rdx ; zero other half 47 | mov rbx, 10 48 | 49 | print_rdi_start: 50 | xor rdx, rdx ; zero other half 51 | div rbx ; divide by 10 52 | 53 | add rdx, 0x30 54 | mov [printbuffer+rcx], dl 55 | dec rcx 56 | cmp rax, 9 57 | ja print_rdi_start 58 | 59 | add rax, 0x30 ;last digit 60 | mov [printbuffer+rcx], al 61 | 62 | pop rcx ;restore original length 63 | 64 | mov rdi, printbuffer 65 | mov rsi, rcx 66 | call sys_write 67 | 68 | pop rcx 69 | pop rbx 70 | pop rax 71 | stackpop 72 | ret 73 | 74 | -------------------------------------------------------------------------------- /dirent.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | ; d_inode = off + 0 20 | ; d_offset = off + 8 21 | ; d_reclen = off + 16 22 | ; d_name = off + 18 23 | ; null byte 24 | ; d_type = reclen - 1 25 | 26 | ; Get total number of getdents entries 27 | get_dir_ents_number: ;ret rax entries 28 | stackpush 29 | 30 | xor rax, rax 31 | xor rcx, rcx ; hold offset to current reclen entry 32 | xor rbx, rbx ; hold total number of entries read 33 | xor rdx, rdx ; hold total reclen bytes read 34 | mov rcx, 16 ; point to first reclen offset 35 | 36 | read_dir_ents_reclen: 37 | mov rsi, [dir_ent_pointer] ; points to linux_dirents buffer 38 | add rsi, rcx 39 | lodsw ; ax now contains length of current entry 40 | inc rbx 41 | add rcx, rax 42 | add rdx, rax 43 | cmp rdx, [dir_ent_size] 44 | jne read_dir_ents_reclen 45 | 46 | mov rax, rbx 47 | stackpop 48 | ret 49 | 50 | ; Add a list of HTML formatted entries into a buffer 51 | generate_dir_entries: ;rdi - buffer, ret - rax length of string in buffer 52 | stackpush 53 | ; Add heading 54 | mov rsi, http_200_dir_list_open_h1_tag 55 | call string_concat 56 | ; Add // into heading contents 57 | mov rsi, [rbp-16] 58 | add rsi, r9 59 | call string_concat 60 | mov rsi, [directory_path] 61 | call string_remove 62 | ; Close heading 63 | mov rsi, http_200_dir_list_close_h1_tag 64 | call string_concat 65 | 66 | mov rsi, crlf 67 | call string_concat 68 | 69 | xor rcx, rcx ; hold offset to current reclen entry 70 | xor rbx, rbx ; hold total number of entries read 71 | xor rdx, rdx ; hold total reclen bytes read 72 | mov rcx, 16 ; point to first reclen offset 73 | 74 | read_dir_ents: 75 | mov rsi, [dir_ent_pointer] ; points to linux_dirents buffer 76 | add rsi, rcx 77 | lodsw ; ax now contains length of current entry 78 | inc rbx 79 | add rcx, rax 80 | add rdx, rax 81 | 82 | ; ignore the '.' entry 83 | cmp word[rsi], 0x002e 84 | je read_dir_ents_end 85 | 86 | mov rbx, rsi 87 | push rbx ; save for second time 88 | 89 | push rsi 90 | mov rsi, http_dir_entry_open_a_tag_pre 91 | call string_concat 92 | pop rsi 93 | 94 | call string_concat ; add name, prepend with request dir 95 | 96 | cmp word[rbx], 0x2e2e ; check for '..' 97 | jne finish_link_tag 98 | push rsi 99 | mov rsi, char_slash 100 | call string_concat 101 | pop rsi 102 | 103 | finish_link_tag: 104 | push rsi 105 | mov rsi, http_dir_entry_open_a_tag_post 106 | call string_concat 107 | pop rsi 108 | 109 | pop rbx 110 | mov rsi, rbx 111 | call string_concat ; add name again 112 | 113 | push rsi 114 | mov rsi, http_dir_entry_close_a_tag 115 | call string_concat 116 | pop rsi 117 | 118 | read_dir_ents_end: 119 | cmp rdx, [dir_ent_size] 120 | jne read_dir_ents 121 | 122 | call get_string_length 123 | stackpop 124 | ret 125 | -------------------------------------------------------------------------------- /http.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | ;This writes the text after "Content-Type: " at rsi 20 | detect_content_type: ;rdi - pointer to buffer that contains request, ret - rax: type flag 21 | stackpush 22 | 23 | mov rsi, extension_htm 24 | call string_ends_with 25 | mov r10, CONTENT_TYPE_HTML 26 | cmp rax, 1 27 | je detect_content_type_ret 28 | 29 | mov rsi, extension_html 30 | call string_ends_with 31 | mov r10, CONTENT_TYPE_HTML 32 | cmp rax, 1 33 | je detect_content_type_ret 34 | 35 | mov rsi, extension_css 36 | call string_ends_with 37 | mov r10, CONTENT_TYPE_CSS 38 | cmp rax, 1 39 | je detect_content_type_ret 40 | 41 | mov rsi, extension_javascript 42 | call string_ends_with 43 | mov r10, CONTENT_TYPE_JAVASCRIPT 44 | cmp rax, 1 45 | je detect_content_type_ret 46 | 47 | mov rsi, extension_xhtml 48 | call string_ends_with 49 | mov r10, CONTENT_TYPE_XHTML 50 | cmp rax, 1 51 | je detect_content_type_ret 52 | 53 | mov rsi, extension_xml 54 | call string_ends_with 55 | mov r10, CONTENT_TYPE_XML 56 | cmp rax, 1 57 | je detect_content_type_ret 58 | 59 | mov rsi, extension_gif 60 | call string_ends_with 61 | mov r10, CONTENT_TYPE_GIF 62 | cmp rax, 1 63 | je detect_content_type_ret 64 | 65 | mov rsi, extension_png 66 | call string_ends_with 67 | mov r10, CONTENT_TYPE_PNG 68 | cmp rax, 1 69 | je detect_content_type_ret 70 | 71 | mov rsi, extension_jpeg 72 | call string_ends_with 73 | mov r10, CONTENT_TYPE_JPEG 74 | cmp rax, 1 75 | je detect_content_type_ret 76 | 77 | mov rsi, extension_jpg 78 | call string_ends_with 79 | mov r10, CONTENT_TYPE_JPEG 80 | cmp rax, 1 81 | je detect_content_type_ret 82 | 83 | mov rsi, extension_svg 84 | call string_ends_with 85 | mov r10, CONTENT_TYPE_SVG 86 | cmp rax, 1 87 | je detect_content_type_ret 88 | 89 | mov rsi, extension_txt 90 | call string_ends_with 91 | mov r10, CONTENT_TYPE_TXT 92 | cmp rax, 1 93 | je detect_content_type_ret 94 | 95 | mov r10, CONTENT_TYPE_OCTET_STREAM ; default to octet-stream 96 | detect_content_type_ret: 97 | mov rax, r10 98 | stackpop 99 | ret 100 | 101 | add_content_type_header: ;rdi - pointer to buffer, rsi - type 102 | stackpush 103 | 104 | mov r10, rsi 105 | 106 | mov rsi, content_type 107 | call string_concat 108 | 109 | cmp r10, CONTENT_TYPE_HTML 110 | je add_response_html 111 | cmp r10, CONTENT_TYPE_OCTET_STREAM 112 | je add_response_octet_stream 113 | cmp r10, CONTENT_TYPE_CSS 114 | je add_response_css 115 | cmp r10, CONTENT_TYPE_JAVASCRIPT 116 | je add_response_javascript 117 | cmp r10, CONTENT_TYPE_XHTML 118 | je add_response_xhtml 119 | cmp r10, CONTENT_TYPE_XML 120 | je add_response_xml 121 | cmp r10, CONTENT_TYPE_GIF 122 | je add_response_gif 123 | cmp r10, CONTENT_TYPE_PNG 124 | je add_response_png 125 | cmp r10, CONTENT_TYPE_JPEG 126 | je add_response_jpeg 127 | cmp r10, CONTENT_TYPE_SVG 128 | je add_response_svg 129 | cmp r10, CONTENT_TYPE_TXT 130 | je add_response_txt 131 | 132 | jmp add_response_octet_stream 133 | 134 | add_response_html: 135 | mov rsi, content_type_html 136 | call string_concat 137 | jmp add_response_cont 138 | 139 | add_response_octet_stream: 140 | mov rsi, content_type_octet_stream 141 | call string_concat 142 | jmp add_response_cont 143 | 144 | add_response_css: 145 | mov rsi, content_type_css 146 | call string_concat 147 | jmp add_response_cont 148 | 149 | add_response_javascript: 150 | mov rsi, content_type_javascript 151 | call string_concat 152 | jmp add_response_cont 153 | 154 | add_response_xhtml: 155 | mov rsi, content_type_xhtml 156 | call string_concat 157 | jmp add_response_cont 158 | 159 | add_response_xml: 160 | mov rsi, content_type_xml 161 | call string_concat 162 | jmp add_response_cont 163 | 164 | add_response_gif: 165 | mov rsi, content_type_gif 166 | call string_concat 167 | jmp add_response_cont 168 | 169 | add_response_png: 170 | mov rsi, content_type_png 171 | call string_concat 172 | jmp add_response_cont 173 | 174 | add_response_jpeg: 175 | mov rsi, content_type_jpeg 176 | call string_concat 177 | jmp add_response_cont 178 | 179 | add_response_svg: 180 | mov rsi, content_type_svg 181 | call string_concat 182 | jmp add_response_cont 183 | 184 | add_response_txt: 185 | mov rsi, content_type_txt 186 | call string_concat 187 | jmp add_response_cont 188 | 189 | 190 | add_response_cont: 191 | stackpop 192 | ret 193 | 194 | create_httpError_response: ;rdi - pointer, rsi - error code: 400, 416, 413 195 | stackpush 196 | 197 | cmp rsi, 416 198 | je create_httpError_response_416 199 | cmp rsi, 413 200 | je create_httpError_response_413 201 | 202 | ;garbage/default is 400 203 | mov rsi, http_400 204 | mov rdx, http_400_len 205 | call string_copy 206 | jmp create_httpError_response_cont 207 | 208 | create_httpError_response_416: 209 | mov rsi, http_416 210 | mov rdx, http_416_len 211 | call string_copy 212 | jmp create_httpError_response_cont 213 | 214 | create_httpError_response_413: 215 | mov rsi, http_413 216 | mov rdx, http_413_len 217 | call string_copy 218 | jmp create_httpError_response_cont 219 | 220 | create_httpError_response_cont: 221 | mov rsi, server_header 222 | call string_concat 223 | 224 | mov rsi, connection_header 225 | call string_concat 226 | 227 | mov rsi, crlfx2 228 | call string_concat 229 | 230 | call get_string_length 231 | 232 | stackpop 233 | ret 234 | 235 | 236 | create_http206_response: ;rdi - pointer, rsi - from, rdx - to, r10 - total r9 - type 237 | ; looks like Content-Length: `rdx subtract rsi add 1` 238 | ; Content-Range: bytes rsi-rdx/r10 239 | stackpush 240 | 241 | push rsi 242 | push rdx 243 | 244 | mov rsi, http_206 ; copy first one 245 | mov rdx, http_206_len 246 | call string_copy 247 | 248 | mov rsi, server_header 249 | call string_concat 250 | 251 | mov rsi, connection_header 252 | call string_concat 253 | 254 | mov rsi, range_header 255 | call string_concat 256 | 257 | mov rsi, r9 258 | call add_content_type_header 259 | 260 | mov rsi, content_length 261 | call string_concat 262 | 263 | pop rdx 264 | pop rsi 265 | push rsi 266 | 267 | mov r8, rdx 268 | sub r8, rsi 269 | inc r8 ; inc cause 'to' is zero based 270 | mov rsi, r8 271 | 272 | call string_concat_int 273 | 274 | mov rsi, crlf 275 | call string_concat 276 | 277 | mov rsi, content_range 278 | call string_concat 279 | 280 | pop rsi 281 | call string_concat_int 282 | 283 | mov rsi, char_hyphen 284 | call string_concat 285 | 286 | mov rsi, rdx 287 | call string_concat_int 288 | 289 | mov rsi, char_slash 290 | call string_concat 291 | 292 | mov rsi, r10 ; val 293 | call string_concat_int 294 | 295 | mov rsi, crlfx2 296 | call string_concat 297 | 298 | call get_string_length 299 | jmp create_http206_response_ret 300 | 301 | create_http206_response_fail: 302 | mov rax, 0 303 | stackpop 304 | ret 305 | 306 | create_http206_response_ret: 307 | stackpop 308 | ret 309 | 310 | create_http200_response: ;rdi - pointer to buffer, rsi - type, rdx - length 311 | stackpush 312 | 313 | push rdx ; save length 314 | 315 | mov r10, rsi ;type 316 | 317 | mov rsi, http_200 ;First one we copy 318 | mov rdx, http_200_len 319 | call string_copy 320 | 321 | mov rsi, server_header 322 | call string_concat 323 | 324 | ;mov rsi, connection_header 325 | ;call string_concat 326 | 327 | mov rsi, range_header 328 | call string_concat 329 | 330 | mov rsi, content_length 331 | call string_concat 332 | 333 | pop rsi ; length 334 | call string_concat_int 335 | 336 | mov rsi, crlf 337 | call string_concat 338 | 339 | mov rsi, r10 340 | call add_content_type_header 341 | 342 | mov rsi, crlf 343 | call string_concat 344 | 345 | call get_string_length 346 | 347 | stackpop 348 | ret 349 | 350 | create_http404_response: ;rdi - pointer to buffer 351 | stackpush 352 | 353 | mov rsi, http_404 ;First one we copy 354 | mov rdx, http_404_len 355 | call string_copy 356 | 357 | mov rsi, server_header 358 | call string_concat 359 | 360 | mov rsi, connection_header 361 | call string_concat 362 | 363 | mov rsi, crlf 364 | call string_concat 365 | 366 | mov rsi, http_404_text 367 | call string_concat 368 | 369 | mov rsi, crlf 370 | call string_concat 371 | 372 | call get_string_length 373 | 374 | stackpop 375 | ret 376 | 377 | create_http301_response: ;rdi - pointer to buffer 378 | stackpush 379 | 380 | mov rsi, http_301 ;First one we copy 381 | mov rdx, http_301_len 382 | call string_copy 383 | 384 | mov rsi, server_header 385 | call string_concat 386 | 387 | mov rsi, r10 388 | call add_content_type_header 389 | 390 | mov rsi, connection_header 391 | call string_concat 392 | 393 | mov rsi, location 394 | call string_concat 395 | 396 | ; Remove directory path (web_root) from buffer 397 | mov rsi, [rbp-16] 398 | add rsi, r9 399 | call string_concat 400 | mov rsi, [directory_path] 401 | call string_remove 402 | 403 | mov rsi, char_slash 404 | call string_concat 405 | 406 | mov rsi, crlf 407 | call string_concat 408 | 409 | call get_string_length 410 | 411 | stackpop 412 | ret 413 | 414 | get_request_type: ;rdi - pointer to buffer, ret = rax: request type 415 | stackpush 416 | 417 | cld 418 | mov r10, -1 419 | mov rsi, rdi 420 | find_request_string: 421 | inc r10 422 | lodsb 423 | cmp al, 0x20 424 | jne find_request_string 425 | mov rax, r10 426 | add rax, 0x03 427 | mov [request_offset], rax 428 | 429 | mov rax, REQ_UNK 430 | 431 | check_get: 432 | cmp byte[rdi+0], 0x47 433 | jne check_head 434 | cmp byte[rdi+1], 0x45 435 | jne check_head 436 | cmp byte[rdi+2], 0x54 437 | jne check_head 438 | mov rax, REQ_GET 439 | 440 | check_head: 441 | cmp byte[rdi+0], 0x48 442 | jne request_type_return 443 | cmp byte[rdi+1], 0x45 444 | jne request_type_return 445 | cmp byte[rdi+2], 0x41 446 | jne request_type_return 447 | cmp byte[rdi+3], 0x44 448 | jne request_type_return 449 | mov rax, REQ_HEAD 450 | 451 | request_type_return: 452 | stackpop 453 | ret 454 | -------------------------------------------------------------------------------- /macros.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | ; Simple Macros 20 | %macro stackpush 0 21 | push rdi 22 | push rsi 23 | push rdx 24 | push r10 25 | push r8 26 | push r9 27 | push rbx 28 | push rcx 29 | %endmacro 30 | 31 | %macro stackpop 0 32 | pop rcx 33 | pop rbx 34 | pop r9 35 | pop r8 36 | pop r10 37 | pop rdx 38 | pop rsi 39 | pop rdi 40 | %endmacro 41 | 42 | -------------------------------------------------------------------------------- /main.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | %include "constants.asm" 20 | %include "macros.asm" 21 | 22 | %define ASMTTPD_VERSION "0.4.7" 23 | 24 | %define THREAD_COUNT 10 ; Number of worker threads 25 | 26 | ;Following amd64 syscall standards for internal function calls: rdi rsi rdx r10 r8 r9 27 | 28 | section .data 29 | %include "data.asm" 30 | 31 | section .bss 32 | %include "bss.asm" 33 | 34 | section .text 35 | %include "string.asm" 36 | %include "http.asm" 37 | %include "syscall.asm" 38 | %include "dirent.asm" 39 | ;%include "mutex.asm" 40 | ;%include "debug.asm" 41 | 42 | global _start 43 | 44 | _start: 45 | 46 | mov QWORD [one_constant], 1 47 | 48 | mov rdi, start_text 49 | mov rsi, start_text_len 50 | call print_line 51 | 52 | mov rdi, [rsp] ;Num of args 53 | cmp rdi,3 ;Exit if no argument, should be directory location 54 | jne exit_with_help 55 | 56 | mov rdi, [rsp+16+8]; Port (second) parameter 57 | call string_atoi 58 | xchg al, ah 59 | mov [listen_port], eax 60 | 61 | mov rax, [rsp+16] ;Directory (first) parameter 62 | mov [directory_path], rax 63 | 64 | ; Register signal handlers ( just close all other threads by jumping to SYS_EXIT_GROUP ) 65 | mov r10, 8 ; sizeof(sigset_t) displays 128, but strace shows 8 ... so 8 it is! -_- 66 | xor rdx, rdx 67 | mov QWORD [sa_handler], exit 68 | mov rsi, sigaction 69 | mov rdi, SIGINT 70 | mov rax, SYS_RT_SIGACTION 71 | syscall 72 | mov rdi, SIGTERM 73 | mov rax, SYS_RT_SIGACTION 74 | syscall 75 | mov QWORD [sa_handler], SIGIGN 76 | mov rdi, SIGPIPE 77 | mov rax, SYS_RT_SIGACTION 78 | syscall 79 | 80 | ;Try opening directory 81 | mov rdi, [directory_path] 82 | mov rdx, OPEN_DIRECTORY 83 | call sys_open_directory 84 | 85 | cmp rax, 0 86 | jl exit_with_no_directory_error 87 | 88 | ;Create socket 89 | call sys_create_tcp_socket 90 | cmp rax, 0 91 | jl exit_error 92 | mov [listen_socket], rax 93 | 94 | ;reuseaddr 95 | mov rdi, [listen_socket] 96 | call sys_reuse 97 | 98 | ;Bind to port 99 | call sys_bind_server 100 | cmp rax, 0 101 | jl exit_bind_error 102 | 103 | ;Start listening 104 | call sys_listen 105 | 106 | ;Create threads 107 | mov r10, THREAD_COUNT 108 | 109 | thread_pool_setup: 110 | push r10 111 | 112 | mov rdi, worker_thread 113 | xor rsi, rsi 114 | call sys_clone 115 | 116 | pop r10 117 | dec r10 118 | cmp r10, 0 119 | 120 | jne thread_pool_setup 121 | 122 | main_thread: 123 | 124 | 125 | mov rdi, 10 126 | call sys_sleep 127 | 128 | jmp main_thread 129 | 130 | worker_thread: 131 | 132 | mov rbp, rsp 133 | sub rsp, 16 134 | ;Offsets: 8 - socket fd, 16 - buffer 135 | 136 | mov QWORD [rbp-16], 0 ; Used for pointer to recieve buffer 137 | 138 | mov rdi, THREAD_BUFFER_SIZE+2+URL_LENGTH_LIMIT+DIRECTORY_LENGTH_LIMIT+DIRECTORY_LIST_BUFFER+CUSTOM_CONTENT_BUFFER ; Allow room to append null, and to create path 139 | call sys_mmap_mem 140 | mov QWORD [rbp-16], rax 141 | 142 | worker_thread_start: 143 | 144 | call sys_accept 145 | 146 | mov [rbp-8], rax ; save fd 147 | 148 | mov rdi, rax 149 | call sys_cork ; cork it 150 | 151 | worker_thread_continue: 152 | 153 | ;HTTP Stuff starts here 154 | mov rdi, QWORD [rbp-8] ;fd 155 | mov rsi, [rbp-16] ;buffer 156 | mov rdx, THREAD_BUFFER_SIZE ;size 157 | call sys_recv 158 | 159 | cmp rax, 0 160 | jle worker_thread_close 161 | 162 | push rax ; save original received length 163 | 164 | ;stackpush 165 | ;push rax 166 | ;mov rdi, rsi 167 | ;mov rsi, rax 168 | ;call print_line ; debug 169 | ;pop rax 170 | ;stackpop 171 | 172 | ; add null 173 | mov rdi, [rbp-16] 174 | add rdi, rax 175 | mov BYTE [rdi], 0x00 176 | 177 | ;Make sure its a valid request 178 | mov rdi, [rbp-16] 179 | mov rsi, crlfx2 180 | call string_ends_with 181 | cmp rax, 1 182 | jne worker_thread_400_response 183 | 184 | mov rdi, [rbp-16] 185 | call get_request_type 186 | mov [request_type], rax 187 | cmp BYTE [request_type], REQ_UNK 188 | je worker_thread_400_response 189 | 190 | ;Find request 191 | mov rax, 0x2F ; '/' character 192 | mov rdi, [rbp-16] ;scan buffer 193 | mov rcx, -1 ;Start count 194 | cld ;Increment rdi 195 | repne scasb 196 | jne worker_thread_400_response 197 | mov rax, -2 198 | sub rax, rcx ;Get the length 199 | 200 | mov r8, rax ; start offset for requested file 201 | mov rdi, [rbp-16] 202 | add rdi, r8 203 | mov rax, 0x20 ;'space' character 204 | mov rcx, -1 205 | cld 206 | repne scasb 207 | jne worker_thread_400_response 208 | mov rax, -1 209 | sub rax, rcx 210 | mov r9, rax 211 | add r9, r8 ;end offset 212 | 213 | pop r11 ; restore orig recvd length 214 | mov rdi, [rbp-16] 215 | add rdi, r11 ; end of buffer, lets use it! 216 | mov r12, r11 ; keeping count 217 | 218 | mov rsi, [directory_path] 219 | xor r15, r15 ; Make sure directory path does not exceed DIRECTORY_LENGTH_LIMIT 220 | 221 | worker_thread_append_directory_path: 222 | inc r15 223 | cmp r15, DIRECTORY_LENGTH_LIMIT 224 | je worker_thread_400_response 225 | lodsb 226 | stosb 227 | inc r12 228 | cmp al, 0x00 229 | jne worker_thread_append_directory_path 230 | 231 | dec r12 ; get rid of 0x00 232 | 233 | ;Check if default document needed 234 | cmp r9, [request_offset] ; Offset of document requested 235 | jne no_default_document 236 | mov rsi, default_document 237 | mov rdi, [rbp-16] 238 | add rdi, r12 239 | mov rcx, default_document_len 240 | add r12, rcx 241 | rep movsb 242 | mov r9, r11 ; saving offset into a stack saved register 243 | jmp worker_thread_remove_pre_dir 244 | 245 | no_default_document: 246 | 247 | ; Adds the file to the end of buffer ( where we juts put the document prefix ) 248 | mov rsi, [rbp-16] 249 | add rsi, r8 ; points to beginning of path 250 | mov rdi, [rbp-16] 251 | add rdi, r12 ;go to end of buffer 252 | mov rcx, r9 253 | sub rcx, r8 254 | cmp rcx, URL_LENGTH_LIMIT ; Make sure this does not exceed URL_PATH_LENGTH 255 | jg worker_thread_400_response 256 | add r12, rcx 257 | rep movsb 258 | 259 | dec r12 ; exclude space character 260 | mov rdi, [rbp-16] 261 | add rdi, r12 262 | mov BYTE [rdi], 0x00 ; add null 263 | 264 | mov r9, r11 ; saving offset into a stack saved register 265 | ; [rbp-16] + r9 now holds string for file opening 266 | 267 | worker_thread_remove_pre_dir: 268 | 269 | ;-----Simple request logging 270 | ;mov rdi, msg_request_log 271 | ;mov rsi, msg_request_log_len 272 | ;call sys_write 273 | ;mov rdi, [rbp-16] 274 | ;add rdi, r9 275 | ;call get_string_length 276 | ;mov rsi, rax 277 | ;call print_line 278 | ;-----End Simple logging 279 | mov rdi, [rbp-16] 280 | add rdi, r9 281 | mov rsi, filter_prev_dir ; remove any '../' 282 | call string_remove 283 | cmp rax, 0 284 | jne worker_thread_remove_pre_dir 285 | 286 | 287 | mov rdi, [rbp-16] 288 | add rdi, r9 289 | call detect_content_type 290 | mov r8, rax ;r8: Content Type 291 | 292 | cmp r8, CONTENT_TYPE_OCTET_STREAM 293 | jne worker_thread_response 294 | 295 | worker_thread_test_dir: 296 | mov rdi, [rbp-16] 297 | add rdi, r9 298 | mov rdx, OPEN_RDONLY | OPEN_DIRECTORY 299 | call sys_open_directory 300 | cmp rax, 0 301 | jl worker_thread_response ; TODO error cannot open dir - 404? 302 | 303 | ; Check if request ends in '/' and if not respond 301, which in turn triggers another request with a trailing '/' 304 | push rax 305 | mov rdi, [rbp-16] 306 | add rdi, r9 307 | call get_string_length 308 | add rdi, rax 309 | dec rdi 310 | cmp byte[rdi], 0x2f 311 | jne worker_thread_301_response 312 | pop rax 313 | 314 | mov rbx, THREAD_BUFFER_SIZE+2+URL_LENGTH_LIMIT+DIRECTORY_LENGTH_LIMIT 315 | mov rsi, [rbp-16] 316 | add rsi, rbx 317 | push r9 ; Save pointer to http buffer 318 | mov r9, rsi ; Pointer to dir list buffer, first entry contains bytes read 319 | 320 | mov rdi, rax ; fd 321 | mov rdx, DIRECTORY_LIST_BUFFER 322 | call sys_get_dir_listing 323 | cmp rax, 0 ; rax = bytes read 324 | jl worker_thread_response ; TODO error no bytes read - 404? 325 | 326 | mov [dir_ent_pointer], r9 327 | mov [dir_ent_size], rax 328 | 329 | pop r9 330 | jmp worker_thread_200_response_dir_list 331 | 332 | worker_thread_response: 333 | 334 | ;Try to open requested file 335 | mov rdi, [rbp-16] 336 | add rdi, r9 337 | call sys_open 338 | cmp rax, 0 339 | 340 | jl worker_thread_404_response ;file not found, so 404 341 | ; Done with buffer offsets, put response and data into it starting at beg 342 | mov r10, rax ; r10: file fd 343 | 344 | ;Determine if request requires a 206 response 345 | 346 | mov rdi, r10 ; fd 347 | xor rsi, rsi 348 | mov rdx, LSEEK_END 349 | call sys_lseek 350 | push rax 351 | 352 | ;Basically if "Range:" is in the header 353 | mov rdi, [rbp-16] 354 | mov rsi, header_range_search 355 | call string_contains 356 | 357 | pop rdi 358 | cmp rax, -1 359 | jne worker_thread_206_response 360 | 361 | jmp worker_thread_200_response ;else, we're good to go 362 | 363 | ;---------404 Response Start------------- 364 | worker_thread_404_response: 365 | 366 | mov rdi, [rbp-16] 367 | call create_http404_response 368 | 369 | ;Send response 370 | mov rdi, [rbp-8] 371 | mov rsi, [rbp-16] 372 | mov rdx, rax 373 | call sys_send 374 | 375 | ;and exit 376 | jmp worker_thread_close 377 | ;---------404 Response End-------------- 378 | 379 | ;---------301 Response Start------------- 380 | worker_thread_301_response: 381 | 382 | mov rdi, [rbp-16] 383 | mov r10, CONTENT_TYPE_HTML 384 | call create_http301_response 385 | 386 | ;Send response 387 | mov rdi, [rbp-8] 388 | mov rsi, [rbp-16] 389 | mov rdx, rax 390 | call sys_send 391 | 392 | ;and exit 393 | jmp worker_thread_close 394 | ;---------301 Response End-------------- 395 | 396 | ;---------206 Response Start------------ 397 | worker_thread_206_response: 398 | ; r8: content type , r10: fd, rax: Range: start 399 | 400 | push r10 401 | push r8 402 | 403 | mov r8, rdi ; r8 now size 404 | 405 | ;Seek to beg of file 406 | mov rdi, r10 ; fd 407 | mov rsi, 0 408 | mov rdx, LSEEK_SET 409 | call sys_lseek 410 | 411 | ; find 'bytes=' 412 | mov rdi, [rbp-16] 413 | add rdi, rax 414 | mov rsi, find_bytes_range 415 | call string_contains 416 | cmp rax, -1 417 | je worker_thread_400_response 418 | 419 | add rdi, rax 420 | add rdi, 6 ; go to number 421 | 422 | push rdi ; save beg of first number 423 | 424 | mov rax, 0 425 | create_http206_response_lbeg: 426 | inc rdi 427 | inc rax 428 | cmp rax, 200 ; todo tweak this number 429 | jge worker_thread_close_file 430 | cmp BYTE [rdi], 0x2D ; look for '-' 431 | jne create_http206_response_lbeg 432 | 433 | mov BYTE [rdi], 0x00 ; replace '-' with null 434 | mov rbx, rdi ; save new beg 435 | inc rbx 436 | pop rdi ; restore beg of first number, convert to int 437 | call string_atoi 438 | 439 | mov rdi, rbx ; char after null 440 | mov rbx, rax ; rbx: from byte range 441 | 442 | push rdi ; save beginning of 2nd byte range 443 | 444 | create_http206_response_rbeg: 445 | inc rdi 446 | cmp BYTE [rdi], 0x0a ; look for end of line 447 | jne create_http206_response_rbeg 448 | 449 | dec rdi 450 | mov BYTE [rdi], 0x00; replace end with null 451 | pop rdi ; restore 2nd byte range 452 | 453 | call string_atoi 454 | 455 | mov rcx,rax ; rcx: to byte range, -1 if there is no end 456 | ;byte range: rbx -> rcx(-1 if to end) 457 | 458 | 459 | cmp rcx, -1 460 | jne worker_thread_206_skip_unknown_end 461 | mov rcx, r8 462 | dec rcx ; zero based 463 | worker_thread_206_skip_unknown_end: 464 | 465 | cmp rcx, r8 466 | jge worker_thread_413_response 467 | 468 | cmp rbx, rcx 469 | jg worker_thread_416_response 470 | 471 | pop r9 ; type 472 | mov r10, r8 ;total 473 | mov rdi, [rbp-16] 474 | mov rsi, rbx ;from 475 | mov r13, rsi ; r13: from offset 476 | mov rdx, rcx ;to 477 | mov r12, rcx ; r12: to byte range 478 | call create_http206_response 479 | mov r9, rax ; r9: header size 480 | 481 | sub r12, r13 ; r12: amount to send 482 | inc r12; zero based 483 | 484 | ;Send it 485 | mov rdi, [rbp-8] 486 | mov rsi, [rbp-16] 487 | mov rdx, r9 488 | call sys_send 489 | 490 | pop rdi ; sock fd - stack is empty now 491 | push rdi ; save it so we can close it 492 | 493 | mov rsi, r13 ; file offset ( range 'from' ) 494 | mov rdx, LSEEK_SET 495 | call sys_lseek 496 | 497 | 498 | mov rdx, r12 ;file size to send 499 | mov rsi, rdi 500 | mov rdi, [rbp-8] 501 | call sys_sendfile 502 | 503 | ;stackpush 504 | ;push rax 505 | ;mov rdi, rsi 506 | ;mov rsi, r9 507 | ;call print_line ; debug 508 | ;pop rax 509 | ;stackpop 510 | 511 | pop r10; restore fd for close 512 | jmp worker_thread_close_file 513 | ;---------206 Response End-------------- 514 | 515 | ;------200 Dir List Response Start------ 516 | worker_thread_200_response_dir_list: 517 | mov rdi, [rbp-16] 518 | mov rbx, THREAD_BUFFER_SIZE+2+URL_LENGTH_LIMIT+DIRECTORY_LENGTH_LIMIT+DIRECTORY_LIST_BUFFER 519 | inc rbx ; zero pad start 520 | add rdi, rbx 521 | push rdi ; save start of directory list buffer for later 522 | 523 | call generate_dir_entries ; rax = new length 524 | push rax ; save length of contents for later 525 | 526 | ;Create Response 527 | mov rdi, [rbp-16] 528 | mov rsi, CONTENT_TYPE_HTML ; as we are sending custom HTML, change type 529 | mov rdx, rax ; total file size 530 | call create_http200_response 531 | 532 | mov r8, rax ; header size 533 | 534 | mov rdi, [rbp-8] 535 | mov rsi, [rbp-16] 536 | mov rdx, rax 537 | call sys_send 538 | 539 | ;Send the html formatted directory contents 540 | pop rax ; restore buffer pointer and length 541 | pop rdi 542 | mov rsi, rdi 543 | mov rdi, [rbp-8] 544 | mov rdx, rax 545 | call sys_send 546 | jmp worker_thread_close 547 | ;-------200 Dir List Response End------- 548 | 549 | ;---------200 Response Start------------ 550 | worker_thread_200_response: 551 | 552 | ;rdi - total filesize 553 | push rdi 554 | 555 | ;Seek to beg of file 556 | mov rdi, r10 ; fd 557 | mov rsi, 0 558 | mov rdx, LSEEK_SET 559 | call sys_lseek 560 | 561 | ;Create Response 562 | mov rdi, [rbp-16] 563 | mov rsi, r8 ; type, figured out above 564 | pop rdx ; total file size 565 | push rdx ; save for sendfile 566 | call create_http200_response 567 | 568 | mov r8, rax ; header size 569 | 570 | mov rdi, [rbp-8] 571 | mov rsi, [rbp-16] 572 | mov rdx, rax 573 | call sys_send 574 | 575 | cmp rax, 0 576 | jle worker_thread_close_file 577 | 578 | cmp BYTE [request_type], REQ_HEAD 579 | je worker_thread_close_file 580 | 581 | mov rdi, [rbp-8] 582 | mov rsi, r10 583 | pop rdx 584 | call sys_sendfile 585 | jmp worker_thread_close_file 586 | ;---------200 Response End-------------- 587 | 588 | ;---------400 Response Start------------ 589 | worker_thread_400_response: 590 | mov rdi, [rbp-16] 591 | mov rsi, 400 592 | call create_httpError_response 593 | 594 | mov rdi, [rbp-8] 595 | mov rsi, [rbp-16] 596 | mov rdx, rax 597 | call sys_send 598 | 599 | jmp worker_thread_close 600 | ;---------400 Response End-------------- 601 | 602 | ;---------413 Response Start------------ 603 | worker_thread_413_response: 604 | mov rdi, [rbp-16] 605 | mov rsi, 413 606 | call create_httpError_response 607 | 608 | mov rdi, [rbp-8] 609 | mov rsi, [rbp-16] 610 | mov rdx, rax 611 | call sys_send 612 | 613 | jmp worker_thread_close 614 | ;---------413 Response End-------------- 615 | 616 | ;---------416 Response Start------------ 617 | worker_thread_416_response: 618 | mov rdi, [rbp-16] 619 | mov rsi, 416 620 | call create_httpError_response 621 | 622 | mov rdi, [rbp-8] 623 | mov rsi, [rbp-16] 624 | mov rdx, rax 625 | call sys_send 626 | 627 | jmp worker_thread_close 628 | ;---------416 Response End-------------- 629 | 630 | worker_thread_close_file: 631 | ;Uncork 632 | mov rdi, [rbp-8] 633 | call sys_uncork 634 | 635 | ;Close File 636 | mov rdi, r10 637 | call sys_close 638 | 639 | ;Close Socket 640 | worker_thread_close: 641 | mov rdi, [rbp-8] 642 | call sys_close 643 | 644 | jmp worker_thread_start 645 | 646 | exit_with_no_directory_error: 647 | mov rdi, msg_not_a_directory 648 | mov rsi, msg_not_a_directory_len 649 | call print_line 650 | jmp exit 651 | 652 | exit_with_help: 653 | mov rdi, msg_help 654 | mov rsi, msg_help_len 655 | call print_line 656 | jmp exit 657 | 658 | exit_error: 659 | mov rdi, msg_error 660 | mov rsi, msg_error_len 661 | call print_line 662 | 663 | mov rdi, -1 664 | mov rax, SYS_EXIT_GROUP 665 | syscall 666 | jmp exit 667 | 668 | exit_bind_error: 669 | mov rdi, msg_bind_error 670 | mov rsi, msg_bind_error_len 671 | call print_line 672 | 673 | mov rdi, -1 674 | mov rax, SYS_EXIT_GROUP 675 | syscall 676 | jmp exit 677 | 678 | exit_thread: 679 | 680 | xor rdi, rdi 681 | mov rax, SYS_EXIT 682 | syscall 683 | jmp exit 684 | 685 | exit: 686 | 687 | mov rdi, [listen_socket] 688 | call sys_close 689 | 690 | xor rdi, rdi 691 | mov rax, SYS_EXIT_GROUP 692 | syscall 693 | 694 | -------------------------------------------------------------------------------- /mutex.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | mutex_leave: 20 | stackpush 21 | 22 | mov rax, 1 23 | mov rdi, 0 24 | lock cmpxchg [queue_futex], rdi ; 1 -> 0 case 25 | cmp rax, 1 26 | je mutex_leave_end 27 | 28 | mov QWORD [queue_futex], 0 29 | mov rdi, 1 30 | call sys_futex_wake 31 | 32 | mutex_leave_end: 33 | stackpop 34 | ret 35 | 36 | mutex_enter: 37 | stackpush 38 | 39 | mov rax, 0 40 | mov rdi, 1 41 | lock cmpxchg [queue_futex], rdi 42 | cmp rax, 0 43 | je mutex_enter_end 44 | 45 | mutex_enter_begin: 46 | cmp rax, 2 47 | je mutex_enter_wait 48 | mov rax, 1 49 | mov rdi, 2 50 | lock cmpxchg [queue_futex], rdi 51 | cmp rax, 1 52 | je mutex_enter_wait 53 | ;Both tries ( c == 2 || cmpxchg( 1, 2 ) ) failed 54 | mutex_enter_cont: 55 | mov rax, 0 56 | mov rdi, 2 57 | lock cmpxchg [queue_futex], rdi 58 | cmp rax, 0 59 | jne mutex_enter_begin 60 | jmp mutex_enter_end 61 | 62 | mutex_enter_wait: 63 | mov rdi, 2 64 | call sys_futex_wait 65 | jmp mutex_enter_cont 66 | 67 | mutex_enter_end: 68 | stackpop 69 | ret 70 | -------------------------------------------------------------------------------- /string.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | string_itoa:; rdi - buffer, rsi - int 19 | stackpush 20 | push rcx 21 | push rbx 22 | 23 | xchg rdi, rsi 24 | call get_number_of_digits 25 | xchg rdi, rsi 26 | mov rcx, rax ; 27 | 28 | ;add null 29 | mov al, 0x0 30 | mov [rdi+rcx], al 31 | dec rcx 32 | 33 | mov rax, rsi ; value to print 34 | xor rdx, rdx ; zero other half 35 | mov rbx, 10 36 | 37 | string_itoa_start: 38 | xor rdx, rdx ; zero other half 39 | div rbx ; divide by 10 40 | 41 | add rdx, 0x30 42 | mov [rdi+rcx], dl 43 | dec rcx 44 | cmp rax, 9 45 | ja string_itoa_start 46 | 47 | cmp rcx, 0 48 | jl string_itoa_done 49 | add rax, 0x30 ;last digit 50 | mov [rdi+rcx], al 51 | 52 | string_itoa_done: 53 | pop rbx 54 | pop rcx 55 | stackpop 56 | ret 57 | 58 | string_atoi: ; rdi = string, rax = int 59 | stackpush 60 | 61 | mov r8, 0 ; ;return 62 | 63 | call get_string_length 64 | mov r10, rax ; length 65 | cmp rax, 0 66 | je string_atoi_ret_empty 67 | 68 | mov r9, 1 ; multiplier 69 | 70 | dec r10 71 | string_atoi_loop: 72 | xor rbx, rbx 73 | mov bl, BYTE [rdi+r10] 74 | sub bl, 0x30 ;get byte, subtract to get real from ascii value 75 | mov rax, r9 76 | mul rbx ; multiply value by multiplier 77 | add r8, rax ; add result to running total 78 | dec r10 ; next digit 79 | mov rax, 10 ; multiply r9 ( multiplier ) by 10 80 | mul r9 81 | mov r9, rax 82 | cmp r10, -1 83 | jne string_atoi_loop 84 | jmp string_atoi_ret 85 | 86 | string_atoi_ret_empty: 87 | mov rax, -1 88 | stackpop 89 | ret 90 | 91 | string_atoi_ret: 92 | mov rax, r8 93 | stackpop 94 | ret 95 | 96 | string_copy: ; rdi = dest, rsi = source, rdx = bytes to copy 97 | stackpush 98 | mov rcx, rdx 99 | inc rcx ; to get null 100 | cld 101 | rep movsb 102 | stackpop 103 | ret 104 | 105 | string_concat_int: ;rdi = string being added to, rsi = int to add, ret: new length 106 | stackpush 107 | 108 | call get_string_length 109 | add rdi, rax 110 | call string_itoa 111 | 112 | call get_string_length 113 | 114 | stackpop 115 | ret 116 | 117 | string_concat: ;rdi = string being added to, rsi = string to add, ret: new length 118 | stackpush 119 | 120 | call get_string_length 121 | add rdi, rax ; Go to end of string 122 | mov r10, rax 123 | 124 | ;Get length of source ie. bytes to copy 125 | push rdi 126 | mov rdi, rsi 127 | call get_string_length 128 | inc rax ; null 129 | mov rcx, rax 130 | add r10, rax 131 | pop rdi 132 | 133 | rep movsb 134 | 135 | mov rax, r10 136 | 137 | stackpop 138 | ret 139 | 140 | string_contains: ;rdi = haystack, rsi = needle, ret = rax: location of string, else -1 141 | stackpush 142 | 143 | xor r10, r10 ; total length from beginning 144 | xor r8, r8 ; count from offset 145 | 146 | string_contains_start: 147 | mov dl, BYTE [rdi] 148 | cmp dl, 0x00 149 | je string_contains_ret_no 150 | cmp dl, BYTE [rsi] 151 | je string_contains_check 152 | inc rdi 153 | inc r10 ; count from base ( total will be r10 + r8 ) 154 | jmp string_contains_start 155 | 156 | string_contains_check: 157 | inc r8 ; already checked at pos 0 158 | cmp BYTE [rsi+r8], 0x00 159 | je string_contains_ret_ok 160 | mov dl, [rdi+r8] 161 | cmp dl ,0x00 162 | je string_contains_ret_no 163 | cmp dl, [rsi+r8] 164 | je string_contains_check 165 | 166 | inc rdi 167 | inc r10 168 | xor r8, r8 169 | jmp string_contains_start 170 | 171 | string_contains_ret_ok: 172 | mov rax, r10 173 | jmp string_contains_ret 174 | 175 | string_contains_ret_no: 176 | mov rax, -1 177 | 178 | string_contains_ret: 179 | stackpop 180 | ret 181 | 182 | 183 | ;Removes first instance of string 184 | string_remove: ;rdi = source, rsi = string to remove, ret = 1 for removed, 0 for not found 185 | stackpush 186 | 187 | mov r9, 0 ; return flag 188 | 189 | call get_string_length 190 | mov r8, rax ; r8: source length 191 | cmp r8, 0 192 | mov rax, 0 193 | jle string_remove_ret ; source string empty? 194 | 195 | push rdi 196 | mov rdi, rsi 197 | call get_string_length 198 | mov r10, rax ; r10: string to remove length 199 | pop rdi 200 | cmp r10, 0 201 | mov rax, 0 202 | jle string_remove_ret ; string to remove is blank? 203 | 204 | string_remove_start: 205 | 206 | call string_contains 207 | 208 | cmp rax,-1 209 | je string_remove_ret 210 | 211 | ;Shift source string over 212 | add rdi, rax 213 | mov rsi, rdi 214 | add rsi, r10 ; copying to itself sans found string 215 | 216 | cld 217 | string_remove_do_copy: 218 | lodsb 219 | stosb 220 | cmp al, 0x00 221 | jne string_remove_do_copy 222 | 223 | mov r9, 1 224 | 225 | string_remove_ret: 226 | mov rax, r9 227 | stackpop 228 | ret 229 | 230 | string_ends_with:;rdi = haystack, rsi = needle, ret = rax: 0 false, 1 true 231 | stackpush 232 | 233 | ;Get length of haystack, store in r8 234 | call get_string_length 235 | mov r8, rax 236 | 237 | ;Get length of needle, store in r10 238 | push rdi 239 | mov rdi, rsi 240 | call get_string_length 241 | mov r10, rax 242 | pop rdi 243 | 244 | add rdi, r8 245 | add rsi, r10 246 | 247 | xor rax, rax 248 | xor rdx, rdx 249 | 250 | string_ends_with_loop: 251 | ;Start from end, dec r10 till 0 252 | mov dl, BYTE [rdi] 253 | cmp dl, BYTE [rsi] 254 | jne string_ends_with_ret 255 | dec rdi 256 | dec rsi 257 | dec r10 258 | cmp r10, 0 259 | jne string_ends_with_loop 260 | mov rax, 1 261 | 262 | string_ends_with_ret: 263 | stackpop 264 | ret 265 | 266 | string_char_at_reverse: ;rdi = haystack, rsi = count from end, rdx = character(not pointer), ret = rax: 0 false, 1 true 267 | stackpush 268 | inc rsi ; include null 269 | call get_string_length 270 | add rdi, rax ; go to end 271 | sub rdi, rsi ; subtract count 272 | mov rax, 0 ; set return to false 273 | cmp dl, BYTE [rdi] ; compare rdx(dl) 274 | jne string_char_at_reverse_ret 275 | mov rax, 1 276 | string_char_at_reverse_ret: 277 | stackpop 278 | ret 279 | 280 | print_line: ; rdi = pointer, rsi = length 281 | stackpush 282 | call sys_write 283 | mov rdi, new_line 284 | mov rsi, 1 285 | call sys_write 286 | stackpop 287 | ret 288 | 289 | get_string_length: ; rdi = pointer, ret rax 290 | stackpush 291 | cld 292 | mov r10, -1 293 | mov rsi, rdi 294 | get_string_length_start: 295 | inc r10 296 | lodsb 297 | cmp al, 0x00 298 | jne get_string_length_start 299 | mov rax, r10 300 | stackpop 301 | ret 302 | 303 | get_number_of_digits: ; of rdi, ret rax 304 | stackpush 305 | push rbx 306 | push rcx 307 | 308 | mov rax, rdi 309 | mov rbx, 10 310 | mov rcx, 1 ;count 311 | gnod_cont: 312 | cmp rax, 10 313 | jb gnod_ret 314 | 315 | xor rdx,rdx 316 | div rbx 317 | 318 | inc rcx 319 | jmp gnod_cont 320 | gnod_ret: 321 | mov rax, rcx 322 | 323 | pop rcx 324 | pop rbx 325 | stackpop 326 | ret 327 | 328 | -------------------------------------------------------------------------------- /syscall.asm: -------------------------------------------------------------------------------- 1 | ;asmttpd - Web server for Linux written in amd64 assembly. 2 | ;Copyright (C) 2014 nemasu 3 | ; 4 | ;This file is part of asmttpd. 5 | ; 6 | ;asmttpd is free software: you can redistribute it and/or modify 7 | ;it under the terms of the GNU General Public License as published by 8 | ;the Free Software Foundation, either version 2 of the License, or 9 | ;(at your option) any later version. 10 | ; 11 | ;asmttpd is distributed in the hope that it will be useful, 12 | ;but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;GNU General Public License for more details. 15 | ; 16 | ;You should have received a copy of the GNU General Public License 17 | ;along with asmttpd. If not, see . 18 | 19 | section .text 20 | 21 | sys_cork:;rdi - socket 22 | stackpush 23 | mov r10, one_constant ;pointer to 1 24 | mov r8, 8 ;sizeof int 25 | mov rsi, LEVEL_IPPROTO_TCP 26 | mov rdx, SOCKOPT_TCP_CORK 27 | mov rax, SYS_SETSOCKOPT 28 | syscall 29 | stackpop 30 | ret 31 | 32 | sys_uncork;rdi - socket 33 | stackpush 34 | mov r10, one_constant ;pointer to 1 35 | mov r8, 8 ;sizeof int 36 | mov rsi, LEVEL_IPPROTO_TCP 37 | mov rdx, SOCKOPT_TCP_CORK 38 | mov rax, SYS_SETSOCKOPT 39 | syscall 40 | stackpop 41 | ret 42 | 43 | sys_reuse;rdi - socket 44 | stackpush 45 | mov r8, 8 ;sizeof int 46 | mov r10, one_constant ;pointer to 1 47 | mov rsi, LEVEL_SOL_TCP 48 | mov rdx, SOCKOPT_TCP_REUSEADDR 49 | mov rax, SYS_SETSOCKOPT 50 | syscall 51 | stackpop 52 | ret 53 | 54 | sys_sendfile: ;rdi - outfd, rsi - infd, rdx - file size 55 | stackpush 56 | mov r10, rdx 57 | xor rdx, rdx 58 | mov rax, SYS_SENDFILE 59 | syscall 60 | stackpop 61 | ret 62 | 63 | sys_lseek:; rdi - fd, rsi - offset, rdx - flag 64 | stackpush 65 | mov rax, SYS_LSEEK 66 | syscall 67 | stackpop 68 | ret 69 | 70 | sys_open: 71 | stackpush 72 | mov rsi, OPEN_RDONLY ;flags 73 | mov rax, SYS_OPEN 74 | syscall 75 | stackpop 76 | ret 77 | 78 | sys_close: 79 | stackpush 80 | mov rax, SYS_CLOSE 81 | syscall 82 | stackpop 83 | ret 84 | 85 | sys_send: 86 | stackpush 87 | xor r10, r10 88 | xor r8, r8 89 | xor r9, r9 90 | mov rax, SYS_SENDTO 91 | syscall 92 | stackpop 93 | ret 94 | 95 | sys_recv: 96 | stackpush 97 | xor r10, r10 ; flags 98 | xor r8, r8 99 | xor r9, r9 100 | mov rax, SYS_RECVFROM 101 | syscall 102 | stackpop 103 | ret 104 | 105 | sys_accept: 106 | stackpush 107 | mov rdi, [listen_socket] 108 | xor rsi, rsi 109 | xor rdx, rdx 110 | mov rax, SYS_ACCEPT 111 | syscall 112 | stackpop 113 | ret 114 | 115 | sys_listen: 116 | stackpush 117 | mov rdi, [listen_socket] 118 | mov rsi, 100000000;backlog 119 | mov rax, SYS_LISTEN 120 | syscall 121 | stackpop 122 | ret 123 | 124 | sys_bind_server: 125 | stackpush 126 | 127 | mov rsi, [listen_port] 128 | mov [sa + sin_port], rsi 129 | 130 | mov rdi, [listen_socket] 131 | mov rsi, sa 132 | mov rdx, 16 133 | mov rax, SYS_BIND 134 | syscall 135 | stackpop 136 | ret 137 | 138 | sys_create_tcp_socket: 139 | stackpush 140 | mov rdi, AF_INET 141 | mov rsi, SOCK_STREAM 142 | mov rdx, PROTO_TCP 143 | mov rax, SYS_SOCKET 144 | syscall 145 | stackpop 146 | ret 147 | 148 | sys_open_directory:;rdi = path, rax = ret ( fd ), rdx = flags 149 | stackpush 150 | mov rsi, rdx ;flags 151 | mov rax, SYS_OPEN 152 | syscall 153 | stackpop 154 | ret 155 | 156 | sys_get_dir_listing:;rdi = fd, rsi = buffer, rdx = buffer_size 157 | stackpush 158 | mov rax, SYS_GETDENTS 159 | syscall 160 | stackpop 161 | ret 162 | 163 | sys_write: 164 | stackpush 165 | mov rdx, rsi ;length 166 | mov rsi, rdi ;buffer 167 | mov rdi, FD_STDOUT 168 | mov rax, SYS_WRITE 169 | syscall 170 | stackpop 171 | ret 172 | 173 | sys_nanosleep: 174 | stackpush 175 | mov qword [tv_usec], rdi 176 | mov qword [tv_sec],0 177 | xor rsi, rsi 178 | mov rdi, timeval 179 | mov rax, SYS_NANOSLEEP 180 | syscall 181 | stackpop 182 | ret 183 | 184 | sys_sleep: 185 | stackpush 186 | mov qword [tv_sec], rdi 187 | mov qword [tv_usec],0 188 | xor rsi, rsi 189 | mov rdi, timeval 190 | mov rax, SYS_NANOSLEEP 191 | syscall 192 | stackpop 193 | ret 194 | 195 | sys_mmap_mem: 196 | stackpush 197 | mov rsi, rdi ;Size 198 | xor rdi, rdi ;Preferred address (don't care) 199 | mov rdx, MMAP_PROT_READ | MMAP_PROT_WRITE ;Protection Flags 200 | mov r10, MMAP_MAP_PRIVATE | MMAP_MAP_ANON ;Flags 201 | xor r8, r8 202 | dec r8 ;-1 fd because of MMAP_MAP_ANON 203 | xor r9, r9 ;Offset 204 | mov rax, SYS_MMAP 205 | syscall 206 | stackpop 207 | ret 208 | 209 | sys_mmap_stack: 210 | stackpush 211 | mov rsi, rdi ;Size 212 | xor rdi, rdi ;Preferred address (don't care) 213 | mov rdx, MMAP_PROT_READ | MMAP_PROT_WRITE ;Protection Flags 214 | mov r10, MMAP_MAP_PRIVATE | MMAP_MAP_ANON | MMAP_MAP_GROWSDOWN ;Flags 215 | xor r8, r8 216 | dec r8 ;-1 fd because of MMAP_MAP_ANON 217 | xor r9, r9 ;Offset 218 | mov rax, SYS_MMAP 219 | syscall 220 | stackpop 221 | ret 222 | 223 | sys_clone: 224 | mov r14, rdi ;Address of the thread_func 225 | mov r15, rsi ;Thread Param 226 | mov rdi, THREAD_STACK_SIZE 227 | call sys_mmap_stack 228 | lea rsi, [rax + THREAD_STACK_SIZE] ;Set newly allocated memory 229 | mov rdi, CLONE_FILES | CLONE_VM | CLONE_FS | CLONE_THREAD | CLONE_SIGHAND | SIGCHILD ;Flags 230 | xor r10, r10 ;parent_tid 231 | xor r8, r8 ;child_tid 232 | xor r9, r9 ;regs 233 | mov rax, SYS_CLONE 234 | syscall 235 | cmp rax, 0 ;If ret is not 0, then it's the ID of the new thread 236 | jnz parent 237 | push r14 ;Else, set new return address 238 | mov rdi, r15 ;and set param 239 | ret ;Return to thread_proc 240 | parent: 241 | ret 242 | 243 | -------------------------------------------------------------------------------- /web_root/index.html: -------------------------------------------------------------------------------- 1 | hi

hello world

--------------------------------------------------------------------------------