Exemplo n.º 1
0
void HTTPClient::ReadyFile() {
	std::stringstream _header_path_stream;
	_header_path_stream << HTTPManager::Share()->GetTemporaryHeaderPath() + "/";
	_header_path_stream << __http_client_identity;
	header_file_path = _header_path_stream.str();
	
	header.open(header_file_path.c_str());
	OPEN_FD();
	HTTP_DEBUG(!header.is_open(), std::string("응답헤더를 저장할 파일이 열리지 않습니다.HTTPConfig.h의 HTTP_MANAGER_DIRECTORY, HTTP_RESPONSE_HEADER_FILE_PREFIX의 경로를 확인해주세요.권한문제 혹은 잘못된 경로일 수 있습니다.\n경로: ") + header_file_path + "\n");
	
	std::stringstream _body_path_stream;
	_body_path_stream << HTTPManager::Share()->GetTemporaryBodyPath() + "/";
	_body_path_stream << __http_client_identity;
	body_file_path = _body_path_stream.str();
	
	body.open(body_file_path.c_str());
	OPEN_FD();
	HTTP_DEBUG(!body.is_open(), std::string("응답바디를 저장할 파일이 열리지 않습니다.HTTPConfig.h의 HTTP_MANAGER_DIRECTORY, HTTP_RESPONSE_BODY_FILE_PREFIX의 경로를 확인해주세요.권한문제 혹은 잘못된 경로일 수 있습니다.\n경로: ") + body_file_path + "\n");
	
	__http_client_identity++;

#ifdef ANDROID_NDK
    if (is_https) {
        requestHttps(tag, request.url, this);
    }
#endif
}
Exemplo n.º 2
0
void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, http_callback user_callback)
{
	HTTP_DEBUG("DNS request\n");

	request_args *req = (request_args *)os_malloc(sizeof(request_args));
	req->hostname = esp_strdup(hostname);
	req->path = esp_strdup(path);
	req->port = port;
	req->post_data = esp_strdup(post_data);
	req->buffer_size = 1;
	req->buffer = (char *)os_malloc(1);
	req->buffer[0] = '\0'; // Empty string.
	req->user_callback = user_callback;

	ip_addr_t addr;
	err_t error = espconn_gethostbyname((struct espconn *)req, // It seems we don't need a real espconn pointer here.
										hostname, &addr, dns_callback);

	if (error == ESPCONN_INPROGRESS) {
		HTTP_DEBUG("DNS pending\n");
	}
	else if (error == ESPCONN_OK) {
		// Already in the local names table (or hostname was an IP address), execute the callback ourselves.
		dns_callback(hostname, &addr, req);
	}
	else if (error == ESPCONN_ARG) {
		HTTP_DEBUG("DNS error %s\n", hostname);
	}
	else {
		HTTP_DEBUG("DNS error code %d\n", error);
	}
}
Exemplo n.º 3
0
/*
 * Parse an URL of the form http://host:port/path
 * <host> can be a hostname or an IP address
 * <port> is optional
 */
void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback)
{
	// FIXME: handle HTTP auth with http://user:pass@host/
	// FIXME: get rid of the #anchor part if present.

	char hostname[128] = "";
	int port = 80;
	bool secure = false;

	bool is_http  = os_strncmp(url, "http://",  strlen("http://"))  == 0;
	bool is_https = os_strncmp(url, "https://", strlen("https://")) == 0;

	if (is_http)
		url += strlen("http://"); // Get rid of the protocol.
	else if (is_https) {
		port = 443;
		secure = true;
		url += strlen("https://"); // Get rid of the protocol.
	} else {
		os_printf("URL is not HTTP or HTTPS %s\n", url);
		return;
	}

	char * path = os_strchr(url, '/');
	if (path == NULL) {
		path = os_strchr(url, '\0'); // Pointer to end of string.
	}

	char * colon = os_strchr(url, ':');
	if (colon > path) {
		colon = NULL; // Limit the search to characters before the path.
	}

	if (colon == NULL) { // The port is not present.
		os_memcpy(hostname, url, path - url);
		hostname[path - url] = '\0';
	}
	else {
		port = atoi(colon + 1);
		if (port == 0) {
			os_printf("Port error %s\n", url);
			return;
		}

		os_memcpy(hostname, url, colon - url);
		hostname[colon - url] = '\0';
	}


	if (path[0] == '\0') { // Empty path is not allowed.
		path = "/";
	}

	HTTP_DEBUG("hostname=%s\n", hostname);
	HTTP_DEBUG("port=%d\n", port);
	HTTP_DEBUG("path=%s\n", path);
	http_raw_request(hostname, port, path, post_data, headers, user_callback);
}
Exemplo n.º 4
0
static void ICACHE_FLASH_ATTR reconnect_callback(void * arg, sint8 errType)
{
	struct espconn *conn = (struct espconn *)arg;
	HTTP_DEBUG("RECONNECT\n");
	if (errType != ESPCONN_OK)
		HTTP_DEBUG("Connection error: %d - %s\r\n", errType, ((errType>-16)&&(errType<1))? sEspconnErr[-errType] : "?");
	if(conn->proto.tcp != NULL)
	{
		os_free(conn->proto.tcp);
		HTTP_DEBUG("os_free: conn->proto.tcp\r\n");
	}
	os_free(conn);
	HTTP_DEBUG("os_free: conn\r\n");
}
Exemplo n.º 5
0
static void ICACHE_FLASH_ATTR receive_callback(void * arg, char * buf, unsigned short len)
{
	struct espconn * conn = (struct espconn *)arg;
	request_args * req = (request_args *)conn->reverse;

	if (req->buffer == NULL) {
		return;
	}

	// Let's do the equivalent of a realloc().
	const int new_size = req->buffer_size + len;
	char * new_buffer;
	if (new_size > BUFFER_SIZE_MAX || NULL == (new_buffer = (char *)os_malloc(new_size))) {
		HTTP_DEBUG("Response too long %d\n", new_size);
		os_free(req->buffer);
		req->buffer = NULL;
		// TODO: espconn_disconnect(conn) without crashing.
		return;
	}

	os_memcpy(new_buffer, req->buffer, req->buffer_size);
	os_memcpy(new_buffer + req->buffer_size - 1 /*overwrite the null character*/, buf, len); // Append new data.
	new_buffer[new_size - 1] = '\0'; // Make sure there is an end of string.

	os_free(req->buffer);
	req->buffer = new_buffer;
	req->buffer_size = new_size;
}
Exemplo n.º 6
0
static void ICACHE_FLASH_ATTR dns_callback(const char * hostname, ip_addr_t * addr, void * arg)
{
	request_args * req = (request_args *)arg;

	if (addr == NULL) {
		os_printf("DNS failed for %s\n", hostname);
		if (req->user_callback != NULL) {
			req->user_callback("", -1, "");
		}
		os_free(req);
	}
	else {
		HTTP_DEBUG("DNS found %s " IPSTR "\n", hostname, IP2STR(addr));

		struct espconn * conn = (struct espconn *)os_malloc(sizeof(struct espconn));
		conn->type = ESPCONN_TCP;
		conn->state = ESPCONN_NONE;
		conn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp));
		conn->proto.tcp->local_port = espconn_port();
		conn->proto.tcp->remote_port = req->port;
		conn->reverse = req;

		os_memcpy(conn->proto.tcp->remote_ip, addr, 4);

		espconn_regist_connectcb(conn, connect_callback);
		espconn_regist_disconcb(conn, disconnect_callback);
		espconn_regist_reconcb(conn, error_callback);

        espconn_connect(conn);
	}
}
Exemplo n.º 7
0
static void ICACHE_FLASH_ATTR sent_callback(void * arg)
{
	struct espconn * conn = (struct espconn *)arg;
	request_args * req = (request_args *)conn->reverse;

	if (req->post_data == NULL) {
		HTTP_DEBUG("All sent\n");
	}
	else {
		// The headers were sent, now send the contents.
		HTTP_DEBUG("Sending request body\n");
        espconn_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data));
		os_free(req->post_data);
		req->post_data = NULL;
	}
}
Exemplo n.º 8
0
static void ICACHE_FLASH_ATTR sent_callback(void * arg)
{
	struct espconn * conn = (struct espconn *)arg;
	request_args * req = (request_args *)conn->reverse;

	if (req->post_data == NULL) {
		HTTP_DEBUG("All sent\n");
	}
	else {
		// The headers were sent, now send the contents.
		HTTP_DEBUG("Sending request body\n");
		sint8 espsent_status = espconn_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data));
		if(espsent_status == ESPCONN_OK) {
			HTTP_DEBUG("Request body sent, req->post_data = %s\n", req->post_data);
		} else {
			HTTP_DEBUG("Error while sending request body.\n");
		}
		os_free(req->post_data);
		req->post_data = NULL;
	}
}
Exemplo n.º 9
0
static void ICACHE_FLASH_ATTR connect_callback(void * arg)
{
	HTTP_DEBUG("Connected\n");
	struct espconn * conn = (struct espconn *)arg;
	request_args * req = (request_args *)conn->reverse;

	espconn_regist_recvcb(conn, receive_callback);
	espconn_regist_sentcb(conn, sent_callback);

	const char * method = "GET";
	char post_headers[32] = "";

	if (req->post_data != NULL) { // If there is data this is a POST request.
		method = "POST";
		os_sprintf(post_headers, "Content-Length: %d\r\n", strlen(req->post_data));
	}

	char buf[69 + strlen(method) + strlen(req->path) + strlen(req->hostname) +
			 strlen(req->headers) + strlen(post_headers)];
    char hostname[strlen(req->hostname)+7];
    if (req->port != 80) {
        os_sprintf(hostname, "%s:%d", req->hostname, req->port);
    } else {
        os_strcpy(hostname, req->hostname);
    }
	int len = os_sprintf(buf,
        "%s %s HTTP/1.1\r\n"
        "Host: %s\r\n"
        "Connection: close\r\n"
        "User-Agent: ESP8266\r\n"
        "%s"
        "%s"
        "\r\n",
    method, req->path, hostname, req->headers, post_headers);

    espconn_sent(conn, (uint8_t *)buf, len);
	os_free(req->headers);
	req->headers = NULL;
	HTTP_DEBUG("Sending request header\n");
}
Exemplo n.º 10
0
static void ICACHE_FLASH_ATTR disconnect_callback(void * arg)
{
	HTTP_DEBUG("Disconnected\n");
	struct espconn *conn = (struct espconn *)arg;

	if(conn == NULL) {
		return;
	}

	if(conn->proto.tcp != NULL) {
		os_free(conn->proto.tcp);
	}
	if(conn->reverse != NULL) {
		request_args * req = (request_args *)conn->reverse;
		if (req->buffer != NULL) {
			// FIXME: make sure this is not a partial response, using the Content-Length header.

			const char * version = "HTTP/1.1 ";
			if (os_strncmp(req->buffer, version, strlen(version)) != 0) {
				HTTP_DEBUG("Invalid version in %s\n", req->buffer);
				return;
			}
			int http_status = atoi(req->buffer + strlen(version));

			//char * body = (char *)os_strstr(req->buffer, "\r\n\r\n") + 4;
			char * body = (char *)os_strstr(req->buffer, "\r\n\r\n");
			if (body)
				body+=4;

			if (req->user_callback != NULL) { // Callback is optional.
				req->user_callback(body, http_status, req->buffer);
			}
			os_free(req->buffer);
		}
		os_free(req->hostname);
		os_free(req->path);
		os_free(req);
	}
	os_free(conn);
}
Exemplo n.º 11
0
static char * esp_strdup(const char * str)
{
	if (str == NULL) {
		return NULL;
	}
	char * new_str = (char *)os_malloc(os_strlen(str) + 1); // 1 for null character
	if (new_str == NULL) {
		HTTP_DEBUG("esp_strdup: malloc error");
		return NULL;
	}
	os_strcpy(new_str, str);
	return new_str;
}
Exemplo n.º 12
0
static void ICACHE_FLASH_ATTR connect_callback(void * arg)
{
	HTTP_DEBUG("Connected\n");
	struct espconn * conn = (struct espconn *)arg;
	request_args * req = (request_args *)conn->reverse;

	espconn_regist_recvcb(conn, receive_callback);
	espconn_regist_sentcb(conn, sent_callback);

	const char * method = "GET";
	char post_headers[128] = "";

	if (req->post_data != NULL) { // If there is data this is a POST request.
		method = "POST";
		os_sprintf(post_headers,
				   "Content-Type: application/x-www-form-urlencoded\r\n"
				   "Content-Length: %d\r\n", strlen(req->post_data));
	}

	char buf[2048];
	int len = os_sprintf(buf,
						 "%s %s HTTP/1.1\r\n"
						 "Host: %s:%d\r\n"
						 "Connection: close\r\n"
						 "User-Agent: ESP8266\r\n"
						 "%s"
						 "\r\n",
						 method, req->path, req->hostname, req->port, post_headers);

	sint8 espsent_status = espconn_sent(conn, (uint8_t *)buf, len);
	if(espsent_status == ESPCONN_OK) {
		HTTP_DEBUG("Data sent, buf = %s\n", buf);
	} else {
		HTTP_DEBUG("Error while sending data.\n");
	}
	HTTP_DEBUG("Sending request header\n");
}
Exemplo n.º 13
0
HTTPRequest::HTTPRequest()
  : m_method((http_method) -1),
    m_path(0), m_query(0),
    m_currentHeader(-1), m_headerLength(0), m_headerValue(true),
    m_age(millis()), m_id(__id++)
{
  HTTP_DEBUG("   <%lu> HTTPRequest::HTTPRequest\n", m_id)

  http_parser_url_init(&m_urlP);

  // we store some headers by defult
  storeHeader("Host");
  storeHeader("Content-Type");
  storeHeader("Content-Length");

  // CORS support
  storeHeader("Access-Control-Request-Method");
  storeHeader("Access-Control-Request-Headers");
}
Exemplo n.º 14
0
static void ICACHE_FLASH_ATTR dns_callback(const char * hostname, ip_addr_t * addr, void * arg)
{
	request_args * req = (request_args *)arg;

	if (addr == NULL) {
		HTTP_DEBUG("DNS failed, host: %s\n", hostname);
	}
	else {
		HTTP_DEBUG("DNS found, host: %s, address: " IPSTR "\n", hostname, IP2STR(addr));

		struct espconn * conn = (struct espconn *)os_malloc(sizeof(struct espconn));
		conn->type = ESPCONN_TCP;
		conn->state = ESPCONN_NONE;
		conn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp));
		conn->proto.tcp->local_port = espconn_port();
		conn->proto.tcp->remote_port = req->port;
		conn->reverse = req;

		os_memcpy(conn->proto.tcp->remote_ip, addr, 4);

		espconn_regist_connectcb(conn, connect_callback);
		espconn_regist_disconcb(conn, disconnect_callback);
		espconn_regist_reconcb(conn, reconnect_callback);

		// TODO: consider using espconn_regist_reconcb (for timeouts?)
		// cf esp8266_sdk_v0.9.1/examples/at/user/at_ipCmd.c  (TCP ARQ retransmission?)

		sint8 espcon_status = espconn_connect(conn);
		switch(espcon_status)
		{
			case ESPCONN_OK:
				HTTP_DEBUG("TCP created.\r\n");
				break;
			case ESPCONN_RTE:
				HTTP_DEBUG("Error connection, routing problem.\r\n");
				break;
			case ESPCONN_TIMEOUT:
				HTTP_DEBUG("Error connection, timeout.\r\n");
				break;
			default:
				HTTP_DEBUG("Connection error: %d - %s\r\n", espcon_status, ((espcon_status>-16)&&(espcon_status<1))? sEspconnErr[-espcon_status] : "?");
		}
	}
}
Exemplo n.º 15
0
  http_parser_url_init(&m_urlP);

  // we store some headers by defult
  storeHeader("Host");
  storeHeader("Content-Type");
  storeHeader("Content-Length");

  // CORS support
  storeHeader("Access-Control-Request-Method");
  storeHeader("Access-Control-Request-Headers");
}

HTTPRequest::~HTTPRequest()
{
  HTTP_DEBUG("   <%lu> HTTPRequest::~HTTPRequest \n", m_id)
}

void HTTPRequest::storeHeader(const char * name, bool store) {
  int i = 0;
  while (i < HTTPSERVER_MAX_HEADER_LINES && m_header[i].field.buf()) i++;
  if (i < HTTPSERVER_MAX_HEADER_LINES) {
    m_header[i].field.set(name);
    m_header[i].store = true;
  }
}

int HTTPRequest::findHeader(const char * startsWith, size_t length)
{
  int i = 0;
  while (i < HTTPSERVER_MAX_HEADER_LINES && m_header[i].field) {
Exemplo n.º 16
0
bool HTTPClient::Init(void* _ptr) {
	if(_ptr) {
		is_raise_error_multi_handle = true;
		code_multi = *(CURLMcode*)_ptr;
		return true;
	}
	if(is_raise_error_multi_handle)
		return true;
	
	//디비에서 URL이랑 매치되는 필드가져오기
	sqlite3* _db = NULL;
	char* _db_message = NULL;
	HTTP_DEBUG((sqlite3_open(HTTPManager::Share()->GetDBPath().c_str(), &_db)),
			   "sqlite 디비 열기에 실패하였습니다." << opened_file << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	std::string _query = "SELECT * FROM request WHERE url='" + request.url + "' LIMIT 1";
	HTTP_DEBUG((sqlite3_exec(_db, _query.c_str(), SQLMatchURLCallback, this, &_db_message)),
			   "sqllite 디비 검색에 실패하였습니다." << "\nError Message:" << _db_message);
	HTTP_DEBUG((sqlite3_close(_db)),
			   "sqlite 디비 닫기에 실패하였습니다." << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	
	if(db_id.length()) {
		if(db_expires > HTTP::CurrentTime()) {
			//저장된것 사용
			cache_type = HTTPResponse::CacheType_Expires;
		} else if(db_max_age > 0) {
			if(last_updated - db_last_updated < db_max_age) {
				//저장된것 사용
				cache_type = HTTPResponse::CacheType_Expires;
			} else {
				//연결(이후 Last-Modified로 캐쉬 체크)
				cache_type = HTTPResponse::CacheType_Last_Modified;
			}
		} else {
			//연결(이후 Last-Modified로 캐쉬 체크)
			cache_type = HTTPResponse::CacheType_Last_Modified;
		}
	} else {
		//처음 다운
		cache_type = HTTPResponse::CacheType_None;
	}
	
	if(!request.use_cache)
		cache_type = HTTPResponse::CacheType_None;
	
	//파일 준비
	ReadyFile();

#ifdef ANDROID_NDK
    if (is_https)
        return true;
#endif
    
	//연결이 필요한경우는 curl생성
	if(cache_type != HTTPResponse::CacheType_Expires)
		curl = curl_easy_init();
	
	if(curl) {
		curl_easy_setopt(curl, CURLOPT_URL, request.GetURL().c_str());
		
		ReadyHeader();
		ReadyBody();
		
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPClient::ReadBody);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, ReadHeader);
		curl_easy_setopt(curl, CURLOPT_WRITEHEADER, this);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
		
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, HTTPClient::Progress);
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
		
		curl_multi_add_handle(HTTPManager::Share()->GetCURLMulti(), curl);
	}
	
	return true;
}
Exemplo n.º 17
0
bool HTTPClient::UpdateDB() {
	if(!is_recieve)
		return false;
	if(code != CURLE_OK)
		return false;
	
	if(header.is_open()) {
		header.close();
		CLOSE_FD();
	}
	if(body.is_open()) {
		body.close();
		CLOSE_FD();
	}
	
	if(request.GetUseCache()) {
		if(request.force_max_age > 0) {
			max_age = request.force_max_age;
			
			if(expires == 0 && max_age != 0) {
				expires = HTTP::CurrentTime() + max_age;
			}
		}
	}
	
	std::stringstream _query;
	bool _need_update = false;
	bool _is_insert = false;
	if(cache_type == HTTPResponse::CacheType_None) {
		
		if(!db_id.length()) {
			_query << "INSERT OR REPLACE INTO request (url, Expires, Last_Modified, Last_Updated, Max_Age) VALUES ('"
			<< request.url << "', '"
			<< expires << "', '"
			<< last_modified << "', '"
			<< last_updated << "', '"
			<< max_age << "')";
			_is_insert = true;
		} else {
			_query << "UPDATE request SET Expires='" << expires
			<< "', Last_Modified='" << last_modified
			<< "', Last_Updated='" << last_updated
			<< "', Max_Age='" << max_age
			<< "' WHERE id='" << db_id << "'";
		}
		_need_update = true;
	
	} else if(cache_type == HTTPResponse::CacheType_Last_Modified) {
		if(last_modified && db_last_modified) {
			if(last_modified != db_last_modified) {
				_query << "UPDATE request SET Last_Modified='" << last_modified
				<< "', Last_Updated='" << last_updated
				<< "' WHERE id='" << db_id << "'";
				_need_update = true;
			}
		}
	}
	
	if(!_need_update) {
		return false;
	}
	
	sqlite3* _db = NULL;
	char* _db_message = NULL;
	
	HTTP_DEBUG((sqlite3_open(HTTPManager::Share()->GetDBPath().c_str(), &_db)),
			   "열기실패" << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	HTTP_DEBUG((sqlite3_exec(_db, _query.str().c_str(), NULL, NULL, &_db_message)),
			   "error:" << _db_message);
	
	if(_is_insert) {
		_query.str("");
		_query << "SELECT * FROM request WHERE url='" << request.url << "' LIMIT 1";
		HTTP_DEBUG((sqlite3_exec(_db, _query.str().c_str(), SQLMatchURLCallback, this, &_db_message)), 
				   "sqllite 디비 검색에 실패하였습니다." << "\nError Message:" << _db_message);
	}
	
	HTTP_DEBUG((sqlite3_close(_db)),
			   "닫기실패" << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	
	rename(header_file_path.c_str(), cache_header_file_path.c_str());
	rename(body_file_path.c_str(), cache_body_file_path.c_str());
	response = HTTPResponse(cache_header_file_path, cache_body_file_path, cache_type);
	
	return true;
}
Exemplo n.º 18
0
static void ICACHE_FLASH_ATTR error_callback(void *arg, sint8 errType)
{
	HTTP_DEBUG("Disconnected with error\n");
	disconnect_callback(arg);
}