Example #1
0
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {

	ERR_EXPLAIN("Invalid packet received. Size too small.");
	ERR_FAIL_COND(p_packet_len < 5);
	int id = decode_uint32(&p_packet[1]);

	String paths;
	paths.parse_utf8((const char *)&p_packet[5], p_packet_len - 5);

	NodePath path = paths;

	if (!path_get_cache.has(p_from)) {
		path_get_cache[p_from] = PathGetCache();
	}

	PathGetCache::NodeInfo ni;
	ni.path = path;
	ni.instance = 0;

	path_get_cache[p_from].nodes[id] = ni;

	// Encode path to send ack.
	CharString pname = String(path).utf8();
	int len = encode_cstring(pname.get_data(), NULL);

	Vector<uint8_t> packet;

	packet.resize(1 + len);
	packet.write[0] = NETWORK_COMMAND_CONFIRM_PATH;
	encode_cstring(pname.get_data(), &packet.write[1]);

	network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
	network_peer->set_target_peer(p_from);
	network_peer->put_packet(packet.ptr(), packet.size());
}
Example #2
0
static String _get_clipboard(Atom p_source, Window x11_window, ::Display* x11_display, String p_internal_clipboard) {

	String ret;

	Atom type;
	Atom selection = XA_PRIMARY;
	int format, result;
	unsigned long len, bytes_left, dummy;
	unsigned char *data;
	Window Sown = XGetSelectionOwner (x11_display, p_source);

	if (Sown == x11_window) {

		printf("returning internal clipboard\n");
		return p_internal_clipboard;
	};

	if (Sown != None) {
		XConvertSelection (x11_display, p_source, XA_STRING, selection,
					 x11_window, CurrentTime);
		XFlush (x11_display);
		while (true) {
			XEvent event;
			XNextEvent(x11_display, &event);
			if (event.type == SelectionNotify && event.xselection.requestor == x11_window) {
				break;
			};
		};

		//
		// Do not get any data, see how much data is there
		//
		XGetWindowProperty (x11_display, x11_window,
			selection, 	  // Tricky..
			0, 0,	  	  // offset - len
			0, 	 	  // Delete 0==FALSE
			AnyPropertyType,  //flag
			&type,		  // return type
			&format,	  // return format
			&len, &bytes_left,  //that
			&data);
		// DATA is There
		if (bytes_left > 0)
		{
			result = XGetWindowProperty (x11_display, x11_window,
				selection, 0,bytes_left,0,
				AnyPropertyType, &type,&format,
				&len, &dummy, &data);
			if (result == Success) {
				ret.parse_utf8((const char*)data);
			} else printf ("FAIL\n");
			XFree (data);
		}
	}

	return ret;

};
Example #3
0
String FileAccess::get_pascal_string() {

	uint32_t sl = get_32();
	CharString cs;
	cs.resize(sl + 1);
	get_buffer((uint8_t *)cs.ptr(), sl);
	cs[sl] = 0;

	String ret;
	ret.parse_utf8(cs.ptr());

	return ret;
};
Example #4
0
String StreamPeer::get_utf8_string(int p_bytes) {

	ERR_FAIL_COND_V(p_bytes < 0, String());

	Vector<uint8_t> buf;
	Error err = buf.resize(p_bytes);
	ERR_FAIL_COND_V(err != OK, String());
	err = get_data(buf.ptr(), p_bytes);
	ERR_FAIL_COND_V(err != OK, String());

	String ret;
	ret.parse_utf8((const char *)buf.ptr(), buf.size());
	return ret;
}
Example #5
0
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {

	ERR_FAIL_COND(p_packet_len < 2);

	String paths;
	paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1);

	NodePath path = paths;

	PathSentCache *psc = path_send_cache.getptr(path);
	ERR_FAIL_COND(!psc);

	Map<int, bool>::Element *E = psc->confirmed_peers.find(p_from);
	ERR_FAIL_COND(!E);
	E->get() = true;
}
Example #6
0
StringName ResourceInteractiveLoaderBinary::_get_string() {

	uint32_t id = f->get_32();
	if (id & 0x80000000) {
		uint32_t len = id & 0x7FFFFFFF;
		if ((int)len > str_buf.size()) {
			str_buf.resize(len);
		}
		if (len == 0)
			return StringName();
		f->get_buffer((uint8_t *)&str_buf[0], len);
		String s;
		s.parse_utf8(&str_buf[0]);
		return s;
	}

	return string_map[id];
}
void RichTextEditor::_file_selected(const String& p_path) {

	CharString cs;
	FileAccess *fa = FileAccess::open(p_path,FileAccess::READ);
	if (!fa) {
		ERR_FAIL();
	}

	while(!fa->eof_reached())
		cs.push_back(fa->get_8());
	cs.push_back(0);
	memdelete(fa);

	String bbcode;
	bbcode.parse_utf8(&cs[0]);
	node->parse_bbcode(bbcode);

}
Example #8
0
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {

	ERR_EXPLAIN("Invalid packet received. Size too small.");
	ERR_FAIL_COND(p_packet_len < 2);

	String paths;
	paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1);

	NodePath path = paths;

	PathSentCache *psc = path_send_cache.getptr(path);
	ERR_EXPLAIN("Invalid packet received. Tries to confirm a path which was not found in cache.");
	ERR_FAIL_COND(!psc);

	Map<int, bool>::Element *E = psc->confirmed_peers.find(p_from);
	ERR_EXPLAIN("Invalid packet received. Source peer was not found in cache for the given path.");
	ERR_FAIL_COND(!E);
	E->get() = true;
}
Example #9
0
Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len) {

	uint32_t target = decode_uint32(&p_packet[1]);
	Node *node = NULL;

	if (target & 0x80000000) {
		// Use full path (not cached yet).

		int ofs = target & 0x7FFFFFFF;

		ERR_EXPLAIN("Invalid packet received. Size smaller than declared.");
		ERR_FAIL_COND_V(ofs >= p_packet_len, NULL);

		String paths;
		paths.parse_utf8((const char *)&p_packet[ofs], p_packet_len - ofs);

		NodePath np = paths;

		node = root_node->get_node(np);

		if (!node)
			ERR_PRINTS("Failed to get path from RPC: " + String(np));
	} else {
		// Use cached path.
		int id = target;

		Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
		ERR_EXPLAIN("Invalid packet received. Requests invalid peer cache.");
		ERR_FAIL_COND_V(!E, NULL);

		Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(id);
		ERR_EXPLAIN("Invalid packet received. Unabled to find requested cached node.");
		ERR_FAIL_COND_V(!F, NULL);

		PathGetCache::NodeInfo *ni = &F->get();
		// Do proper caching later.

		node = root_node->get_node(ni->path);
		if (!node)
			ERR_PRINTS("Failed to get cached path from RPC: " + String(ni->path));
	}
	return node;
}
Error EditorSceneImporterFBXConv::_parse_json(State& state, const String &p_path) {

	//not the happiest....
	Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
	ERR_FAIL_COND_V(!data.size(),ERR_FILE_CANT_OPEN);
	String str;
	bool utferr = str.parse_utf8((const char*)data.ptr(),data.size());
	ERR_FAIL_COND_V(utferr,ERR_PARSE_ERROR);

	Dictionary dict;
	Error err = dict.parse_json(str);
	str=String(); //free mem immediately
	ERR_FAIL_COND_V(err,err);

	if (dict.has("meshes"))
		state.meshes=dict["meshes"];
	if (dict.has("materials"))
		state.materials=dict["materials"];
	if (dict.has("nodes"))
		state.nodes=dict["nodes"];
	if (dict.has("animations"))
		state.animations=dict["animations"];


	state.scene = memnew( Spatial );
	_detect_bones(state);
	_parse_surfaces(state);
	_parse_materials(state);
	err = _parse_nodes(state,state.nodes,state.scene);
	if (err)
		return err;

	if (state.import_animations) {
		err = _parse_animations(state);
		if (err)
			return err;
	}

	print_line("JSON PARSED O-K!");

	return OK;
}
Example #11
0
String OS_Unix::get_executable_path() const {

#ifdef __linux__
	//fix for running from a symlink
	char buf[256];
	memset(buf, 0, 256);
	readlink("/proc/self/exe", buf, sizeof(buf));
	String b;
	b.parse_utf8(buf);
	if (b == "") {
		WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]");
		return OS::get_executable_path();
	}
	return b;
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
	char resolved_path[MAXPATHLEN];

	realpath(OS::get_executable_path().utf8().get_data(), resolved_path);

	return String(resolved_path);
#elif defined(__APPLE__)
	char temp_path[1];
	uint32_t buff_size = 1;
	_NSGetExecutablePath(temp_path, &buff_size);

	char *resolved_path = new char[buff_size + 1];

	if (_NSGetExecutablePath(resolved_path, &buff_size) == 1)
		WARN_PRINT("MAXPATHLEN is too small");

	String path(resolved_path);
	delete[] resolved_path;

	return path;
#else
	ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly.");
	return OS::get_executable_path();
#endif
}
Example #12
0
Error read_all_file_utf8(const String &p_path, String &r_content) {
	PoolVector<uint8_t> sourcef;
	Error err;
	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
	ERR_FAIL_COND_V(err != OK, err);

	int len = f->get_len();
	sourcef.resize(len + 1);
	PoolVector<uint8_t>::Write w = sourcef.write();
	int r = f->get_buffer(w.ptr(), len);
	f->close();
	memdelete(f);
	ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
	w[len] = 0;

	String source;
	if (source.parse_utf8((const char *)w.ptr())) {
		ERR_FAIL_V(ERR_INVALID_DATA);
	}

	r_content = source;
	return OK;
}
Example #13
0
static String _parse_string(const uint8_t *p_bytes,bool p_utf8) {

	uint32_t offset=0;
	uint32_t len = decode_uint16(&p_bytes[offset]);

	if (p_utf8) {
		//don't know how to read extended utf8, this will have to be for now
		len>>=8;

	}
	offset+=2;
	//printf("len %i, unicode: %i\n",len,int(p_utf8));

	if (p_utf8) {

		Vector<uint8_t> str8;
		str8.resize(len+1);
		for(int i=0;i<len;i++) {
			str8[i]=p_bytes[offset+i];
		}
		str8[len]=0;
		String str;
		str.parse_utf8((const char*)str8.ptr());
		return str;
	} else {

		String str;
		for(int i=0;i<len;i++) {
			CharType c = decode_uint16(&p_bytes[offset+i*2]);
			if (c==0)
				break;
			str += String::chr(c);
		}
		return str;
	}

}
Example #14
0
void EditorFileServer::_subthread_start(void *s) {

	ClientData *cd = (ClientData *)s;

	cd->connection->set_nodelay(true);
	uint8_t buf4[8];
	Error err = cd->connection->get_data(buf4, 4);
	if (err != OK) {
		_close_client(cd);
		ERR_FAIL_COND(err != OK);
	}

	int passlen = decode_uint32(buf4);

	if (passlen > 512) {

		_close_client(cd);
		ERR_FAIL_COND(passlen > 512);
	} else if (passlen > 0) {

		Vector<char> passutf8;
		passutf8.resize(passlen + 1);
		err = cd->connection->get_data((uint8_t *)passutf8.ptr(), passlen);
		if (err != OK) {
			_close_client(cd);
			ERR_FAIL_COND(err != OK);
		}
		passutf8[passlen] = 0;
		String s;
		s.parse_utf8(passutf8.ptr());
		if (s != cd->efs->password) {
			encode_uint32(ERR_INVALID_DATA, buf4);
			cd->connection->put_data(buf4, 4);
			OS::get_singleton()->delay_usec(1000000);
			_close_client(cd);
			ERR_PRINT("CLIENT PASSWORD MISMATCH");
			ERR_FAIL();
		}
	} else {
		if (cd->efs->password != "") {
			encode_uint32(ERR_INVALID_DATA, buf4);
			cd->connection->put_data(buf4, 4);
			OS::get_singleton()->delay_usec(1000000);
			_close_client(cd);
			ERR_PRINT("CLIENT PASSWORD MISMATCH (should be empty!)");
			ERR_FAIL();
		}
	}

	encode_uint32(OK, buf4);
	cd->connection->put_data(buf4, 4);

	while (!cd->quit) {

		//wait for ID
		err = cd->connection->get_data(buf4, 4);
		//#define DEBUG_PRINT(m_p) print_line(m_p)
		DEBUG_TIME("get_data")

		if (err != OK) {
			_close_client(cd);
			ERR_FAIL_COND(err != OK);
		}
		int id = decode_uint32(buf4);

		//wait for command
		err = cd->connection->get_data(buf4, 4);
		if (err != OK) {
			_close_client(cd);
			ERR_FAIL_COND(err != OK);
		}
		int cmd = decode_uint32(buf4);

		switch (cmd) {

			case FileAccessNetwork::COMMAND_FILE_EXISTS:
			case FileAccessNetwork::COMMAND_GET_MODTIME:
			case FileAccessNetwork::COMMAND_OPEN_FILE: {

				DEBUG_TIME("open_file")
				err = cd->connection->get_data(buf4, 4);
				if (err != OK) {
					_close_client(cd);
					ERR_FAIL_COND(err != OK);
				}

				int namelen = decode_uint32(buf4);
				Vector<char> fileutf8;
				fileutf8.resize(namelen + 1);
				err = cd->connection->get_data((uint8_t *)fileutf8.ptr(), namelen);
				if (err != OK) {
					_close_client(cd);
					ERR_FAIL_COND(err != OK);
				}
				fileutf8[namelen] = 0;
				String s;
				s.parse_utf8(fileutf8.ptr());

				if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) {
					print_line("FILE EXISTS: " + s);
				}
				if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) {
					print_line("MOD TIME: " + s);
				}
				if (cmd == FileAccessNetwork::COMMAND_OPEN_FILE) {
					print_line("OPEN: " + s);
				}

				if (!s.begins_with("res://")) {

					_close_client(cd);
					ERR_FAIL_COND(!s.begins_with("res://"));
				}
				ERR_CONTINUE(cd->files.has(id));

				if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) {

					encode_uint32(id, buf4);
					cd->connection->put_data(buf4, 4);
					encode_uint32(FileAccessNetwork::RESPONSE_FILE_EXISTS, buf4);
					cd->connection->put_data(buf4, 4);
					encode_uint32(FileAccess::exists(s), buf4);
					cd->connection->put_data(buf4, 4);
					DEBUG_TIME("open_file_end")
					break;
				}

				if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) {

					encode_uint32(id, buf4);
					cd->connection->put_data(buf4, 4);
					encode_uint32(FileAccessNetwork::RESPONSE_GET_MODTIME, buf4);
					cd->connection->put_data(buf4, 4);
					encode_uint64(FileAccess::get_modified_time(s), buf4);
					cd->connection->put_data(buf4, 8);
					DEBUG_TIME("open_file_end")
					break;
				}

				FileAccess *fa = FileAccess::open(s, FileAccess::READ);
				if (!fa) {
					//not found, continue
					encode_uint32(id, buf4);
					cd->connection->put_data(buf4, 4);
					encode_uint32(FileAccessNetwork::RESPONSE_OPEN, buf4);
					cd->connection->put_data(buf4, 4);
					encode_uint32(ERR_FILE_NOT_FOUND, buf4);
					cd->connection->put_data(buf4, 4);
					DEBUG_TIME("open_file_end")
					break;
				}

				encode_uint32(id, buf4);
				cd->connection->put_data(buf4, 4);
				encode_uint32(FileAccessNetwork::RESPONSE_OPEN, buf4);
				cd->connection->put_data(buf4, 4);
				encode_uint32(OK, buf4);
				cd->connection->put_data(buf4, 4);
				encode_uint64(fa->get_len(), buf4);
				cd->connection->put_data(buf4, 8);

				cd->files[id] = fa;
				DEBUG_TIME("open_file_end")

			} break;
Example #15
0
Error HTTPClient::poll(){

	switch(status) {


		case STATUS_RESOLVING: {
			ERR_FAIL_COND_V(resolving==IP::RESOLVER_INVALID_ID,ERR_BUG);

			IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
			switch(rstatus) {
				case IP::RESOLVER_STATUS_WAITING: return OK; //still resolving

				case IP::RESOLVER_STATUS_DONE: {

					IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving);
					Error err = tcp_connection->connect(host,conn_port);
					IP::get_singleton()->erase_resolve_item(resolving);
					resolving=IP::RESOLVER_INVALID_ID;
					if (err) {
						status=STATUS_CANT_CONNECT;
						return err;
					}

					status=STATUS_CONNECTING;
				} break;
				case IP::RESOLVER_STATUS_NONE:
				case IP::RESOLVER_STATUS_ERROR: {

					IP::get_singleton()->erase_resolve_item(resolving);
					resolving=IP::RESOLVER_INVALID_ID;
					close();
					status=STATUS_CANT_RESOLVE;
					return ERR_CANT_RESOLVE;
				} break;

			}
		} break;
		case STATUS_CONNECTING: {

			StreamPeerTCP::Status s = tcp_connection->get_status();
			switch(s) {

				case StreamPeerTCP::STATUS_CONNECTING: {
					return OK; //do none
				} break;
				case StreamPeerTCP::STATUS_CONNECTED: {
					status=STATUS_CONNECTED;
					return OK;
				} break;
				case StreamPeerTCP::STATUS_ERROR:
				case StreamPeerTCP::STATUS_NONE: {

					close();
					status=STATUS_CANT_CONNECT;
					return ERR_CANT_CONNECT;
				} break;
			}
		} break;
		case STATUS_CONNECTED: {
			//request something please
			return OK;
		} break;
		case STATUS_REQUESTING: {


			while(true) {
				uint8_t byte;
				int rec=0;
				Error err = connection->get_partial_data(&byte,1,rec);
				if (err!=OK) {
					close();
					status=STATUS_CONNECTION_ERROR;
					return ERR_CONNECTION_ERROR;
				}

				if (rec==0)
					return OK; //keep trying!

				response_str.push_back(byte);
				int rs = response_str.size();
				if (
					(rs>=2 && response_str[rs-2]=='\n' && response_str[rs-1]=='\n') ||
					(rs>=4 && response_str[rs-4]=='\r' && response_str[rs-3]=='\n' && rs>=4 && response_str[rs-2]=='\r' && response_str[rs-1]=='\n')
				) {


					//end of response, parse.
					response_str.push_back(0);
					String response;
					response.parse_utf8((const char*)response_str.ptr());
					print_line("END OF RESPONSE? :\n"+response+"\n------");
					Vector<String> responses = response.split("\n");
					body_size=0;
					chunked=false;
					body_left=0;
					chunk_left=0;
					response_headers.clear();
					response_num = RESPONSE_OK;

					for(int i=0;i<responses.size();i++) {

						String s = responses[i].strip_edges();
						if (s.length()==0)
							continue;						
						if (s.begins_with("Content-Length:")) {
							body_size = s.substr(s.find(":")+1,s.length()).strip_edges().to_int();
							body_left=body_size;
						}

						if (s.begins_with("Transfer-Encoding:")) {
							String encoding = s.substr(s.find(":")+1,s.length()).strip_edges();
							print_line("TRANSFER ENCODING: "+encoding);
							if (encoding=="chunked") {
								chunked=true;
							}

						}

						if (i==0 && responses[i].begins_with("HTTP")) {

							String num = responses[i].get_slice(" ",1);
							response_num=num.to_int();
						} else {

							response_headers.push_back(s);
						}

					}

					if (body_size==0 && !chunked) {

						status=STATUS_CONNECTED; //ask for something again?
					} else {
						status=STATUS_BODY;
					}
					return OK;
				}
			}
			//wait for response
			return OK;
		} break;
		case STATUS_DISCONNECTED: {
			return ERR_UNCONFIGURED;
		} break;
		case STATUS_CONNECTION_ERROR: {
			return ERR_CONNECTION_ERROR;
		} break;
		case STATUS_CANT_CONNECT: {
			return ERR_CANT_CONNECT;
		} break;
		case STATUS_CANT_RESOLVE: {
			return ERR_CANT_RESOLVE;
		} break;
	}


	return OK;
}
Example #16
0
Error HTTPClient::poll() {

	switch (status) {

		case STATUS_RESOLVING: {
			ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG);

			IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
			switch (rstatus) {
				case IP::RESOLVER_STATUS_WAITING:
					return OK; // Still resolving

				case IP::RESOLVER_STATUS_DONE: {

					IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving);
					Error err = tcp_connection->connect_to_host(host, conn_port);
					IP::get_singleton()->erase_resolve_item(resolving);
					resolving = IP::RESOLVER_INVALID_ID;
					if (err) {
						status = STATUS_CANT_CONNECT;
						return err;
					}

					status = STATUS_CONNECTING;
				} break;
				case IP::RESOLVER_STATUS_NONE:
				case IP::RESOLVER_STATUS_ERROR: {

					IP::get_singleton()->erase_resolve_item(resolving);
					resolving = IP::RESOLVER_INVALID_ID;
					close();
					status = STATUS_CANT_RESOLVE;
					return ERR_CANT_RESOLVE;
				} break;
			}
		} break;
		case STATUS_CONNECTING: {

			StreamPeerTCP::Status s = tcp_connection->get_status();
			switch (s) {

				case StreamPeerTCP::STATUS_CONNECTING: {
					return OK;
				} break;
				case StreamPeerTCP::STATUS_CONNECTED: {
					if (ssl) {
						Ref<StreamPeerSSL> ssl;
						if (!handshaking) {
							// Connect the StreamPeerSSL and start handshaking
							ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create());
							ssl->set_blocking_handshake_enabled(false);
							Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host);
							if (err != OK) {
								close();
								status = STATUS_SSL_HANDSHAKE_ERROR;
								return ERR_CANT_CONNECT;
							}
							connection = ssl;
							handshaking = true;
						} else {
							// We are already handshaking, which means we can use your already active SSL connection
							ssl = static_cast<Ref<StreamPeerSSL> >(connection);
							ssl->poll(); // Try to finish the handshake
						}

						if (ssl->get_status() == StreamPeerSSL::STATUS_CONNECTED) {
							// Handshake has been successful
							handshaking = false;
							status = STATUS_CONNECTED;
							return OK;
						} else if (ssl->get_status() != StreamPeerSSL::STATUS_HANDSHAKING) {
							// Handshake has failed
							close();
							status = STATUS_SSL_HANDSHAKE_ERROR;
							return ERR_CANT_CONNECT;
						}
						// ... we will need to poll more for handshake to finish
					} else {
						status = STATUS_CONNECTED;
					}
					return OK;
				} break;
				case StreamPeerTCP::STATUS_ERROR:
				case StreamPeerTCP::STATUS_NONE: {

					close();
					status = STATUS_CANT_CONNECT;
					return ERR_CANT_CONNECT;
				} break;
			}
		} break;
		case STATUS_BODY:
		case STATUS_CONNECTED: {
			// Check if we are still connected
			if (ssl) {
				Ref<StreamPeerSSL> tmp = connection;
				tmp->poll();
				if (tmp->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
					status = STATUS_CONNECTION_ERROR;
					return ERR_CONNECTION_ERROR;
				}
			} else if (tcp_connection->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
				status = STATUS_CONNECTION_ERROR;
				return ERR_CONNECTION_ERROR;
			}
			// Connection established, requests can now be made
			return OK;
		} break;
		case STATUS_REQUESTING: {

			while (true) {
				uint8_t byte;
				int rec = 0;
				Error err = _get_http_data(&byte, 1, rec);
				if (err != OK) {
					close();
					status = STATUS_CONNECTION_ERROR;
					return ERR_CONNECTION_ERROR;
				}

				if (rec == 0)
					return OK; // Still requesting, keep trying!

				response_str.push_back(byte);
				int rs = response_str.size();
				if (
						(rs >= 2 && response_str[rs - 2] == '\n' && response_str[rs - 1] == '\n') ||
						(rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) {

					// End of response, parse.
					response_str.push_back(0);
					String response;
					response.parse_utf8((const char *)response_str.ptr());
					Vector<String> responses = response.split("\n");
					body_size = -1;
					chunked = false;
					body_left = 0;
					chunk_left = 0;
					read_until_eof = false;
					response_str.clear();
					response_headers.clear();
					response_num = RESPONSE_OK;

					// Per the HTTP 1.1 spec, keep-alive is the default, but in practice
					// it's safe to assume it only if the explicit header is found, allowing
					// to handle body-up-to-EOF responses on naive servers; that's what Curl
					// and browsers do
					bool keep_alive = false;

					for (int i = 0; i < responses.size(); i++) {

						String header = responses[i].strip_edges();
						String s = header.to_lower();
						if (s.length() == 0)
							continue;
						if (s.begins_with("content-length:")) {
							body_size = s.substr(s.find(":") + 1, s.length()).strip_edges().to_int();
							body_left = body_size;

						} else if (s.begins_with("transfer-encoding:")) {
							String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges();
							if (encoding == "chunked") {
								chunked = true;
							}
						} else if (s.begins_with("connection: keep-alive")) {
							keep_alive = true;
						}

						if (i == 0 && responses[i].begins_with("HTTP")) {

							String num = responses[i].get_slicec(' ', 1);
							response_num = num.to_int();
						} else {

							response_headers.push_back(header);
						}
					}

					if (body_size != -1 || chunked) {

						status = STATUS_BODY;
					} else if (!keep_alive) {

						read_until_eof = true;
						status = STATUS_BODY;
					} else {

						status = STATUS_CONNECTED;
					}
					return OK;
				}
			}
			// Wait for response
			return OK;
		} break;
		case STATUS_DISCONNECTED: {
			return ERR_UNCONFIGURED;
		} break;
		case STATUS_CONNECTION_ERROR:
		case STATUS_SSL_HANDSHAKE_ERROR: {
			return ERR_CONNECTION_ERROR;
		} break;
		case STATUS_CANT_CONNECT: {
			return ERR_CANT_CONNECT;
		} break;
		case STATUS_CANT_RESOLVE: {
			return ERR_CANT_RESOLVE;
		} break;
	}

	return OK;
}
Example #17
0
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) {

	const uint8_t *buf = p_buffer;
	int len = p_len;

	if (len < 4) {

		ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
	}

	uint32_t type = decode_uint32(buf);

	ERR_FAIL_COND_V((type & ENCODE_MASK) >= Variant::VARIANT_MAX, ERR_INVALID_DATA);

	buf += 4;
	len -= 4;
	if (r_len)
		*r_len = 4;

	switch (type & ENCODE_MASK) {

		case Variant::NIL: {

			r_variant = Variant();
		} break;
		case Variant::BOOL: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			bool val = decode_uint32(buf);
			r_variant = val;
			if (r_len)
				(*r_len) += 4;
		} break;
		case Variant::INT: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			if (type & ENCODE_FLAG_64) {
				int64_t val = decode_uint64(buf);
				r_variant = val;
				if (r_len)
					(*r_len) += 8;

			} else {
				int32_t val = decode_uint32(buf);
				r_variant = val;
				if (r_len)
					(*r_len) += 4;
			}

		} break;
		case Variant::REAL: {

			ERR_FAIL_COND_V(len < (int)4, ERR_INVALID_DATA);

			if (type & ENCODE_FLAG_64) {
				double val = decode_double(buf);
				r_variant = val;
				if (r_len)
					(*r_len) += 8;
			} else {
				float val = decode_float(buf);
				r_variant = val;
				if (r_len)
					(*r_len) += 4;
			}

		} break;
		case Variant::STRING: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t strlen = decode_uint32(buf);
			buf += 4;
			len -= 4;
			ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);

			String str;
			str.parse_utf8((const char *)buf, strlen);
			r_variant = str;

			if (r_len) {
				if (strlen % 4)
					(*r_len) += 4 - strlen % 4;
				(*r_len) += 4 + strlen;
			}

		} break;
		// math types

		case Variant::VECTOR2: {

			ERR_FAIL_COND_V(len < (int)4 * 2, ERR_INVALID_DATA);
			Vector2 val;
			val.x = decode_float(&buf[0]);
			val.y = decode_float(&buf[4]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 2;

		} break; // 5
		case Variant::RECT2: {

			ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
			Rect2 val;
			val.position.x = decode_float(&buf[0]);
			val.position.y = decode_float(&buf[4]);
			val.size.x = decode_float(&buf[8]);
			val.size.y = decode_float(&buf[12]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 4;

		} break;
		case Variant::VECTOR3: {

			ERR_FAIL_COND_V(len < (int)4 * 3, ERR_INVALID_DATA);
			Vector3 val;
			val.x = decode_float(&buf[0]);
			val.y = decode_float(&buf[4]);
			val.z = decode_float(&buf[8]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 3;

		} break;
		case Variant::TRANSFORM2D: {

			ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
			Transform2D val;
			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 2; j++) {

					val.elements[i][j] = decode_float(&buf[(i * 2 + j) * 4]);
				}
			}

			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 6;

		} break;
		case Variant::PLANE: {

			ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
			Plane val;
			val.normal.x = decode_float(&buf[0]);
			val.normal.y = decode_float(&buf[4]);
			val.normal.z = decode_float(&buf[8]);
			val.d = decode_float(&buf[12]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 4;

		} break;
		case Variant::QUAT: {

			ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
			Quat val;
			val.x = decode_float(&buf[0]);
			val.y = decode_float(&buf[4]);
			val.z = decode_float(&buf[8]);
			val.w = decode_float(&buf[12]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 4;

		} break;
		case Variant::RECT3: {

			ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
			Rect3 val;
			val.position.x = decode_float(&buf[0]);
			val.position.y = decode_float(&buf[4]);
			val.position.z = decode_float(&buf[8]);
			val.size.x = decode_float(&buf[12]);
			val.size.y = decode_float(&buf[16]);
			val.size.z = decode_float(&buf[20]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 6;

		} break;
		case Variant::BASIS: {

			ERR_FAIL_COND_V(len < (int)4 * 9, ERR_INVALID_DATA);
			Basis val;
			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 3; j++) {

					val.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]);
				}
			}

			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 9;

		} break;
		case Variant::TRANSFORM: {

			ERR_FAIL_COND_V(len < (int)4 * 12, ERR_INVALID_DATA);
			Transform val;
			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 3; j++) {

					val.basis.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]);
				}
			}
			val.origin[0] = decode_float(&buf[36]);
			val.origin[1] = decode_float(&buf[40]);
			val.origin[2] = decode_float(&buf[44]);

			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 12;

		} break;

		// misc types
		case Variant::COLOR: {

			ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
			Color val;
			val.r = decode_float(&buf[0]);
			val.g = decode_float(&buf[4]);
			val.b = decode_float(&buf[8]);
			val.a = decode_float(&buf[12]);
			r_variant = val;

			if (r_len)
				(*r_len) += 4 * 4;

		} break;
		case Variant::NODE_PATH: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t strlen = decode_uint32(buf);

			if (strlen & 0x80000000) {
				//new format
				ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA);
				Vector<StringName> names;
				Vector<StringName> subnames;
				StringName prop;

				uint32_t namecount = strlen &= 0x7FFFFFFF;
				uint32_t subnamecount = decode_uint32(buf + 4);
				uint32_t flags = decode_uint32(buf + 8);

				len -= 12;
				buf += 12;

				int total = namecount + subnamecount;
				if (flags & 2)
					total++;

				if (r_len)
					(*r_len) += 12;

				for (int i = 0; i < total; i++) {

					ERR_FAIL_COND_V((int)len < 4, ERR_INVALID_DATA);
					strlen = decode_uint32(buf);

					int pad = 0;

					if (strlen % 4)
						pad += 4 - strlen % 4;

					buf += 4;
					len -= 4;
					ERR_FAIL_COND_V((int)strlen + pad > len, ERR_INVALID_DATA);

					String str;
					str.parse_utf8((const char *)buf, strlen);

					if (i < namecount)
						names.push_back(str);
					else if (i < namecount + subnamecount)
						subnames.push_back(str);
					else
						prop = str;

					buf += strlen + pad;
					len -= strlen + pad;

					if (r_len)
						(*r_len) += 4 + strlen + pad;
				}

				r_variant = NodePath(names, subnames, flags & 1, prop);

			} else {
				//old format, just a string

				buf += 4;
				len -= 4;
				ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);

				String str;
				str.parse_utf8((const char *)buf, strlen);

				r_variant = NodePath(str);

				if (r_len)
					(*r_len) += 4 + strlen;
			}

		} break;
		/*case Variant::RESOURCE: {

			ERR_EXPLAIN("Can't marshallize resources");
			ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go
		} break;*/
		case Variant::_RID: {

			r_variant = RID();
		} break;
		case Variant::OBJECT: {

			r_variant = (Object *)NULL;
		} break;
		case Variant::DICTIONARY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			//  bool shared = count&0x80000000;
			count &= 0x7FFFFFFF;

			buf += 4;
			len -= 4;

			if (r_len) {
				(*r_len) += 4;
			}

			Dictionary d;

			for (uint32_t i = 0; i < count; i++) {

				Variant key, value;

				int used;
				Error err = decode_variant(key, buf, len, &used);
				ERR_FAIL_COND_V(err, err);

				buf += used;
				len -= used;
				if (r_len) {
					(*r_len) += used;
				}

				err = decode_variant(value, buf, len, &used);
				ERR_FAIL_COND_V(err, err);

				buf += used;
				len -= used;
				if (r_len) {
					(*r_len) += used;
				}

				d[key] = value;
			}

			r_variant = d;

		} break;
		case Variant::ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			//  bool shared = count&0x80000000;
			count &= 0x7FFFFFFF;

			buf += 4;
			len -= 4;

			if (r_len) {
				(*r_len) += 4;
			}

			Array varr;

			for (uint32_t i = 0; i < count; i++) {

				int used = 0;
				Variant v;
				Error err = decode_variant(v, buf, len, &used);
				ERR_FAIL_COND_V(err, err);
				buf += used;
				len -= used;
				varr.push_back(v);
				if (r_len) {
					(*r_len) += used;
				}
			}

			r_variant = varr;

		} break;

		// arrays
		case Variant::POOL_BYTE_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			buf += 4;
			len -= 4;
			ERR_FAIL_COND_V((int)count > len, ERR_INVALID_DATA);

			PoolVector<uint8_t> data;

			if (count) {
				data.resize(count);
				PoolVector<uint8_t>::Write w = data.write();
				for (int i = 0; i < count; i++) {

					w[i] = buf[i];
				}

				w = PoolVector<uint8_t>::Write();
			}

			r_variant = data;

			if (r_len) {
				if (count % 4)
					(*r_len) += 4 - count % 4;
				(*r_len) += 4 + count;
			}

		} break;
		case Variant::POOL_INT_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			buf += 4;
			len -= 4;
			ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA);

			PoolVector<int> data;

			if (count) {
				//const int*rbuf=(const int*)buf;
				data.resize(count);
				PoolVector<int>::Write w = data.write();
				for (int i = 0; i < count; i++) {

					w[i] = decode_uint32(&buf[i * 4]);
				}

				w = PoolVector<int>::Write();
			}
			r_variant = Variant(data);
			if (r_len) {
				(*r_len) += 4 + count * sizeof(int);
			}

		} break;
		case Variant::POOL_REAL_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			buf += 4;
			len -= 4;
			ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA);

			PoolVector<float> data;

			if (count) {
				//const float*rbuf=(const float*)buf;
				data.resize(count);
				PoolVector<float>::Write w = data.write();
				for (int i = 0; i < count; i++) {

					w[i] = decode_float(&buf[i * 4]);
				}

				w = PoolVector<float>::Write();
			}
			r_variant = data;

			if (r_len) {
				(*r_len) += 4 + count * sizeof(float);
			}

		} break;
		case Variant::POOL_STRING_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);

			PoolVector<String> strings;
			buf += 4;
			len -= 4;

			if (r_len)
				(*r_len) += 4;
			//printf("string count: %i\n",count);

			for (int i = 0; i < (int)count; i++) {

				ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
				uint32_t strlen = decode_uint32(buf);

				buf += 4;
				len -= 4;
				ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);

				//printf("loaded string: %s\n",(const char*)buf);
				String str;
				str.parse_utf8((const char *)buf, strlen);

				strings.push_back(str);

				buf += strlen;
				len -= strlen;

				if (r_len)
					(*r_len) += 4 + strlen;

				if (strlen % 4) {
					int pad = 4 - (strlen % 4);
					buf += pad;
					len -= pad;
					if (r_len) {
						(*r_len) += pad;
					}
				}
			}

			r_variant = strings;

		} break;
		case Variant::POOL_VECTOR2_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			buf += 4;
			len -= 4;

			ERR_FAIL_COND_V((int)count * 4 * 2 > len, ERR_INVALID_DATA);
			PoolVector<Vector2> varray;

			if (r_len) {
				(*r_len) += 4;
			}

			if (count) {
				varray.resize(count);
				PoolVector<Vector2>::Write w = varray.write();

				for (int i = 0; i < (int)count; i++) {

					w[i].x = decode_float(buf + i * 4 * 2 + 4 * 0);
					w[i].y = decode_float(buf + i * 4 * 2 + 4 * 1);
				}

				int adv = 4 * 2 * count;

				if (r_len)
					(*r_len) += adv;
				len -= adv;
				buf += adv;
			}

			r_variant = varray;

		} break;
		case Variant::POOL_VECTOR3_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			buf += 4;
			len -= 4;

			ERR_FAIL_COND_V((int)count * 4 * 3 > len, ERR_INVALID_DATA);
			PoolVector<Vector3> varray;

			if (r_len) {
				(*r_len) += 4;
			}

			if (count) {
				varray.resize(count);
				PoolVector<Vector3>::Write w = varray.write();

				for (int i = 0; i < (int)count; i++) {

					w[i].x = decode_float(buf + i * 4 * 3 + 4 * 0);
					w[i].y = decode_float(buf + i * 4 * 3 + 4 * 1);
					w[i].z = decode_float(buf + i * 4 * 3 + 4 * 2);
				}

				int adv = 4 * 3 * count;

				if (r_len)
					(*r_len) += adv;
				len -= adv;
				buf += adv;
			}

			r_variant = varray;

		} break;
		case Variant::POOL_COLOR_ARRAY: {

			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
			uint32_t count = decode_uint32(buf);
			buf += 4;
			len -= 4;

			ERR_FAIL_COND_V((int)count * 4 * 4 > len, ERR_INVALID_DATA);
			PoolVector<Color> carray;

			if (r_len) {
				(*r_len) += 4;
			}

			if (count) {
				carray.resize(count);
				PoolVector<Color>::Write w = carray.write();

				for (int i = 0; i < (int)count; i++) {

					w[i].r = decode_float(buf + i * 4 * 4 + 4 * 0);
					w[i].g = decode_float(buf + i * 4 * 4 + 4 * 1);
					w[i].b = decode_float(buf + i * 4 * 4 + 4 * 2);
					w[i].a = decode_float(buf + i * 4 * 4 + 4 * 3);
				}

				int adv = 4 * 4 * count;

				if (r_len)
					(*r_len) += adv;
				len -= adv;
				buf += adv;
			}

			r_variant = carray;

		} break;
		default: { ERR_FAIL_V(ERR_BUG); }
	}

	return OK;
}