summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-07-16 22:55:07 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-07-16 22:55:07 +0300
commit0d9c3c4cb9bc9571cd3c38446c720f93e36cc8ad (patch)
tree7787e4433b49b8196cf8725bb27a2c9eb41a6fbb /src
parentb89dc234998b75c67cf3cd080102f623519496c8 (diff)
GmRequest: Support for Titan payloads
Diffstat (limited to 'src')
-rw-r--r--src/gmrequest.c91
-rw-r--r--src/gmrequest.h2
2 files changed, 82 insertions, 11 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c
index 44ef063f..1d84ef47 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -118,6 +118,31 @@ void deserialize_GmResponse(iGmResponse *d, iStream *ins) {
118 118
119/*----------------------------------------------------------------------------------------------*/ 119/*----------------------------------------------------------------------------------------------*/
120 120
121iDeclareType(TitanData)
122iDeclareTypeConstruction(TitanData)
123
124struct Impl_TitanData {
125 iBlock data;
126 iString mime;
127 iString token;
128};
129
130iDefineTypeConstruction(TitanData)
131
132void init_TitanData(iTitanData *d) {
133 init_Block(&d->data, 0);
134 init_String(&d->mime);
135 init_String(&d->token);
136}
137
138void deinit_TitanData(iTitanData *d) {
139 deinit_String(&d->token);
140 deinit_String(&d->mime);
141 deinit_Block(&d->data);
142}
143
144/*----------------------------------------------------------------------------------------------*/
145
121static iAtomicInt idGen_; 146static iAtomicInt idGen_;
122 147
123enum iGmRequestState { 148enum iGmRequestState {
@@ -135,6 +160,7 @@ struct Impl_GmRequest {
135 iGmCerts * certs; /* not owned */ 160 iGmCerts * certs; /* not owned */
136 enum iGmRequestState state; 161 enum iGmRequestState state;
137 iString url; 162 iString url;
163 iTitanData * titan;
138 iTlsRequest * req; 164 iTlsRequest * req;
139 iGopher gopher; 165 iGopher gopher;
140 iGmResponse * resp; 166 iGmResponse * resp;
@@ -498,20 +524,21 @@ static void beginGopherConnection_GmRequest_(iGmRequest *d, const iString *host,
498/*----------------------------------------------------------------------------------------------*/ 524/*----------------------------------------------------------------------------------------------*/
499 525
500void init_GmRequest(iGmRequest *d, iGmCerts *certs) { 526void init_GmRequest(iGmRequest *d, iGmCerts *certs) {
501 d->mtx = new_Mutex(); 527 d->mtx = new_Mutex();
502 d->id = add_Atomic(&idGen_, 1) + 1; 528 d->id = add_Atomic(&idGen_, 1) + 1;
503 d->resp = new_GmResponse(); 529 d->resp = new_GmResponse();
504 d->isFilterEnabled = iTrue; 530 d->isFilterEnabled = iTrue;
505 d->isRespLocked = iFalse; 531 d->isRespLocked = iFalse;
506 d->isRespFiltered = iFalse; 532 d->isRespFiltered = iFalse;
507 set_Atomic(&d->allowUpdate, iTrue); 533 set_Atomic(&d->allowUpdate, iTrue);
508 init_String(&d->url); 534 init_String(&d->url);
509 init_Gopher(&d->gopher); 535 init_Gopher(&d->gopher);
510 d->certs = certs; 536 d->titan = NULL;
511 d->req = NULL; 537 d->certs = certs;
512 d->updated = NULL; 538 d->req = NULL;
513 d->finished = NULL; 539 d->updated = NULL;
514 d->state = initialized_GmRequestState; 540 d->finished = NULL;
541 d->state = initialized_GmRequestState;
515} 542}
516 543
517void deinit_GmRequest(iGmRequest *d) { 544void deinit_GmRequest(iGmRequest *d) {
@@ -529,6 +556,7 @@ void deinit_GmRequest(iGmRequest *d) {
529 unlock_Mutex(d->mtx); 556 unlock_Mutex(d->mtx);
530 } 557 }
531 iReleasePtr(&d->req); 558 iReleasePtr(&d->req);
559 delete_TitanData(d->titan);
532 deinit_Gopher(&d->gopher); 560 deinit_Gopher(&d->gopher);
533 delete_Audience(d->finished); 561 delete_Audience(d->finished);
534 delete_Audience(d->updated); 562 delete_Audience(d->updated);
@@ -553,6 +581,20 @@ void setUrl_GmRequest(iGmRequest *d, const iString *url) {
553 urlEncodeSpaces_String(&d->url); 581 urlEncodeSpaces_String(&d->url);
554} 582}
555 583
584static iBool isTitan_GmRequest_(const iGmRequest *d) {
585 return equalCase_Rangecc(urlScheme_String(&d->url), "titan");
586}
587
588void setTitanData_GmRequest(iGmRequest *d, const iString *mime, const iBlock *payload,
589 const iString *token) {
590 if (!d->titan) {
591 d->titan = new_TitanData();
592 }
593 set_Block(&d->titan->data, payload);
594 set_String(&d->titan->mime, mime);
595 set_String(&d->titan->token, token);
596}
597
556static iBool isDirectory_(const iString *path) { 598static iBool isDirectory_(const iString *path) {
557 /* TODO: move this to the_Foundation */ 599 /* TODO: move this to the_Foundation */
558 iFileInfo *info = new_FileInfo(path); 600 iFileInfo *info = new_FileInfo(path);
@@ -837,7 +879,8 @@ void submit_GmRequest(iGmRequest *d) {
837 beginGopherConnection_GmRequest_(d, host, port ? port : 79); 879 beginGopherConnection_GmRequest_(d, host, port ? port : 79);
838 return; 880 return;
839 } 881 }
840 else if (!equalCase_Rangecc(url.scheme, "gemini")) { 882 else if (!equalCase_Rangecc(url.scheme, "gemini") &&
883 !equalCase_Rangecc(url.scheme, "titan")) {
841 resp->statusCode = unsupportedProtocol_GmStatusCode; 884 resp->statusCode = unsupportedProtocol_GmStatusCode;
842 d->state = finished_GmRequestState; 885 d->state = finished_GmRequestState;
843 iNotifyAudience(d, finished, GmRequestFinished); 886 iNotifyAudience(d, finished, GmRequestFinished);
@@ -855,8 +898,34 @@ void submit_GmRequest(iGmRequest *d) {
855 port = GEMINI_DEFAULT_PORT; /* default Gemini port */ 898 port = GEMINI_DEFAULT_PORT; /* default Gemini port */
856 } 899 }
857 setHost_TlsRequest(d->req, host, port); 900 setHost_TlsRequest(d->req, host, port);
858 setContent_TlsRequest(d->req, 901 /* Titan requests can have an arbitrary payload. */
859 utf8_String(collectNewFormat_String("%s\r\n", cstr_String(&d->url)))); 902 if (isTitan_GmRequest_(d)) {
903 iBlock content;
904 initCopy_Block(&content, utf8_String(&d->url));
905 if (d->titan) {
906 printf_Block(&content,
907 ";mime=%s;size=%zu",
908 cstr_String(&d->titan->mime),
909 size_Block(&d->titan->data));
910 if (!isEmpty_String(&d->titan->token)) {
911 appendCStr_Block(&content, ";token=");
912 append_Block(&content, utf8_String(&d->titan->token));
913 }
914 appendCStr_Block(&content, "\r\n");
915 append_Block(&content, &d->titan->data);
916 }
917 else {
918 /* Empty data. */
919 appendCStr_Block(&content, ";mime=application/octet-stream;size=0\r\n");
920 }
921 setContent_TlsRequest(d->req, &content);
922 deinit_Block(&content);
923 }
924 else {
925 /* Gemini request. */
926 setContent_TlsRequest(d->req,
927 utf8_String(collectNewFormat_String("%s\r\n", cstr_String(&d->url))));
928 }
860 submit_TlsRequest(d->req); 929 submit_TlsRequest(d->req);
861} 930}
862 931
diff --git a/src/gmrequest.h b/src/gmrequest.h
index 0cba4ea3..48b672ef 100644
--- a/src/gmrequest.h
+++ b/src/gmrequest.h
@@ -67,6 +67,8 @@ iDeclareAudienceGetter(GmRequest, finished)
67 67
68void enableFilters_GmRequest (iGmRequest *, iBool enable); 68void enableFilters_GmRequest (iGmRequest *, iBool enable);
69void setUrl_GmRequest (iGmRequest *, const iString *url); 69void setUrl_GmRequest (iGmRequest *, const iString *url);
70void setTitanData_GmRequest (iGmRequest *, const iString *mime,
71 const iBlock *payload, const iString *token);
70void submit_GmRequest (iGmRequest *); 72void submit_GmRequest (iGmRequest *);
71void cancel_GmRequest (iGmRequest *); 73void cancel_GmRequest (iGmRequest *);
72 74