Commit 4ac688e5 authored by Sergey Lyubka's avatar Sergey Lyubka Committed by rojer

Make mg_http_check_digest_auth() public

PUBLISHED_FROM=f00b94cabc2a89d27d5bc78d68d67db0930811b4
parent 5d0a5cfe
......@@ -104,6 +104,10 @@
"type": "markdown",
"name": "mg_file_upload_handler.md"
},
{
"type": "markdown",
"name": "mg_http_check_digest_auth.md"
},
{
"type": "markdown",
"name": "mg_fu_fname_fn.md"
......
---
title: "mg_http_check_digest_auth()"
decl_name: "mg_http_check_digest_auth"
symbol_kind: "func"
signature: |
int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
FILE *fp);
---
Authenticate HTTP request against opened passwords file.
Returns 1 if authenticated, 0 otherwise.
=== CoAP
CoAP message format:
```
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
| Options (if any) ... |1 1 1 1 1 1 1 1| Payload (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
```
==== struct mg_coap_option
[source,c]
----
struct mg_coap_option {
struct mg_coap_option *next;
uint32_t number;
struct mg_str value;
};
----
CoAP options.
Use mg_coap_add_option and mg_coap_free_options
for creation and destruction.
==== struct mg_coap_message
[source,c]
----
struct mg_coap_message {
uint32_t flags;
uint8_t msg_type;
uint8_t code_class;
uint8_t code_detail;
uint16_t msg_id;
struct mg_str token;
struct mg_coap_option *options;
struct mg_str payload;
struct mg_coap_option *optiomg_tail;
};
----
CoAP message. See RFC 7252 for details.
==== mg_set_protocol_coap()
[source,c]
----
int mg_set_protocol_coap(struct mg_connection *nc);
----
Set CoAP protocol handler - trigger CoAP specific events
==== mg_coap_add_option()
[source,c]
----
struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
uint32_t number, char *value,
size_t len);
----
Add new option to mg_coap_message structure.
Returns pointer to the newly created option.
==== mg_coap_free_options()
[source,c]
----
void mg_coap_free_options(struct mg_coap_message *cm);
----
Free the memory allocated for options,
if cm paramater doesn't contain any option does nothing.
==== mg_coap_send_message()
[source,c]
----
uint32_t mg_coap_send_message(struct mg_connection *nc,
struct mg_coap_message *cm);
----
Compose CoAP message from `mg_coap_message`
and send it into `nc` connection.
Return 0 on success. On error, it is a bitmask:
- `#define MG_COAP_ERROR 0x10000`
- `#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)`
- `#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)`
- `#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)`
- `#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)`
==== mg_coap_send_ack()
[source,c]
----
uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);
----
Compose CoAP acknowledgement from `mg_coap_message`
and send it into `nc` connection.
Return value: see `mg_coap_send_message()`
==== mg_coap_parse()
[source,c]
----
uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);
----
Parse COAP message and fills mg_coap_message and returns cm->flags.
This is a helper function.
NOTE: usually CoAP work over UDP, so lack of data means format error,
but in theory it is possible to use CoAP over TCP (according to RFC)
The caller have to check results and treat COAP_NOT_ENOUGH_DATA according to
underlying protocol:
- in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,
- in case of TCP client can try to receive more data
Return value: see `mg_coap_send_message()`
==== mg_coap_compose()
[source,c]
----
uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
----
Composes CoAP message from mg_coap_message structure.
This is a helper function.
Return value: see `mg_coap_send_message()`
Local tweaks, applied before any of Mongoose's own headers.
=== DNS server
Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`.
==== mg_dns_create_reply()
[source,c]
----
struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
struct mg_dns_message *msg);
----
Create a DNS reply.
The reply will be based on an existing query message `msg`.
The query body will be appended to the output buffer.
"reply + recursion allowed" will be added to the message flags and
message's num_answers will be set to 0.
Answer records can be appended with `mg_dns_send_reply` or by lower
level function defined in the DNS API.
In order to send the reply use `mg_dns_send_reply`.
It's possible to use a connection's send buffer as reply buffers,
and it will work for both UDP and TCP connections.
Example:
```c
reply = mg_dns_create_reply(&nc->send_mbuf, msg);
for (i = 0; i < msg->num_questions; i++) {
rr = &msg->questions[i];
if (rr->rtype == MG_DNS_A_RECORD) {
mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4);
}
}
mg_dns_send_reply(nc, &reply);
```
==== mg_dns_reply_record()
[source,c]
----
int mg_dns_reply_record(struct mg_dns_reply *reply,
struct mg_dns_resource_record *question,
const char *name, int rtype, int ttl, const void *rdata,
size_t rdata_len);
----
Append a DNS reply record to the IO buffer and to the DNS message.
The message num_answers field will be incremented. It's caller's duty
to ensure num_answers is propertly initialized.
Returns -1 on error.
==== mg_dns_send_reply()
[source,c]
----
void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);
----
Send a DNS reply through a connection.
The DNS data is stored in an IO buffer pointed by reply structure in `r`.
This function mutates the content of that buffer in order to ensure that
the DNS header reflects size and flags of the mssage, that might have been
updated either with `mg_dns_reply_record` or by direct manipulation of
`r->message`.
Once sent, the IO buffer will be trimmed unless the reply IO buffer
is the connection's send buffer and the connection is not in UDP mode.
=== DNS
==== struct mg_dns_resource_record
[source,c]
----
struct mg_dns_resource_record {
struct mg_str name; /* buffer with compressed name */
int rtype;
int rclass;
int ttl;
enum mg_dns_resource_record_kind kind;
struct mg_str rdata; /* protocol data (can be a compressed name) */
};
----
DNS resource record.
==== struct mg_dns_message
[source,c]
----
struct mg_dns_message {
struct mg_str pkt; /* packet body */
uint16_t flags;
uint16_t transaction_id;
int num_questions;
int num_answers;
struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
};
----
DNS message (request and response).
==== mg_dns_parse_record_data()
[source,c]
----
int mg_dns_parse_record_data(struct mg_dns_message *msg,
struct mg_dns_resource_record *rr, void *data,
size_t data_len);
----
Parse the record data from a DNS resource record.
- A: struct in_addr *ina
- AAAA: struct in6_addr *ina
- CNAME: char buffer
Returns -1 on error.
TODO(mkm): MX
==== mg_send_dns_query()
[source,c]
----
void mg_send_dns_query(struct mg_connection *nc, const char *name,
int query_type);
----
Send a DNS query to the remote end.
==== mg_dns_insert_header()
[source,c]
----
int mg_dns_insert_header(struct mbuf *io, size_t pos,
struct mg_dns_message *msg);
----
Insert a DNS header to an IO buffer.
Return number of bytes inserted.
==== mg_dns_copy_questions()
[source,c]
----
int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
----
Append already encoded questions from an existing message.
This is useful when generating a DNS reply message which includes
all question records.
Return number of appened bytes.
==== mg_dns_encode_record()
[source,c]
----
int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
const char *name, size_t nlen, const void *rdata,
size_t rlen);
----
Encode and append a DNS resource record to an IO buffer.
The record metadata is taken from the `rr` parameter, while the name and data
are taken from the parameters, encoded in the appropriate format depending on
record type, and stored in the IO buffer. The encoded values might contain
offsets within the IO buffer. It's thus important that the IO buffer doesn't
get trimmed while a sequence of records are encoded while preparing a DNS
*reply.
This function doesn't update the `name` and `rdata` pointers in the `rr`
*struct
because they might be invalidated as soon as the IO buffer grows again.
Return the number of bytes appened or -1 in case of error.
==== mg_parse_dns()
[source,c]
----
int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
----
Low-level: parses a DNS response.
==== mg_dns_uncompress_name()
[source,c]
----
size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
char *dst, int dst_len);
----
Uncompress a DNS compressed name.
The containing dns message is required because the compressed encoding
and reference suffixes present elsewhere in the packet.
If name is less than `dst_len` characters long, the remainder
of `dst` is terminated with `\0' characters. Otherwise, `dst` is not
*terminated.
If `dst_len` is 0 `dst` can be NULL.
Return the uncompressed name length.
==== mg_set_protocol_dns()
[source,c]
----
void mg_set_protocol_dns(struct mg_connection *nc);
----
Attach built-in DNS event handler to the given listening connection.
DNS event handler parses incoming UDP packets, treating them as DNS
requests. If incoming packet gets successfully parsed by the DNS event
handler, a user event handler will receive `MG_DNS_REQUEST` event, with
`ev_data` pointing to the parsed `struct mg_dns_message`.
See
[captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server)
example on how to handle DNS request and send DNS reply.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
==== mg_do_connect()
[source,c]
----
MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc,
int proto,
union socket_address *sa);
----
internals that need to be accessible in unit tests
==== to_wchar()
[source,c]
----
int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len);
----
Retur value is the same as for MultiByteToWideChar.
==== mg_handle_chunked()
[source,c]
----
MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc,
struct http_message *hm, char *buf,
size_t blen);
----
Reassemble the content of the buffer (buf, blen) which should be
in the HTTP chunked encoding, by collapsing data chunks to the
beginning of the buffer.
If chunks get reassembled, modify hm->body to point to the reassembled
body and fire MG_EV_HTTP_CHUNK event. If handler sets MG_F_DELETE_CHUNK
in nc->flags, delete reassembled body from the mbuf.
Return reassembled body size.
=== JSON-RPC
==== struct mg_rpc_request
[source,c]
----
struct mg_rpc_request {
struct json_token *message; /* Whole RPC message */
struct json_token *id; /* Message ID */
struct json_token *method; /* Method name */
struct json_token *params; /* Method params */
};
----
JSON-RPC request
==== struct mg_rpc_reply
[source,c]
----
struct mg_rpc_reply {
struct json_token *message; /* Whole RPC message */
struct json_token *id; /* Message ID */
struct json_token *result; /* Remote call result */
};
----
JSON-RPC response
==== struct mg_rpc_error
[source,c]
----
struct mg_rpc_error {
struct json_token *message; /* Whole RPC message */
struct json_token *id; /* Message ID */
struct json_token *error_code; /* error.code */
struct json_token *error_message; /* error.message */
struct json_token *error_data; /* error.data, can be NULL */
};
----
JSON-RPC error
==== mg_rpc_parse_reply()
[source,c]
----
int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks,
int max_toks, struct mg_rpc_reply *,
struct mg_rpc_error *);
----
Parse JSON-RPC reply contained in `buf`, `len` into JSON tokens array
`toks`, `max_toks`. If buffer contains valid reply, `reply` structure is
populated. The result of RPC call is located in `reply.result`. On error,
`error` structure is populated. Returns: the result of calling
`parse_json(buf, len, toks, max_toks)`:
On success, an offset inside `json_string` is returned
where parsing has finished. On failure, a negative number is
returned, one of:
- `#define JSON_STRING_INVALID -1`
- `#define JSON_STRING_INCOMPLETE -2`
- `#define JSON_TOKEN_ARRAY_TOO_SMALL -3`
==== mg_rpc_create_request()
[source,c]
----
int mg_rpc_create_request(char *buf, int len, const char *method,
const char *id, const char *params_fmt, ...);
----
Create JSON-RPC request in a given buffer.
Return length of the request, which
can be larger then `len` that indicates an overflow.
`params_fmt` format string should conform to `json_emit()` API,
see https://github.com/cesanta/frozen
==== mg_rpc_create_reply()
[source,c]
----
int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req,
const char *result_fmt, ...);
----
Create JSON-RPC reply in a given buffer.
Return length of the reply, which
can be larger then `len` that indicates an overflow.
`result_fmt` format string should conform to `json_emit()` API,
see https://github.com/cesanta/frozen
==== mg_rpc_create_error()
[source,c]
----
int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req,
int code, const char *message, const char *fmt, ...);
----
Create JSON-RPC error reply in a given buffer.
Return length of the error, which
can be larger then `len` that indicates an overflow.
`fmt` format string should conform to `json_emit()` API,
see https://github.com/cesanta/frozen
==== mg_rpc_create_std_error()
[source,c]
----
int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req,
int code);
----
Create JSON-RPC error in a given buffer.
Return length of the error, which
can be larger then `len` that indicates an overflow. See
JSON_RPC_*_ERROR definitions for standard error values:
- `#define JSON_RPC_PARSE_ERROR (-32700)`
- `#define JSON_RPC_INVALID_REQUEST_ERROR (-32600)`
- `#define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)`
- `#define JSON_RPC_INVALID_PARAMS_ERROR (-32602)`
- `#define JSON_RPC_INTERNAL_ERROR (-32603)`
- `#define JSON_RPC_SERVER_ERROR (-32000)`
==== mg_rpc_dispatch()
[source,c]
----
int mg_rpc_dispatch(const char *buf, int, char *dst, int dst_len,
const char **methods, mg_rpc_handler_t *handlers);
----
Dispatches a JSON-RPC request.
Parses JSON-RPC request contained in `buf`, `len`.
Then, dispatches the request to the correct handler method.
Valid method names should be specified in NULL
terminated array `methods`, and corresponding handlers in `handlers`.
Result is put in `dst`, `dst_len`. Return: length of the result, which
can be larger then `dst_len` that indicates an overflow.
Overflown bytes are not written to the buffer.
If method is not found, an error is automatically generated.
=== Memory Buffers
Mbufs are mutable/growing memory buffers, like C++ strings.
Mbuf can append data to the end of a buffer, or insert data into arbitrary
position in the middle of a buffer. The buffer grows automatically when
needed.
==== struct mbuf
[source,c]
----
struct mbuf {
char *buf; /* Buffer pointer */
size_t len; /* Data length. Data is located between offset 0 and len. */
size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
};
----
Memory buffer descriptor
==== mbuf_init()
[source,c]
----
void mbuf_init(struct mbuf *, size_t initial_capacity);
----
Initialize an Mbuf.
`initial_capacity` specifies the initial capacity of the mbuf.
==== mbuf_free()
[source,c]
----
void mbuf_free(struct mbuf *);
----
Free the space allocated for the mbuffer and resets the mbuf structure.
==== mbuf_append()
[source,c]
----
size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
----
Appends data to the Mbuf.
Return the number of bytes appended, or 0 if out of memory.
==== mbuf_insert()
[source,c]
----
size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
----
Insert data at a specified offset in the Mbuf.
Existing data will be shifted forwards and the buffer will
be grown if necessary.
Return the number of bytes inserted.
==== mbuf_remove()
[source,c]
----
void mbuf_remove(struct mbuf *, size_t data_size);
----
Remove `data_size` bytes from the beginning of the buffer.
==== mbuf_resize()
[source,c]
----
void mbuf_resize(struct mbuf *, size_t new_size);
----
Resize an Mbuf.
If `new_size` is smaller than buffer's `len`, the
resize is not performed.
==== mbuf_trim()
[source,c]
----
void mbuf_trim(struct mbuf *);
----
Shrink an Mbuf by resizing its `size` to `len`.
=== MQTT Broker
==== struct mg_mqtt_session
[source,c]
----
struct mg_mqtt_session {
struct mg_mqtt_broker *brk; /* Broker */
struct mg_mqtt_session *next, *prev; /* mg_mqtt_broker::sessions linkage */
struct mg_connection *nc; /* Connection with the client */
size_t num_subscriptions; /* Size of `subscriptions` array */
struct mg_mqtt_topic_expression *subscriptions;
void *user_data; /* User data */
};
----
MQTT session (Broker side).
==== struct mg_mqtt_broker
[source,c]
----
struct mg_mqtt_broker {
struct mg_mqtt_session *sessions; /* Session list */
void *user_data; /* User data */
};
----
MQTT broker.
==== mg_mqtt_broker_init()
[source,c]
----
void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);
----
Initialize a MQTT broker.
==== mg_mqtt_broker()
[source,c]
----
void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);
----
Process a MQTT broker message.
Listening connection expects a pointer to an initialized `mg_mqtt_broker`
structure in the `user_data` field.
Basic usage:
```c
mg_mqtt_broker_init(&brk, NULL);
if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
// fail;
}
nc->user_data = &brk;
```
New incoming connections will receive a `mg_mqtt_session` structure
in the connection `user_data`. The original `user_data` will be stored
in the `user_data` field of the session structure. This allows the user
handler to store user data before `mg_mqtt_broker` creates the session.
Since only the MG_EV_ACCEPT message is processed by the listening socket,
for most events the `user_data` will thus point to a `mg_mqtt_session`.
==== mg_mqtt_next()
[source,c]
----
struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
struct mg_mqtt_session *s);
----
Iterate over all mqtt sessions connections. Example:
```c
struct mg_mqtt_session *s;
for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
// Do something
}
```
=== MQTT
==== mg_set_protocol_mqtt()
[source,c]
----
void mg_set_protocol_mqtt(struct mg_connection *nc);
----
Attach built-in MQTT event handler to the given connection.
The user-defined event handler will receive following extra events:
- MG_EV_MQTT_CONNACK
- MG_EV_MQTT_PUBLISH
- MG_EV_MQTT_PUBACK
- MG_EV_MQTT_PUBREC
- MG_EV_MQTT_PUBREL
- MG_EV_MQTT_PUBCOMP
- MG_EV_MQTT_SUBACK
==== mg_send_mqtt_handshake()
[source,c]
----
void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);
----
Send MQTT handshake.
==== mg_send_mqtt_handshake_opt()
[source,c]
----
void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
struct mg_send_mqtt_handshake_opts);
----
Send MQTT handshake with optional parameters.
==== mg_mqtt_publish()
[source,c]
----
void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
uint16_t message_id, int flags, const void *data,
size_t len);
----
Publish a message to a given topic.
==== mg_mqtt_subscribe()
[source,c]
----
void mg_mqtt_subscribe(struct mg_connection *nc,
const struct mg_mqtt_topic_expression *topics,
size_t topics_len, uint16_t message_id);
----
Subscribe to a bunch of topics.
==== mg_mqtt_unsubscribe()
[source,c]
----
void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
size_t topics_len, uint16_t message_id);
----
Unsubscribe from a bunch of topics.
==== mg_mqtt_disconnect()
[source,c]
----
void mg_mqtt_disconnect(struct mg_connection *nc);
----
Send a DISCONNECT command.
==== mg_mqtt_connack()
[source,c]
----
void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);
----
Send a CONNACK command with a given `return_code`.
==== mg_mqtt_puback()
[source,c]
----
void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);
----
Send a PUBACK command with a given `message_id`.
==== mg_mqtt_pubrec()
[source,c]
----
void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);
----
Send a PUBREC command with a given `message_id`.
==== mg_mqtt_pubrel()
[source,c]
----
void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);
----
Send a PUBREL command with a given `message_id`.
==== mg_mqtt_pubcomp()
[source,c]
----
void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);
----
Send a PUBCOMP command with a given `message_id`.
==== mg_mqtt_suback()
[source,c]
----
void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
uint16_t message_id);
----
Send a SUBACK command with a given `message_id`
and a sequence of granted QoSs.
==== mg_mqtt_unsuback()
[source,c]
----
void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);
----
Send a UNSUBACK command with a given `message_id`.
==== mg_mqtt_ping()
[source,c]
----
void mg_mqtt_ping(struct mg_connection *nc);
----
Send a PINGREQ command.
==== mg_mqtt_pong()
[source,c]
----
void mg_mqtt_pong(struct mg_connection *nc);
----
Send a PINGRESP command.
==== mg_mqtt_next_subscribe_topic()
[source,c]
----
int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
struct mg_str *topic, uint8_t *qos, int pos);
----
Extract the next topic expression from a SUBSCRIBE command payload.
Topic expression name will point to a string in the payload buffer.
Return the pos of the next topic expression or -1 when the list
of topics is exhausted.
This diff is collapsed.
==== mg_if_connect_tcp()
[source,c]
----
void mg_if_connect_tcp(struct mg_connection *nc,
const union socket_address *sa);
----
Request that a TCP connection is made to the specified address.
==== mg_if_connect_udp()
[source,c]
----
void mg_if_connect_udp(struct mg_connection *nc);
----
Open a UDP socket. Doesn't actually connect anything.
==== mg_if_connect_cb()
[source,c]
----
void mg_if_connect_cb(struct mg_connection *nc, int err);
----
Callback invoked by connect methods. err = 0 -> ok, != 0 -> error.
==== mg_if_listen_tcp()
[source,c]
----
int mg_if_listen_tcp(struct mg_connection *nc, union socket_address *sa);
----
Set up a listening TCP socket on a given address. rv = 0 -> ok.
==== mg_if_accept_new_conn()
[source,c]
----
struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc);
----
Deliver a new TCP connection. Returns NULL in case on error (unable to
create connection, in which case interface state should be discarded.
This is phase 1 of the two-phase process - MG_EV_ACCEPT will be delivered
when mg_if_accept_tcp_cb is invoked.
==== mg_if_listen_udp()
[source,c]
----
int mg_if_listen_udp(struct mg_connection *nc, union socket_address *sa);
----
Request that a "listening" UDP socket be created.
==== mg_if_tcp_send()
[source,c]
----
void mg_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len);
----
Send functions for TCP and UDP. Sent data is copied before return.
==== mg_if_sent_cb()
[source,c]
----
void mg_if_sent_cb(struct mg_connection *nc, int num_sent);
----
Callback that reports that data has been put on the wire.
==== mg_if_recv_tcp_cb()
[source,c]
----
void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len);
----
Receive callback.
buf must be heap-allocated and ownership is transferred to the core.
Core will acknowledge consumption by calling mg_if_recved.
==== mg_if_poll()
[source,c]
----
void mg_if_poll(struct mg_connection *nc, time_t now);
----
Deliver a POLL event to the connection.
==== mg_if_timer()
[source,c]
----
void mg_if_timer(struct mg_connection *c, double now);
----
Deliver a TIMER event to the connection.
==== mg_if_create_conn()
[source,c]
----
int mg_if_create_conn(struct mg_connection *nc);
----
Perform interface-related connection initialization. Return 1 on success.
==== mg_if_destroy_conn()
[source,c]
----
void mg_if_destroy_conn(struct mg_connection *nc);
----
Perform interface-related cleanup on connection before destruction.
==== mg_if_get_conn_addr()
[source,c]
----
void mg_if_get_conn_addr(struct mg_connection *nc, int remote,
union socket_address *sa);
----
Put connection's address into *sa, local (remote = 0) or remote.
==== mg_sock_set()
[source,c]
----
void mg_sock_set(struct mg_connection *nc, sock_t sock);
----
Associate a socket to a connection.
=== Asynchronouns DNS resolver
==== struct mg_resolve_async_opts
[source,c]
----
struct mg_resolve_async_opts {
const char *nameserver_url;
int max_retries; /* defaults to 2 if zero */
int timeout; /* in seconds; defaults to 5 if zero */
int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
int only_literal; /* only resolves literal addrs; sync cb invocation */
struct mg_connection **dns_conn; /* return DNS connection */
};
----
Options for `mg_resolve_async_opt`.
==== mg_resolve_async()
[source,c]
----
int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
mg_resolve_callback_t cb, void *data);
----
See `mg_resolve_async_opt()`
==== mg_resolve_async_opt()
[source,c]
----
int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
mg_resolve_callback_t cb, void *data,
struct mg_resolve_async_opts opts);
----
Resolved a DNS name asynchronously.
Upon successful resolution, the user callback will be invoked
with the full DNS response message and a pointer to the user's
context `data`.
In case of timeout while performing the resolution the callback
will receive a NULL `msg`.
The DNS answers can be extracted with `mg_next_record` and
`mg_dns_parse_record_data`:
[source,c]
----
struct in_addr ina;
struct mg_dns_resource_record *rr = mg_next_record(msg, MG_DNS_A_RECORD,
NULL);
mg_dns_parse_record_data(msg, rr, &ina, sizeof(ina));
----
==== mg_resolve_from_hosts_file()
[source,c]
----
int mg_resolve_from_hosts_file(const char *host, union socket_address *usa);
----
Resolve a name from `/etc/hosts`.
Returns 0 on success, -1 on failure.
=== URI
==== mg_parse_uri()
[source,c]
----
int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
struct mg_str *user_info, struct mg_str *host,
unsigned int *port, struct mg_str *path, struct mg_str *query,
struct mg_str *fragment);
----
Parses an URI and fills string chunks with locations of the respective
uri components within the input uri string. NULL pointers will be
ignored.
General syntax:
[scheme://[user_info@]]host[:port][/path][?query][#fragment]
Example:
foo.com:80
tcp://foo.com:1234
http://foo.com:80/bar?baz=1
https://user:pw@foo.com:443/blah
`path` will include the leading slash. `query` won't include the leading `?`.
`host` can contain embedded colons if surrounded by square brackets in order
to support IPv6 literal addresses.
Returns 0 on success, -1 on error.
=== Utilities
==== mg_skip()
[source,c]
----
const char *mg_skip(const char *s, const char *end_string,
const char *delimiters, struct mg_str *v);
----
Fetch substring from input string `s`, `end` into `v`.
Skips initial delimiter characters. Records first non-delimiter character
as the beginning of substring `v`. Then scans the rest of the string
until a delimiter character or end-of-string is found.
`delimiters` is a 0-terminated string containing delimiter characters.
Either one of `delimiters` or `end_string` terminates the search.
Return an `s` pointer, advanced forward where parsing stopped.
==== mg_ncasecmp()
[source,c]
----
int mg_ncasecmp(const char *s1, const char *s2, size_t len);
----
Cross-platform version of `strncasecmp()`.
==== mg_casecmp()
[source,c]
----
int mg_casecmp(const char *s1, const char *s2);
----
Cross-platform version of `strcasecmp()`.
==== mg_vcmp()
[source,c]
----
int mg_vcmp(const struct mg_str *str2, const char *str1);
----
Cross-platform version of `strcmp()` where where first string is
specified by `struct mg_str`.
==== mg_vcasecmp()
[source,c]
----
int mg_vcasecmp(const struct mg_str *str2, const char *str1);
----
Cross-platform version of `strncasecmp()` where first string is
specified by `struct mg_str`.
==== mg_base64_decode()
[source,c]
----
int mg_base64_decode(const unsigned char *s, int len, char *dst);
----
Decode base64-encoded string `s`, `len` into the destination `dst`.
Destination has to have enough space to hold decoded buffer.
Decoding stops either when all string has been decoded, or invalid
character appeared.
Destination is '\0'-terminated.
Return number of decoded characters. On success, that should be equal to
`len`. On error (invalid character) the return value is smaller then `len`.
==== mg_base64_encode()
[source,c]
----
void mg_base64_encode(const unsigned char *src, int src_len, char *dst);
----
Base64-encode chunk of memory `src`, `src_len` into the destination `dst`.
Destination has to have enough space to hold encoded buffer.
Destination is '\0'-terminated.
==== mg_stat()
[source,c]
----
int mg_stat(const char *path, cs_stat_t *st);
----
Perform a 64-bit `stat()` call against given file.
`path` should be UTF8 encoded.
Return value is the same as for `stat()` syscall.
==== mg_fopen()
[source,c]
----
FILE *mg_fopen(const char *path, const char *mode);
----
Open the given file and return a file stream.
`path` and `mode` should be UTF8 encoded.
Return value is the same as for the `fopen()` call.
==== mg_open()
[source,c]
----
int mg_open(const char *path, int flag, int mode);
----
Open the given file and return a file stream.
`path` should be UTF8 encoded.
Return value is the same as for the `open()` syscall.
==== mg_start_thread()
[source,c]
----
void *mg_start_thread(void *(*thread_func);
----
Start a new detached thread.
Arguments and semantic is the same as pthead's `pthread_create()`.
`thread_func` is a thread function, `thread_func_param` is a parameter
that is passed to the thread function.
==== mg_conn_addr_to_str()
[source,c]
----
void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
int flags);
----
Convert connection's local or remote address into string.
The `flags` parameter is a bit mask that controls the behavior,
see `MG_SOCK_STRINGIFY_*` definitions.
- MG_SOCK_STRINGIFY_IP - print IP address
- MG_SOCK_STRINGIFY_PORT - print port number
- MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address
If both port number and IP address are printed, they are separated by `:`.
If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported.
==== mg_sock_to_str()
[source,c]
----
void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
----
Legacy interface.
==== mg_sock_addr_to_str()
[source,c]
----
void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
int flags);
----
Convert socket's address into string.
`flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT.
==== mg_hexdump()
[source,c]
----
int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
----
Generates human-readable hexdump of memory chunk.
Takes a memory buffer `buf` of length `len` and creates a hex dump of that
buffer in `dst`. Generated output is a-la hexdump(1).
Return length of generated string, excluding terminating `\0`. If returned
length is bigger than `dst_len`, overflow bytes are discarded.
==== mg_hexdump_connection()
[source,c]
----
void mg_hexdump_connection(struct mg_connection *nc, const char *path,
const void *buf, int num_bytes, int ev);
----
Generates human-readable hexdump of the data sent or received by connection.
`path` is a file name where hexdump should be written. `num_bytes` is
a number of bytes sent/received. `ev` is one of the `MG_*` events sent to
an event handler. This function is supposed to be called from the
event handler.
==== mg_avprintf()
[source,c]
----
int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
----
Print message to buffer. If buffer is large enough to hold the message,
return buffer. If buffer is to small, allocate large enough buffer on heap,
and return allocated buffer.
This is a supposed use case:
char buf[5], *p = buf;
p = mg_avprintf(&p, sizeof(buf), "%s", "hi there");
use_p_somehow(p);
if (p != buf) {
free(p);
}
The purpose of this is to avoid malloc-ing if generated strings are small.
==== mg_is_big_endian()
[source,c]
----
int mg_is_big_endian(void);
----
Return true if target platform is big endian.
==== mg_next_comma_list_entry()
[source,c]
----
const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
struct mg_str *eq_val);
----
A helper function for traversing a comma separated list of values.
It returns a list pointer shifted to the next value, or NULL if the end
of the list found.
Value is stored in val vector. If value has form "x=y", then eq_val
vector is initialized to point to the "y" part, and val vector length
is adjusted to point only to "x".
If list is just a comma separated list of entries, like "aa,bb,cc" then
`eq_val` will contain zero-length string.
The purpose of this function is to parse comma separated string without
any copying/memory allocation.
==== mg_match_prefix()
[source,c]
----
int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
----
Match 0-terminated string (mg_match_prefix) or string with given length
mg_match_prefix_n against a glob pattern.
Match is case-insensitive. Return number of bytes matched, or -1 if no match.
==== mg_mk_str()
[source,c]
----
struct mg_str mg_mk_str(const char *s);
----
A helper function for creating mg_str struct from plain C string.
`NULL` is allowed and becomes `{NULL, 0}`.
==== MG_MK_STR()
[source,c]
----
#define MG_MK_STR(str_literal);
----
Macro for initializing mg_str.
......@@ -6247,12 +6247,8 @@ static int mg_check_nonce(const char *nonce) {
return now < val || now - val < 3600;
}
/*
* Authenticate HTTP request against opened passwords file.
* Returns 1 if authenticated, 0 otherwise.
*/
static int mg_http_check_digest_auth(struct http_message *hm,
const char *auth_domain, FILE *fp) {
int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
FILE *fp) {
struct mg_str *hdr;
char buf[128], f_user[sizeof(buf)], f_ha1[sizeof(buf)], f_domain[sizeof(buf)];
char user[50], cnonce[33], response[40], uri[200], qop[20], nc[20], nonce[30];
......
......@@ -2715,6 +2715,13 @@ void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
mg_fu_fname_fn local_name_fn);
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
/*
* Authenticate HTTP request against opened passwords file.
* Returns 1 if authenticated, 0 otherwise.
*/
int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
FILE *fp);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment