Commit graph

15 commits

Author SHA1 Message Date
Laslo Hunhold
0823ba4c3e
Add logmsg() and refactor connection handling
Also use compound literals for immediate pointers we don't use later
(same as with setsockopt() in 32223c96bd).

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-29 13:02:51 +02:00
Laslo Hunhold
a36b901d40
Add http_send_body() and data_send_error() and refactor
This turns the data-functions into the only functions "allowed"
to send body-data (called with http_send_body()). The previous (hacky)
approach of doing this in http_send_header() is not only out of place,
it's an easy source of bugs given, for instance, the sending of body
data is not expected with HEAD-requests.

Given html_escape() is now only used in data.c, we move it there from
util.c and make it a static method again.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-29 00:49:16 +02:00
Laslo Hunhold
c0909c70e4
Improve http_prepare_response()'s error semantics
I don't like the juggling with status-values in serve. It makes
sense for http_recv_header() and http_parse_header(), because we
don't have a response-struct yet that we can "fill". We could pass
it to them, but that would make the usage a bit messy.

However, in http_prepare_response(), we are already entrusted with
a pointer to a response-struct, and just failing here (by returning
an error value) leaves the response-struct in an invalid state. Instead,
we make it a void function and reflect the status using the status field
in the passed response struct.

This way, there is no case where the response struct is in an
invalid state after calling a http_prepare_*()-method.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-28 22:52:04 +02:00
Laslo Hunhold
123f168a3b
Replace http_send_status() with http_prepare_error_response()
This approach fits better in line of first initializing the response
struct and then sending the header with http_send_header() later.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-28 22:34:46 +02:00
Laslo Hunhold
50c85ec642
Rename "target" to "URI" where appropriate
Of course URIs point at "targets", but the URIs themselves should
be called what they are, not only in the interest of clarity in terms
of nomenclature.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-22 23:38:38 +02:00
Laslo Hunhold
68be64e2c1
Remove unused field in the request-struct
Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-22 23:31:42 +02:00
Laslo Hunhold
58d0f44e03
Refactor http_send_response() into http_prepare_response()
The function http_send_response() did too much. It not only took
the request fields and built them together into a response, it
delegated too little and many functions were "hacked" into it, for
instance shady directory-changes for vhosts and hand-construction
of response structs.

The preparations for a rework were already made in previous commits,
including a tighter focus on the response-struct itself. Instead of
doing everything locally in the http_send_response() function, the
new http_prepare_response() only really takes the request-struct and
builds a response-struct. The response-struct is expanded such that
it's possible to do the data-sending simply with the response-struct
itself and not any other magic parameters that just drop out of the
function.

Another matter are the http_send_status()-calls. Because the
aforementioned function is so central, this refactoring has included
many areas. Instead of calling http_send_status() in every error-case,
which makes little sense now given we first delegate everything through
a response struct, errors are just sent as a return value and caught
centrally (in serve() in main.c), which centralizes the error handling
a bit.

It might look a bit strange now and it might not be clear in which
direction this is going, but subsequent commits will hopefully give
clarity in this regard.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-22 23:20:00 +02:00
Laslo Hunhold
a5163d0813
Split up http_get_request()
The function has become too long and basically did two things: Receiving
the header and parsing it. To better reflect this, we split it up into
the two functions http_recv_header() and http_parse_header(). This way,
we also obtain a better separation of concerns and can further reduce
the scope of each parameter-list.

http_recv_header() has been written in such a way that it can be
reentered and fill up the header-buffer bit by bit using a pointer to
an offset value.

The error handling was improved by only returning the immediate error
status codes and letting the caller do the error-handling with
http_send_status().

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-22 11:05:20 +02:00
Laslo Hunhold
c1b242e405
Add connection struct
This struct contains the request and response structs, represents a state
and has some utility-buffers.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-22 09:24:57 +02:00
Laslo Hunhold
6d2fe7f29e
Move infd and header into request-struct
This compacts the connection state into one struct.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-21 19:38:29 +02:00
Laslo Hunhold
65600ffe7a
Reduce global state by localizing the server-struct
The server-struct variable s was global, which made it readable and
modifiable from any point in the code. Making it a local variable in
main() instead and passing it as a pointer to constant memory to each
function needing it makes much more sense and allows the compiler to
warn us if we do try to modify it, which it wouldn't have before.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-17 11:37:25 +02:00
Laslo Hunhold
d105c28aad
Ensure const-correctness where possible and refactor parse_range()
I know that the effect of 'const' on compiler optimizations is smaller
than many believe, but it provides a good insight to the caller which
parameters are not modified and simplifies parallelization, in case
that is desired at a later point.

Throughout processing, the big structs mostly remained unmodified, with
the exception of parse_range(), which added a null-byte in the "Range"-
header to simplify its parsing. This commit refactors parse_range()
such that it won't modify this string anymore.

Additionally, the parser was made even stricter: Usually, strtoll()
(which is wrapped by strtonum()) allows whitespace and plus and minus
signs before the number, which is not part of the specification. The
stricter parser also better differentiates now between invalid requests
and range-lists. In that context, the switch in http_send_response()
was replaced for better readability.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-05 18:28:21 +02:00
Laslo Hunhold
90d5179ea0
Rename REQ_MOD to REQ_IF_MODIFIED_SINCE
The named constants for header fields of the response struct all
pretty much matched the actual header name, which I think improves
readability for everyone familiar with the HTTP-spec.

The request header fields named constants followed the rule, except
the "If-Modified-Since"-header, which is addressed in this commit.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-05 15:46:03 +02:00
Laslo Hunhold
c51b31d7ac
Refactor response-generation
I wasn't happy with how responses were generated. HTTP-headers were
handled by hand and it was duplicated in multiple parts of the code.
Due to the duplication, some functions like timestamp() had really
ugly semantics.

The HTTP requests are parsed much better: We have an enum of fields
we care about that are automatically read into our request struct. This
commit adapts this idea to the response: We have an enum of fields
we might put into our response, and a response-struct holds the
content of these fields. A function http_send_header() automatically
sends a header based on the entries in response. In case we don't
use a field, we just leave the field in the response-struct empty.

With this commit, some logical changes came with it:

  - timestamp() now has a sane signature, TIMESTAMP_LEN is no more and
    it can now return proper errors and is also reentrant by using
    gmtime_r() instead of gmtime()
  - No more use of a static timestamp-array, making all the methods
    also reentrant
  - Better internal-error-reporting: Because the fields are filled
    before and not during sending the response-headers, we can better
    report any internal errors as status 500 instead of sending a
    partial non-500-header and then dying.

These improved data structures make it easier to read and hack the code
and implement new features, if desired.

Signed-off-by: Laslo Hunhold <dev@frign.de>
2020-08-05 13:41:44 +02:00
Laslo Hunhold
ccdb51b96d Refactor the single source file into multiple modules
And many other things, too many to list here. For example, it now
properly logs uds instead of erroring out.
Separating concerns in many places definitely improves the readability.
2018-02-04 21:27:33 +01:00