forked from oerkki/voxelands
http part 2
This commit is contained in:
parent
8c213bfeed
commit
1c5b35e18d
|
@ -158,6 +158,8 @@
|
|||
#time_send_interval = 20
|
||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
||||
#time_speed = 72
|
||||
# enable a http microserver for admin and player textures
|
||||
#enable_http = true
|
||||
#server_unload_unused_data_timeout = 60
|
||||
#server_map_save_interval = 60
|
||||
#full_block_send_enable_min_time_from_building = 2.0
|
||||
|
|
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
#include "http.h"
|
||||
|
||||
/*
|
||||
QueuedMeshUpdate
|
||||
|
@ -211,6 +212,8 @@ Client::Client(
|
|||
//m_env_mutex.Init();
|
||||
//m_con_mutex.Init();
|
||||
|
||||
m_httpclient = new HTTPClient(this);
|
||||
|
||||
m_mesh_update_thread.Start();
|
||||
|
||||
/*
|
||||
|
@ -248,6 +251,8 @@ void Client::connect(Address address)
|
|||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||
m_con.SetTimeoutMs(0);
|
||||
m_con.Connect(address);
|
||||
if (g_settings->getBool("enable_http"))
|
||||
m_httpclient->start(address);
|
||||
}
|
||||
|
||||
bool Client::connectedAndInitialized()
|
||||
|
@ -760,6 +765,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
writeU16(&reply[0], TOSERVER_INIT2);
|
||||
// Send as reliable
|
||||
m_con.Send(PEER_ID_SERVER, 1, reply, true);
|
||||
sendWantCookie();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1046,6 +1052,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
}
|
||||
|
||||
player->updateName((char*)&data[start+2]);
|
||||
std::string p_name((char*)&data[start+2]);
|
||||
m_httpclient->pushRequest(HTTPREQUEST_SKIN_HASH,p_name);
|
||||
|
||||
start += item_size;
|
||||
}
|
||||
|
@ -1507,6 +1515,22 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
event.deathscreen.camera_point_target_z = camera_point_target.Z;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_HAVECOOKIE)
|
||||
{
|
||||
/*
|
||||
u16 command
|
||||
u16 textlen
|
||||
textdata
|
||||
*/
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u16 len = readU16(is);
|
||||
char buff[len+1];
|
||||
is.read(buff,len);
|
||||
buff[len] = 0;
|
||||
printf("received cookie '%s'\n",buff);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
|
@ -1756,6 +1780,19 @@ void Client::sendRespawn()
|
|||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendWantCookie()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
writeU16(os, TOSERVER_WANTCOOKIE);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendPlayerPos()
|
||||
{
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
|
|
@ -139,6 +139,8 @@ struct ClientEvent
|
|||
};
|
||||
};
|
||||
|
||||
class HTTPClient;
|
||||
|
||||
class Client : public con::PeerHandler, public InventoryManager
|
||||
{
|
||||
public:
|
||||
|
@ -199,6 +201,7 @@ public:
|
|||
const std::wstring newpassword);
|
||||
void sendDamage(u8 damage);
|
||||
void sendRespawn();
|
||||
void sendWantCookie();
|
||||
|
||||
// locks envlock
|
||||
void removeNode(v3s16 p);
|
||||
|
@ -330,6 +333,7 @@ private:
|
|||
ClientEnvironment m_env;
|
||||
|
||||
con::Connection m_con;
|
||||
HTTPClient *m_httpclient;
|
||||
|
||||
IrrlichtDevice *m_device;
|
||||
|
||||
|
|
|
@ -191,6 +191,13 @@ enum ToClientCommand
|
|||
u8 bool set camera point target
|
||||
v3f1000 camera point target (to point the death cause or whatever)
|
||||
*/
|
||||
|
||||
TOCLIENT_HAVECOOKIE = 0x38,
|
||||
/*
|
||||
u16 command
|
||||
u16 textlen
|
||||
textdata
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
@ -344,6 +351,11 @@ enum ToServerCommand
|
|||
/*
|
||||
u16 TOSERVER_RESPAWN
|
||||
*/
|
||||
|
||||
TOSERVER_WANTCOOKIE=0x39,
|
||||
/*
|
||||
u16 TOSERVER_WANTCOOKIE
|
||||
*/
|
||||
};
|
||||
|
||||
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
|
||||
|
|
|
@ -96,6 +96,7 @@ void set_default_settings(Settings *settings)
|
|||
settings->setDefault("default_privs", "build, shout");
|
||||
settings->setDefault("borderstone_radius","5");
|
||||
|
||||
settings->setDefault("enable_http","true");
|
||||
settings->setDefault("profiler_print_interval", "0");
|
||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||
settings->setDefault("objectdata_interval", "0.2");
|
||||
|
|
475
src/http.cpp
475
src/http.cpp
|
@ -27,3 +27,478 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "utility.h"
|
||||
#include "connection.h"
|
||||
#include "log.h"
|
||||
#include "sha1.h"
|
||||
|
||||
void * HTTPServerThread::Thread()
|
||||
{
|
||||
ThreadStarted();
|
||||
|
||||
log_register_thread("HTTPServerThread");
|
||||
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
while (getRun())
|
||||
{
|
||||
try{
|
||||
m_server->step();
|
||||
}catch (con::NoIncomingDataException &e) {
|
||||
}catch(con::PeerNotFoundException &e) {
|
||||
}
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTPServer
|
||||
*/
|
||||
|
||||
HTTPServer::HTTPServer(Server &server):
|
||||
m_thread(this)
|
||||
{
|
||||
m_server = &server;
|
||||
}
|
||||
|
||||
HTTPServer::~HTTPServer()
|
||||
{
|
||||
}
|
||||
|
||||
void HTTPServer::start(u16 port)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
// Stop thread if already running
|
||||
m_thread.stop();
|
||||
|
||||
m_socket = new TCPSocket();
|
||||
m_socket->setTimeoutMs(30);
|
||||
m_socket->Bind(port);
|
||||
|
||||
// Start thread
|
||||
m_thread.setRun(true);
|
||||
m_thread.Start();
|
||||
|
||||
infostream<<"HTTPServer: Started on port "<<port<<std::endl;
|
||||
}
|
||||
|
||||
void HTTPServer::stop()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
m_thread.stop();
|
||||
delete m_socket;
|
||||
|
||||
infostream<<"HTTPServer: Threads stopped"<<std::endl;
|
||||
}
|
||||
|
||||
void HTTPServer::step()
|
||||
{
|
||||
if (m_socket->WaitData(50)) {
|
||||
TCPSocket *s = m_socket->Accept();
|
||||
HTTPRemoteClient *c = new HTTPRemoteClient(s,this);
|
||||
m_peers.push_back(c);
|
||||
}
|
||||
|
||||
for (std::vector<HTTPRemoteClient*>::iterator it = m_peers.begin(); it != m_peers.end(); ++it) {
|
||||
HTTPRemoteClient *c = *it;
|
||||
try{
|
||||
if (c->receive()) {
|
||||
m_peers.erase(it);
|
||||
delete c;
|
||||
}
|
||||
}catch (SocketException &e) {
|
||||
// assume it's closed
|
||||
m_peers.erase(it);
|
||||
delete c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTPRemoteClient
|
||||
*/
|
||||
|
||||
HTTPRemoteClient::~HTTPRemoteClient()
|
||||
{
|
||||
}
|
||||
|
||||
int HTTPRemoteClient::receive()
|
||||
{
|
||||
char buff[2048];
|
||||
if (!m_socket->WaitData(30))
|
||||
return 0;
|
||||
int r = m_socket->Receive(buff,2048);
|
||||
if (r<1)
|
||||
return 1;
|
||||
|
||||
m_recv_headers.clear();
|
||||
m_send_headers.clear();
|
||||
|
||||
int h = m_recv_headers.read(buff,r);
|
||||
if (h == 1) {
|
||||
return 1;
|
||||
}else if (h == 2) {
|
||||
//if (m_recv_headers.url() == "")
|
||||
//return 1;
|
||||
//while (m_socket->WaitData(1000)) {
|
||||
//r = m_socket->Receive(buff,2048);
|
||||
//if (r<1)
|
||||
//return 1;
|
||||
//h = m_recv_headers.read(buff,r);
|
||||
//if (!h)
|
||||
//break;
|
||||
//if (h == 1)
|
||||
//return 1;
|
||||
//}
|
||||
//if (h)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m_recv_headers.cookie() != "" && m_recv_headers.get("User") != "") {
|
||||
if (m_recv_headers.cookie() == m_server->getPlayerCookie(m_recv_headers.get("User"))) {
|
||||
m_send_headers.setCookie(m_recv_headers.cookie());
|
||||
m_auth = true;
|
||||
}
|
||||
}
|
||||
|
||||
//std::string u;
|
||||
//for (int i=0; (u = m_recv_headers.url(i)) != ""; i++) {
|
||||
//printf("%d: '%s'\n",i,u.c_str());
|
||||
//}
|
||||
|
||||
|
||||
//setResponse("404 Not Found");
|
||||
//std::string html("<html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1></body></html>");
|
||||
//send(html);
|
||||
send((char*)"grar");
|
||||
|
||||
return 0;//m_recv_headers.keepAlive() == true ? 0 : 1;
|
||||
}
|
||||
|
||||
void HTTPRemoteClient::send(char* data)
|
||||
{
|
||||
int l = strlen(data);
|
||||
m_send_headers.set("Content-Type","text/plain");
|
||||
m_send_headers.setLength(l);
|
||||
sendHeaders();
|
||||
m_socket->Send(data,l);
|
||||
}
|
||||
|
||||
void HTTPRemoteClient::sendHTML(char* data)
|
||||
{
|
||||
int l = strlen(data);
|
||||
m_send_headers.set("Content-Type","text/html");
|
||||
m_send_headers.setLength(l);
|
||||
sendHeaders();
|
||||
m_socket->Send(data,l);
|
||||
}
|
||||
|
||||
void HTTPRemoteClient::sendFile(std::string &file)
|
||||
{
|
||||
m_send_headers.set("Content-Type","text/plain");
|
||||
m_send_headers.setLength(0);
|
||||
sendHeaders();
|
||||
}
|
||||
|
||||
void HTTPRemoteClient::sendHeaders()
|
||||
{
|
||||
std::string v;
|
||||
int s;
|
||||
char buff[1024];
|
||||
|
||||
//v = m_response;
|
||||
//if (v == "")
|
||||
//v = std::string("200 OK");
|
||||
|
||||
//s = snprintf(buff,1024,"HTTP/1.1 %s\r\n",v.c_str());
|
||||
//m_socket->Send(buff,s);
|
||||
m_socket->Send("HTTP/1.1 200 OK\r\n",17);
|
||||
|
||||
//v = m_send_headers.get("Content-Type");
|
||||
//if (v == "") {
|
||||
m_socket->Send("Content-Type: text/plain\r\n",26);
|
||||
//}else{
|
||||
//s = snprintf(buff,1024,"Content-Type: %s\r\n",v.c_str());
|
||||
//m_socket->Send(buff,s);
|
||||
//}
|
||||
|
||||
s = m_send_headers.length();
|
||||
s = snprintf(buff,1024,"Content-Length: %d\r\n",s);
|
||||
m_socket->Send(buff,s);
|
||||
|
||||
//v = m_send_headers.cookie();
|
||||
//if (v != "") {
|
||||
//s = snprintf(buff,1024,"Set-Cookie: MTID=%s\r\n",v.c_str());
|
||||
//m_socket->Send(buff,s);
|
||||
//}
|
||||
|
||||
m_socket->Send("\r\n",2);
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
#include "client.h"
|
||||
|
||||
void * HTTPClientThread::Thread()
|
||||
{
|
||||
ThreadStarted();
|
||||
|
||||
log_register_thread("HTTPClientThread");
|
||||
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
while (getRun())
|
||||
{
|
||||
try{
|
||||
m_client->step();
|
||||
}catch (con::NoIncomingDataException &e) {
|
||||
}catch(con::PeerNotFoundException &e) {
|
||||
}
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTPClient
|
||||
*/
|
||||
|
||||
HTTPClient::HTTPClient(Client *client):
|
||||
m_cookie(""),
|
||||
m_thread(this)
|
||||
{
|
||||
m_client = client;
|
||||
m_req_mutex.Init();
|
||||
}
|
||||
|
||||
HTTPClient::~HTTPClient()
|
||||
{
|
||||
}
|
||||
|
||||
void HTTPClient::start(const Address &address)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
// Stop thread if already running
|
||||
m_thread.stop();
|
||||
|
||||
m_socket = new TCPSocket();
|
||||
m_socket->setTimeoutMs(30);
|
||||
m_socket->Connect(address);
|
||||
|
||||
// Start thread
|
||||
m_thread.setRun(true);
|
||||
m_thread.Start();
|
||||
|
||||
infostream<<"HTTPClient: Started"<<std::endl;
|
||||
}
|
||||
|
||||
void HTTPClient::stop()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
m_thread.stop();
|
||||
delete m_socket;
|
||||
|
||||
infostream<<"HTTPClient: Threads stopped"<<std::endl;
|
||||
}
|
||||
|
||||
void HTTPClient::step()
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
|
||||
{
|
||||
switch (type) {
|
||||
case HTTPREQUEST_NULL:
|
||||
break;
|
||||
/*
|
||||
* /player/<name>/skin
|
||||
* request the skin texture for <name>
|
||||
* response:
|
||||
* if skin exists:
|
||||
* 200 OK + texture data
|
||||
* else:
|
||||
* 303 See Other + Location header to /texture/character.png
|
||||
* this client will ignore the redirect, while browsers will see the default skin
|
||||
*/
|
||||
case HTTPREQUEST_SKIN:
|
||||
{
|
||||
std::string url("/player/");
|
||||
url += data + "/skin";
|
||||
HTTPRequest r(url);
|
||||
m_req_mutex.Lock();
|
||||
m_requests.push_back(r);
|
||||
m_req_mutex.Unlock();
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* /player/<name>/skin/hash/<sha1>
|
||||
* sends the sha1 hash of the skin texture for <name>
|
||||
* response:
|
||||
* if hash is the same on client and server:
|
||||
* 204 No Content
|
||||
* if client is authenticated as <name>:
|
||||
* 304 Not Modified
|
||||
* else:
|
||||
* 200 OK + texture data
|
||||
*/
|
||||
case HTTPREQUEST_SKIN_HASH:
|
||||
{
|
||||
std::string tex = std::string("players/player_")+data+".png";
|
||||
std::string ptex = getTexturePath(tex);
|
||||
if (ptex == "") {
|
||||
pushRequest(HTTPREQUEST_SKIN,data);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* /player/<name>/skin
|
||||
* PUT request type, sends the skin to the server
|
||||
* response:
|
||||
* if client is authenticated as <name>:
|
||||
* 201 Created
|
||||
* else:
|
||||
* 405 Method Not Allowed
|
||||
*/
|
||||
case HTTPREQUEST_SKIN_SEND:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPClient::pushRequest(std::string &url, std::string &data)
|
||||
{
|
||||
HTTPRequest r(url,data);
|
||||
m_req_mutex.Lock();
|
||||
m_requests.push_back(r);
|
||||
m_req_mutex.Unlock();
|
||||
}
|
||||
|
||||
void HTTPClient::get(std::string &url)
|
||||
{
|
||||
}
|
||||
|
||||
void HTTPClient::post(std::string &url, char* data)
|
||||
{
|
||||
}
|
||||
|
||||
void HTTPClient::postFile(std::string &url, std::string &file)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPRequest HTTPClient::popRequest()
|
||||
{
|
||||
m_req_mutex.Lock();
|
||||
HTTPRequest r = m_requests.front();
|
||||
m_requests.erase(m_requests.begin());
|
||||
m_req_mutex.Unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
void HTTPClient::sendHeaders()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HTTPHeaders
|
||||
*/
|
||||
|
||||
int HTTPHeaders::read(char* buff, int length)
|
||||
{
|
||||
char nbuff[1024];
|
||||
char vbuff[1024];
|
||||
int n = 1;
|
||||
int o = 0;
|
||||
int c = m_url == "" ? 0 : 1;
|
||||
|
||||
for (int i=0; i<length; i++) {
|
||||
if (buff[i] == '\r' || (!o && buff[i] == ' '))
|
||||
continue;
|
||||
if (buff[i] == '\n') {
|
||||
if (!c) {
|
||||
nbuff[o] = 0;
|
||||
printf("%s\n",nbuff);
|
||||
char* u = strchr(nbuff,' ');
|
||||
if (!u)
|
||||
return 1;
|
||||
*u = 0;
|
||||
setMethod(nbuff);
|
||||
u++;
|
||||
while (*u == ' ') {
|
||||
u++;
|
||||
}
|
||||
printf("%s\n",u);
|
||||
char* p = strchr(u,' ');
|
||||
if (!p)
|
||||
return 1;
|
||||
*p = 0;
|
||||
p++;
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
printf("%s\n",p);
|
||||
if (!strcmp(p,"HTTP/1.1")) {
|
||||
setKeepAlive(true);
|
||||
setProtocol(p);
|
||||
}else{
|
||||
setKeepAlive(false);
|
||||
setProtocol("HTTP/1.0");
|
||||
}
|
||||
setUrl(nbuff);
|
||||
//size_t current;
|
||||
//size_t next = -1;
|
||||
//std::string s(u);
|
||||
//do{
|
||||
//current = next + 1;
|
||||
//next = s.find_first_of("/", current);
|
||||
//if (s.substr(current, next-current) != "")
|
||||
//m_url_split.push_back(s.substr(current, next-current));
|
||||
//} while (next != std::string::npos);
|
||||
c++;
|
||||
}else{
|
||||
if (n)
|
||||
return 0;
|
||||
vbuff[o] = 0;
|
||||
if (!strcmp(nbuff,"Content-Length")) {
|
||||
setLength(strtoul(vbuff,NULL,10));
|
||||
}else if (!strcmp(nbuff,"Cookie")) {
|
||||
setCookie(vbuff);
|
||||
}else if (!strcmp(nbuff,"Connection")) {
|
||||
if (!strcmp(vbuff,"keep-alive") || !strcmp(vbuff,"Keep-Alive")) {
|
||||
setKeepAlive(true);
|
||||
}else if (!strcmp(vbuff,"close") || !strcmp(vbuff,"Close")) {
|
||||
setKeepAlive(false);
|
||||
}
|
||||
}else{
|
||||
set(nbuff,vbuff);
|
||||
}
|
||||
}
|
||||
o = 0;
|
||||
n = 1;
|
||||
}else if (n && buff[i] == ':') {
|
||||
nbuff[o] = 0;
|
||||
o = 0;
|
||||
n = 0;
|
||||
}else if (n) {
|
||||
nbuff[o++] = buff[i];
|
||||
}else{
|
||||
vbuff[o++] = buff[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
|
171
src/http.h
171
src/http.h
|
@ -25,24 +25,185 @@
|
|||
|
||||
#include "socket.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "utility.h"
|
||||
#include "server.h"
|
||||
#include <map>
|
||||
|
||||
class HTTPServer;
|
||||
|
||||
class HTTPServerThread : public SimpleThread
|
||||
{
|
||||
HTTPServer *m_server;
|
||||
|
||||
public:
|
||||
|
||||
HTTPServerThread(HTTPServer *server):
|
||||
SimpleThread(),
|
||||
m_server(server)
|
||||
{
|
||||
}
|
||||
|
||||
void * Thread();
|
||||
};
|
||||
|
||||
class HTTPHeaders
|
||||
{
|
||||
public:
|
||||
HTTPHeaders()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
~HTTPHeaders() {};
|
||||
void clear()
|
||||
{
|
||||
m_contentLength = 0;
|
||||
m_keepalive = false;
|
||||
m_cookie = std::string("");
|
||||
m_url = std::string("");
|
||||
m_url_split.clear();
|
||||
}
|
||||
int read(char* buff, int length);
|
||||
u32 length() {return m_contentLength;}
|
||||
bool keepAlive() {return m_keepalive;}
|
||||
std::string &cookie() {return m_cookie;}
|
||||
std::string &url() {return m_url;}
|
||||
std::string &url(int index) {return m_url_split[index];}
|
||||
std::string &get(std::string name) {return m_headers[name];}
|
||||
void set(std::string name, std::string value) {m_headers[name] = value;}
|
||||
void setLength(u32 length) {m_contentLength = length;}
|
||||
void setKeepAlive(bool ka) {m_keepalive = ka;}
|
||||
void setCookie(std::string cookie) {std::string c(cookie.c_str()); m_cookie = c;}
|
||||
void setUrl(std::string url) {std::string u(url); m_url = u;}
|
||||
void setMethod(std::string method) {std::string m(method); m_method = m;}
|
||||
void setProtocol(std::string proto) {std::string p(proto); m_protocol = p;}
|
||||
private:
|
||||
std::map<std::string,std::string> m_headers;
|
||||
u32 m_contentLength;
|
||||
bool m_keepalive;
|
||||
std::string m_cookie;
|
||||
std::string m_url;
|
||||
std::vector<std::string> m_url_split;
|
||||
std::string m_method;
|
||||
std::string m_protocol;
|
||||
};
|
||||
|
||||
class HTTPRemoteClient
|
||||
{
|
||||
public:
|
||||
HTTPRemoteClient(TCPSocket *sock, HTTPServer *server):
|
||||
m_response(""),
|
||||
m_auth(false)
|
||||
{
|
||||
m_socket = sock;
|
||||
m_server = server;
|
||||
}
|
||||
~HTTPRemoteClient();
|
||||
int receive();
|
||||
void send(char* data);
|
||||
void send(std::string &data) {send((char*)data.c_str());}
|
||||
void sendHTML(char* data);
|
||||
void sendHTML(std::string &data) {sendHTML((char*)data.c_str());}
|
||||
void sendFile(std::string &file);
|
||||
void setResponse(const char* response) {std::string r(response); m_response = r;}
|
||||
private:
|
||||
void sendHeaders();
|
||||
HTTPHeaders m_recv_headers;
|
||||
HTTPHeaders m_send_headers;
|
||||
std::string m_response;
|
||||
bool m_auth;
|
||||
TCPSocket *m_socket;
|
||||
HTTPServer *m_server;
|
||||
};
|
||||
|
||||
class HTTPServer
|
||||
{
|
||||
public:
|
||||
HTTPServer();
|
||||
HTTPServer(Server &server);
|
||||
~HTTPServer();
|
||||
void start(u16 port);
|
||||
void stop();
|
||||
void step();
|
||||
std::string getPlayerCookie(std::string &name) {return m_server->getPlayerCookie(name);}
|
||||
private:
|
||||
TCPSocket &m_socket;
|
||||
core::map<u16,TCPSocket&> m_peers;
|
||||
TCPSocket *m_socket;
|
||||
std::vector<HTTPRemoteClient*> m_peers;
|
||||
HTTPServerThread m_thread;
|
||||
Server *m_server;
|
||||
};
|
||||
|
||||
enum HTTPRequestType {
|
||||
HTTPREQUEST_NULL,
|
||||
HTTPREQUEST_SKIN,
|
||||
HTTPREQUEST_SKIN_HASH,
|
||||
HTTPREQUEST_SKIN_SEND
|
||||
};
|
||||
|
||||
struct HTTPRequest
|
||||
{
|
||||
HTTPRequest():
|
||||
url(""),
|
||||
post("")
|
||||
{
|
||||
}
|
||||
HTTPRequest(std::string &u, std::string &p)
|
||||
{
|
||||
url = u;
|
||||
post = p;
|
||||
}
|
||||
HTTPRequest(std::string &u)
|
||||
{
|
||||
url = u;
|
||||
post = "";
|
||||
}
|
||||
std::string url;
|
||||
std::string post;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
#include "client.h"
|
||||
class HTTPClient;
|
||||
|
||||
class HTTPClientThread : public SimpleThread
|
||||
{
|
||||
HTTPClient *m_client;
|
||||
|
||||
public:
|
||||
|
||||
HTTPClientThread(HTTPClient *client):
|
||||
SimpleThread(),
|
||||
m_client(client)
|
||||
{
|
||||
}
|
||||
|
||||
void * Thread();
|
||||
};
|
||||
|
||||
class HTTPClient
|
||||
{
|
||||
public:
|
||||
HTTPClient();
|
||||
HTTPClient(Client *client);
|
||||
~HTTPClient();
|
||||
void start(const Address &address);
|
||||
void stop();
|
||||
void step();
|
||||
void setCookie(std::string &cookie) {std::string c(cookie.c_str()); m_cookie = c;}
|
||||
void pushRequest(HTTPRequestType type, std::string &data);
|
||||
void pushRequest(std::string &url, std::string &data);
|
||||
private:
|
||||
TCPSocket &m_socket;
|
||||
void get(std::string &url);
|
||||
void post(std::string &url, char* data);
|
||||
void postFile(std::string &url, std::string &file);
|
||||
HTTPRequest popRequest();
|
||||
void sendHeaders();
|
||||
TCPSocket *m_socket;
|
||||
HTTPHeaders m_recv_headers;
|
||||
HTTPHeaders m_send_headers;
|
||||
std::string m_cookie;
|
||||
std::vector<HTTPRequest> m_requests;
|
||||
JMutex m_req_mutex;
|
||||
HTTPClientThread m_thread;
|
||||
Client *m_client;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
15
src/player.h
15
src/player.h
|
@ -138,6 +138,7 @@ public:
|
|||
{
|
||||
light = light_at_pos;
|
||||
}
|
||||
virtual std::string getCookie() {return "";}
|
||||
|
||||
virtual void updateAnim(u8 anim_id)
|
||||
{}
|
||||
|
@ -194,7 +195,8 @@ class ServerRemotePlayer : public Player
|
|||
{
|
||||
public:
|
||||
ServerRemotePlayer():
|
||||
m_addr("")
|
||||
m_addr(""),
|
||||
m_cookie("")
|
||||
{
|
||||
}
|
||||
virtual ~ServerRemotePlayer()
|
||||
|
@ -214,7 +216,18 @@ public:
|
|||
std::string getAddress() {return m_addr;}
|
||||
|
||||
private:
|
||||
virtual std::string getCookie()
|
||||
{
|
||||
if (m_cookie == "") {
|
||||
char buff[256];
|
||||
snprintf(buff,256,"%s%.4X",getName(),peer_id);
|
||||
m_cookie = std::string(buff);
|
||||
}
|
||||
return m_cookie;
|
||||
}
|
||||
|
||||
std::string m_addr;
|
||||
std::string m_cookie;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
|
|
|
@ -4228,6 +4228,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
actionstream<<player->getName()<<" respawns at "
|
||||
<<PP(player->getPosition()/BS)<<std::endl;
|
||||
}
|
||||
else if(command == TOSERVER_WANTCOOKIE)
|
||||
{
|
||||
SendPlayerCookie(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Server::ProcessData(): Ignoring "
|
||||
|
@ -4650,6 +4654,22 @@ void Server::SendPlayerHP(Player *player)
|
|||
SendHP(m_con, player->peer_id, player->hp);
|
||||
}
|
||||
|
||||
void Server::SendPlayerCookie(Player *player)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
std::string c = player->getCookie();
|
||||
|
||||
writeU16(os, TOCLIENT_HAVECOOKIE);
|
||||
writeU16(os, c.size());
|
||||
os.write(c.c_str(),c.size());
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(player->peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
void Server::SendMovePlayer(Player *player)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
|
|
@ -448,6 +448,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::string getPlayerCookie(std::string &name)
|
||||
{
|
||||
Player *p = m_env.getPlayer(name.c_str());
|
||||
if (p == NULL)
|
||||
return "";
|
||||
return p->getCookie();
|
||||
}
|
||||
|
||||
// Saves g_settings to configpath given at initialization
|
||||
void saveConfig();
|
||||
|
||||
|
@ -511,6 +519,7 @@ private:
|
|||
void SendChatMessage(u16 peer_id, const std::wstring &message);
|
||||
void BroadcastChatMessage(const std::wstring &message);
|
||||
void SendPlayerHP(Player *player);
|
||||
void SendPlayerCookie(Player *player);
|
||||
/*
|
||||
Send a node removal/addition event to all clients except ignore_id.
|
||||
Additionally, if far_players!=NULL, players further away than
|
||||
|
|
|
@ -78,6 +78,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_craft.h"
|
||||
#include "content_craftitem.h"
|
||||
#include "content_toolitem.h"
|
||||
#include "http.h"
|
||||
|
||||
/*
|
||||
Settings.
|
||||
|
@ -370,9 +371,13 @@ int main(int argc, char *argv[])
|
|||
// Create server
|
||||
Server server(map_dir.c_str(), configpath);
|
||||
server.start(port);
|
||||
HTTPServer http_server(server);
|
||||
if (g_settings->getBool("enable_http"))
|
||||
http_server.start(port);
|
||||
|
||||
// Run server
|
||||
dedicated_server_loop(server, kill);
|
||||
http_server.stop();
|
||||
|
||||
} //try
|
||||
catch(con::PeerNotFoundException &e)
|
||||
|
|
|
@ -113,7 +113,7 @@ std::string getTexturePath(const std::string &filename)
|
|||
Check from cache
|
||||
*/
|
||||
bool incache = g_texturename_to_path_cache.get(filename, &fullpath);
|
||||
if(incache)
|
||||
if (incache && fullpath != "")
|
||||
return fullpath;
|
||||
|
||||
std::string rel_path = std::string("textures")+DIR_DELIM+filename;
|
||||
|
|
Loading…
Reference in New Issue