diff --git a/src/camera.cpp b/src/camera.cpp
index 520307a..c9cbc4b 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -491,7 +491,6 @@ void Camera::wield(const InventoryItem* item)
m_wieldnode->setArm();
m_wieldnode_baserotation = v3f(-30, 130, 20);
m_wieldnode_baseposition = v3f(45, -43, 65);
- //m_wieldnode->setSprite(g_texturesource->getTextureRaw("hand.png"));
m_wieldnode->setScale(v3f(40));
m_wieldnode->setVisible(true);
}
diff --git a/src/client.cpp b/src/client.cpp
index ff2d393..e10c646 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -239,6 +239,8 @@ Client::~Client()
//JMutexAutoLock conlock(m_con_mutex); //bulk comment-out
m_con.Disconnect();
}
+ if (g_settings->getBool("enable_http"))
+ m_httpclient->stop();
m_mesh_update_thread.setRun(false);
while(m_mesh_update_thread.IsRunning())
@@ -1529,7 +1531,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
char buff[len+1];
is.read(buff,len);
buff[len] = 0;
- printf("received cookie '%s'\n",buff);
+ std::string c(buff);
+ std::string p(getLocalPlayer()->getName());
+ m_httpclient->setCookie(c);
+ m_httpclient->pushRequest(HTTPREQUEST_SKIN_HASH,p);
}
else
{
diff --git a/src/http.cpp b/src/http.cpp
index 1aa717a..461972a 100644
--- a/src/http.cpp
+++ b/src/http.cpp
@@ -53,6 +53,7 @@ void * HTTPServerThread::Thread()
m_server->step();
}catch (con::NoIncomingDataException &e) {
}catch(con::PeerNotFoundException &e) {
+ }catch(SendFailedException &e) {
}
}
@@ -279,35 +280,43 @@ int HTTPRemoteClient::handlePlayer()
return 1;
/* player skin */
}else if (m_recv_headers.getUrl(2) == "skin") {
- std::string data_path = g_settings->get("data_path");
- if (data_path == "")
- data_path = "data";
- std::string file = data_path + DIR_DELIM + "textures" + DIR_DELIM + "players" + DIR_DELIM + "player_" + m_recv_headers.getUrl(1) + ".png";
- /* compare hash */
- if (m_recv_headers.getUrl(3) != "") {
- FILE *f;
- f = fopen(file.c_str(),"rb");
- if (!f)
- return handleSpecial("204 No Content");
- fclose(f);
- SHA1 s;
- s.addFile(file.c_str());
- s.getDigest(buff);
- if (std::string(buff) == m_recv_headers.getUrl(3)) {
- return handleSpecial("204 No Content");
- }else if (m_auth && m_recv_headers.getHeader("User") == m_recv_headers.getUrl(1)) {
- return handleSpecial("304 Not Modified");
- }
- m_send_headers.setHeader("Content-Type","image/png");
- sendFile(file);
- return 1;
- }
- /* get file */
+ std::string file = getPath("player","player_" + m_recv_headers.getUrl(1) + ".png",true);
if (m_recv_headers.getMethod() != "PUT") {
+ if (file == "") {
+ if (m_auth && m_recv_headers.getHeader("User") == m_recv_headers.getUrl(1))
+ return handleSpecial("304 Not Modified");
+ if (m_recv_headers.getUrl(3) == "hash")
+ return handleSpecial("204 No Content");
+ m_send_headers.setHeader("Location","/texture/character.png");
+ return handleSpecial("303 See Other","
/texture/character.png
");
+ }
+ /* compare hash */
+ if (m_recv_headers.getUrl(3) == "hash") {
+ FILE *f;
+ f = fopen(file.c_str(),"rb");
+ if (!f)
+ return handleSpecial("204 No Content");
+ fseek(f,0,SEEK_END);
+ size_t l = ftell(f);
+ fclose(f);
+ if (!l)
+ return handleSpecial("204 No Content");
+ SHA1 s;
+ s.addFile(file.c_str());
+ s.getDigest(buff);
+ if (std::string(buff) == m_recv_headers.getUrl(4)) {
+ return handleSpecial("204 No Content");
+ }else if (m_auth && m_recv_headers.getHeader("User") == m_recv_headers.getUrl(1)) {
+ return handleSpecial("304 Not Modified");
+ }
+ }
+ /* get file */
m_send_headers.setHeader("Content-Type","image/png");
sendFile(file);
return 1;
}
+ if (file == "")
+ file = getPath("player","player_" + m_recv_headers.getUrl(1) + ".png",false);
/* put only works for the owner */
if (!m_auth || m_recv_headers.getHeader("User") != m_server->getPlayerFromCookie(m_recv_headers.getCookie()))
return handleSpecial("405 Method Not Allowed");
@@ -316,15 +325,19 @@ int HTTPRemoteClient::handlePlayer()
if (!f)
return handleSpecial("500 Internal Server Error");
size_t s = m_recv_headers.getLength();
- if (!s)
+ if (!s) {
+ fclose(f);
return handleSpecial("411 Length Required");
+ }
size_t l;
size_t c = 2048;
+ size_t t = 0;
if (c > s)
c = s;
if (c) {
while ((l = read(buff,c)) > 0) {
s -= l;
+ t += l;
c = fwrite(buff,1,l,f);
if (c != l) {
fclose(f);
@@ -337,6 +350,7 @@ int HTTPRemoteClient::handlePlayer()
break;
}
}
+printf("recieved: %lu %lu\n",s,l);
fclose(f);
return handleSpecial("201 Created");
}else if (m_server->getGameServer()->getPlayer(m_recv_headers.getUrl(1))) {
@@ -369,7 +383,9 @@ int HTTPRemoteClient::handlePlayer()
/* handle /texture/ url's */
int HTTPRemoteClient::handleTexture()
{
- std::string file = getTexturePath(m_recv_headers.getUrl(1));
+ std::string file = getPath("texture",m_recv_headers.getUrl(1),true);
+ if (file == "")
+ return handleSpecial("404 Not Found");
m_send_headers.setHeader("Content-Type","image/png");
sendFile(file);
return 1;
@@ -378,7 +394,9 @@ int HTTPRemoteClient::handleTexture()
/* handle /model/ url's */
int HTTPRemoteClient::handleModel()
{
- std::string file = getModelPath(m_recv_headers.getUrl(1));
+ std::string file = getPath("model",m_recv_headers.getUrl(1),true);
+ if (file == "")
+ return handleSpecial("404 Not Found");
m_send_headers.setHeader("Content-Type","application/octet-stream");
sendFile(file);
return 1;
@@ -444,21 +462,10 @@ void HTTPRemoteClient::sendHTML(char* data)
FILE *f;
int l[4];
char* b;
- std::string data_path = g_settings->get("data_path");
- if (data_path == "")
- data_path = "data";
- std::string file = data_path + DIR_DELIM + "html" + DIR_DELIM + "header.html";
+ std::string file = getPath("html","header.html",true);
h = fopen(file.c_str(),"r");
- if (!h && data_path != "data") {
- file = std::string("data") + DIR_DELIM + "html" + DIR_DELIM + "header.html";
- h = fopen(file.c_str(),"r");
- }
- file = data_path + DIR_DELIM + "html" + DIR_DELIM + "footer.html";
+ file = getPath("html","footer.html",true);
f = fopen(file.c_str(),"r");
- if (!f && data_path != "data") {
- file = std::string("data") + DIR_DELIM + "html" + DIR_DELIM + "footer.html";
- f = fopen(file.c_str(),"r");
- }
if (h) {
fseek(h,0,SEEK_END);
@@ -505,28 +512,24 @@ void HTTPRemoteClient::sendFile(std::string &file)
FILE *f;
f = fopen(file.c_str(),"rb");
if (!f) {
- std::string data_path = g_settings->get("data_path");
- if (data_path == "")
- data_path = "data";
- if (file.substr(data_path.size()+1,24) == "textures/players/player_") {
- m_send_headers.setHeader("Location","/texture/character.png");
- handleSpecial("303 See Other","/texture/character.png
");
- return;
- }
handleSpecial("404 Not Found");
return;
}
fseek(f,0,SEEK_END);
size_t l = ftell(f);
fseek(f,0,SEEK_SET);
+ size_t s = l;
+ size_t t = 0;
m_send_headers.setLength(l);
sendHeaders();
char buff[1024];
while ((l = fread(buff,1,1024,f)) > 0) {
+ t += l;
m_socket->Send(buff,l);
}
+printf("sent: %lu %lu\n",s,t);
fclose(f);
}
@@ -632,9 +635,7 @@ void HTTPClient::start(const Address &address)
// Stop thread if already running
m_thread.stop();
- m_socket = new TCPSocket();
- m_socket->setTimeoutMs(30);
- m_socket->Connect(address);
+ m_address = address;
// Start thread
m_thread.setRun(true);
@@ -649,7 +650,6 @@ void HTTPClient::stop()
DSTACK(__FUNCTION_NAME);
m_thread.stop();
- delete m_socket;
infostream<<"HTTPClient: Threads stopped"< 0 || m_cookie == "")
+ //m_client->sendWantCookie();
+ sleep(1);
+ return;
+ }
+
+ std::vector p;
+
+ m_req_mutex.Lock();
+ p.swap(m_requests);
+ m_req_mutex.Unlock();
+
+ for (std::vector::iterator i = p.begin(); i != p.end(); ++i) {
+ HTTPRequest q = *i;
+ m_socket = new TCPSocket();
+ if (m_socket == NULL) {
+ m_req_mutex.Lock();
+ m_requests.push_back(q);
+ m_req_mutex.Unlock();
+ continue;
+ }
+ if (m_socket->Connect(m_address) == false) {
+ delete m_socket;
+ m_req_mutex.Lock();
+ m_requests.push_back(q);
+ m_req_mutex.Unlock();
+ continue;
+ }
+
+ m_recv_headers.clear();
+ m_send_headers.clear();
+
+ if (q.post == "") {
+ get(q.url);
+ }else{
+ put(q.url,q.post);
+ }
+
+ int r = 0;
+ int h = -1;
+ m_start = 0;
+ m_end = 0;
+ while (m_socket->WaitData(1000)) {
+ r = fillBuffer();
+ if (r<1) {
+ delete m_socket;
+ m_req_mutex.Lock();
+ m_requests.push_back(q);
+ m_req_mutex.Unlock();
+ h = -1;
+ break;
+ }
+ h = m_recv_headers.read(m_buff,r);
+ if (h > -1)
+ break;
+ if (h == -1 || m_recv_headers.getResponse() == 500) {
+ delete m_socket;
+ m_req_mutex.Lock();
+ m_requests.push_back(q);
+ m_req_mutex.Unlock();
+ r = 0;
+ break;
+ }
+ }
+ if (h < 0) {
+ delete m_socket;
+ continue;
+ }
+
+ r = m_recv_headers.getResponse();
+
+ if (q.post == "") {
+ if (r == 204 || r == 303) {
+ delete m_socket;
+ continue;
+ }else if (r == 304) {
+ std::string d(m_client->getLocalPlayer()->getName());
+ pushRequest(HTTPREQUEST_SKIN_SEND,d);
+ delete m_socket;
+ continue;
+ }
+ if (r != 200) {
+ errorstream << "receive skin returned " << r << std::endl;
+ delete m_socket;
+ continue;
+ }
+ if (q.data == "") {
+ errorstream << "receive skin returned successful for no player?" << std::endl;
+ delete m_socket;
+ continue;
+ }
+ if (q.data == m_client->getLocalPlayer()->getName()) {
+ delete m_socket;
+ continue;
+ }
+ char buff[2048];
+ std::string file = getPath("player",std::string("player_")+q.data+".png",false);
+ FILE *f;
+ f = fopen(file.c_str(),"wb");
+ if (!f) {
+ delete m_socket;
+ continue;
+ }
+ size_t s = m_recv_headers.getLength();
+ if (!s) {
+ delete m_socket;
+ fclose(f);
+ continue;
+ }
+ size_t l;
+ size_t c = 2048;
+ if (c > s)
+ c = s;
+ if (c) {
+ while ((l = read(buff,c)) > 0) {
+ s -= l;
+ c = fwrite(buff,1,l,f);
+ if (c != l)
+ break;
+ c = 2048;
+ if (c > s)
+ c = s;
+ if (!c)
+ break;
+ }
+ }
+ fclose(f);
+ }else if (r == 405) {
+ errorstream << "send skin returned 405 Method Not Allowed" << std::endl;
+ }
+ delete m_socket;
+ }
+ p.clear();
}
/* add a request to the http client queue */
void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
{
+ if (m_thread.getRun() == false)
+ return;
switch (type) {
case HTTPREQUEST_NULL:
break;
@@ -681,6 +818,7 @@ void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
std::string url("/player/");
url += data + "/skin";
HTTPRequest r(url);
+ r.data = data;
m_req_mutex.Lock();
m_requests.push_back(r);
m_req_mutex.Unlock();
@@ -699,8 +837,8 @@ void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
*/
case HTTPREQUEST_SKIN_HASH:
{
- std::string tex = std::string("players") + DIR_DELIM + "player_" + data + ".png";
- std::string ptex = getTexturePath(tex);
+ std::string tex = std::string("player_") + data + ".png";
+ std::string ptex = getPath("player",tex,true);
if (ptex == "") {
pushRequest(HTTPREQUEST_SKIN,data);
return;
@@ -710,8 +848,9 @@ void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
s.addFile(ptex.c_str());
s.getDigest(buff);
std::string url("/player/");
- url += data + "/skin/" + buff;
+ url += data + "/skin/hash/" + buff;
HTTPRequest r(url);
+ r.data = data;
m_req_mutex.Lock();
m_requests.push_back(r);
m_req_mutex.Unlock();
@@ -729,13 +868,13 @@ void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
case HTTPREQUEST_SKIN_SEND:
{
std::string tex = std::string("player.png");
- std::string ptex = getTexturePath(tex);
+ std::string ptex = getPath("texture",tex,true);
if (ptex == "")
return;
std::string url("/player/");
url += data + "/skin";
- HTTPRequest r(url,ptex);
+ HTTPRequest r(url,ptex,data);
m_req_mutex.Lock();
m_requests.push_back(r);
m_req_mutex.Unlock();
@@ -748,6 +887,8 @@ void HTTPClient::pushRequest(HTTPRequestType type, std::string &data)
/* add a request to the http client queue */
void HTTPClient::pushRequest(std::string &url, std::string &data)
{
+ if (m_thread.getRun() == false)
+ return;
HTTPRequest r(url,data);
m_req_mutex.Lock();
m_requests.push_back(r);
@@ -755,33 +896,126 @@ void HTTPClient::pushRequest(std::string &url, std::string &data)
}
/* send a http GET request to the server */
-void HTTPClient::get(std::string &url)
+bool HTTPClient::get(std::string &url)
{
+ m_send_headers.setLength(0);
+ m_send_headers.setMethod("GET");
+ m_send_headers.setUrl(url);
+
+ sendHeaders();
+ return true;
}
/* send a http POST request to the server */
-void HTTPClient::post(std::string &url, char* data)
+bool HTTPClient::post(std::string &url, char* data)
{
+ return false;
}
/* send a file to the server with a http PUT request */
-void HTTPClient::put(std::string &url, std::string &file)
+bool HTTPClient::put(std::string &url, std::string &file)
{
+ FILE *f;
+ u32 s;
+ f = fopen(file.c_str(),"r");
+ if (!f)
+ return false;
+ fseek(f,0,SEEK_END);
+ s = ftell(f);
+printf("filesize: %u\n",s);
+ fseek(f,0,SEEK_SET);
+ m_send_headers.setLength(s);
+ m_send_headers.setHeader("Content-Type","image/png");
+ m_send_headers.setMethod("PUT");
+ m_send_headers.setUrl(url);
+
+ sendHeaders();
+
+ char buff[1024];
+ while ((s = fread(buff,1,1024,f)) > 0) {
+ m_socket->Send(buff,s);
+ }
+ fclose(f);
+ return true;
}
-/* get a request from the client queue */
-HTTPRequest HTTPClient::popRequest()
+/* read data from a remote http client */
+int HTTPClient::read(char* buff, int size)
{
- m_req_mutex.Lock();
- HTTPRequest r = m_requests.front();
- m_requests.erase(m_requests.begin());
- m_req_mutex.Unlock();
- return r;
+ if (size > 2048) {
+ int r = 0;
+ int l;
+ int c = 2048;
+ int s = size;
+ while (fillBuffer()) {
+ c = 2048;
+ if (sWaitData(30))
+ return m_end;
+
+ return m_end+m_socket->Receive(m_buff+m_end,l);
}
/* send http headers to the server */
void HTTPClient::sendHeaders()
{
+ std::string v;
+ int s;
+ char buff[1024];
+
+ s = snprintf(buff,1024,"%s %s HTTP/1.0\r\n",m_send_headers.getMethod().c_str(),m_send_headers.getUrl().c_str());
+ m_socket->Send(buff,s);
+
+ v = m_send_headers.getHeader("Content-Type");
+ if (v != "") {
+ 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);
+
+ s = snprintf(buff,1024,"Cookie: MTID=%s\r\n",m_cookie.c_str());
+ m_socket->Send(buff,s);
+
+ s = snprintf(buff,1024,"User: %s\r\n",m_client->getLocalPlayer()->getName());
+ m_socket->Send(buff,s);
+
+ m_socket->Send("\r\n",2);
}
#endif
@@ -870,7 +1104,7 @@ int HTTPResponseHeaders::read(char* buff, int length)
int n = 1;
int o = 0;
int i = 0;
- int c = getUrl() == "" ? 0 : 1;
+ int c = getResponse();
for (i=0; iget("data_path");
- if(data_path != "")
- {
- std::string testpath = data_path + DIR_DELIM + rel_path;
- // Check all filename extensions. Returns "" if not found.
- fullpath = getImagePath(testpath);
- }
-
- /*
- Check from default data directory
- */
- if(fullpath == "")
- {
- std::string testpath = porting::path_data + DIR_DELIM + rel_path;
- // Check all filename extensions. Returns "" if not found.
- fullpath = getImagePath(testpath);
- }
-
- // Add to cache (also an empty result is cached)
- g_texturename_to_path_cache.set(filename, fullpath);
-
- // Finally return it
- return fullpath;
-}
-
-/*
- Gets the path to a model by first checking if the model exists
- in data_path and if not, using the default data path.
-
- Checks all supported extensions by replacing the original extension.
-
- If not found, returns "".
-
- Utilizes a thread-safe cache.
-*/
-std::string getModelPath(const std::string &filename)
-{
- std::string fullpath = "";
- /*
- Check from cache
- */
+ /* check from cache */
bool incache = g_modelname_to_path_cache.get(filename, &fullpath);
- if(incache)
- return fullpath;
+ if (incache) {
+ if (must_exist == true) {
+ if (!fs::PathExists(fullpath))
+ fullpath = "";
+ }
+ if (fullpath != "")
+ return fullpath;
+ }
- std::string rel_path = std::string("models")+DIR_DELIM+filename;
- /*
- Check from data_path /models
- */
+ std::string rel_path = std::string("");
+ if (type == "model") {
+ rel_path += std::string("models")+DIR_DELIM+filename;
+ }else if (type == "texture") {
+ rel_path += std::string("textures")+DIR_DELIM+filename;
+ }else if (type == "html") {
+ rel_path += std::string("html")+DIR_DELIM+filename;
+ }else if (type == "player") {
+ rel_path += std::string("textures")+DIR_DELIM+"players"+DIR_DELIM+filename;
+ }
+
+ /* check from data_path */
std::string data_path = g_settings->get("data_path");
- if(data_path != "")
- {
+ if (data_path != "") {
std::string testpath = data_path + DIR_DELIM + rel_path;
- if(fs::PathExists(testpath))
- fullpath = std::string(testpath);
+ if (type == "model" || type == "html") {
+ if (fs::PathExists(testpath))
+ fullpath = std::string(testpath);
+ }else{
+ fullpath = getImagePath(testpath);
+ }
}
- /*
- Check from default data directory
- */
- if(fullpath == "")
- {
+ /* check from user data directory */
+ if (fullpath == "") {
+ std::string testpath = porting::path_userdata + DIR_DELIM + rel_path;
+ if (type == "model" || type == "html") {
+ if (fs::PathExists(testpath))
+ fullpath = std::string(testpath);
+ }else{
+ fullpath = getImagePath(testpath);
+ }
+ }
+
+ /* check from default data directory */
+ if (fullpath == "") {
std::string testpath = porting::path_data + DIR_DELIM + rel_path;
- if(fs::PathExists(testpath))
- fullpath = std::string(testpath);
+ if (type == "model" || type == "html") {
+ if (fs::PathExists(testpath))
+ fullpath = std::string(testpath);
+ }else{
+ fullpath = getImagePath(testpath);
+ }
}
- // Add to cache (also an empty result is cached)
+ if (must_exist == false && fullpath == "")
+#ifdef RUN_IN_PLACE
+ fullpath = porting::path_data + DIR_DELIM + rel_path;
+#else
+ fullpath = porting::path_userdata + DIR_DELIM + rel_path;
+#endif
+
+ /* add to cache (also an empty result is cached) */
g_modelname_to_path_cache.set(filename, fullpath);
- // Finally return it
+ /* finally return it */
return fullpath;
}
diff --git a/src/path.h b/src/path.h
index fd4ea2f..c97f585 100644
--- a/src/path.h
+++ b/src/path.h
@@ -33,7 +33,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Utilizes a thread-safe cache.
*/
-std::string getTexturePath(const std::string &filename);
-std::string getModelPath(const std::string &filename);
+std::string getPath(const char* type, const std::string &filename, bool must_exist);
+
+/* wrappers for the old functions, because too lazy to replace them all */
+inline std::string getTexturePath(const std::string &filename)
+{
+ return getPath("texture",filename,true);
+}
+inline std::string getModelPath(const std::string &filename)
+{
+ return getPath("model",filename,true);
+}
#endif
diff --git a/src/player.cpp b/src/player.cpp
index 6b82ef6..e5ad478 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -256,9 +256,9 @@ void RemotePlayer::updateName(const char *name)
mbstowcs(wname, m_name, strlen(m_name)+1);
m_text->setText(wname);
}
- if (m_node != NULL) {
- std::string tex = std::string("players") + DIR_DELIM + "player_" + m_name + ".png";
- std::string ptex = getTexturePath(tex);
+ if (m_node != NULL && !isLocal()) {
+ std::string tex = std::string("player_") + m_name + ".png";
+ std::string ptex = getPath("player",tex,true);
printf("'%s' '%s'\n",tex.c_str(),ptex.c_str());
if (ptex == "")
return;
diff --git a/src/porting.h b/src/porting.h
index 4970a84..55e4312 100644
--- a/src/porting.h
+++ b/src/porting.h
@@ -71,7 +71,7 @@ extern std::string path_userdata;
/*
Get full path of stuff in data directory.
- Example: "stone.png" -> "../data/stone.png"
+ Example: "stone.png" -> "../data/textures/stone.png"
*/
std::string getDataPath(const char *subpath);