agoo 2.5.4 → 2.5.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/bin/agoo +3 -1
- data/ext/agoo/base64.h +3 -3
- data/ext/agoo/bind.c +1 -1
- data/ext/agoo/bind.h +3 -3
- data/ext/agoo/con.c +4 -2
- data/ext/agoo/con.h +3 -3
- data/ext/agoo/debug.c +7 -0
- data/ext/agoo/debug.h +13 -6
- data/ext/agoo/doc.c +159 -0
- data/ext/agoo/doc.h +34 -0
- data/ext/agoo/dtime.h +3 -3
- data/ext/agoo/err.h +3 -3
- data/ext/agoo/error_stream.h +3 -3
- data/ext/agoo/extconf.rb +1 -1
- data/ext/agoo/gqlintro.c +333 -0
- data/ext/agoo/gqlintro.h +10 -0
- data/ext/agoo/gqlvalue.c +1035 -0
- data/ext/agoo/gqlvalue.h +88 -0
- data/ext/agoo/graphql.c +1078 -0
- data/ext/agoo/graphql.h +198 -0
- data/ext/agoo/hook.c +2 -0
- data/ext/agoo/hook.h +4 -3
- data/ext/agoo/http.c +2 -1
- data/ext/agoo/http.h +3 -3
- data/ext/agoo/kinds.h +3 -3
- data/ext/agoo/log.h +3 -3
- data/ext/agoo/log_queue.h +3 -3
- data/ext/agoo/method.h +3 -3
- data/ext/agoo/page.h +3 -3
- data/ext/agoo/pub.h +3 -3
- data/ext/agoo/queue.h +3 -3
- data/ext/agoo/rack_logger.h +3 -3
- data/ext/agoo/req.c +2 -2
- data/ext/agoo/req.h +3 -3
- data/ext/agoo/request.h +3 -3
- data/ext/agoo/res.h +3 -3
- data/ext/agoo/response.h +3 -3
- data/ext/agoo/rhook.c +2 -2
- data/ext/agoo/rhook.h +4 -3
- data/ext/agoo/rlog.h +3 -3
- data/ext/agoo/rresponse.h +3 -3
- data/ext/agoo/rserver.c +64 -0
- data/ext/agoo/rserver.h +3 -3
- data/ext/agoo/rupgraded.c +1 -1
- data/ext/agoo/rupgraded.h +3 -3
- data/ext/agoo/sdl.c +334 -0
- data/ext/agoo/sdl.h +10 -0
- data/ext/agoo/seg.h +3 -3
- data/ext/agoo/server.c +3 -1
- data/ext/agoo/server.h +5 -4
- data/ext/agoo/sha1.h +3 -3
- data/ext/agoo/sse.h +3 -3
- data/ext/agoo/sub.h +3 -3
- data/ext/agoo/subject.h +3 -3
- data/ext/agoo/text.h +3 -3
- data/ext/agoo/upgraded.h +3 -3
- data/ext/agoo/websocket.h +3 -3
- data/lib/agoo/version.rb +1 -1
- data/lib/rack/handler/agoo.rb +3 -1
- metadata +12 -12
- data/ext/agoo/foo/agoo.c +0 -109
- data/ext/agoo/foo/con.c +0 -1220
- data/ext/agoo/foo/con.h +0 -65
- data/ext/agoo/foo/page.c +0 -699
- data/ext/agoo/foo/pub.c +0 -131
- data/ext/agoo/foo/pub.h +0 -40
- data/ext/agoo/foo/rserver.c +0 -1016
- data/ext/agoo/foo/server.c +0 -303
- data/ext/agoo/foo/server.h +0 -67
- data/ext/agoo/foo/upgraded.c +0 -182
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 409a4fe687d9ff75a67d4b25f559b5baa9df782d828bfeb1645daf696ba30035
|
4
|
+
data.tar.gz: a57f3d142cdee7c3ac6fc9d73fd05e2b1e5e4c90a1a2f276e4af0f69764f232b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4f662d43b893105689f50df6a8942ec2e86e82bec8534cff159e5a5b634a5075c1a80283c474b855c41bdff208ed1f3d605ba5b98a0591bd385202a751ac884
|
7
|
+
data.tar.gz: 2fd33f0f3021820efc68a4b073526fa584ba4792d10cd25806a81b11131ffcd13d35863dc1c58a11a203f03e4d10e6943dedaf6b9f9adfbfacce97c46ea4e918
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
### 2.5.5 - 2018-11-12
|
4
|
+
|
5
|
+
More optimizations and some cleanup.
|
6
|
+
|
7
|
+
- New optional hint to the server that allows responses to `#call` to be cached.
|
8
|
+
|
9
|
+
- Change C header file guards. No change in behavior. Just code cleanup.
|
10
|
+
|
11
|
+
- Fixed change that slowed down the server.
|
12
|
+
|
3
13
|
### 2.5.4 - 2018-11-10
|
4
14
|
|
5
15
|
Third times a charm.
|
data/bin/agoo
CHANGED
@@ -46,6 +46,7 @@ Example:
|
|
46
46
|
@threads = 0
|
47
47
|
@workers = 0
|
48
48
|
@first = false
|
49
|
+
@graphql = nil
|
49
50
|
|
50
51
|
@opts = OptionParser.new(usage)
|
51
52
|
@opts.on('-h', '--help', 'Show this display.') { puts @opts.help; Process.exit!(0) }
|
@@ -54,6 +55,7 @@ Example:
|
|
54
55
|
@opts.on('-f', '--root_first', 'Check the root directory before the handle paths.') { @first = true }
|
55
56
|
@opts.on('-p', '--port PORT', Integer, 'Port to listen on.') { |p| @port = p }
|
56
57
|
@opts.on('-d', '--dir DIR', String, 'Directory to serve static assets from.') { |d| @root = d }
|
58
|
+
@opts.on('-g', '--graphql PATH', String, 'URL path for GraphQL requests.') { |g| @graphql = g }
|
57
59
|
@opts.on('-r', '--require FILE', String, 'Ruby require.') { |r| require r }
|
58
60
|
@opts.on('-t', '--threads COUNT', Integer, 'Number of threads to use.') { |t| @threads = t }
|
59
61
|
@opts.on('-w', '--workers COUNT', Integer, 'Number of workers to use.') { |w| @workers = w }
|
@@ -81,7 +83,7 @@ Agoo::Log.configure(dir: @log_dir,
|
|
81
83
|
push: 2 <= @verbose,
|
82
84
|
})
|
83
85
|
|
84
|
-
Agoo::Server.init(@port, @root, thread_count: @threads, worker_count: @workers, root_first: @first)
|
86
|
+
Agoo::Server.init(@port, @root, thread_count: @threads, worker_count: @workers, root_first: @first, graphql: @graphql)
|
85
87
|
|
86
88
|
puts "Agoo #{Agoo::VERSION} is listening on port #{@port}. Path mappings are:" if 1 <= @verbose
|
87
89
|
|
data/ext/agoo/base64.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright 2011, 2016, 2018 by Peter Ohler, All Rights Reserved
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_BASE64_H
|
4
|
+
#define AGOO_BASE64_H
|
5
5
|
|
6
6
|
typedef unsigned char uchar;
|
7
7
|
|
@@ -12,4 +12,4 @@ extern unsigned long b64_orig_size(const char *text);
|
|
12
12
|
extern int b64_to(const uchar *src, int len, char *b64);
|
13
13
|
extern void b64_from(const char *b64, uchar *str);
|
14
14
|
|
15
|
-
#endif
|
15
|
+
#endif // AGOO_BASE64_H
|
data/ext/agoo/bind.c
CHANGED
data/ext/agoo/bind.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_BIND_H
|
4
|
+
#define AGOO_BIND_H
|
5
5
|
|
6
6
|
#include <stdbool.h>
|
7
7
|
#include <sys/socket.h>
|
@@ -41,4 +41,4 @@ extern void bind_destroy(Bind b);
|
|
41
41
|
extern int bind_listen(Err err, Bind b);
|
42
42
|
extern void bind_close(Bind b);
|
43
43
|
|
44
|
-
#endif //
|
44
|
+
#endif // AGOO_BIND_H
|
data/ext/agoo/con.c
CHANGED
@@ -974,8 +974,10 @@ short
|
|
974
974
|
con_http_events(Con c) {
|
975
975
|
short events = 0;
|
976
976
|
|
977
|
-
if (
|
977
|
+
if (NULL != c->res_head && NULL != res_message(c->res_head)) {
|
978
978
|
events = POLLIN | POLLOUT;
|
979
|
+
} else if (!c->closing) {
|
980
|
+
events = POLLIN;
|
979
981
|
}
|
980
982
|
return events;
|
981
983
|
}
|
@@ -1142,7 +1144,7 @@ con_loop(void *x) {
|
|
1142
1144
|
goto CON_CHECK;
|
1143
1145
|
}
|
1144
1146
|
}
|
1145
|
-
if (0 != (pp->revents & POLLOUT)
|
1147
|
+
if (0 != (pp->revents & POLLOUT)) {
|
1146
1148
|
if (con_write(c)) {
|
1147
1149
|
c->dead = true;
|
1148
1150
|
goto CON_CHECK;
|
data/ext/agoo/con.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_CON_H
|
4
|
+
#define AGOO_CON_H
|
5
5
|
|
6
6
|
#include <poll.h>
|
7
7
|
#include <pthread.h>
|
@@ -62,4 +62,4 @@ extern bool con_http_read(Con c);
|
|
62
62
|
extern bool con_http_write(Con c);
|
63
63
|
extern short con_http_events(Con c);
|
64
64
|
|
65
|
-
#endif /*
|
65
|
+
#endif /* AGOO_CON_H */
|
data/ext/agoo/debug.c
CHANGED
@@ -28,6 +28,13 @@ atomic_int mem_cslot = 0;
|
|
28
28
|
atomic_int mem_err_stream = 0;
|
29
29
|
atomic_int mem_eval_threads = 0;
|
30
30
|
atomic_int mem_group = 0;
|
31
|
+
atomic_int mem_graphql_arg = 0;
|
32
|
+
atomic_int mem_graphql_directive = 0;
|
33
|
+
atomic_int mem_graphql_field = 0;
|
34
|
+
atomic_int mem_graphql_link = 0;
|
35
|
+
atomic_int mem_graphql_slot = 0;
|
36
|
+
atomic_int mem_graphql_type = 0;
|
37
|
+
atomic_int mem_graphql_value = 0;
|
31
38
|
atomic_int mem_group_path = 0;
|
32
39
|
atomic_int mem_header = 0;
|
33
40
|
atomic_int mem_hook = 0;
|
data/ext/agoo/debug.h
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_DEBUG_H
|
4
|
+
#define AGOO_DEBUG_H
|
5
5
|
|
6
6
|
#include <stdatomic.h>
|
7
7
|
|
8
8
|
#ifdef MEM_DEBUG
|
9
|
-
#define DEBUG_ALLOC(var, ptr) { atomic_fetch_add(&var, 1); debug_add(ptr, #var,
|
10
|
-
#define DEBUG_REALLOC(var, orig, ptr) { debug_update(orig, ptr, #var,
|
11
|
-
#define DEBUG_FREE(var, ptr) { atomic_fetch_sub(&var, 1); debug_del(ptr,
|
9
|
+
#define DEBUG_ALLOC(var, ptr) { atomic_fetch_add(&var, 1); debug_add(ptr, #var, FILE, LINE); }
|
10
|
+
#define DEBUG_REALLOC(var, orig, ptr) { debug_update(orig, ptr, #var, FILE, LINE); }
|
11
|
+
#define DEBUG_FREE(var, ptr) { atomic_fetch_sub(&var, 1); debug_del(ptr, FILE, LINE); }
|
12
12
|
#else
|
13
13
|
#define DEBUG_ALLOC(var, ptr) { }
|
14
14
|
#define DEBUG_REALLOC(var, orig, ptr) { }
|
@@ -21,6 +21,13 @@ extern atomic_int mem_con;
|
|
21
21
|
extern atomic_int mem_cslot;
|
22
22
|
extern atomic_int mem_err_stream;
|
23
23
|
extern atomic_int mem_eval_threads;
|
24
|
+
extern atomic_int mem_graphql_arg;
|
25
|
+
extern atomic_int mem_graphql_directive;
|
26
|
+
extern atomic_int mem_graphql_field;
|
27
|
+
extern atomic_int mem_graphql_link;
|
28
|
+
extern atomic_int mem_graphql_slot;
|
29
|
+
extern atomic_int mem_graphql_type;
|
30
|
+
extern atomic_int mem_graphql_value;
|
24
31
|
extern atomic_int mem_group;
|
25
32
|
extern atomic_int mem_group_path;
|
26
33
|
extern atomic_int mem_header;
|
@@ -54,4 +61,4 @@ extern void debug_del(void *ptr, const char *file, int line);
|
|
54
61
|
extern void debug_report();
|
55
62
|
extern void debug_rreport(); // when called from ruby
|
56
63
|
|
57
|
-
#endif /*
|
64
|
+
#endif /* AGOO_DEBUG_H */
|
data/ext/agoo/doc.c
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <stdbool.h>
|
4
|
+
#include <stdint.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <string.h>
|
7
|
+
|
8
|
+
#include "doc.h"
|
9
|
+
#include "gqlvalue.h"
|
10
|
+
|
11
|
+
static char char_map[256] = "\
|
12
|
+
.........ww..w..................\
|
13
|
+
wpq.....pp..w.p.ttttttttttp..p..\
|
14
|
+
pttttttttttttttttttttttttttp.p.t\
|
15
|
+
.ttttttttttttttttttttttttttppp..\
|
16
|
+
................................\
|
17
|
+
................................\
|
18
|
+
................................\
|
19
|
+
................................";
|
20
|
+
|
21
|
+
void
|
22
|
+
doc_init(Doc doc, const char *str, int len) {
|
23
|
+
if (0 >= len) {
|
24
|
+
len = (int)strlen(str);
|
25
|
+
}
|
26
|
+
doc->str = str;
|
27
|
+
doc->cur = str;
|
28
|
+
doc->end = str + len;
|
29
|
+
// If there is a BOM, skip it.
|
30
|
+
if (0xEF == (uint8_t)*doc->str && 0xBB == (uint8_t)doc->str[1] && 0xBF == (uint8_t)doc->str[2]) {
|
31
|
+
doc->cur += 3;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
int
|
36
|
+
doc_skip_white(Doc doc) {
|
37
|
+
const char *start = doc->cur;
|
38
|
+
|
39
|
+
for (; 'w' == char_map[*(uint8_t*)doc->cur]; doc->cur++) {
|
40
|
+
}
|
41
|
+
return (int)(doc->cur - start);
|
42
|
+
}
|
43
|
+
|
44
|
+
void
|
45
|
+
doc_skip_comment(Doc doc) {
|
46
|
+
for (; true; doc->cur++) {
|
47
|
+
switch (*doc->cur) {
|
48
|
+
case '\r':
|
49
|
+
case '\n':
|
50
|
+
return;
|
51
|
+
default:
|
52
|
+
break;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
void
|
58
|
+
doc_read_token(Doc doc) {
|
59
|
+
if ('t' == char_map[*(uint8_t*)doc->cur] && '9' < *doc->cur) {
|
60
|
+
doc->cur++;
|
61
|
+
for (; 't' == char_map[*(uint8_t*)doc->cur]; doc->cur++) {
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
void
|
67
|
+
doc_next_token(Doc doc) {
|
68
|
+
while (true) {
|
69
|
+
doc_skip_white(doc);
|
70
|
+
if ('#' == *doc->cur) {
|
71
|
+
doc_skip_comment(doc);
|
72
|
+
} else {
|
73
|
+
break;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
// Just find end.
|
79
|
+
int
|
80
|
+
doc_read_string(Err err, Doc doc) {
|
81
|
+
doc->cur++; // skip first "
|
82
|
+
if ('"' == *doc->cur) { // a """ string or an empty string
|
83
|
+
doc->cur++;
|
84
|
+
if ('"' != *doc->cur) {
|
85
|
+
return ERR_OK; // empty string
|
86
|
+
}
|
87
|
+
doc->cur++;
|
88
|
+
for (; doc->cur < doc->end; doc->cur++) {
|
89
|
+
if ('"' == *doc->cur && '"' == doc->cur[1] && '"' == doc->cur[2]) {
|
90
|
+
doc->cur += 3;
|
91
|
+
break;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
} else {
|
95
|
+
for (; doc->cur < doc->end; doc->cur++) {
|
96
|
+
if ('"' == *doc->cur) {
|
97
|
+
if ('\\' != doc->cur[-1]) {
|
98
|
+
doc->cur++;
|
99
|
+
break;
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
if (doc->end <= doc->cur) {
|
105
|
+
return doc_err(doc, err, "String not terminated");
|
106
|
+
}
|
107
|
+
return ERR_OK;
|
108
|
+
}
|
109
|
+
|
110
|
+
int
|
111
|
+
doc_err(Doc doc, Err err, const char *fmt, ...) {
|
112
|
+
va_list ap;
|
113
|
+
char msg[248];
|
114
|
+
int line = 0;
|
115
|
+
int col = 0;
|
116
|
+
|
117
|
+
va_start(ap, fmt);
|
118
|
+
vsnprintf(msg, sizeof(msg), fmt, ap);
|
119
|
+
doc_location(doc, &line, &col);
|
120
|
+
va_end(ap);
|
121
|
+
|
122
|
+
return err_set(err, ERR_PARSE, "%s at %d:%d", msg, line, col);
|
123
|
+
}
|
124
|
+
|
125
|
+
void
|
126
|
+
doc_location(Doc doc, int *linep, int *colp) {
|
127
|
+
const char *s;
|
128
|
+
int line = 1;
|
129
|
+
int col = 1;
|
130
|
+
|
131
|
+
for (s = doc->str; s < doc->cur; s++) {
|
132
|
+
switch (*s) {
|
133
|
+
case '\n':
|
134
|
+
line++;
|
135
|
+
col = 1;
|
136
|
+
break;
|
137
|
+
case '\r':
|
138
|
+
if ('\n' == *(s + 1)) {
|
139
|
+
s++;
|
140
|
+
}
|
141
|
+
line++;
|
142
|
+
col = 1;
|
143
|
+
break;
|
144
|
+
default:
|
145
|
+
col++;
|
146
|
+
break;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
*linep = line;
|
150
|
+
*colp = col;
|
151
|
+
}
|
152
|
+
|
153
|
+
gqlValue
|
154
|
+
doc_read_value(Err err, Doc doc) {
|
155
|
+
// TBD handle list and object as well as scalars, object is typeless
|
156
|
+
// TBD put this in doc_read_value
|
157
|
+
return NULL;
|
158
|
+
}
|
159
|
+
|
data/ext/agoo/doc.h
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#ifndef AGOO_DOC_H
|
4
|
+
#define AGOO_DOC_H
|
5
|
+
|
6
|
+
#include <stdarg.h>
|
7
|
+
|
8
|
+
#include "err.h"
|
9
|
+
|
10
|
+
struct _gqlValue;
|
11
|
+
|
12
|
+
typedef struct _Doc {
|
13
|
+
const char *str;
|
14
|
+
const char *cur;
|
15
|
+
const char *end;
|
16
|
+
} *Doc;
|
17
|
+
|
18
|
+
extern void doc_init(Doc doc, const char *str, int len);
|
19
|
+
|
20
|
+
extern int doc_skip_white(Doc doc);
|
21
|
+
extern void doc_skip_comment(Doc doc);
|
22
|
+
extern int doc_read_desc(Err err, Doc doc);
|
23
|
+
|
24
|
+
extern void doc_next_token(Doc doc);
|
25
|
+
extern void doc_read_token(Doc doc);
|
26
|
+
|
27
|
+
extern int doc_read_string(Err err, Doc doc);
|
28
|
+
|
29
|
+
extern int doc_err(Doc doc, Err err, const char *fmt, ...);
|
30
|
+
extern void doc_location(Doc doc, int *linep, int *colp);
|
31
|
+
|
32
|
+
extern struct _gqlValue* doc_read_value(Err err, Doc doc);
|
33
|
+
|
34
|
+
#endif // AGOO_DOC_H
|
data/ext/agoo/dtime.h
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
// Copyright 2009, 2015, 2018, 2016 by Peter Ohler, All Rights Reserved
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_DTIME_H
|
4
|
+
#define AGOO_DTIME_H
|
5
5
|
|
6
6
|
extern double dtime(void);
|
7
7
|
extern double dsleep(double t);
|
8
8
|
extern double dwait(double t);
|
9
9
|
|
10
|
-
#endif /*
|
10
|
+
#endif /* AGOO_DTIME_H */
|
data/ext/agoo/err.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_ERR_H
|
4
|
+
#define AGOO_ERR_H
|
5
5
|
|
6
6
|
#include <errno.h>
|
7
7
|
|
@@ -42,4 +42,4 @@ extern int err_no(Err err, const char *fmt, ...);
|
|
42
42
|
extern const char* err_str(ErrCode code);
|
43
43
|
extern void err_clear(Err err);
|
44
44
|
|
45
|
-
#endif /*
|
45
|
+
#endif /* AGOO_ERR_H */
|
data/ext/agoo/error_stream.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_ERROR_STREAM_H
|
4
|
+
#define AGOO_ERROR_STREAM_H
|
5
5
|
|
6
6
|
#include <ruby.h>
|
7
7
|
|
@@ -10,4 +10,4 @@
|
|
10
10
|
extern void error_stream_init(VALUE mod);
|
11
11
|
extern VALUE error_stream_new();
|
12
12
|
|
13
|
-
#endif //
|
13
|
+
#endif // AGOO_ERROR_STREAM_H
|
data/ext/agoo/extconf.rb
CHANGED
@@ -4,7 +4,7 @@ require 'rbconfig'
|
|
4
4
|
extension_name = 'agoo'
|
5
5
|
dir_config(extension_name)
|
6
6
|
|
7
|
-
$
|
7
|
+
$CFLAGS += " -DPLATFORM_LINUX" if 'x86_64-linux' == RUBY_PLATFORM
|
8
8
|
|
9
9
|
# Adding the __attribute__ flag only works with gcc compilers and even then it
|
10
10
|
# does not work to check args with varargs s just remove the check.
|
data/ext/agoo/gqlintro.c
ADDED
@@ -0,0 +1,333 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <string.h>
|
5
|
+
|
6
|
+
#include "gqlintro.h"
|
7
|
+
#include "gqlvalue.h"
|
8
|
+
#include "graphql.h"
|
9
|
+
|
10
|
+
static gqlType schema_type;
|
11
|
+
static gqlType type_type;
|
12
|
+
static gqlType type_kind_type;
|
13
|
+
static gqlType field_type;
|
14
|
+
static gqlType input_value_type;
|
15
|
+
static gqlType enum_value_type;
|
16
|
+
static gqlType directive_type;
|
17
|
+
static gqlType directive_location_type;
|
18
|
+
|
19
|
+
// type __Schema {
|
20
|
+
// types: [__Type!]!
|
21
|
+
// queryType: __Type!
|
22
|
+
// mutationType: __Type
|
23
|
+
// subscriptionType: __Type
|
24
|
+
// directives: [__Directive!]!
|
25
|
+
// }
|
26
|
+
static gqlRef
|
27
|
+
schema_types_resolve(gqlRef target, const char *fieldName, gqlKeyVal *args) {
|
28
|
+
// TBD
|
29
|
+
return NULL;
|
30
|
+
}
|
31
|
+
|
32
|
+
static gqlRef
|
33
|
+
schema_query_type_resolve(gqlRef target, const char *fieldName, gqlKeyVal *args) {
|
34
|
+
// TBD return schema_type.query.type
|
35
|
+
// lookup "schema" type
|
36
|
+
// get query field
|
37
|
+
// get return type of field
|
38
|
+
return NULL;
|
39
|
+
}
|
40
|
+
|
41
|
+
static int
|
42
|
+
create_schema_type(Err err) {
|
43
|
+
if (NULL == (schema_type = gql_type_create(err, "__Schema", NULL, -1, true, NULL)) ||
|
44
|
+
NULL == gql_type_field(err, schema_type, "types", type_type, NULL, true, true, true, schema_types_resolve) ||
|
45
|
+
NULL == gql_type_field(err, schema_type, "queryType", type_type, NULL, true, false, false, schema_query_type_resolve) ||
|
46
|
+
NULL == gql_type_field(err, schema_type, "mutationType", type_type, NULL, false, false, false, NULL) ||
|
47
|
+
NULL == gql_type_field(err, schema_type, "subscriptionType", type_type, NULL, false, false, false, NULL) ||
|
48
|
+
NULL == gql_type_field(err, schema_type, "directives", directive_type, NULL, true, true, true, NULL)) {
|
49
|
+
|
50
|
+
return err->code;
|
51
|
+
}
|
52
|
+
schema_type->core = true;
|
53
|
+
|
54
|
+
return ERR_OK;
|
55
|
+
}
|
56
|
+
|
57
|
+
// type __Type {
|
58
|
+
// kind: __TypeKind!
|
59
|
+
// name: String
|
60
|
+
// description: String
|
61
|
+
// fields(includeDeprecated: Boolean = false): [__Field!]
|
62
|
+
// interfaces: [__Type!]
|
63
|
+
// possibleTypes: [__Type!]
|
64
|
+
// enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
|
65
|
+
// inputFields: [__InputValue!]
|
66
|
+
// ofType: __Type
|
67
|
+
// }
|
68
|
+
static int
|
69
|
+
create_type_type(Err err) {
|
70
|
+
gqlField fields = NULL;
|
71
|
+
gqlField enum_values = NULL;
|
72
|
+
gqlValue dv;
|
73
|
+
|
74
|
+
if (NULL == (type_type = gql_type_create(err, "__Type", NULL, -1, true, NULL)) ||
|
75
|
+
NULL == gql_type_field(err, type_type, "kind", type_kind_type, NULL, true, false, false, NULL) ||
|
76
|
+
NULL == gql_type_field(err, type_type, "name", &gql_string_type, NULL, false, false, false, NULL) ||
|
77
|
+
NULL == gql_type_field(err, type_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
|
78
|
+
NULL == (fields = gql_type_field(err, type_type, "fields", field_type, NULL, false, true, true, NULL)) ||
|
79
|
+
NULL == gql_type_field(err, type_type, "interfaces", type_type, NULL, false, true, true, NULL) ||
|
80
|
+
NULL == gql_type_field(err, type_type, "possibleTypes", type_type, NULL, false, true, true, NULL) ||
|
81
|
+
NULL == (enum_values = gql_type_field(err, type_type, "enumValues", enum_value_type, NULL, false, true, true, NULL)) ||
|
82
|
+
NULL == gql_type_field(err, type_type, "inputFields", input_value_type, NULL, false, true, true, NULL) ||
|
83
|
+
NULL == gql_type_field(err, type_type, "ofType", type_type, NULL, false, false, false, NULL)) {
|
84
|
+
|
85
|
+
return err->code;
|
86
|
+
}
|
87
|
+
type_type->core = true;
|
88
|
+
|
89
|
+
if (NULL == (dv = gql_bool_create(err, false)) ||
|
90
|
+
NULL == gql_field_arg(err, fields, "includeDeprecated", &gql_bool_type, NULL, dv, false) ||
|
91
|
+
NULL == (dv = gql_bool_create(err, false)) ||
|
92
|
+
NULL == gql_field_arg(err, enum_values, "includeDeprecated", &gql_bool_type, NULL, dv, false)) {
|
93
|
+
|
94
|
+
return err->code;
|
95
|
+
}
|
96
|
+
return ERR_OK;
|
97
|
+
}
|
98
|
+
|
99
|
+
static int
|
100
|
+
create_type_kind_type(Err err) {
|
101
|
+
const char *choices[] = {
|
102
|
+
"SCALAR",
|
103
|
+
"OBJECT",
|
104
|
+
"INTERFACE",
|
105
|
+
"UNION",
|
106
|
+
"ENUM",
|
107
|
+
"INPUT_OBJECT",
|
108
|
+
"LIST",
|
109
|
+
"NON_NULL",
|
110
|
+
NULL
|
111
|
+
};
|
112
|
+
const char **cp;
|
113
|
+
|
114
|
+
type_kind_type = gql_enum_create(err, "__TypeKind", NULL, -1, true);
|
115
|
+
type_kind_type->core = true;
|
116
|
+
for (cp = choices; NULL != *cp; cp++) {
|
117
|
+
if (ERR_OK != gql_enum_append(err, type_kind_type, *cp, -1)) {
|
118
|
+
return err->code;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
return err->code;
|
122
|
+
}
|
123
|
+
|
124
|
+
// type __Field {
|
125
|
+
// name: String!
|
126
|
+
// description: String
|
127
|
+
// args: [__InputValue!]!
|
128
|
+
// type: __Type!
|
129
|
+
// isDeprecated: Boolean!
|
130
|
+
// deprecationReason: String
|
131
|
+
// }
|
132
|
+
static int
|
133
|
+
create_field_type(Err err) {
|
134
|
+
if (NULL == (field_type = gql_type_create(err, "__Field", NULL, -1, true, NULL)) ||
|
135
|
+
NULL == gql_type_field(err, field_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
|
136
|
+
NULL == gql_type_field(err, field_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
|
137
|
+
NULL == gql_type_field(err, field_type, "args", input_value_type, NULL, true, true, true, NULL) ||
|
138
|
+
NULL == gql_type_field(err, field_type, "type", type_type, NULL, true, false, false, NULL) ||
|
139
|
+
NULL == gql_type_field(err, field_type, "isDeprecated", &gql_bool_type, NULL, true, false, false, NULL) ||
|
140
|
+
NULL == gql_type_field(err, field_type, "reason", &gql_string_type, NULL, false, false, false, NULL)) {
|
141
|
+
|
142
|
+
return err->code;
|
143
|
+
}
|
144
|
+
field_type->core = true;
|
145
|
+
|
146
|
+
return ERR_OK;
|
147
|
+
}
|
148
|
+
|
149
|
+
// type __InputValue {
|
150
|
+
// name: String!
|
151
|
+
// description: String
|
152
|
+
// type: __Type!
|
153
|
+
// defaultValue: String
|
154
|
+
// }
|
155
|
+
static int
|
156
|
+
create_input_type(Err err) {
|
157
|
+
if (NULL == (input_value_type = gql_type_create(err, "__InputValue", NULL, -1, true, NULL)) ||
|
158
|
+
NULL == gql_type_field(err, input_value_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
|
159
|
+
NULL == gql_type_field(err, input_value_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
|
160
|
+
NULL == gql_type_field(err, input_value_type, "type", type_type, NULL, true, false, false, NULL) ||
|
161
|
+
NULL == gql_type_field(err, input_value_type, "defaultValue", &gql_string_type, NULL, false, false, false, NULL)) {
|
162
|
+
|
163
|
+
return err->code;
|
164
|
+
}
|
165
|
+
input_value_type->core = true;
|
166
|
+
|
167
|
+
return ERR_OK;
|
168
|
+
}
|
169
|
+
|
170
|
+
// type __EnumValue {
|
171
|
+
// name: String!
|
172
|
+
// description: String
|
173
|
+
// isDeprecated: Boolean!
|
174
|
+
// deprecationReason: String
|
175
|
+
// }
|
176
|
+
static int
|
177
|
+
create_enum_type(Err err) {
|
178
|
+
if (NULL == (enum_value_type = gql_type_create(err, "__EnumValue", NULL, -1, true, NULL)) ||
|
179
|
+
NULL == gql_type_field(err, enum_value_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
|
180
|
+
NULL == gql_type_field(err, enum_value_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
|
181
|
+
NULL == gql_type_field(err, enum_value_type, "isDeprecated", &gql_bool_type, NULL, true, false, false, NULL) ||
|
182
|
+
NULL == gql_type_field(err, enum_value_type, "deprecationReason", &gql_string_type, NULL, false, false, false, NULL)) {
|
183
|
+
|
184
|
+
return err->code;
|
185
|
+
}
|
186
|
+
enum_value_type->core = true;
|
187
|
+
|
188
|
+
return ERR_OK;
|
189
|
+
}
|
190
|
+
|
191
|
+
// type __Directive {
|
192
|
+
// name: String!
|
193
|
+
// description: String
|
194
|
+
// locations: [__DirectiveLocation!]!
|
195
|
+
// args: [__InputValue!]!
|
196
|
+
// }
|
197
|
+
static int
|
198
|
+
create_directive_type(Err err) {
|
199
|
+
if (NULL == (directive_type = gql_type_create(err, "__Directive", NULL, -1, true, NULL)) ||
|
200
|
+
NULL == gql_type_field(err, directive_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
|
201
|
+
NULL == gql_type_field(err, directive_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
|
202
|
+
NULL == gql_type_field(err, directive_type, "location", directive_location_type, NULL, true, true, true, NULL) ||
|
203
|
+
NULL == gql_type_field(err, directive_type, "args", input_value_type, NULL, true, true, true, NULL)) {
|
204
|
+
|
205
|
+
return err->code;
|
206
|
+
}
|
207
|
+
directive_type->core = true;
|
208
|
+
|
209
|
+
return ERR_OK;
|
210
|
+
}
|
211
|
+
|
212
|
+
static int
|
213
|
+
create_directive_location_type(Err err) {
|
214
|
+
const char *choices[] = {
|
215
|
+
"QUERY",
|
216
|
+
"MUTATION",
|
217
|
+
"SUBSCRIPTION",
|
218
|
+
"FIELD",
|
219
|
+
"FRAGMENT_DEFINITION",
|
220
|
+
"FRAGMENT_SPREAD",
|
221
|
+
"INLINE_FRAGMENT",
|
222
|
+
"SCHEMA",
|
223
|
+
"SCALAR",
|
224
|
+
"OBJECT",
|
225
|
+
"FIELD_DEFINITION",
|
226
|
+
"ARGUMENT_DEFINITION",
|
227
|
+
"INTERFACE",
|
228
|
+
"UNION",
|
229
|
+
"ENUM",
|
230
|
+
"ENUM_VALUE",
|
231
|
+
"INPUT_OBJECT",
|
232
|
+
"INPUT_FIELD_DEFINITION",
|
233
|
+
NULL };
|
234
|
+
const char **cp;
|
235
|
+
|
236
|
+
directive_location_type = gql_enum_create(err, "__DirectiveLocation", NULL, -1, true);
|
237
|
+
directive_location_type->core = true;
|
238
|
+
for (cp = choices; NULL != *cp; cp++) {
|
239
|
+
if (ERR_OK != gql_enum_append(err, directive_location_type, *cp, -1)) {
|
240
|
+
return err->code;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
return err->code;
|
244
|
+
}
|
245
|
+
|
246
|
+
static int
|
247
|
+
create_dir_skip(Err err) {
|
248
|
+
gqlDir dir = gql_directive_create(err, "skip", NULL, -1, true);
|
249
|
+
|
250
|
+
if (NULL == dir) {
|
251
|
+
return err->code;
|
252
|
+
}
|
253
|
+
if (ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
|
254
|
+
ERR_OK != gql_directive_on(err, dir, "FRAGMENT_SPREAD", -1) ||
|
255
|
+
ERR_OK != gql_directive_on(err, dir, "INLINE_FRAGMENT", -1) ||
|
256
|
+
NULL == gql_dir_arg(err, dir, "if", "Boolean", NULL, -1, NULL, true)) {
|
257
|
+
|
258
|
+
return err->code;
|
259
|
+
}
|
260
|
+
return ERR_OK;
|
261
|
+
}
|
262
|
+
|
263
|
+
static int
|
264
|
+
create_dir_include(Err err) {
|
265
|
+
gqlDir dir = gql_directive_create(err, "include", NULL, -1, true);
|
266
|
+
|
267
|
+
if (NULL == dir) {
|
268
|
+
return err->code;
|
269
|
+
}
|
270
|
+
if (ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
|
271
|
+
ERR_OK != gql_directive_on(err, dir, "FRAGMENT_SPREAD", -1) ||
|
272
|
+
ERR_OK != gql_directive_on(err, dir, "INLINE_FRAGMENT", -1) ||
|
273
|
+
NULL == gql_dir_arg(err, dir, "if", "Boolean", NULL, -1, NULL, true)) {
|
274
|
+
|
275
|
+
return err->code;
|
276
|
+
}
|
277
|
+
return ERR_OK;
|
278
|
+
}
|
279
|
+
|
280
|
+
static int
|
281
|
+
create_dir_deprecated(Err err) {
|
282
|
+
gqlDir dir = gql_directive_create(err, "deprecated", NULL, -1, true);
|
283
|
+
gqlValue dv;
|
284
|
+
|
285
|
+
if (NULL == dir) {
|
286
|
+
return err->code;
|
287
|
+
}
|
288
|
+
if (ERR_OK != gql_directive_on(err, dir, "FIELD_DEFINITION", -1) ||
|
289
|
+
ERR_OK != gql_directive_on(err, dir, "ENUM_VALUE", -1) ||
|
290
|
+
NULL == (dv = gql_string_create(err, "No longer supported", -1)) ||
|
291
|
+
NULL == gql_dir_arg(err, dir, "reason", "String", NULL, -1, dv, false)) {
|
292
|
+
|
293
|
+
return err->code;
|
294
|
+
}
|
295
|
+
return ERR_OK;
|
296
|
+
}
|
297
|
+
|
298
|
+
int
|
299
|
+
gql_intro_init(Err err) {
|
300
|
+
gqlField f;
|
301
|
+
|
302
|
+
if (ERR_OK != create_type_kind_type(err) ||
|
303
|
+
ERR_OK != create_input_type(err) ||
|
304
|
+
ERR_OK != create_type_type(err) ||
|
305
|
+
ERR_OK != create_enum_type(err) ||
|
306
|
+
ERR_OK != create_field_type(err) ||
|
307
|
+
ERR_OK != create_directive_location_type(err) ||
|
308
|
+
ERR_OK != create_directive_type(err) ||
|
309
|
+
ERR_OK != create_schema_type(err) ||
|
310
|
+
ERR_OK != create_dir_deprecated(err) ||
|
311
|
+
ERR_OK != create_dir_include(err) ||
|
312
|
+
ERR_OK != create_dir_skip(err)) {
|
313
|
+
|
314
|
+
return err->code;
|
315
|
+
}
|
316
|
+
// InputValue and Type as well Field and Type as have a depency loop so
|
317
|
+
// complete the loop.
|
318
|
+
for (f = input_value_type->fields; NULL != f; f = f->next) {
|
319
|
+
if (0 == strcmp("type", f->name)) {
|
320
|
+
f->type = type_type;
|
321
|
+
break;
|
322
|
+
}
|
323
|
+
}
|
324
|
+
for (f = type_type->fields; NULL != f; f = f->next) {
|
325
|
+
if (0 == strcmp("fields", f->name)) {
|
326
|
+
f->type = field_type;
|
327
|
+
} else if (0 == strcmp("enumValues", f->name)) {
|
328
|
+
f->type = enum_value_type;
|
329
|
+
break;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
return ERR_OK;
|
333
|
+
}
|