diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-08 22:02:14 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-08 22:02:58 +0300 |
commit | 496122b446d2084f6117e2b8704d7c9ec6706422 (patch) | |
tree | b379efe7f6a2ed530ec9a9bc982e7f48cbd3a29a /src/gmrequest.c | |
parent | 7b98d7af353c31706d5d6b20ff7d65272f8b7445 (diff) |
Handling "about:home"; GmRequest decoupling
GmRequest is given a pointer to the GmCerts to use. Also, timeouts are handled via a posted command so they get processed in the main thread.
Diffstat (limited to 'src/gmrequest.c')
-rw-r--r-- | src/gmrequest.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c index 7cc8b897..1a6476ba 100644 --- a/src/gmrequest.c +++ b/src/gmrequest.c | |||
@@ -1,11 +1,12 @@ | |||
1 | #include "gmrequest.h" | 1 | #include "gmrequest.h" |
2 | #include "gmutil.h" | 2 | #include "gmutil.h" |
3 | #include "gmcerts.h" | 3 | #include "gmcerts.h" |
4 | #include "app.h" | 4 | #include "app.h" /* dataDir_App() */ |
5 | 5 | ||
6 | #include <the_Foundation/file.h> | 6 | #include <the_Foundation/file.h> |
7 | #include <the_Foundation/tlsrequest.h> | 7 | #include <the_Foundation/tlsrequest.h> |
8 | #include <the_Foundation/mutex.h> | 8 | #include <the_Foundation/mutex.h> |
9 | #include <the_Foundation/path.h> | ||
9 | 10 | ||
10 | #include <SDL_timer.h> | 11 | #include <SDL_timer.h> |
11 | 12 | ||
@@ -62,30 +63,35 @@ enum iGmRequestState { | |||
62 | }; | 63 | }; |
63 | 64 | ||
64 | struct Impl_GmRequest { | 65 | struct Impl_GmRequest { |
65 | iObject object; | 66 | iObject object; |
66 | iMutex mutex; | 67 | iMutex mutex; |
67 | enum iGmRequestState state; | 68 | iGmCerts * certs; /* not owned */ |
68 | iString url; | 69 | enum iGmRequestState state; |
69 | iTlsRequest *req; | 70 | iString url; |
70 | iGmResponse resp; | 71 | iTlsRequest * req; |
71 | uint32_t timeoutId; /* in case server doesn't close the connection */ | 72 | iGmResponse resp; |
72 | iAudience *updated; | 73 | uint32_t timeoutId; /* in case server doesn't close the connection */ |
73 | iAudience *finished; | 74 | iAudience * updated; |
75 | iAudience * timeout; | ||
76 | iAudience * finished; | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | iDefineObjectConstruction(GmRequest) | 79 | iDefineObjectConstructionArgs(GmRequest, (iGmCerts *certs), certs) |
77 | iDefineAudienceGetter(GmRequest, updated) | 80 | iDefineAudienceGetter(GmRequest, updated) |
81 | iDefineAudienceGetter(GmRequest, timeout) | ||
78 | iDefineAudienceGetter(GmRequest, finished) | 82 | iDefineAudienceGetter(GmRequest, finished) |
79 | 83 | ||
80 | void init_GmRequest(iGmRequest *d) { | 84 | void init_GmRequest(iGmRequest *d, iGmCerts *certs) { |
81 | init_Mutex(&d->mutex); | 85 | init_Mutex(&d->mutex); |
82 | d->state = initialized_GmRequestState; | ||
83 | init_GmResponse(&d->resp); | 86 | init_GmResponse(&d->resp); |
84 | init_String(&d->url); | 87 | init_String(&d->url); |
85 | d->req = NULL; | 88 | d->certs = certs; |
86 | d->timeoutId = 0; | 89 | d->timeoutId = 0; |
87 | d->updated = NULL; | 90 | d->req = NULL; |
88 | d->finished = NULL; | 91 | d->state = initialized_GmRequestState; |
92 | d->updated = NULL; | ||
93 | d->timeout = NULL; | ||
94 | d->finished = NULL; | ||
89 | } | 95 | } |
90 | 96 | ||
91 | void deinit_GmRequest(iGmRequest *d) { | 97 | void deinit_GmRequest(iGmRequest *d) { |
@@ -107,6 +113,7 @@ void deinit_GmRequest(iGmRequest *d) { | |||
107 | } | 113 | } |
108 | iRelease(d->req); | 114 | iRelease(d->req); |
109 | d->req = NULL; | 115 | d->req = NULL; |
116 | delete_Audience(d->timeout); | ||
110 | delete_Audience(d->finished); | 117 | delete_Audience(d->finished); |
111 | delete_Audience(d->updated); | 118 | delete_Audience(d->updated); |
112 | deinit_GmResponse(&d->resp); | 119 | deinit_GmResponse(&d->resp); |
@@ -121,7 +128,9 @@ void setUrl_GmRequest(iGmRequest *d, const iString *url) { | |||
121 | 128 | ||
122 | static uint32_t timedOutWhileReceivingBody_GmRequest_(uint32_t interval, void *obj) { | 129 | static uint32_t timedOutWhileReceivingBody_GmRequest_(uint32_t interval, void *obj) { |
123 | /* Note: Called from SDL's timer thread. */ | 130 | /* Note: Called from SDL's timer thread. */ |
124 | postCommandf_App("gmrequest.timeout request:%p", obj); | 131 | iGmRequest *d = obj; |
132 | //postCommandf_App("gmrequest.timeout request:%p", obj); | ||
133 | iNotifyAudience(d, timeout, GmRequestTimeout); | ||
125 | iUnused(interval); | 134 | iUnused(interval); |
126 | return 0; | 135 | return 0; |
127 | } | 136 | } |
@@ -142,7 +151,6 @@ static void checkServerCertificate_GmRequest_(iGmRequest *d) { | |||
142 | const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req); | 151 | const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req); |
143 | d->resp.certFlags = 0; | 152 | d->resp.certFlags = 0; |
144 | if (cert) { | 153 | if (cert) { |
145 | iGmCerts * certDb = certs_App(); | ||
146 | const iRangecc domain = urlHost_String(&d->url); | 154 | const iRangecc domain = urlHost_String(&d->url); |
147 | d->resp.certFlags |= available_GmCertFlag; | 155 | d->resp.certFlags |= available_GmCertFlag; |
148 | if (!isExpired_TlsCertificate(cert)) { | 156 | if (!isExpired_TlsCertificate(cert)) { |
@@ -151,7 +159,7 @@ static void checkServerCertificate_GmRequest_(iGmRequest *d) { | |||
151 | if (verifyDomain_TlsCertificate(cert, domain)) { | 159 | if (verifyDomain_TlsCertificate(cert, domain)) { |
152 | d->resp.certFlags |= domainVerified_GmCertFlag; | 160 | d->resp.certFlags |= domainVerified_GmCertFlag; |
153 | } | 161 | } |
154 | if (checkTrust_GmCerts(certDb, domain, cert)) { | 162 | if (checkTrust_GmCerts(d->certs, domain, cert)) { |
155 | d->resp.certFlags |= trusted_GmCertFlag; | 163 | d->resp.certFlags |= trusted_GmCertFlag; |
156 | } | 164 | } |
157 | validUntil_TlsCertificate(cert, &d->resp.certValidUntil); | 165 | validUntil_TlsCertificate(cert, &d->resp.certValidUntil); |
@@ -243,7 +251,39 @@ void submit_GmRequest(iGmRequest *d) { | |||
243 | clear_GmResponse(&d->resp); | 251 | clear_GmResponse(&d->resp); |
244 | iUrl url; | 252 | iUrl url; |
245 | init_Url(&url, &d->url); | 253 | init_Url(&url, &d->url); |
246 | if (equalCase_Rangecc(&url.protocol, "file")) { | 254 | /* Check for special protocols. */ |
255 | /* TODO: If this were a library, these could be handled via callbacks. */ | ||
256 | if (equalCase_Rangecc(&url.protocol, "about")) { | ||
257 | if (equalCase_Rangecc(&url.path, "home")) { | ||
258 | d->resp.statusCode = success_GmStatusCode; | ||
259 | setCStr_String(&d->resp.meta, "text/gemini; charset=utf-8"); | ||
260 | setCStr_Block(&d->resp.body, | ||
261 | "```\n" | ||
262 | "ooooo \n" | ||
263 | "`888' \n" | ||
264 | " 888 .oooo. .oooooooo oooo d8b .oooo. ooo. .oo. .oooooooo .ooooo. \n" | ||
265 | " 888 `P )88b 888' `88b `888\"\"8P `P )88b `888P\"Y88b 888' `88b d88' `88b \n" | ||
266 | " 888 .oP\"888 888 888 888 .oP\"888 888 888 888 888 888ooo888 \n" | ||
267 | " 888 o d8( 888 `88bod8P' 888 d8( 888 888 888 `88bod8P' 888 .o \n" | ||
268 | "o888ooooood8 `Y888\"\"8o `8oooooo. d888b `Y888\"\"8o o888o o888o `8oooooo. `Y8bod8P' \n" | ||
269 | " d\" YD d\" YD \n" | ||
270 | " \"Y88888P' \"Y88888P' \n" | ||
271 | "```\n" | ||
272 | "# A Beautiful Gemini Browser\n" | ||
273 | "## Version " LAGRANGE_APP_VERSION "\n\n" | ||
274 | "=> https://skyjake.fi/@jk by Jaakko Keränen <code@iki.fi>\n" | ||
275 | "Crafted with \u2615 in Finland\n"); | ||
276 | d->state = receivingBody_GmRequestState; | ||
277 | iNotifyAudience(d, updated, GmRequestUpdated); | ||
278 | } | ||
279 | else { | ||
280 | d->resp.statusCode = invalidLocalResource_GmStatusCode; | ||
281 | } | ||
282 | d->state = finished_GmRequestState; | ||
283 | iNotifyAudience(d, finished, GmRequestFinished); | ||
284 | return; | ||
285 | } | ||
286 | else if (equalCase_Rangecc(&url.protocol, "file")) { | ||
247 | iString *path = collect_String(urlDecode_String(collect_String(newRange_String(url.path)))); | 287 | iString *path = collect_String(urlDecode_String(collect_String(newRange_String(url.path)))); |
248 | iFile * f = new_File(path); | 288 | iFile * f = new_File(path); |
249 | if (open_File(f, readOnly_FileMode)) { | 289 | if (open_File(f, readOnly_FileMode)) { |