1 # write-buffered: like 'write', but for a buffered-file 2 3 == code 4 # instruction effective address register displacement immediate 5 # . op subop mod rm32 base index scale r32 6 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes 7 8 write-buffered: # f: (addr buffered-file), msg: (addr array byte) 9 # pseudocode: 10 # in = msg->data 11 # inend = &msg->data[msg->size] 12 # while (in < inend) 13 # if f->write >= f->size 14 # flush(f) 15 # clear-stream(f) 16 # c = *in 17 # f->data[f->write] = c 18 # ++f->write 19 # ++in 20 # 21 # registers: 22 # in: esi 23 # inend: ecx 24 # f: edi 25 # f->size: edx 26 # f->write: ebx (cached; need to keep in sync) 27 # c: eax 28 # 29 # . prologue 30 55/push-ebp 31 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 32 # . save registers 33 50/push-eax 34 51/push-ecx 35 52/push-edx 36 53/push-ebx 37 56/push-esi 38 57/push-edi 39 # eax = msg 40 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax 41 # var in/esi: (addr byte) = msg->data 42 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 6/r32/esi 4/disp8 . # copy eax+4 to esi 43 # var inend/ecx: (addr byte) = &msg->data[msg->size] 44 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 45 8d/copy-address 0/mod/indirect 4/rm32/sib 6/base/esi 1/index/ecx . 1/r32/ecx . . # copy esi+ecx to ecx 46 # edi = f 47 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi 48 # edx = f->size 49 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 0xc/disp8 . # copy *(edi+12) to edx 50 # ebx = f->write 51 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy *(edi+4) to ebx 52 $write-buffered:loop: 53 # if (in >= inend) break 54 39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi with ecx 55 73/jump-if-addr>= $write-buffered:loop-end/disp8 56 # if (f->write >= f->size) flush and clear f's stream 57 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx 58 7c/jump-if-< $write-buffered:to-stream/disp8 59 # . persist f->write 60 89/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy ebx to *(edi+4) 61 # . flush(f) 62 # . . push args 63 57/push-edi 64 # . . call 65 e8/call flush/disp32 66 # . . discard args 67 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 68 # . clear-stream(stream = f+4) 69 # . . push args 70 8d/copy-address 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy edi+4 to eax 71 50/push-eax 72 # . . call 73 e8/call clear-stream/disp32 74 # . . discard args 75 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 76 # . f->write must now be 0; update its cache at ebx 77 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 78 $write-buffered:to-stream: 79 # write to stream 80 # f->data[f->write] = *in 81 # . AL = *in 82 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 83 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL 84 # . f->data[f->write] = AL 85 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 3/index/ebx . 0/r32/AL 0x10/disp8 . # copy AL to *(edi+ebx+16) 86 # ++f->write 87 43/increment-ebx 88 # ++in 89 46/increment-esi 90 eb/jump $write-buffered:loop/disp8 91 $write-buffered:loop-end: 92 # persist necessary variables from registers 93 89/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy ebx to *(edi+4) 94 $write-buffered:end: 95 # . restore registers 96 5f/pop-to-edi 97 5e/pop-to-esi 98 5b/pop-to-ebx 99 5a/pop-to-edx 100 59/pop-to-ecx 101 58/pop-to-eax 102 # . epilogue 103 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 104 5d/pop-to-ebp 105 c3/return 106 107 test-write-buffered: 108 # - check that write-buffered writes to the file 109 # setup 110 # . clear-stream(_test-stream) 111 # . . push args 112 68/push _test-stream/imm32 113 # . . call 114 e8/call clear-stream/disp32 115 # . . discard args 116 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 117 # . clear-stream($_test-buffered-file->buffer) 118 # . . push args 119 68/push $_test-buffered-file->buffer/imm32 120 # . . call 121 e8/call clear-stream/disp32 122 # . . discard args 123 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 124 # write-buffered(_test-buffered-file, "Abc") 125 # . . push args 126 68/push "Abc"/imm32 127 68/push _test-buffered-file/imm32 128 # . . call 129 e8/call write-buffered/disp32 130 # . . discard args 131 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 132 # flush(_test-buffered-file) 133 # . . push args 134 68/push _test-buffered-file/############################################################# ## This config file can live in the following locations: ## ## ## ## ./ ## ## /usr/local/getwtxt/ ## ## /etc/ ## ## /usr/local/etc/ ## ## ## ## The first location found wins. The default filename ## ## is getwtxt.yml. This can be configured via command ## ## line flags: ## ## ## ## For "myconfig.json" ## ## ./getwtxt -config myconfig -type json ## ## ## ############################################################# ############################################################# ## Changing the following options requires a restart. ## ############################################################# # Set to true if getwtxt will be behind a reverse # proxy server, such as Caddy or nginx BehindProxy: true # This is the port that getwtxt will bind to. # If BehindProxy is false, you should probably # set this to 80 or 443 ListenPort: 9001 # Determines whether we're using SSL/TLS. If so, # you should set the Cert and Key files. # Don't use TLS if you're setting up getwtxt # behind a reverse proxy - just let the proxy # handle the connection. UseTLS: false TLSCert: "/etc/ssl/getwtxt.pem" TLSKey: "/etc/ssl/private/getwtxt.pem" # The type of database you want to use. Currently, # the following are supported: # leveldb (default) # sqlite DatabaseType: "leveldb" # The location of the database structure. Can be # a relative or absolute path. DatabasePath: "getwtxt.db" # The path to the assets directory, which contains: # style.css # tmpl/index.html AssetsDirectory: "assets" ############################################################# ## The following options may be changed at any time. ## ## getwtxt will automatically reload the config when ## ## changes are detected. ## ############################################################# # If true, getwtxt will send all log messages, including # requests, to stdout. It will ignore any set log file. # Useful for debugging, but you probably want to keep # logs. StdoutLogging: false # Log files getwtxt will use. Requests will be logged # to RequestLog, while everything else will go into # MessageLog. These can be relative or absolute paths. MessageLog: "logs/message.log" RequestLog: "logs/request.log" # This is the interval between data pushes from the # in-memory cache to the on-disk database. DatabasePushInterval: "5m" # The time getwtxt will wait between attempts to scrape # users' statuses from their twtxt.txt files StatusFetchInterval: "1h" # The following options pertain to your particular instance. # They are used in the default page shown when you visit # getwtxt in a web browser. Instance: # The name of your instance. SiteName: "getwtxt" # Your instance's web address. URL: "https://twtxt.example.com" # Your name. OwnerName: "Anonymous