Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/http.hpp
2 views
1
#ifndef NALL_HTTP_HPP
2
#define NALL_HTTP_HPP
3
4
#if !defined(_WIN32)
5
#include <sys/types.h>
6
#include <sys/socket.h>
7
#include <netinet/in.h>
8
#include <netdb.h>
9
#else
10
#include <windows.h>
11
#include <winsock2.h>
12
#include <ws2tcpip.h>
13
#endif
14
15
#include <nall/platform.hpp>
16
#include <nall/string.hpp>
17
18
namespace nall {
19
20
struct http {
21
string hostname;
22
addrinfo *serverinfo;
23
int serversocket;
24
string header;
25
26
inline void download(const string &path, uint8_t *&data, unsigned &size) {
27
data = 0;
28
size = 0;
29
30
send({
31
"GET ", path, " HTTP/1.1\r\n"
32
"Host: ", hostname, "\r\n"
33
"Connection: close\r\n"
34
"\r\n"
35
});
36
37
header = downloadHeader();
38
downloadContent(data, size);
39
}
40
41
inline bool connect(string host, unsigned port) {
42
hostname = host;
43
44
addrinfo hints;
45
memset(&hints, 0, sizeof(addrinfo));
46
hints.ai_family = AF_UNSPEC;
47
hints.ai_socktype = SOCK_STREAM;
48
hints.ai_flags = AI_PASSIVE;
49
50
int status = getaddrinfo(hostname, string(port), &hints, &serverinfo);
51
if(status != 0) return false;
52
53
serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol);
54
if(serversocket == -1) return false;
55
56
int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen);
57
if(result == -1) return false;
58
59
return true;
60
}
61
62
inline bool send(const string &data) {
63
return send((const uint8_t*)(const char*)data, data.length());
64
}
65
66
inline bool send(const uint8_t *data, unsigned size) {
67
while(size) {
68
int length = ::send(serversocket, (const char*)data, size, 0);
69
if(length == -1) return false;
70
data += length;
71
size -= length;
72
}
73
return true;
74
}
75
76
inline string downloadHeader() {
77
string output;
78
do {
79
char buffer[2];
80
int length = recv(serversocket, buffer, 1, 0);
81
if(length <= 0) return output;
82
buffer[1] = 0;
83
output.append(buffer);
84
} while(output.endswith("\r\n\r\n") == false);
85
return output;
86
}
87
88
inline string downloadChunkLength() {
89
string output;
90
do {
91
char buffer[2];
92
int length = recv(serversocket, buffer, 1, 0);
93
if(length <= 0) return output;
94
buffer[1] = 0;
95
output.append(buffer);
96
} while(output.endswith("\r\n") == false);
97
return output;
98
}
99
100
inline void downloadContent(uint8_t *&data, unsigned &size) {
101
unsigned capacity = 0;
102
103
if(header.iposition("\r\nTransfer-Encoding: chunked\r\n")) {
104
while(true) {
105
unsigned length = hex(downloadChunkLength());
106
if(length == 0) break;
107
capacity += length;
108
data = (uint8_t*)realloc(data, capacity);
109
110
char buffer[length];
111
while(length) {
112
int packetlength = recv(serversocket, buffer, length, 0);
113
if(packetlength <= 0) break;
114
memcpy(data + size, buffer, packetlength);
115
size += packetlength;
116
length -= packetlength;
117
}
118
}
119
} else if(auto position = header.iposition("\r\nContent-Length: ")) {
120
unsigned length = decimal((const char*)header + position() + 18);
121
while(length) {
122
char buffer[256];
123
int packetlength = recv(serversocket, buffer, min(256, length), 0);
124
if(packetlength <= 0) break;
125
capacity += packetlength;
126
data = (uint8_t*)realloc(data, capacity);
127
memcpy(data + size, buffer, packetlength);
128
size += packetlength;
129
length -= packetlength;
130
}
131
} else {
132
while(true) {
133
char buffer[256];
134
int packetlength = recv(serversocket, buffer, 256, 0);
135
if(packetlength <= 0) break;
136
capacity += packetlength;
137
data = (uint8_t*)realloc(data, capacity);
138
memcpy(data + size, buffer, packetlength);
139
size += packetlength;
140
}
141
}
142
143
data = (uint8_t*)realloc(data, capacity + 1);
144
data[capacity] = 0;
145
}
146
147
inline void disconnect() {
148
close(serversocket);
149
freeaddrinfo(serverinfo);
150
serverinfo = 0;
151
serversocket = -1;
152
}
153
154
#ifdef _WIN32
155
inline int close(int sock) {
156
return closesocket(sock);
157
}
158
159
inline http() {
160
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
161
if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) {
162
WSADATA wsaData;
163
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
164
WSACleanup();
165
return;
166
}
167
} else {
168
close(sock);
169
}
170
}
171
#endif
172
};
173
174
}
175
176
#endif
177
178