2014-05-14 22:10:34 -04:00
|
|
|
/*
|
2014-05-16 08:22:25 -04:00
|
|
|
* r3.h
|
2014-06-27 01:24:40 -04:00
|
|
|
* Copyright (C) 2014 c9s <yoanlin93@gmail.com>
|
2014-05-14 22:10:34 -04:00
|
|
|
*
|
|
|
|
* Distributed under terms of the MIT license.
|
|
|
|
*/
|
2014-05-22 10:21:29 -04:00
|
|
|
#ifndef R3_NODE_H
|
|
|
|
#define R3_NODE_H
|
2014-05-14 22:10:34 -04:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2023-10-23 06:38:24 -04:00
|
|
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
|
|
#include <pcre2.h>
|
2015-11-17 08:31:33 -05:00
|
|
|
|
2023-10-02 03:48:47 -04:00
|
|
|
#if __STDC_VERSION__ <= 201710L
|
2015-11-17 08:31:33 -05:00
|
|
|
#ifdef HAVE_STDBOOL_H
|
2021-10-12 05:18:45 -04:00
|
|
|
# include <stdbool.h>
|
|
|
|
#elif !defined(bool) && !defined(__cplusplus)
|
2015-11-17 08:31:33 -05:00
|
|
|
typedef unsigned char bool;
|
2021-10-12 05:18:45 -04:00
|
|
|
# define bool bool /* For redefinition guards */
|
|
|
|
# define false 0
|
|
|
|
# define true 1
|
2015-11-17 08:31:33 -05:00
|
|
|
#endif
|
2023-10-02 03:48:47 -04:00
|
|
|
#endif
|
2015-11-17 08:31:33 -05:00
|
|
|
|
2014-05-28 09:08:06 -04:00
|
|
|
#include "str_array.h"
|
2015-11-17 08:17:18 -05:00
|
|
|
#include "r3_slug.h"
|
2016-03-21 22:23:37 -04:00
|
|
|
#include "memory.h"
|
2014-06-01 06:06:12 -04:00
|
|
|
|
2015-11-17 08:31:33 -05:00
|
|
|
|
2014-06-01 04:48:54 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2014-05-16 03:29:25 -04:00
|
|
|
struct _edge;
|
|
|
|
struct _node;
|
2014-05-18 01:06:36 -04:00
|
|
|
struct _route;
|
2015-11-17 23:52:06 -05:00
|
|
|
typedef struct _edge R3Edge;
|
|
|
|
typedef struct _node R3Node;
|
2015-11-18 01:16:26 -05:00
|
|
|
typedef struct _R3Route R3Route;
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2015-11-12 09:01:55 -05:00
|
|
|
struct _node {
|
2016-03-21 22:23:37 -04:00
|
|
|
R3_VECTOR(R3Edge) edges;
|
|
|
|
R3_VECTOR(R3Route) routes;
|
2015-11-10 05:43:25 -05:00
|
|
|
char * combined_pattern;
|
2023-10-23 06:38:24 -04:00
|
|
|
pcre2_code * pcre_pattern;
|
|
|
|
pcre2_match_data * match_data;
|
2014-05-24 05:13:55 -04:00
|
|
|
|
2014-06-02 08:51:35 -04:00
|
|
|
// edges are mostly less than 255
|
2015-11-10 06:36:01 -05:00
|
|
|
unsigned int compare_type; // compare_type: pcre, opcode, string
|
2015-11-10 22:16:19 -05:00
|
|
|
unsigned int endpoint; // endpoint, should be zero for non-endpoint nodes
|
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
// the pointer of R3Route data
|
2015-11-10 22:16:19 -05:00
|
|
|
void * data;
|
2021-10-18 03:14:26 -04:00
|
|
|
};
|
2014-05-16 02:05:51 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
#define r3_node_edge_pattern(node,i) node->edges.entries[i].pattern.base
|
|
|
|
#define r3_node_edge_pattern_len(node,i) node->edges.entries[i].pattern.len
|
2014-05-28 09:08:06 -04:00
|
|
|
|
2014-05-16 03:29:25 -04:00
|
|
|
struct _edge {
|
2016-03-21 22:23:37 -04:00
|
|
|
r3_iovec_t pattern; // 8 bytes
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Node * child; // 8 bytes
|
2015-11-10 22:08:09 -05:00
|
|
|
unsigned int opcode; // 4byte
|
|
|
|
unsigned int has_slug; // 4byte
|
2021-10-18 03:14:26 -04:00
|
|
|
};
|
2014-05-16 02:05:51 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
struct _R3Route {
|
2016-03-21 22:23:37 -04:00
|
|
|
r3_iovec_t path;
|
|
|
|
R3_VECTOR(r3_iovec_t) slugs;
|
|
|
|
int request_method; // can be (GET || POST)
|
|
|
|
r3_iovec_t host; // required host name
|
2014-05-17 06:57:36 -04:00
|
|
|
|
2014-05-18 00:40:06 -04:00
|
|
|
void * data;
|
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
r3_iovec_t remote_addr_pattern;
|
2019-06-19 23:19:08 -04:00
|
|
|
|
|
|
|
unsigned int remote_addr_v4;
|
|
|
|
int remote_addr_v4_bits;
|
|
|
|
|
2019-08-01 21:37:18 -04:00
|
|
|
unsigned int remote_addr_v6[4];
|
|
|
|
int remote_addr_v6_bits[4];
|
|
|
|
|
2019-07-20 21:14:37 -04:00
|
|
|
int http_scheme; // can be (SCHEME_HTTP or SCHEME_HTTPS)
|
2019-06-26 11:06:32 -04:00
|
|
|
|
2021-10-18 03:14:26 -04:00
|
|
|
};
|
2014-05-17 06:57:36 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
typedef struct _R3Entry match_entry;
|
|
|
|
struct _R3Entry {
|
|
|
|
str_array vars;
|
|
|
|
r3_iovec_t path; // current path to dispatch
|
|
|
|
int request_method; // current request method
|
2014-06-03 10:07:46 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
void * data; // R3Route ptr
|
2014-06-03 10:07:46 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
r3_iovec_t host; // the request host
|
|
|
|
r3_iovec_t remote_addr;
|
2019-06-26 11:06:32 -04:00
|
|
|
|
|
|
|
int http_scheme;
|
2021-10-18 03:14:26 -04:00
|
|
|
};
|
2014-06-03 10:07:46 -04:00
|
|
|
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Node * r3_tree_create(int cap);
|
2014-05-16 03:29:25 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
// R3Node * r3_node_create();
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
void r3_tree_free(R3Node * tree);
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Edge * r3_node_connectl(R3Node * n, const char * pat, int len, int strdup, R3Node *child);
|
2014-05-23 01:49:18 -04:00
|
|
|
|
|
|
|
#define r3_node_connect(n, pat, child) r3_node_connectl(n, pat, strlen(pat), 0, child)
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
R3Edge * r3_node_find_edge(const R3Node * n, const char * pat, unsigned int pat_len);
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
R3Edge * r3_node_append_edge(R3Node *n);
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Edge * r3_node_find_common_prefix(R3Node *n, const char *path, int path_len, int *prefix_len, char **errstr);
|
2014-05-15 06:26:41 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Node * r3_tree_insert_pathl(R3Node *tree, const char *path, int path_len, void * data);
|
2014-05-18 22:12:41 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
#define r3_tree_insert_pathl(tree, path, path_len, data) r3_tree_insert_pathl_ex(tree, path, path_len, 0, 0, data, NULL)
|
2014-06-04 11:13:08 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
R3Route * r3_tree_insert_routel(R3Node * tree, int method, const char *path, int path_len, void *data);
|
2014-05-31 07:56:46 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
R3Route * r3_tree_insert_routel_ex(R3Node * tree, int method, const char *path, int path_len, void *data, char **errstr);
|
2014-06-03 11:50:02 -04:00
|
|
|
|
|
|
|
#define r3_tree_insert_routel(n, method, path, path_len, data) r3_tree_insert_routel_ex(n, method, path, path_len, data, NULL)
|
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
#define r3_tree_insert_path(n,p,d) r3_tree_insert_pathl_ex(n,p,strlen(p), 0, 0, d, NULL)
|
2014-05-31 07:56:46 -04:00
|
|
|
|
|
|
|
#define r3_tree_insert_route(n,method,path,data) r3_tree_insert_routel(n, method, path, strlen(path), data)
|
|
|
|
|
2014-05-18 22:12:41 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The private API to insert a path
|
|
|
|
*/
|
2016-03-21 22:23:37 -04:00
|
|
|
R3Node * r3_tree_insert_pathl_ex(R3Node *tree, const char *path, unsigned int path_len, int method, unsigned int router, void * data, char **errstr);
|
2014-05-15 06:26:41 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
void r3_tree_dump(const R3Node * n, int level);
|
2014-05-15 01:39:50 -04:00
|
|
|
|
2014-05-17 20:13:58 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Edge * r3_node_find_edge_str(const R3Node * n, const char * str, int str_len);
|
2014-05-16 02:05:51 -04:00
|
|
|
|
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
int r3_tree_compile(R3Node *n, char** errstr);
|
2014-05-16 02:05:51 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
int r3_tree_compile_patterns(R3Node * n, char** errstr);
|
2014-05-16 02:05:51 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
R3Node * r3_tree_matchl(const R3Node * n, const char * path, unsigned int path_len, match_entry * entry);
|
2014-05-18 22:34:48 -04:00
|
|
|
|
|
|
|
#define r3_tree_match(n,p,e) r3_tree_matchl(n,p, strlen(p), e)
|
2014-05-15 09:17:30 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
// R3Node * r3_tree_match_entry(R3Node * n, match_entry * entry);
|
2016-03-21 22:23:37 -04:00
|
|
|
#define r3_tree_match_entry(n, entry) r3_tree_matchl(n, entry->path.base, entry->path.len, entry)
|
2014-05-18 00:32:20 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
bool r3_node_has_slug_edges(const R3Node *n);
|
2014-05-16 00:33:59 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
// R3Edge * r3_edge_createl(const char * pattern, int pattern_len, R3Node * child);
|
2014-05-14 22:10:34 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
void r3_edge_initl(R3Edge *e, const char * pattern, int pattern_len, R3Node * child);
|
2015-11-10 07:29:07 -05:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
R3Node * r3_edge_branch(R3Edge *e, int dl);
|
2014-05-15 11:46:49 -04:00
|
|
|
|
2015-11-17 23:52:06 -05:00
|
|
|
void r3_edge_free(R3Edge * edge);
|
2014-05-14 22:10:34 -04:00
|
|
|
|
2014-05-16 06:03:52 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-17 07:25:25 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
R3Route * r3_route_create(const char * path);
|
2014-05-17 07:25:25 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
// R3Route * r3_route_createl(const char * path, int path_len);
|
2014-05-17 07:25:25 -04:00
|
|
|
|
2014-05-17 23:59:30 -04:00
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
R3Route * r3_node_append_route(R3Node *tree, const char * path, int path_len, int method, void *data);
|
2014-05-18 00:24:07 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
void r3_route_free(R3Route * route);
|
2014-05-18 00:24:07 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
int r3_route_cmp(const R3Route *r1, const match_entry *r2);
|
2014-06-03 10:07:46 -04:00
|
|
|
|
2015-11-18 01:16:26 -05:00
|
|
|
R3Route * r3_tree_match_route(const R3Node *n, match_entry * entry);
|
2014-05-18 00:56:53 -04:00
|
|
|
|
2014-06-04 11:13:08 -04:00
|
|
|
#define r3_route_create(p) r3_route_createl(p, strlen(p))
|
|
|
|
|
|
|
|
|
2014-05-17 23:59:30 -04:00
|
|
|
#define METHOD_GET 2
|
|
|
|
#define METHOD_POST 2<<1
|
2014-05-22 12:21:40 -04:00
|
|
|
#define METHOD_PUT 2<<2
|
|
|
|
#define METHOD_DELETE 2<<3
|
|
|
|
#define METHOD_PATCH 2<<4
|
|
|
|
#define METHOD_HEAD 2<<5
|
|
|
|
#define METHOD_OPTIONS 2<<6
|
2014-05-17 23:59:30 -04:00
|
|
|
|
2019-06-26 11:06:32 -04:00
|
|
|
#define SCHEME_HTTP 2
|
|
|
|
#define SCHEME_HTTPS 2<<1
|
2014-05-23 00:08:06 -04:00
|
|
|
|
|
|
|
|
2016-03-21 22:23:37 -04:00
|
|
|
int r3_pattern_to_opcode(const char * pattern, unsigned int len);
|
2014-05-23 00:08:06 -04:00
|
|
|
|
|
|
|
enum { NODE_COMPARE_STR, NODE_COMPARE_PCRE, NODE_COMPARE_OPCODE };
|
2014-05-22 23:25:25 -04:00
|
|
|
|
2019-06-30 22:46:51 -04:00
|
|
|
enum { OP_EXPECT_MORE_DIGITS = 1, OP_EXPECT_MORE_WORDS, OP_EXPECT_NOSLASH,
|
2019-07-20 10:49:25 -04:00
|
|
|
OP_EXPECT_NODASH, OP_EXPECT_MORE_ALPHA, OP_GREEDY_ANY};
|
2014-05-22 23:18:15 -04:00
|
|
|
|
2014-06-03 10:07:46 -04:00
|
|
|
|
|
|
|
|
|
|
|
match_entry * match_entry_createl(const char * path, int path_len);
|
|
|
|
|
|
|
|
#define match_entry_create(path) match_entry_createl(path,strlen(path))
|
|
|
|
|
|
|
|
void match_entry_free(match_entry * entry);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-01 04:48:54 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
2014-06-01 06:06:12 -04:00
|
|
|
#endif
|
2014-05-26 09:39:36 -04:00
|
|
|
|
2014-06-03 08:47:35 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-22 10:21:29 -04:00
|
|
|
#endif /* !R3_NODE_H */
|