Skip to content
This repository was archived by the owner on Jan 7, 2021. It is now read-only.

Commit 1fc170e

Browse files
committed
download functions rewrite/cleanup
1 parent 8eec266 commit 1fc170e

2 files changed

Lines changed: 114 additions & 128 deletions

File tree

source/download.c

Lines changed: 108 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,153 @@
11
#include "download.h"
2-
3-
Result downloadToBuffer(const char * url, u8 ** buf, u32 * bufsize)
4-
{
52

6-
httpcContext context;
3+
Result setupContext(httpcContext * context, const char * url, u32 * size)
4+
{
75
Result ret = 0;
8-
char * newurl = NULL;
96
u32 statuscode = 0;
10-
u32 contentsize = 0, readsize = 0, size = 0;
11-
u8 * lastbuf = NULL;
127

13-
do {
14-
ret = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 1);
15-
ret = httpcAddRequestHeaderField(&context, "User-Agent", "MultiUpdater");
16-
if (ret != 0) {
17-
httpcCloseContext(&context);
18-
if (newurl != NULL) free(newurl);
19-
printf("Error in:\nhttpcAddRequestHeaderField\nreturn: %lx\n", ret);
20-
return ret;
8+
ret = httpcOpenContext(context, HTTPC_METHOD_GET, url, 1);
9+
if (ret != 0) {
10+
printf("Error in:\nhttpcOpenContext\n");
11+
httpcCloseContext(context);
12+
return ret;
13+
}
14+
15+
ret = httpcAddRequestHeaderField(context, "User-Agent", "MultiUpdater");
16+
if (ret != 0) {
17+
printf("Error in:\nhttpcAddRequestHeaderField\n");
18+
httpcCloseContext(context);
19+
return ret;
20+
}
21+
22+
ret = httpcSetSSLOpt(context, SSLCOPT_DisableVerify);
23+
if (ret != 0) {
24+
printf("Error in:\nhttpcSetSSLOpt\n");
25+
httpcCloseContext(context);
26+
return ret;
27+
}
28+
29+
ret = httpcAddRequestHeaderField(context, "Connection", "Keep-Alive");
30+
if (ret != 0) {
31+
printf("Error in:\nhttpcAddRequestHeaderField\n");
32+
httpcCloseContext(context);
33+
return ret;
34+
}
35+
36+
ret = httpcBeginRequest(context);
37+
if (ret != 0) {
38+
printf("Error in:\nhttpcBeginRequest\n");
39+
httpcCloseContext(context);
40+
return ret;
41+
}
42+
43+
ret = httpcGetResponseStatusCode(context, &statuscode);
44+
if (ret != 0) {
45+
printf("Error in:\nhttpcGetResponseStatusCode\n");
46+
httpcCloseContext(context);
47+
return ret;
48+
}
49+
50+
if ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308)) {
51+
char * newurl = malloc(0x1000); // One 4K page for new URL
52+
if (newurl == NULL) {
53+
httpcCloseContext(context);
54+
return DL_ERROR_ALLOC;
2155
}
2256

23-
ret = httpcSetSSLOpt(&context, SSLCOPT_DisableVerify);
24-
ret = httpcAddRequestHeaderField(&context, "Connection", "Keep-Alive");
25-
26-
ret = httpcBeginRequest(&context);
57+
ret = httpcGetResponseHeader(context, "Location", newurl, 0x1000);
2758
if (ret != 0) {
28-
httpcCloseContext(&context);
29-
if (newurl != NULL) free(newurl);
30-
printf("Error in:\nhttpcBeginRequest\nreturn: %lx\n", ret);
59+
printf("Error in:\nhttpcGetResponseHeader\n");
60+
httpcCloseContext(context);
61+
free(newurl);
3162
return ret;
3263
}
3364

34-
ret = httpcGetResponseStatusCode(&context, &statuscode);
35-
if (ret != 0) {
36-
printf("Error in:\nhttpcGetResponseStatusCode\nreturn: %lx\n", ret);
37-
httpcCloseContext(&context);
38-
if (newurl != NULL) free(newurl);
39-
return ret;
40-
}
65+
httpcCloseContext(context); // Close this context before we try the next
4166

42-
if ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308)) {
43-
if (newurl == NULL) newurl = malloc(0x1000); // One 4K page for new URL
44-
if (newurl == NULL) {
45-
httpcCloseContext(&context);
46-
return -1;
47-
}
48-
49-
ret = httpcGetResponseHeader(&context, "Location", newurl, 0x1000);
50-
httpcCloseContext(&context); // Close this context before we try the next
51-
52-
if (newurl[0] == '/') { //if the url starts with a slash, it's local
53-
int slashpos = 0;
54-
char * domainname = strdup(url);
55-
if (strncmp("http", domainname, 4) == 0) slashpos = 7; //if the url in the entry starts with http:// or https:// we need to skip that
56-
slashpos += (int )strchr(domainname+slashpos, '/');
57-
domainname[slashpos] = '\0'; // replace the slash with a nullbyte to cut the url
58-
char * copyurl = strdup(newurl);
59-
sprintf(newurl, "%s%s", domainname, copyurl);
60-
free(copyurl);
61-
free(domainname);
62-
}
63-
url = newurl; // Change pointer to the url that we just learned
64-
printf("Redirecting to url: %s\n", url);
65-
ret = downloadToBuffer(newurl, buf, bufsize);
66-
return ret;
67+
if (newurl[0] == '/') { //if the url starts with a slash, it's local
68+
int slashpos = 0;
69+
char * domainname = strdup(url);
70+
if (strncmp("http", domainname, 4) == 0) slashpos = 8; //if the url in the entry starts with http:// or https:// we need to skip that
71+
slashpos = strchr(domainname+slashpos, '/')-domainname;
72+
domainname[slashpos] = '\0'; // replace the slash with a nullbyte to cut the url
73+
char * copyurl = strdup(newurl);
74+
sprintf(newurl, "%s%s", domainname, copyurl);
75+
free(copyurl);
76+
free(domainname);
6777
}
68-
} while ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308));
78+
79+
printf("Redirecting to url:\n%s\n", newurl);
80+
ret = setupContext(context, newurl, size);
81+
free(newurl);
82+
return ret;
83+
}
6984

7085
if (statuscode != 200) {
7186
printf("Error: HTTP status code is not 200 OK.\nStatus code: %lu\n", statuscode);
72-
httpcCloseContext(&context);
73-
if (newurl != NULL) free(newurl);
74-
return -2;
87+
httpcCloseContext(context);
88+
return DL_ERROR_STATUSCODE;
7589
}
7690

77-
ret = httpcGetDownloadSizeState(&context, NULL, &contentsize);
91+
ret = httpcGetDownloadSizeState(context, NULL, size);
7892
if (ret != 0) {
79-
httpcCloseContext(&context);
80-
if (newurl != NULL) free(newurl);
93+
printf("Error in:\nhttpcGetDownloadSizeState\n");
94+
httpcCloseContext(context);
8195
return ret;
8296
}
8397

84-
// Start with a single page buffer
85-
*buf = (u8 *)malloc(0x1000);
86-
if (buf == NULL) {
87-
httpcCloseContext(&context);
88-
if (newurl != NULL) free(newurl);
89-
return -1;
90-
}
91-
92-
do {
93-
// This download loop resizes the buffer as data is read.
94-
ret = httpcDownloadData(&context, *buf+size, 0x1000, &readsize);
95-
size += readsize;
96-
if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING) {
97-
98-
hidScanInput();
99-
100-
if (hidKeysDown() & KEY_B) {
101-
if (newurl != NULL) free(newurl);
102-
if (lastbuf != NULL) free(lastbuf);
103-
if (buf != NULL) free(buf);
104-
httpcCloseContext(&context);
105-
return 7;
106-
}
107-
108-
lastbuf = *buf; // Save the old pointer, in case realloc() fails.
109-
*buf = realloc(*buf, size + 0x1000);
110-
if (buf == NULL) {
111-
httpcCloseContext(&context);
112-
free(lastbuf);
113-
if (newurl != NULL) free(newurl);
114-
return -1;
115-
}
116-
}
117-
} while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING);
118-
119-
if(ret != 0) {
120-
httpcCloseContext(&context);
121-
if (newurl != NULL) free(newurl);
122-
free(buf);
123-
return -1;
124-
}
125-
126-
// Resize the buffer back down to our actual final size
127-
lastbuf = *buf;
128-
*buf = realloc(*buf, size);
129-
if(buf == NULL) { // realloc() failed.
130-
httpcCloseContext(&context);
131-
free(lastbuf);
132-
if(newurl != NULL) free(newurl);
133-
return -1;
134-
}
135-
136-
*bufsize = contentsize;
137-
httpcCloseContext(&context);
13898
return 0;
13999
}
140100

141101
Result downloadToFile(const char * url, const char * filepath)
142102
{
143-
144103
if (url == NULL) {
145104
printf("Download cannot start, the URL in config.json is blank.\n");
146-
return -1;
105+
return DL_ERROR_CONFIG;
147106
}
148107

149108
if (filepath == NULL) {
150109
printf("Download cannot start, file path in config.json is blank.\n");
151-
return -1;
110+
return DL_ERROR_CONFIG;
152111
}
153112

154113
printf("Downloading file from:\n%s\nto:\n%s\n", url, filepath);
155114

115+
httpcContext context;
156116
Result ret = 0;
157-
u8 * buf = NULL;
158-
u32 size = 0;
117+
u32 contentsize = 0, readsize = 0;
159118

160-
ret = downloadToBuffer(url, &buf, &size);
119+
ret = setupContext(&context, url, &contentsize);
161120
if (ret != 0) return ret;
162121

163-
FILE *fptr = fopen(filepath, "wb");
164-
if (fptr == NULL) {
165-
printf("Couldnt open file to write.\n");
166-
return -1;
122+
printf("Downloading %lu bytes...\n", contentsize);
123+
124+
FILE * fh = fopen(filepath, "wb");
125+
if (fh == NULL) {
126+
printf("Error: couldn't open file to write.\n");
127+
return DL_ERROR_WRITEFILE;
128+
}
129+
130+
u8 * buf = malloc(0x1000);
131+
if (buf == NULL) {
132+
httpcCloseContext(&context);
133+
return DL_ERROR_ALLOC;
167134
}
168-
fwrite(buf, 1, size, fptr);
169-
fclose(fptr);
135+
136+
u64 startTime = osGetTime();
137+
do {
138+
ret = httpcDownloadData(&context, buf, 0x1000, &readsize);
139+
fwrite(buf, 1, readsize, fh);
140+
} while (ret == (Result)HTTPC_RESULTCODE_DOWNLOADPENDING);
141+
printf("Download took %llu milliseconds.\n", osGetTime()-startTime);
142+
170143
free(buf);
144+
fclose(fh);
145+
httpcCloseContext(&context);
146+
147+
if (ret != 0) {
148+
printf("Error in:\nhttpcDownloadData\n");
149+
return ret;
150+
}
151+
171152
return 0;
172153
}

source/download.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,10 @@
22

33
#include "basic.h"
44

5-
Result downloadToBuffer(const char * url, u8 ** buf, u32 * bufsize);
5+
#define DL_ERROR_STATUSCODE -1
6+
#define DL_ERROR_WRITEFILE -2
7+
#define DL_ERROR_ALLOC -3
8+
#define DL_ERROR_CONFIG -4
9+
10+
Result setupContext(httpcContext * context, const char * url, u32 * size);
611
Result downloadToFile(const char * url, const char * filepath);

0 commit comments

Comments
 (0)