Files
ANSCORE/MediaClient/http/http_test.cpp

305 lines
7.1 KiB
C++

/***************************************************************************************
*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
*
* Redistribution and use in binary forms, with or without modification, are permitted.
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*
****************************************************************************************/
#include "sys_inc.h"
#include "http_test.h"
#include "http.h"
#include "http_cln.h"
#include "http_parse.h"
BOOL http_test_req(HTTPREQ * p_http)
{
int ret;
int offset = 0;
char bufs[1024];
char cookie[100];
int buflen = sizeof(bufs);
snprintf(cookie, sizeof(cookie), "%x%x%x", rand(), rand(), sys_os_get_ms());
offset += snprintf(bufs+offset, buflen-offset, "GET %s HTTP/1.1\r\n", p_http->url);
offset += snprintf(bufs+offset, buflen-offset, "Host: %s:%u\r\n", p_http->host, p_http->port);
offset += snprintf(bufs+offset, buflen-offset, "Accept: */*\r\n");
offset += snprintf(bufs+offset, buflen-offset, "x-sessioncookie: %s\r\n", cookie);
offset += snprintf(bufs+offset, buflen-offset, "User-Agent: happytimesoft/1.0\r\n");
if (p_http->need_auth)
{
offset += http_build_auth_msg(p_http, "GET", bufs+offset, buflen-offset);
}
offset += snprintf(bufs+offset, buflen-offset, "\r\n");
bufs[offset] = '\0';
log_print(HT_LOG_DBG, "TX >> %s\r\n", bufs);
ret = http_cln_tx(p_http, bufs, offset);
return (ret == offset) ? TRUE : FALSE;
}
BOOL http_test_rx_timeout(HTTPREQ * p_http, int timeout)
{
int sret, rlen;
BOOL ret = FALSE;
fd_set fdr;
struct timeval tv;
while (1)
{
#ifdef HTTPS
if (p_http->https && SSL_pending(p_http->ssl) > 0)
{
// There is data to read
}
else
#endif
{
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fdr);
FD_SET(p_http->cfd, &fdr);
sret = select((int)(p_http->cfd+1), &fdr, NULL, NULL, &tv);
if (sret == 0)
{
log_print(HT_LOG_WARN, "%s, timeout!!!\r\n", __FUNCTION__);
break;
}
else if (sret < 0)
{
log_print(HT_LOG_ERR, "%s, select err[%s], sret[%d]!!!\r\n",
__FUNCTION__, sys_os_get_socket_error(), sret);
break;
}
else if (!FD_ISSET(p_http->cfd, &fdr))
{
continue;
}
}
if (p_http->rbuf == NULL)
{
p_http->rbuf = p_http->rcv_buf;
p_http->mlen = sizeof(p_http->rcv_buf)-4;
p_http->rcv_dlen = 0;
p_http->ctt_len = 0;
p_http->hdr_len = 0;
}
#ifdef HTTPS
if (p_http->https)
{
sys_os_mutex_enter(p_http->ssl_mutex);
rlen = SSL_read(p_http->ssl, p_http->rbuf+p_http->rcv_dlen, p_http->mlen-p_http->rcv_dlen);
sys_os_mutex_leave(p_http->ssl_mutex);
}
else
#endif
rlen = recv(p_http->cfd, p_http->rbuf+p_http->rcv_dlen, p_http->mlen-p_http->rcv_dlen, 0);
if (rlen < 0)
{
log_print(HT_LOG_INFO, "%s, recv return = %d, dlen[%d], mlen[%d]\r\n",
__FUNCTION__, rlen, p_http->rcv_dlen, p_http->mlen);
return FALSE;
}
p_http->rcv_dlen += rlen;
p_http->rbuf[p_http->rcv_dlen] = '\0';
if (p_http->rcv_dlen < 16)
{
continue;
}
if (http_is_http_msg(p_http->rbuf) == FALSE)
{
break;
}
if (p_http->hdr_len == 0)
{
int parse_len;
int http_pkt_len;
http_pkt_len = http_pkt_find_end(p_http->rbuf);
if (http_pkt_len == 0)
{
continue;
}
p_http->hdr_len = http_pkt_len;
HTTPMSG * rx_msg = http_get_msg_buf(http_pkt_len+1);
if (rx_msg == NULL)
{
log_print(HT_LOG_ERR, "%s, get msg buf failed\r\n", __FUNCTION__);
return FALSE;
}
memcpy(rx_msg->msg_buf, p_http->rbuf, http_pkt_len);
rx_msg->msg_buf[http_pkt_len] = '\0';
log_print(HT_LOG_DBG, "RX from %s << %s\r\n", p_http->host, rx_msg->msg_buf);
parse_len = http_msg_parse_part1(rx_msg->msg_buf, http_pkt_len, rx_msg);
if (parse_len != http_pkt_len)
{
log_print(HT_LOG_ERR, "%s, http_msg_parse_part1=%d, http_pkt_len=%d!!!\r\n",
__FUNCTION__, parse_len, http_pkt_len);
http_free_msg(rx_msg);
return FALSE;
}
p_http->ctt_len = rx_msg->ctt_len;
p_http->rx_msg = rx_msg;
ret = TRUE;
break;
}
}
return ret;
}
BOOL http_test(const char * url, const char * user, const char * pass, HTTPCTT * ctt, int timeout)
{
BOOL ret = FALSE;
int port, https=0;
char proto[32], username[64], password[64], host[100], path[200];
url_split(url, proto, sizeof(proto), username, sizeof(username),
password, sizeof(password), host, sizeof(host), &port, path, sizeof(path));
if (strcasecmp(proto, "https") == 0)
{
https = 1;
port = (port == -1) ? 443 : port;
}
else if (strcasecmp(proto, "http") == 0)
{
port = (port == -1) ? 80 : port;
}
else
{
return FALSE;
}
if (host[0] == '\0')
{
return FALSE;
}
HTTPREQ hreq;
memset(&hreq, 0, sizeof(hreq));
strncpy(hreq.host, host, sizeof(hreq.host) - 1);
if (username[0] != '\0')
{
strcpy(hreq.auth_info.auth_name, username);
}
else if (user && user[0] != '\0')
{
strcpy(hreq.auth_info.auth_name, user);
}
if (password[0] != '\0')
{
strcpy(hreq.auth_info.auth_pwd, password);
}
else if (pass && pass[0] != '\0')
{
strcpy(hreq.auth_info.auth_pwd, pass);
}
if (path[0] != '\0')
{
strcpy(hreq.url, path);
strcpy(hreq.auth_info.auth_uri, path);
}
hreq.port = port;
hreq.https = https;
RETRY:
hreq.cfd = tcp_connect_timeout(inet_addr(hreq.host), hreq.port, timeout);
if (hreq.cfd <= 0)
{
log_print(HT_LOG_ERR, "%s, tcp_connect_timeout\r\n", __FUNCTION__);
return FALSE;
}
if (hreq.https)
{
#ifdef HTTPS
if (!http_cln_ssl_conn(&hreq, timeout))
{
return FALSE;
}
#else
log_print(HT_LOG_ERR, "%s, the server require ssl connection, unsupport!\r\n", __FUNCTION__);
return FALSE;
#endif
}
if (!http_test_req(&hreq))
{
return FALSE;
}
if (!http_test_rx_timeout(&hreq, timeout))
{
return FALSE;
}
if (hreq.rx_msg->msg_sub_type == 200)
{
if (ctt)
{
*ctt = hreq.rx_msg->ctt_type;
}
ret = TRUE;
}
else if (hreq.rx_msg->msg_sub_type == 401)
{
if (!hreq.need_auth)
{
http_cln_auth_set(&hreq, NULL, NULL);
http_cln_free_req(&hreq);
goto RETRY;
}
}
http_cln_free_req(&hreq);
return ret;
}