Initial setup for CLion
This commit is contained in:
221
MediaClient/http/http.h
Normal file
221
MediaClient/http/http.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __H_HTTP_H__
|
||||
#define __H_HTTP_H__
|
||||
|
||||
#include "sys_buf.h"
|
||||
#include "ppstack.h"
|
||||
|
||||
#ifdef HTTPS
|
||||
#include "openssl/ssl.h"
|
||||
#endif
|
||||
|
||||
/***************************************************************************************/
|
||||
typedef enum http_request_msg_type
|
||||
{
|
||||
HTTP_MT_NULL = 0,
|
||||
HTTP_MT_GET,
|
||||
HTTP_MT_HEAD,
|
||||
HTTP_MT_MPOST,
|
||||
HTTP_MT_MSEARCH,
|
||||
HTTP_MT_NOTIFY,
|
||||
HTTP_MT_POST,
|
||||
HTTP_MT_SUBSCRIBE,
|
||||
HTTP_MT_UNSUBSCRIBE,
|
||||
} HTTP_MT;
|
||||
|
||||
/***************************************************************************************/
|
||||
typedef enum http_content_type
|
||||
{
|
||||
CTT_NULL = 0,
|
||||
CTT_SDP,
|
||||
CTT_TXT,
|
||||
CTT_HTM,
|
||||
CTT_XML,
|
||||
CTT_BIN,
|
||||
CTT_JPG,
|
||||
CTT_RTSP_TUNNELLED,
|
||||
CTT_MULTIPART,
|
||||
CTT_FLV
|
||||
} HTTPCTT;
|
||||
|
||||
#define ctt_is_string(type) (type == CTT_XML || type == CTT_HTM || type == CTT_TXT || type == CTT_SDP)
|
||||
|
||||
|
||||
typedef struct _http_msg_content
|
||||
{
|
||||
uint32 msg_type;
|
||||
uint32 msg_sub_type;
|
||||
HDRV first_line;
|
||||
|
||||
PPSN_CTX hdr_ctx;
|
||||
PPSN_CTX ctt_ctx;
|
||||
|
||||
int hdr_len;
|
||||
int ctt_len;
|
||||
HTTPCTT ctt_type;
|
||||
char boundary[256];
|
||||
|
||||
char * msg_buf;
|
||||
int buf_offset;
|
||||
|
||||
uint32 remote_ip;
|
||||
uint16 remote_port;
|
||||
} HTTPMSG;
|
||||
|
||||
/*************************************************************************/
|
||||
typedef struct http_client
|
||||
{
|
||||
uint32 pass_through : 1; // pass through received data flag
|
||||
uint32 https : 1; // https flag
|
||||
uint32 resv : 30;
|
||||
|
||||
SOCKET cfd; // client socket
|
||||
uint32 rip; // remote ip, network byte order
|
||||
uint32 rport; // remote port
|
||||
|
||||
char rcv_buf[2052]; // static receiving buffer
|
||||
char * dyn_recv_buf; // dynamic receiving buffer
|
||||
int rcv_dlen; // received data length
|
||||
int hdr_len; // http header length
|
||||
int ctt_len; // context length
|
||||
HTTPCTT ctt_type; // context type
|
||||
char * rbuf; // pointer to rcv_buf or dyn_recv_buf
|
||||
int mlen; // sizeof(rcv_buf) or size of dyn_recv_buf
|
||||
|
||||
void * p_srv; // pointer to HTTPSRV
|
||||
int use_count; // use count
|
||||
|
||||
void * userdata; // user data
|
||||
void * userdata_mutex; // user data mutex
|
||||
uint32 protocol; // protocol, rtsp over http, websocket etc
|
||||
|
||||
#ifdef HTTPS
|
||||
SSL * ssl; // https SSL
|
||||
void * ssl_mutex; // https SSL mutex
|
||||
#endif
|
||||
} HTTPCLN;
|
||||
|
||||
typedef struct http_req
|
||||
{
|
||||
uint32 need_auth : 1; // need auth flag
|
||||
uint32 https : 1; // https flag
|
||||
uint32 resv : 30;
|
||||
|
||||
SOCKET cfd; // client socket
|
||||
uint32 port; // server port
|
||||
char host[256]; // server host
|
||||
char url[256]; // the request url
|
||||
|
||||
char action[256]; // action
|
||||
char rcv_buf[2052]; // static receiving buffer
|
||||
char * dyn_recv_buf; // dynamic receiving buffer
|
||||
int rcv_dlen; // received data length
|
||||
int hdr_len; // http header length
|
||||
int ctt_len; // context length
|
||||
char boundary[256]; // boundary, for CTT_MULTIPART
|
||||
char * rbuf; // pointer to rcv_buf or dyn_recv_buf
|
||||
int mlen; // sizeof(rcv_buf) or size of dyn_recv_buf
|
||||
|
||||
HTTPMSG * rx_msg; // rx message
|
||||
|
||||
int auth_mode; // 0 - baisc; 1 - digest
|
||||
HD_AUTH_INFO auth_info; // http auth information
|
||||
|
||||
#ifdef HTTPS
|
||||
SSL * ssl; // https SSL
|
||||
void * ssl_mutex; // https SSL mutex
|
||||
#endif
|
||||
} HTTPREQ;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* If rx_msg is NULL, the callback should call the http_free_used_cln function to delete p_cln
|
||||
* If the callback is responsible for deleting rx_msg, it returns TRUE, otherwise it returns FALSE
|
||||
*/
|
||||
typedef BOOL (*http_msg_callback)(void * p_srv, HTTPCLN * p_cln, HTTPMSG * rx_msg, void * userdata);
|
||||
|
||||
/*
|
||||
* Raw data received by http
|
||||
* p_srv : HTTPSRV
|
||||
* p_cln : http client user agent
|
||||
* buff : data buffer
|
||||
* buflen : data buffer length
|
||||
*
|
||||
*/
|
||||
typedef void (*http_data_callback)(void * p_srv, HTTPCLN * p_cln, char * buff, int buflen, void * userdata);
|
||||
|
||||
/*
|
||||
* http new connection callback
|
||||
* p_srv : HTTPSRV
|
||||
* addr : http client connection address, network byte order
|
||||
* port : http client connection port, host byte order
|
||||
*
|
||||
* Return TRUE, accept the new connection, return FALSE, reject the new connection
|
||||
*/
|
||||
typedef BOOL (*http_conn_callback)(void * p_srv, uint32 addr, int port, void * userdata);
|
||||
|
||||
typedef struct http_srv_s
|
||||
{
|
||||
uint32 r_flag : 1; // data receiving flag
|
||||
uint32 https : 1; // https flag
|
||||
uint32 resv : 30;
|
||||
|
||||
SOCKET sfd; // server socket
|
||||
|
||||
char host[128]; // local server address
|
||||
int sport; // server port
|
||||
uint32 saddr; // server address, network byte order
|
||||
uint32 max_cln_nums; // max client number
|
||||
|
||||
PPSN_CTX * cln_fl; // client free list
|
||||
PPSN_CTX * cln_ul; // client used list
|
||||
|
||||
pthread_t rx_tid; // data receiving thread id
|
||||
|
||||
void * mutex_cb; // cabllback mutex
|
||||
http_msg_callback msg_cb; // http message callback
|
||||
http_data_callback data_cb; // http data callback
|
||||
http_conn_callback conn_cb; // http connection callback
|
||||
void * msg_user; // http message callback user data
|
||||
void * data_user; // http data callback user data
|
||||
void * conn_user; // http connection callback user data
|
||||
|
||||
#ifdef EPOLL
|
||||
int ep_fd; // epoll fd
|
||||
struct epoll_event * ep_events; // epoll events
|
||||
int ep_event_num; // epoll event number
|
||||
#endif
|
||||
|
||||
#ifdef HTTPS
|
||||
char cert_file[256]; // cert file name
|
||||
char key_file[256]; // key file name
|
||||
SSL_CTX * ssl_ctx; // ssl context
|
||||
#endif
|
||||
} HTTPSRV;
|
||||
|
||||
|
||||
|
||||
#endif // __H_HTTP_H__
|
||||
|
||||
|
||||
|
||||
|
||||
791
MediaClient/http/http_cln.cpp
Normal file
791
MediaClient/http/http_cln.cpp
Normal file
@@ -0,0 +1,791 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.h"
|
||||
#include "http_parse.h"
|
||||
#include "http_cln.h"
|
||||
#include "rfc_md5.h"
|
||||
#include "sha256.h"
|
||||
#include "base64.h"
|
||||
|
||||
/***************************************************************************************/
|
||||
|
||||
#ifdef HTTPS
|
||||
#if __WINDOWS_OS__
|
||||
#pragma comment(lib, "libcrypto.lib")
|
||||
#pragma comment(lib, "libssl.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/***************************************************************************************/
|
||||
|
||||
#define MAX_CTT_LEN (2*1024*1024)
|
||||
|
||||
|
||||
/***************************************************************************************/
|
||||
|
||||
static inline int http_isspace(int c)
|
||||
{
|
||||
return c == ' ' || c == '\f' || c == '\n' ||
|
||||
c == '\r' || c == '\t' || c == '\v';
|
||||
}
|
||||
|
||||
void http_choose_qop(char * qop, int size)
|
||||
{
|
||||
char * ptr = strstr(qop, "auth");
|
||||
char * end = ptr + strlen("auth");
|
||||
|
||||
if (ptr && (!*end || http_isspace(*end) || *end == ',') &&
|
||||
(ptr == qop || http_isspace(ptr[-1]) || ptr[-1] == ','))
|
||||
{
|
||||
strncpy(qop, "auth", size);
|
||||
}
|
||||
else
|
||||
{
|
||||
qop[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL http_get_digest_params(char * p, int len, HD_AUTH_INFO * p_auth)
|
||||
{
|
||||
char word_buf[128];
|
||||
|
||||
if (GetNameValuePair(p, len, "algorithm", word_buf, sizeof(word_buf)))
|
||||
{
|
||||
strncpy(p_auth->auth_algorithm, word_buf, sizeof(p_auth->auth_algorithm)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_auth->auth_algorithm[0] = '\0';
|
||||
}
|
||||
|
||||
if (GetNameValuePair(p, len, "realm", word_buf, sizeof(word_buf)))
|
||||
{
|
||||
strncpy(p_auth->auth_realm, word_buf, sizeof(p_auth->auth_realm)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GetNameValuePair(p, len, "nonce", word_buf, sizeof(word_buf)))
|
||||
{
|
||||
strncpy(p_auth->auth_nonce, word_buf, sizeof(p_auth->auth_nonce)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GetNameValuePair(p, len, "qop", word_buf, sizeof(word_buf)))
|
||||
{
|
||||
strncpy(p_auth->auth_qop, word_buf, sizeof(p_auth->auth_qop)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_auth->auth_qop[0] = '\0';
|
||||
}
|
||||
|
||||
http_choose_qop(p_auth->auth_qop, sizeof(p_auth->auth_qop));
|
||||
|
||||
if (GetNameValuePair(p, len, "opaque", word_buf, sizeof(word_buf)))
|
||||
{
|
||||
p_auth->auth_opaque_flag = 1;
|
||||
strncpy(p_auth->auth_opaque, word_buf, sizeof(p_auth->auth_opaque)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_auth->auth_opaque_flag = 0;
|
||||
p_auth->auth_opaque[0] = '\0';
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL http_get_digest_info(HTTPMSG * rx_msg, HD_AUTH_INFO * p_auth)
|
||||
{
|
||||
int len;
|
||||
int next_offset;
|
||||
char word_buf[128];
|
||||
HDRV * chap_id = NULL;
|
||||
char * p;
|
||||
|
||||
p_auth->auth_response[0] = '\0';
|
||||
|
||||
RETRY:
|
||||
|
||||
if (chap_id)
|
||||
{
|
||||
chap_id = http_find_headline_next(rx_msg, "WWW-Authenticate", chap_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
chap_id = http_find_headline(rx_msg, "WWW-Authenticate");
|
||||
}
|
||||
|
||||
if (chap_id == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GetLineWord(chap_id->value_string, 0, (int)strlen(chap_id->value_string),
|
||||
word_buf, sizeof(word_buf), &next_offset, WORD_TYPE_STRING);
|
||||
if (strcasecmp(word_buf, "digest") != 0)
|
||||
{
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
p = chap_id->value_string + next_offset;
|
||||
len = (int)strlen(chap_id->value_string) - next_offset;
|
||||
|
||||
if (!http_get_digest_params(p, len, p_auth))
|
||||
{
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
if (p_auth->auth_algorithm[0] != '\0' &&
|
||||
strncasecmp(p_auth->auth_algorithm, "MD5", 3) &&
|
||||
strncasecmp(p_auth->auth_algorithm, "SHA-256", 7))
|
||||
{
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL http_calc_auth_md5_digest(HD_AUTH_INFO * p_auth, const char * method)
|
||||
{
|
||||
uint8 HA1[16];
|
||||
uint8 HA2[16];
|
||||
uint8 HA3[16];
|
||||
char HA1Hex[33];
|
||||
char HA2Hex[33];
|
||||
char HA3Hex[33];
|
||||
md5_context ctx;
|
||||
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_name, strlen(p_auth->auth_name));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_realm, strlen(p_auth->auth_realm));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_pwd, strlen(p_auth->auth_pwd));
|
||||
md5_finish(&ctx, HA1);
|
||||
|
||||
bin_to_hex_str(HA1, 16, HA1Hex, 33);
|
||||
|
||||
if (!strcasecmp(p_auth->auth_algorithm, "MD5-sess"))
|
||||
{
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, (uint8 *)HA1Hex, 32);
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_nonce, strlen(p_auth->auth_nonce));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_cnonce, strlen(p_auth->auth_cnonce));
|
||||
md5_finish(&ctx, HA1);
|
||||
|
||||
bin_to_hex_str(HA1, 16, HA1Hex, 33);
|
||||
}
|
||||
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, (uint8 *)method, strlen(method));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_uri, strlen(p_auth->auth_uri));
|
||||
md5_finish(&ctx, HA2);
|
||||
|
||||
bin_to_hex_str(HA2, 16, HA2Hex, 33);
|
||||
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, (uint8 *)HA1Hex, 32);
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_nonce, strlen(p_auth->auth_nonce));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
|
||||
if (p_auth->auth_qop[0] != '\0')
|
||||
{
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_ncstr, strlen(p_auth->auth_ncstr));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_cnonce, strlen(p_auth->auth_cnonce));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
md5_update(&ctx, (uint8 *)p_auth->auth_qop, strlen(p_auth->auth_qop));
|
||||
md5_update(&ctx, (uint8 *)&(":"), 1);
|
||||
};
|
||||
|
||||
md5_update(&ctx, (uint8 *)HA2Hex, 32);
|
||||
md5_finish(&ctx, HA3);
|
||||
|
||||
bin_to_hex_str(HA3, 16, HA3Hex, 33);
|
||||
|
||||
strcpy(p_auth->auth_response, HA3Hex);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL http_calc_auth_sha256_digest(HD_AUTH_INFO * p_auth, const char * method)
|
||||
{
|
||||
uint8 HA1[32];
|
||||
uint8 HA2[32];
|
||||
uint8 HA3[32];
|
||||
char HA1Hex[65];
|
||||
char HA2Hex[65];
|
||||
char HA3Hex[65];
|
||||
sha256_context ctx;
|
||||
|
||||
sha256_starts(&ctx);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_name, strlen(p_auth->auth_name));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_realm, strlen(p_auth->auth_realm));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_pwd, strlen(p_auth->auth_pwd));
|
||||
sha256_finish(&ctx, HA1);
|
||||
|
||||
bin_to_hex_str(HA1, 32, HA1Hex, 65);
|
||||
|
||||
if (!strcasecmp(p_auth->auth_algorithm, "SHA-256-sess"))
|
||||
{
|
||||
sha256_starts(&ctx);
|
||||
sha256_update(&ctx, (uint8 *)HA1Hex, 64);
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_nonce, strlen(p_auth->auth_nonce));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_cnonce, strlen(p_auth->auth_cnonce));
|
||||
sha256_finish(&ctx, HA1);
|
||||
|
||||
bin_to_hex_str(HA1, 32, HA1Hex, 65);
|
||||
}
|
||||
|
||||
sha256_starts(&ctx);
|
||||
sha256_update(&ctx, (uint8 *)method, strlen(method));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_uri, strlen(p_auth->auth_uri));
|
||||
sha256_finish(&ctx, HA2);
|
||||
|
||||
bin_to_hex_str(HA2, 32, HA2Hex, 65);
|
||||
|
||||
sha256_starts(&ctx);
|
||||
sha256_update(&ctx, (uint8 *)HA1Hex, 64);
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_nonce, strlen(p_auth->auth_nonce));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
|
||||
if (p_auth->auth_qop[0] != '\0')
|
||||
{
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_ncstr, strlen(p_auth->auth_ncstr));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_cnonce, strlen(p_auth->auth_cnonce));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
sha256_update(&ctx, (uint8 *)p_auth->auth_qop, strlen(p_auth->auth_qop));
|
||||
sha256_update(&ctx, (uint8 *)&(":"), 1);
|
||||
};
|
||||
|
||||
sha256_update(&ctx, (uint8 *)HA2Hex, 64);
|
||||
sha256_finish(&ctx, HA3);
|
||||
|
||||
bin_to_hex_str(HA3, 32, HA3Hex, 65);
|
||||
|
||||
strcpy(p_auth->auth_response, HA3Hex);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL http_calc_auth_digest(HD_AUTH_INFO * p_auth, const char * method)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
p_auth->auth_nc++;
|
||||
sprintf(p_auth->auth_ncstr, "%08X", p_auth->auth_nc);
|
||||
sprintf(p_auth->auth_cnonce, "%08X%08X", rand(), rand());
|
||||
|
||||
if (p_auth->auth_algorithm[0] == '\0' ||
|
||||
strncasecmp(p_auth->auth_algorithm, "MD5", 3) == 0)
|
||||
{
|
||||
ret = http_calc_auth_md5_digest(p_auth, method);
|
||||
}
|
||||
else if (strncasecmp(p_auth->auth_algorithm, "SHA-256", 7) == 0)
|
||||
{
|
||||
ret = http_calc_auth_sha256_digest(p_auth, method);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int http_build_auth_msg(HTTPREQ * p_http, const char * method, char * buff, int buflen)
|
||||
{
|
||||
int offset = 0;
|
||||
HD_AUTH_INFO * p_auth = &p_http->auth_info;
|
||||
|
||||
if (p_http->auth_mode == 1) // digest auth
|
||||
{
|
||||
http_calc_auth_digest(p_auth, method);
|
||||
|
||||
offset += snprintf(buff+offset, buflen-offset,
|
||||
"Authorization: Digest username=\"%s\", realm=\"%s\", "
|
||||
"nonce=\"%s\", uri=\"%s\", response=\"%s\"",
|
||||
p_auth->auth_name, p_auth->auth_realm,
|
||||
p_auth->auth_nonce, p_auth->auth_uri, p_auth->auth_response);
|
||||
|
||||
if (p_auth->auth_opaque_flag)
|
||||
{
|
||||
offset += snprintf(buff+offset, buflen-offset,
|
||||
", opaque=\"%s\"", p_auth->auth_opaque);
|
||||
}
|
||||
|
||||
if (p_auth->auth_qop[0] != '\0')
|
||||
{
|
||||
offset += snprintf(buff+offset, buflen-offset,
|
||||
", qop=\"%s\", cnonce=\"%s\", nc=%s",
|
||||
p_auth->auth_qop, p_auth->auth_cnonce, p_auth->auth_ncstr);
|
||||
}
|
||||
|
||||
if (p_auth->auth_algorithm[0] != '\0')
|
||||
{
|
||||
offset += snprintf(buff+offset, buflen-offset,
|
||||
", algorithm=%s", p_auth->auth_algorithm);
|
||||
}
|
||||
|
||||
offset += snprintf(buff+offset, buflen-offset, "\r\n");
|
||||
}
|
||||
else if (p_http->auth_mode == 0) // basic auth
|
||||
{
|
||||
char auth[128] = {'\0'};
|
||||
char basic[256] = {'\0'};
|
||||
|
||||
snprintf(auth, sizeof(auth), "%s:%s", p_auth->auth_name, p_auth->auth_pwd);
|
||||
|
||||
base64_encode((uint8 *)auth, (int)strlen(auth), basic, sizeof(basic));
|
||||
|
||||
offset += snprintf(buff+offset, buflen-offset, "Authorization: Basic %s\r\n", basic);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int http_cln_auth_set(HTTPREQ * p_http, const char * user, const char * pass)
|
||||
{
|
||||
if (user)
|
||||
{
|
||||
strncpy(p_http->auth_info.auth_name, user, sizeof(p_http->auth_info.auth_name)-1);
|
||||
}
|
||||
|
||||
if (pass)
|
||||
{
|
||||
strncpy(p_http->auth_info.auth_pwd, pass, sizeof(p_http->auth_info.auth_pwd)-1);
|
||||
}
|
||||
|
||||
if (http_get_digest_info(p_http->rx_msg, &p_http->auth_info))
|
||||
{
|
||||
p_http->auth_mode = 1; // digest
|
||||
strcpy(p_http->auth_info.auth_uri, p_http->url);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_http->auth_mode = 0; // basic
|
||||
}
|
||||
|
||||
p_http->need_auth = TRUE;
|
||||
|
||||
return p_http->auth_mode;
|
||||
}
|
||||
|
||||
BOOL http_cln_ssl_conn(HTTPREQ * p_http, int timeout)
|
||||
{
|
||||
#ifdef HTTPS
|
||||
SSL_CTX * ctx = NULL;
|
||||
const SSL_METHOD * method = NULL;
|
||||
|
||||
SSLeay_add_ssl_algorithms();
|
||||
SSL_load_error_strings();
|
||||
|
||||
method = SSLv23_client_method();
|
||||
ctx = SSL_CTX_new(method);
|
||||
if (NULL == ctx)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, SSL_CTX_new failed!\r\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if __WINDOWS_OS__
|
||||
int tv = timeout;
|
||||
#else
|
||||
struct timeval tv = {timeout / 1000, (timeout % 1000) * 1000};
|
||||
#endif
|
||||
|
||||
setsockopt(p_http->cfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
|
||||
|
||||
p_http->ssl = SSL_new(ctx);
|
||||
if (NULL == p_http->ssl)
|
||||
{
|
||||
SSL_CTX_free(ctx);
|
||||
log_print(HT_LOG_ERR, "%s, SSL_new failed!\r\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SSL_set_fd(p_http->ssl, p_http->cfd);
|
||||
|
||||
if (SSL_connect(p_http->ssl) == -1)
|
||||
{
|
||||
SSL_CTX_free(ctx);
|
||||
log_print(HT_LOG_ERR, "%s, SSL_connect failed!\r\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SSL_CTX_free(ctx);
|
||||
|
||||
p_http->ssl_mutex = sys_os_create_mutex();
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL http_cln_rx(HTTPREQ * p_http)
|
||||
{
|
||||
int rlen = 0;
|
||||
HTTPMSG * rx_msg;
|
||||
|
||||
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);
|
||||
if (p_http->ssl)
|
||||
{
|
||||
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 (0 == rlen)
|
||||
{
|
||||
if (p_http->rcv_dlen < p_http->ctt_len + p_http->hdr_len && p_http->ctt_len == MAX_CTT_LEN)
|
||||
{
|
||||
// without Content-Length filed, when recv finish, fix the ctt length
|
||||
p_http->ctt_len = p_http->rcv_dlen - p_http->hdr_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_http->rcv_dlen < 16)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (http_is_http_msg(p_http->rbuf) == FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rx_msg = NULL;
|
||||
|
||||
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)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
p_http->hdr_len = http_pkt_len;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (p_http->ctt_len == 0 && p_http->rcv_dlen > p_http->hdr_len)
|
||||
{
|
||||
// without Content-Length field
|
||||
p_http->ctt_len = MAX_CTT_LEN;
|
||||
}
|
||||
|
||||
if ((p_http->ctt_len + p_http->hdr_len) > p_http->mlen)
|
||||
{
|
||||
if (p_http->dyn_recv_buf)
|
||||
{
|
||||
free(p_http->dyn_recv_buf);
|
||||
}
|
||||
|
||||
p_http->dyn_recv_buf = (char *)malloc(p_http->ctt_len + p_http->hdr_len + 1);
|
||||
if (NULL == p_http->dyn_recv_buf)
|
||||
{
|
||||
http_free_msg(rx_msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(p_http->dyn_recv_buf, p_http->rcv_buf, p_http->rcv_dlen);
|
||||
p_http->rbuf = p_http->dyn_recv_buf;
|
||||
p_http->mlen = p_http->ctt_len + p_http->hdr_len;
|
||||
|
||||
http_free_msg(rx_msg);
|
||||
|
||||
// Need more data
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (p_http->rcv_dlen >= (p_http->ctt_len + p_http->hdr_len))
|
||||
{
|
||||
if (rx_msg == NULL)
|
||||
{
|
||||
int nlen;
|
||||
int parse_len;
|
||||
|
||||
nlen = p_http->ctt_len + p_http->hdr_len;
|
||||
|
||||
rx_msg = http_get_msg_buf(nlen+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, p_http->hdr_len);
|
||||
rx_msg->msg_buf[p_http->hdr_len] = '\0';
|
||||
|
||||
parse_len = http_msg_parse_part1(rx_msg->msg_buf, p_http->hdr_len, rx_msg);
|
||||
if (parse_len != p_http->hdr_len)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, http_msg_parse_part1=%d, sip_pkt_len=%d!!!\r\n", __FUNCTION__, parse_len, p_http->hdr_len);
|
||||
|
||||
http_free_msg(rx_msg);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_http->ctt_len > 0)
|
||||
{
|
||||
int parse_len;
|
||||
|
||||
memcpy(rx_msg->msg_buf+p_http->hdr_len, p_http->rbuf+p_http->hdr_len, p_http->ctt_len);
|
||||
rx_msg->msg_buf[p_http->hdr_len + p_http->ctt_len] = '\0';
|
||||
|
||||
if (ctt_is_string(rx_msg->ctt_type))
|
||||
{
|
||||
log_print(HT_LOG_DBG, "%s\r\n\r\n", rx_msg->msg_buf+p_http->hdr_len);
|
||||
}
|
||||
|
||||
parse_len = http_msg_parse_part2(rx_msg->msg_buf+p_http->hdr_len, p_http->ctt_len, rx_msg);
|
||||
if (parse_len != p_http->ctt_len)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, http_msg_parse_part2=%d, sdp_pkt_len=%d!!!\r\n", __FUNCTION__, parse_len, p_http->ctt_len);
|
||||
|
||||
http_free_msg(rx_msg);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
p_http->rx_msg = rx_msg;
|
||||
}
|
||||
|
||||
if (p_http->rx_msg != rx_msg)
|
||||
{
|
||||
http_free_msg(rx_msg);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int http_cln_tx(HTTPREQ * p_http, const char * p_data, int len)
|
||||
{
|
||||
int slen = 0;
|
||||
|
||||
if (p_http->cfd <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HTTPS
|
||||
if (p_http->https)
|
||||
{
|
||||
sys_os_mutex_enter(p_http->ssl_mutex);
|
||||
if (p_http->ssl)
|
||||
{
|
||||
slen = SSL_write(p_http->ssl, p_data, len);
|
||||
}
|
||||
sys_os_mutex_leave(p_http->ssl_mutex);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
slen = send(p_http->cfd, p_data, len, 0);
|
||||
|
||||
return slen;
|
||||
}
|
||||
|
||||
BOOL http_cln_rx_timeout(HTTPREQ * p_http, int timeout)
|
||||
{
|
||||
int count = 0;
|
||||
int sret;
|
||||
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 = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&fdr);
|
||||
FD_SET(p_http->cfd, &fdr);
|
||||
|
||||
sret = select((int)(p_http->cfd+1), &fdr, NULL, NULL, &tv);
|
||||
if (sret == 0)
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count >= timeout / 1000)
|
||||
{
|
||||
log_print(HT_LOG_WARN, "%s, timeout!!!\r\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
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 (http_cln_rx(p_http) == FALSE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (p_http->rx_msg != NULL)
|
||||
{
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void http_cln_free_req(HTTPREQ * p_http)
|
||||
{
|
||||
if (p_http->cfd > 0)
|
||||
{
|
||||
closesocket(p_http->cfd);
|
||||
p_http->cfd = 0;
|
||||
}
|
||||
|
||||
#ifdef HTTPS
|
||||
if (p_http->https)
|
||||
{
|
||||
if (p_http->ssl)
|
||||
{
|
||||
sys_os_mutex_enter(p_http->ssl_mutex);
|
||||
SSL_free(p_http->ssl);
|
||||
p_http->ssl = NULL;
|
||||
sys_os_mutex_leave(p_http->ssl_mutex);
|
||||
}
|
||||
|
||||
if (p_http->ssl_mutex)
|
||||
{
|
||||
sys_os_destroy_sig_mutex(p_http->ssl_mutex);
|
||||
p_http->ssl_mutex = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_http->dyn_recv_buf)
|
||||
{
|
||||
free(p_http->dyn_recv_buf);
|
||||
p_http->dyn_recv_buf = NULL;
|
||||
}
|
||||
|
||||
if (p_http->rx_msg)
|
||||
{
|
||||
http_free_msg(p_http->rx_msg);
|
||||
p_http->rx_msg = NULL;
|
||||
}
|
||||
|
||||
p_http->rcv_dlen = 0;
|
||||
p_http->hdr_len = 0;
|
||||
p_http->ctt_len = 0;
|
||||
p_http->rbuf = NULL;
|
||||
p_http->mlen = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
46
MediaClient/http/http_cln.h
Normal file
46
MediaClient/http/http_cln.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef HTTP_CLN_H
|
||||
#define HTTP_CLN_H
|
||||
|
||||
#include "http.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
BOOL http_get_digest_params(char * p, int len, HD_AUTH_INFO * p_auth);
|
||||
BOOL http_get_digest_info(HTTPMSG * rx_msg, HD_AUTH_INFO * auth_info);
|
||||
BOOL http_calc_auth_digest(HD_AUTH_INFO * auth_info, const char * method);
|
||||
int http_build_auth_msg(HTTPREQ * p_http, const char * method, char * buff, int buflen);
|
||||
int http_cln_auth_set(HTTPREQ * p_http, const char * user, const char * pass);
|
||||
BOOL http_cln_ssl_conn(HTTPREQ * p_http, int timeout);
|
||||
BOOL http_cln_rx(HTTPREQ * p_http);
|
||||
int http_cln_tx(HTTPREQ * p_http, const char * p_data, int len);
|
||||
BOOL http_cln_rx_timeout(HTTPREQ * p_http, int timeout);
|
||||
void http_cln_free_req(HTTPREQ * p_http);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
1449
MediaClient/http/http_flv_cln.cpp
Normal file
1449
MediaClient/http/http_flv_cln.cpp
Normal file
File diff suppressed because it is too large
Load Diff
151
MediaClient/http/http_flv_cln.h
Normal file
151
MediaClient/http/http_flv_cln.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef HTTP_FLV_CLN_H
|
||||
#define HTTP_FLV_CLN_H
|
||||
|
||||
#include "rtmp.h"
|
||||
#include "http.h"
|
||||
|
||||
|
||||
#define HTTP_FLV_EVE_STOPPED 80
|
||||
#define HTTP_FLV_EVE_CONNECTING 81
|
||||
#define HTTP_FLV_EVE_CONNFAIL 82
|
||||
#define HTTP_FLV_EVE_NOSIGNAL 83
|
||||
#define HTTP_FLV_EVE_RESUME 84
|
||||
#define HTTP_FLV_EVE_AUTHFAILED 85
|
||||
#define HTTP_FLV_EVE_NODATA 86
|
||||
#define HTTP_FLV_EVE_VIDEOREADY 87
|
||||
#define HTTP_FLV_EVE_AUDIOREADY 88
|
||||
|
||||
#define HTTP_FLV_RX_FAIL -1
|
||||
#define HTTP_FLV_RX_TIMEOUT 1
|
||||
#define HTTP_FLV_RX_SUCC 2
|
||||
|
||||
typedef int (*http_flv_notify_cb)(int, void *);
|
||||
typedef int (*http_flv_video_cb)(uint8 *, int, uint32, void *);
|
||||
typedef int (*http_flv_audio_cb)(uint8 *, int, uint32, void *);
|
||||
|
||||
|
||||
class CHttpFlvClient
|
||||
{
|
||||
public:
|
||||
CHttpFlvClient(void);
|
||||
~CHttpFlvClient(void);
|
||||
|
||||
public:
|
||||
BOOL http_flv_start(const char * url, const char * user, const char * pass);
|
||||
BOOL http_flv_play();
|
||||
BOOL http_flv_stop();
|
||||
BOOL http_flv_pause();
|
||||
BOOL http_flv_close();
|
||||
|
||||
char * get_url() {return m_url;}
|
||||
char * get_user() {return m_user;}
|
||||
char * get_pass() {return m_pass;}
|
||||
int audio_codec() {return m_nAudioCodec;}
|
||||
int video_codec() {return m_nVideoCodec;}
|
||||
void get_h264_params();
|
||||
BOOL get_h264_params(uint8 * p_sps, int * sps_len, uint8 * p_pps, int * pps_len);
|
||||
void get_h265_params();
|
||||
BOOL get_h265_params(uint8 * p_sps, int * sps_len, uint8 * p_pps, int * pps_len, uint8 * p_vps, int * vps_len);
|
||||
int get_video_width() {return m_nWidth;}
|
||||
int get_video_height() {return m_nHeight;}
|
||||
double get_video_framerate() {return m_nFrameRate;}
|
||||
int get_audio_samplerate() {return m_nSamplerate;}
|
||||
int get_audio_channels() {return m_nChannels;}
|
||||
uint8 * get_audio_config() {return m_pAudioConfig;}
|
||||
int get_audio_config_len() {return m_nAudioConfigLen;}
|
||||
uint32 get_video_init_ts() {return m_nVideoInitTS;}
|
||||
uint32 get_audio_init_ts() {return m_nAudioInitTS;}
|
||||
|
||||
void set_notify_cb(http_flv_notify_cb notify, void * userdata);
|
||||
void set_video_cb(http_flv_video_cb cb);
|
||||
void set_audio_cb(http_flv_audio_cb cb);
|
||||
void set_rx_timeout(int timeout);
|
||||
|
||||
void rx_thread();
|
||||
void http_flv_video_data_cb(uint8 * p_data, int len, uint32 ts);
|
||||
void http_flv_audio_data_cb(uint8 * p_data, int len, uint32 ts);
|
||||
|
||||
private:
|
||||
BOOL http_flv_req(HTTPREQ * p_http);
|
||||
BOOL http_flv_connect();
|
||||
int http_flv_h264_rx(uint8 * data, uint32 size, uint32 ts);
|
||||
int http_flv_h265_rx(uint8 * data, uint32 size, uint32 ts);
|
||||
int http_flv_video_rx(uint8 * data, uint32 size, uint32 ts);
|
||||
int http_flv_g711_rx(uint8 * data, uint32 size, uint32 ts);
|
||||
int http_flv_aac_rx(uint8 * data, uint32 size, uint32 ts);
|
||||
int http_flv_audio_rx(uint8 * data, uint32 size, uint32 ts);
|
||||
int http_flv_metadata_rx(uint8 * data, uint32 size);
|
||||
BOOL http_flv_res_rx(HTTPREQ * p_http);
|
||||
BOOL http_flv_data_handler(HTTPREQ * p_http);
|
||||
BOOL http_flv_header_rx(HTTPREQ * p_http);
|
||||
BOOL http_flv_chunked(HTTPREQ * p_http);
|
||||
BOOL http_flv_data_rx(HTTPREQ * p_http);
|
||||
int http_flv_rx(HTTPREQ * p_http);
|
||||
void http_flv_send_notify(int event);
|
||||
|
||||
private:
|
||||
char m_url[512];
|
||||
char m_user[64];
|
||||
char m_pass[64];
|
||||
|
||||
HTTPREQ m_http;
|
||||
BOOL m_bRunning;
|
||||
BOOL m_bVideoReady;
|
||||
BOOL m_bAudioReady;
|
||||
BOOL m_bChunked;
|
||||
BOOL m_bFlvHeader;
|
||||
pthread_t m_tidRx;
|
||||
|
||||
uint8 m_pVps[256];
|
||||
int m_nVpsLen;
|
||||
uint8 m_pSps[256];
|
||||
int m_nSpsLen;
|
||||
uint8 m_pPps[256];
|
||||
int m_nPpsLen;
|
||||
|
||||
uint8 m_pAudioConfig[32];
|
||||
uint32 m_nAudioConfigLen;
|
||||
|
||||
int m_nVideoCodec;
|
||||
int m_nWidth;
|
||||
int m_nHeight;
|
||||
double m_nFrameRate;
|
||||
int m_nAudioCodec;
|
||||
int m_nSamplerate;
|
||||
int m_nChannels;
|
||||
|
||||
uint32 m_nVideoInitTS;
|
||||
uint32 m_nAudioInitTS;
|
||||
|
||||
http_flv_notify_cb m_pNotify;
|
||||
void * m_pUserdata;
|
||||
http_flv_video_cb m_pVideoCB;
|
||||
http_flv_audio_cb m_pAudioCB;
|
||||
void * m_pMutex;
|
||||
int m_nRxTimeout;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
674
MediaClient/http/http_mjpeg_cln.cpp
Normal file
674
MediaClient/http/http_mjpeg_cln.cpp
Normal file
@@ -0,0 +1,674 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.h"
|
||||
#include "http_parse.h"
|
||||
#include "http_cln.h"
|
||||
#include "http_mjpeg_cln.h"
|
||||
|
||||
|
||||
void * mjpeg_rx_thread(void * argv)
|
||||
{
|
||||
CHttpMjpeg * p_mjpeg = (CHttpMjpeg *)argv;
|
||||
|
||||
p_mjpeg->rx_thread();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
CHttpMjpeg::CHttpMjpeg(void)
|
||||
: m_running(FALSE)
|
||||
, m_rx_tid(0)
|
||||
, m_header(FALSE)
|
||||
, m_pNotify(NULL)
|
||||
, m_pUserdata(NULL)
|
||||
, m_pVideoCB(NULL)
|
||||
, m_pMutex(NULL)
|
||||
, m_nRxTimeout(10)
|
||||
{
|
||||
memset(&m_http, 0, sizeof(m_http));
|
||||
memset(m_url, 0, sizeof(m_url));
|
||||
|
||||
m_pMutex = sys_os_create_mutex();
|
||||
}
|
||||
|
||||
CHttpMjpeg::~CHttpMjpeg(void)
|
||||
{
|
||||
mjpeg_close();
|
||||
|
||||
if (m_pMutex)
|
||||
{
|
||||
sys_os_destroy_sig_mutex(m_pMutex);
|
||||
m_pMutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CHttpMjpeg::mjpeg_start(const char * url, const char * user, const char * pass)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
strncpy(m_http.host, host, sizeof(m_http.host) - 1);
|
||||
|
||||
if (username[0] != '\0')
|
||||
{
|
||||
strcpy(m_http.auth_info.auth_name, username);
|
||||
}
|
||||
else if (user && user[0] != '\0')
|
||||
{
|
||||
strcpy(m_http.auth_info.auth_name, user);
|
||||
}
|
||||
|
||||
if (password[0] != '\0')
|
||||
{
|
||||
strcpy(m_http.auth_info.auth_pwd, password);
|
||||
}
|
||||
else if (pass && pass[0] != '\0')
|
||||
{
|
||||
strcpy(m_http.auth_info.auth_pwd, pass);
|
||||
}
|
||||
|
||||
if (path[0] != '\0')
|
||||
{
|
||||
strcpy(m_http.url, path);
|
||||
strcpy(m_http.auth_info.auth_uri, path);
|
||||
}
|
||||
|
||||
m_http.port = port;
|
||||
m_http.https = https;
|
||||
strncpy(m_url, url, sizeof(m_url)-1);
|
||||
|
||||
m_running = TRUE;
|
||||
m_rx_tid = sys_os_create_thread((void *)mjpeg_rx_thread, this);
|
||||
if (m_rx_tid == 0)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, sys_os_create_thread failed!!!\r\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CHttpMjpeg::mjpeg_stop()
|
||||
{
|
||||
return mjpeg_close();
|
||||
}
|
||||
|
||||
BOOL CHttpMjpeg::mjpeg_close()
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pVideoCB = NULL;
|
||||
m_pNotify = NULL;
|
||||
m_pUserdata = NULL;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
|
||||
#ifdef HTTPS
|
||||
if (m_http.https && m_http.ssl)
|
||||
{
|
||||
SSL_shutdown(m_http.ssl);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_http.cfd > 0)
|
||||
{
|
||||
closesocket(m_http.cfd);
|
||||
m_http.cfd = 0;
|
||||
}
|
||||
|
||||
m_running = FALSE;
|
||||
|
||||
while (m_rx_tid != 0)
|
||||
{
|
||||
usleep(10*1000);
|
||||
}
|
||||
|
||||
http_cln_free_req(&m_http);
|
||||
|
||||
m_header = 0;
|
||||
memset(&m_http, 0, sizeof(m_http));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CHttpMjpeg::mjpeg_req(HTTPREQ * p_http)
|
||||
{
|
||||
int ret;
|
||||
int offset = 0;
|
||||
char bufs[1024];
|
||||
int buflen = sizeof(bufs);
|
||||
|
||||
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, "User-Agent: happytimesoft/1.0\r\n");
|
||||
offset += snprintf(bufs+offset, buflen-offset, "Range: bytes=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 CHttpMjpeg::mjpeg_conn(HTTPREQ * p_http, int timeout)
|
||||
{
|
||||
p_http->cfd = tcp_connect_timeout(inet_addr(p_http->host), p_http->port, timeout);
|
||||
if (p_http->cfd <= 0)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, tcp_connect_timeout\r\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (p_http->https)
|
||||
{
|
||||
#ifdef HTTPS
|
||||
if (!http_cln_ssl_conn(p_http, timeout))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
log_print(HT_LOG_ERR, "%s, the server require ssl connection, unsupport!\r\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CHttpMjpeg::mjpeg_parse_header(HTTPREQ * p_http)
|
||||
{
|
||||
if (http_is_http_msg(p_http->rbuf) == FALSE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HTTPMSG * rx_msg = NULL;
|
||||
|
||||
int parse_len;
|
||||
int http_pkt_len;
|
||||
|
||||
http_pkt_len = http_pkt_find_end(p_http->rbuf);
|
||||
if (http_pkt_len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 -1;
|
||||
}
|
||||
|
||||
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 -1;
|
||||
}
|
||||
|
||||
p_http->rx_msg = rx_msg;
|
||||
|
||||
p_http->rcv_dlen -= parse_len;
|
||||
if (p_http->rcv_dlen > 0)
|
||||
{
|
||||
memmove(p_http->rbuf, p_http->rbuf+parse_len, p_http->rcv_dlen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHttpMjpeg::mjpeg_parse_header_ex(HTTPREQ * p_http)
|
||||
{
|
||||
HTTPMSG * rx_msg = NULL;
|
||||
|
||||
int offset = 0;
|
||||
int http_pkt_len;
|
||||
int line_len = 0;
|
||||
BOOL bHaveNextLine;
|
||||
char * p_buf;
|
||||
|
||||
while (*(p_http->rbuf+offset) == '\r' || *(p_http->rbuf+offset) == '\n')
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
|
||||
http_pkt_len = http_pkt_find_end(p_http->rbuf+offset);
|
||||
if (http_pkt_len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
p_http->hdr_len = http_pkt_len+offset;
|
||||
|
||||
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 -1;
|
||||
}
|
||||
|
||||
memcpy(rx_msg->msg_buf, p_http->rbuf+offset, 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);
|
||||
|
||||
p_buf = rx_msg->msg_buf;
|
||||
|
||||
READ_LINE:
|
||||
|
||||
if (GetSipLine(p_buf, http_pkt_len, &line_len, &bHaveNextLine) == FALSE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (line_len < 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
while (*(p_buf+offset) == '-')
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (strncmp(p_buf+offset, p_http->boundary, strlen(p_http->boundary)))
|
||||
{
|
||||
p_buf += line_len;
|
||||
goto READ_LINE;
|
||||
}
|
||||
|
||||
p_buf += line_len;
|
||||
rx_msg->hdr_len = http_line_parse(p_buf, http_pkt_len-line_len, ':', &(rx_msg->hdr_ctx));
|
||||
if (rx_msg->hdr_len <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
http_ctt_parse(rx_msg);
|
||||
|
||||
p_http->rx_msg = rx_msg;
|
||||
p_http->ctt_len = rx_msg->ctt_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CHttpMjpeg::mjpeg_data_rx(uint8 * data, int len)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
if (m_pVideoCB)
|
||||
{
|
||||
m_pVideoCB(data, len, m_pUserdata);
|
||||
}
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
int CHttpMjpeg::mjpeg_rx(HTTPREQ * p_http)
|
||||
{
|
||||
int ret;
|
||||
int rlen;
|
||||
|
||||
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);
|
||||
|
||||
closesocket(p_http->cfd);
|
||||
p_http->cfd = 0;
|
||||
return MJPEG_RX_ERR;
|
||||
}
|
||||
|
||||
p_http->rcv_dlen += rlen;
|
||||
p_http->rbuf[p_http->rcv_dlen] = '\0';
|
||||
|
||||
rx_analyse_point:
|
||||
|
||||
if (p_http->rcv_dlen < 16)
|
||||
{
|
||||
return MJPEG_MORE_DATA;
|
||||
}
|
||||
|
||||
if (!m_header)
|
||||
{
|
||||
ret = mjpeg_parse_header(p_http);
|
||||
if (ret > 0)
|
||||
{
|
||||
if (p_http->rx_msg->msg_sub_type == 401 && p_http->need_auth == FALSE)
|
||||
{
|
||||
http_cln_auth_set(p_http, NULL, NULL);
|
||||
|
||||
http_cln_free_req(p_http);
|
||||
|
||||
return MJPEG_NEED_AUTH;
|
||||
}
|
||||
else if (p_http->rx_msg->msg_sub_type == 401 && p_http->need_auth == TRUE)
|
||||
{
|
||||
return MJPEG_AUTH_ERR;
|
||||
}
|
||||
|
||||
if (p_http->rx_msg->ctt_type != CTT_MULTIPART)
|
||||
{
|
||||
http_free_msg(p_http->rx_msg);
|
||||
p_http->rx_msg = NULL;
|
||||
|
||||
return MJPEG_PARSE_ERR;
|
||||
}
|
||||
|
||||
m_header = 1;
|
||||
strcpy(p_http->boundary, p_http->rx_msg->boundary);
|
||||
|
||||
http_free_msg(p_http->rx_msg);
|
||||
p_http->rx_msg = NULL;
|
||||
|
||||
send_notify(MJPEG_EVE_CONNSUCC);
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
return MJPEG_PARSE_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_header)
|
||||
{
|
||||
return MJPEG_MORE_DATA;
|
||||
}
|
||||
|
||||
if (p_http->rcv_dlen < 16)
|
||||
{
|
||||
return MJPEG_MORE_DATA;
|
||||
}
|
||||
|
||||
if (p_http->hdr_len == 0)
|
||||
{
|
||||
ret = mjpeg_parse_header_ex(p_http);
|
||||
if (ret < 0)
|
||||
{
|
||||
return MJPEG_PARSE_ERR;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
return MJPEG_MORE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p_http->rx_msg->ctt_type != CTT_JPG)
|
||||
{
|
||||
http_free_msg(p_http->rx_msg);
|
||||
p_http->rx_msg = NULL;
|
||||
|
||||
return MJPEG_PARSE_ERR;
|
||||
}
|
||||
|
||||
http_free_msg(p_http->rx_msg);
|
||||
p_http->rx_msg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p_http->ctt_len + p_http->hdr_len) > p_http->mlen)
|
||||
{
|
||||
if (p_http->dyn_recv_buf)
|
||||
{
|
||||
free(p_http->dyn_recv_buf);
|
||||
}
|
||||
|
||||
p_http->dyn_recv_buf = (char *)malloc(p_http->ctt_len + p_http->hdr_len + 1);
|
||||
if (NULL == p_http->dyn_recv_buf)
|
||||
{
|
||||
return MJPEG_MALLOC_ERR;
|
||||
}
|
||||
|
||||
memcpy(p_http->dyn_recv_buf, p_http->rcv_buf, p_http->rcv_dlen);
|
||||
p_http->rbuf = p_http->dyn_recv_buf;
|
||||
p_http->mlen = p_http->ctt_len + p_http->hdr_len;
|
||||
|
||||
return MJPEG_MORE_DATA;
|
||||
}
|
||||
|
||||
if (p_http->rcv_dlen >= (p_http->ctt_len + p_http->hdr_len))
|
||||
{
|
||||
mjpeg_data_rx((uint8 *)p_http->rbuf+p_http->hdr_len, p_http->ctt_len);
|
||||
|
||||
p_http->rcv_dlen -= p_http->hdr_len + p_http->ctt_len;
|
||||
|
||||
if (p_http->dyn_recv_buf == NULL)
|
||||
{
|
||||
if (p_http->rcv_dlen > 0)
|
||||
{
|
||||
memmove(p_http->rcv_buf, p_http->rcv_buf+p_http->hdr_len + p_http->ctt_len, p_http->rcv_dlen);
|
||||
p_http->rcv_buf[p_http->rcv_dlen] = '\0';
|
||||
}
|
||||
|
||||
p_http->rbuf = p_http->rcv_buf;
|
||||
p_http->mlen = sizeof(p_http->rcv_buf)-4;
|
||||
p_http->hdr_len = 0;
|
||||
p_http->ctt_len = 0;
|
||||
|
||||
if (p_http->rcv_dlen > 16)
|
||||
{
|
||||
goto rx_analyse_point;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(p_http->dyn_recv_buf);
|
||||
p_http->dyn_recv_buf = NULL;
|
||||
p_http->hdr_len = 0;
|
||||
p_http->ctt_len = 0;
|
||||
p_http->rbuf = NULL;
|
||||
p_http->rcv_dlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return MJPEG_RX_SUCC;
|
||||
}
|
||||
|
||||
void CHttpMjpeg::rx_thread()
|
||||
{
|
||||
int ret;
|
||||
int tm_count = 0;
|
||||
BOOL nodata_notify = FALSE;
|
||||
int sret;
|
||||
fd_set fdr;
|
||||
struct timeval tv;
|
||||
|
||||
send_notify(MJPEG_EVE_CONNECTING);
|
||||
|
||||
RETRY:
|
||||
|
||||
if (!mjpeg_conn(&m_http, 10*1000))
|
||||
{
|
||||
send_notify(MJPEG_EVE_CONNFAIL);
|
||||
goto FAILED;
|
||||
}
|
||||
|
||||
if (!mjpeg_req(&m_http))
|
||||
{
|
||||
send_notify(MJPEG_EVE_CONNFAIL);
|
||||
goto FAILED;
|
||||
}
|
||||
|
||||
while (m_running)
|
||||
{
|
||||
#ifdef HTTPS
|
||||
if (m_http.https && SSL_pending(m_http.ssl) > 0)
|
||||
{
|
||||
// There is data to read
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&fdr);
|
||||
FD_SET(m_http.cfd, &fdr);
|
||||
|
||||
sret = select((int)(m_http.cfd+1), &fdr, NULL, NULL, &tv);
|
||||
if (sret == 0)
|
||||
{
|
||||
tm_count++;
|
||||
if (tm_count >= m_nRxTimeout && !nodata_notify) // in 10s without data
|
||||
{
|
||||
nodata_notify = TRUE;
|
||||
send_notify(MJPEG_EVE_NODATA);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
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(m_http.cfd, &fdr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nodata_notify)
|
||||
{
|
||||
nodata_notify = FALSE;
|
||||
send_notify(MJPEG_EVE_RESUME);
|
||||
}
|
||||
|
||||
tm_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mjpeg_rx(&m_http);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret == MJPEG_AUTH_ERR)
|
||||
{
|
||||
send_notify(MJPEG_EVE_AUTHFAILED);
|
||||
}
|
||||
|
||||
log_print(HT_LOG_ERR, "%s, mjpeg_rx failed. ret = %d\r\n", __FUNCTION__, ret);
|
||||
break;
|
||||
}
|
||||
else if (ret == MJPEG_NEED_AUTH)
|
||||
{
|
||||
goto RETRY;
|
||||
}
|
||||
}
|
||||
|
||||
send_notify(MJPEG_EVE_STOPPED);
|
||||
|
||||
FAILED:
|
||||
|
||||
m_rx_tid = 0;
|
||||
|
||||
log_print(HT_LOG_DBG, "%s, exit\r\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CHttpMjpeg::set_notify_cb(mjpeg_notify_cb notify, void * userdata)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pNotify = notify;
|
||||
m_pUserdata = userdata;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CHttpMjpeg::set_video_cb(mjpeg_video_cb cb)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pVideoCB = cb;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CHttpMjpeg::set_rx_timeout(int timeout)
|
||||
{
|
||||
m_nRxTimeout = timeout;
|
||||
}
|
||||
|
||||
void CHttpMjpeg::send_notify(int event)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
if (m_pNotify)
|
||||
{
|
||||
m_pNotify(event, m_pUserdata);
|
||||
}
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
95
MediaClient/http/http_mjpeg_cln.h
Normal file
95
MediaClient/http/http_mjpeg_cln.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef HTTP_MJPEG_CLN_H
|
||||
#define HTTP_MJPEG_CLN_H
|
||||
|
||||
#include "http.h"
|
||||
#include "http_parse.h"
|
||||
|
||||
|
||||
typedef int (*mjpeg_notify_cb)(int, void *);
|
||||
typedef int (*mjpeg_video_cb)(uint8 *, int, void *);
|
||||
|
||||
#define MJPEG_EVE_STOPPED 20
|
||||
#define MJPEG_EVE_CONNECTING 21
|
||||
#define MJPEG_EVE_CONNFAIL 22
|
||||
#define MJPEG_EVE_CONNSUCC 23
|
||||
#define MJPEG_EVE_NOSIGNAL 24
|
||||
#define MJPEG_EVE_RESUME 25
|
||||
#define MJPEG_EVE_AUTHFAILED 26
|
||||
#define MJPEG_EVE_NODATA 27
|
||||
|
||||
#define MJPEG_RX_ERR -1
|
||||
#define MJPEG_PARSE_ERR -2
|
||||
#define MJPEG_AUTH_ERR -3
|
||||
#define MJPEG_MALLOC_ERR -4
|
||||
#define MJPEG_MORE_DATA 0
|
||||
#define MJPEG_RX_SUCC 1
|
||||
#define MJPEG_NEED_AUTH 2
|
||||
|
||||
|
||||
class CHttpMjpeg
|
||||
{
|
||||
public:
|
||||
CHttpMjpeg(void);
|
||||
~CHttpMjpeg(void);
|
||||
|
||||
public:
|
||||
BOOL mjpeg_start(const char * url, const char * user, const char * pass);
|
||||
BOOL mjpeg_stop();
|
||||
BOOL mjpeg_close();
|
||||
|
||||
char * get_url() {return m_url;}
|
||||
char * get_user() {return m_http.auth_info.auth_name;}
|
||||
char * get_pass() {return m_http.auth_info.auth_pwd;}
|
||||
|
||||
void set_notify_cb(mjpeg_notify_cb notify, void * userdata);
|
||||
void set_video_cb(mjpeg_video_cb cb);
|
||||
void set_rx_timeout(int timeout);
|
||||
|
||||
void rx_thread();
|
||||
|
||||
private:
|
||||
BOOL mjpeg_req(HTTPREQ * p_http);
|
||||
BOOL mjpeg_conn(HTTPREQ * p_http, int timeout);
|
||||
void mjpeg_data_rx(uint8 * data, int len);
|
||||
int mjpeg_parse_header(HTTPREQ * p_http);
|
||||
int mjpeg_parse_header_ex(HTTPREQ * p_http);
|
||||
int mjpeg_rx(HTTPREQ * p_http);
|
||||
|
||||
void send_notify(int event);
|
||||
|
||||
private:
|
||||
HTTPREQ m_http;
|
||||
BOOL m_running;
|
||||
pthread_t m_rx_tid;
|
||||
BOOL m_header;
|
||||
char m_url[512];
|
||||
|
||||
mjpeg_notify_cb m_pNotify;
|
||||
void * m_pUserdata;
|
||||
mjpeg_video_cb m_pVideoCB;
|
||||
void * m_pMutex;
|
||||
int m_nRxTimeout;
|
||||
};
|
||||
|
||||
#endif // end of HTTP_MJPEG_CLN_H
|
||||
|
||||
|
||||
839
MediaClient/http/http_parse.cpp
Normal file
839
MediaClient/http/http_parse.cpp
Normal file
@@ -0,0 +1,839 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.h"
|
||||
#include "http_parse.h"
|
||||
#include "sys_buf.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HTTP_MT msg_type;
|
||||
char msg_str[32];
|
||||
int msg_len;
|
||||
} REQMTV;
|
||||
|
||||
static const REQMTV req_mtvs[] =
|
||||
{
|
||||
{HTTP_MT_GET, "GET", 3},
|
||||
{HTTP_MT_POST, "POST", 4},
|
||||
{HTTP_MT_HEAD, "HEAD", 4},
|
||||
{HTTP_MT_MPOST, "M-POST", 6},
|
||||
{HTTP_MT_MSEARCH, "M-SEARCH", 8},
|
||||
{HTTP_MT_NOTIFY, "NOTIFY", 6},
|
||||
{HTTP_MT_SUBSCRIBE, "SUBSCRIBE", 9},
|
||||
{HTTP_MT_UNSUBSCRIBE, "UNSUBSCRIBE", 11}
|
||||
};
|
||||
|
||||
HT_API BOOL http_is_http_msg(char * msg_buf)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i=0; i<sizeof(req_mtvs)/sizeof(REQMTV); i++)
|
||||
{
|
||||
if (memcmp(msg_buf, req_mtvs[i].msg_str, req_mtvs[i].msg_len) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(msg_buf, "HTTP/1.1", strlen("HTTP/1.1")) == 0 || memcmp(msg_buf, "HTTP/1.0", strlen("HTTP/1.0")) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HT_API int http_pkt_find_end(char * p_buf)
|
||||
{
|
||||
int end_off = 0;
|
||||
int end_len = 4;
|
||||
int http_pkt_finish = 0;
|
||||
|
||||
while (p_buf[end_off] != '\0')
|
||||
{
|
||||
if ((p_buf[end_off] == '\r' && p_buf[end_off+1] == '\n') &&
|
||||
(p_buf[end_off+2] == '\r' && p_buf[end_off+3] == '\n'))
|
||||
{
|
||||
end_len = 4;
|
||||
http_pkt_finish = 1;
|
||||
break;
|
||||
}
|
||||
else if (p_buf[end_off] == '\n' && p_buf[end_off+1] == '\n')
|
||||
{
|
||||
end_len = 2;
|
||||
http_pkt_finish = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
end_off++;
|
||||
}
|
||||
|
||||
if (http_pkt_finish)
|
||||
{
|
||||
return (end_off + end_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HT_API void http_headl_parse(char * pline, int llen, HTTPMSG * p_msg)
|
||||
{
|
||||
char word_buf[256];
|
||||
int word_len;
|
||||
int next_word_offset;
|
||||
BOOL bHaveNextWord;
|
||||
|
||||
bHaveNextWord = GetLineWord(pline, 0, llen, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING);
|
||||
word_len = (int)strlen(word_buf);
|
||||
|
||||
if (word_len > 0 && word_len < 31)
|
||||
{
|
||||
memcpy(p_msg->first_line.header, pline, word_len);
|
||||
p_msg->first_line.header[word_len] = '\0';
|
||||
|
||||
while (pline[next_word_offset] == ' ')
|
||||
{
|
||||
next_word_offset++;
|
||||
}
|
||||
|
||||
p_msg->first_line.value_string = pline+next_word_offset;
|
||||
|
||||
if (strcasecmp(word_buf,"HTTP/1.1") == 0 || strcasecmp(word_buf,"HTTP/1.0") == 0)
|
||||
{
|
||||
if (bHaveNextWord)
|
||||
{
|
||||
bHaveNextWord = GetLineWord(pline, next_word_offset, llen, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_NUM);
|
||||
word_len = (int)strlen(word_buf);
|
||||
if (word_len > 0)
|
||||
{
|
||||
p_msg->msg_type = 1;
|
||||
p_msg->msg_sub_type = atoi(word_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
p_msg->msg_type = 0;
|
||||
|
||||
for (i=0; i<sizeof(req_mtvs)/sizeof(REQMTV); i++)
|
||||
{
|
||||
if (strcasecmp(word_buf, (char *)(req_mtvs[i].msg_str)) == 0)
|
||||
{
|
||||
p_msg->msg_sub_type = req_mtvs[i].msg_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HT_API int http_line_parse(char * p_buf, int max_len, char sep_char, PPSN_CTX * p_ctx)
|
||||
{
|
||||
char word_buf[256];
|
||||
BOOL bHaveNextLine = TRUE;
|
||||
int line_len = 0;
|
||||
int parse_len = 0;
|
||||
|
||||
char * ptr = p_buf;
|
||||
|
||||
do {
|
||||
int next_word_offset = 0;
|
||||
char nchar;
|
||||
HDRV * pHdrV;
|
||||
|
||||
if (GetSipLine(ptr, max_len, &line_len, &bHaveNextLine) == FALSE)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, get sip line error!!!\r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (line_len == 2)
|
||||
{
|
||||
return (parse_len + 2);
|
||||
}
|
||||
|
||||
|
||||
GetLineWord(ptr, 0, line_len-2, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING);
|
||||
|
||||
while (ptr[next_word_offset] == ' ')
|
||||
{
|
||||
next_word_offset++;
|
||||
}
|
||||
|
||||
nchar = *(ptr + next_word_offset);
|
||||
|
||||
if (nchar != sep_char) // SIP is ':',SDP is '='
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, format error!!!\r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
next_word_offset++;
|
||||
|
||||
while (ptr[next_word_offset] == ' ')
|
||||
{
|
||||
next_word_offset++;
|
||||
}
|
||||
|
||||
pHdrV = hdrv_buf_get_idle();
|
||||
if (pHdrV == NULL)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(pHdrV->header, word_buf, 32);
|
||||
pHdrV->value_string = ptr+next_word_offset;
|
||||
pps_ctx_ul_add(p_ctx, pHdrV);
|
||||
|
||||
ptr += line_len;
|
||||
max_len -= line_len;
|
||||
parse_len += line_len;
|
||||
|
||||
} while (bHaveNextLine);
|
||||
|
||||
return parse_len;
|
||||
}
|
||||
|
||||
HT_API BOOL http_get_headline_uri(HTTPMSG * rx_msg, char * p_uri, int size)
|
||||
{
|
||||
int len;
|
||||
char * p_end;
|
||||
char * p_ptr = rx_msg->first_line.value_string;
|
||||
if (p_ptr == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
p_end = p_ptr;
|
||||
while (*p_end != ' ') p_end++;
|
||||
|
||||
len = (int) (p_end - p_ptr);
|
||||
if (len >= size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(p_uri, p_ptr, len);
|
||||
p_uri[len] = '\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HT_API int http_ctt_parse(HTTPMSG * p_msg)
|
||||
{
|
||||
int flag = 0;
|
||||
HTTPCTT w_ctx_type;
|
||||
|
||||
HDRV * pHdrV = (HDRV *)pps_lookup_start(&(p_msg->hdr_ctx));
|
||||
while (pHdrV != NULL)
|
||||
{
|
||||
if (strcasecmp(pHdrV->header, "Content-Length") == 0)
|
||||
{
|
||||
p_msg->ctt_len = atol(pHdrV->value_string);
|
||||
flag++;
|
||||
}
|
||||
else if (strcasecmp(pHdrV->header, "Content-Type") == 0)
|
||||
{
|
||||
char type_word[64];
|
||||
int next_tmp;
|
||||
|
||||
GetLineWord(pHdrV->value_string, 0, (int)strlen(pHdrV->value_string),
|
||||
type_word, sizeof(type_word), &next_tmp, WORD_TYPE_STRING);
|
||||
|
||||
if (strcasecmp(type_word, "application/sdp") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_SDP;
|
||||
}
|
||||
else if (strcasecmp(type_word, "application/soap+xml") == 0 ||
|
||||
strcasecmp(type_word, "text/xml") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_XML;
|
||||
}
|
||||
else if (strcasecmp(type_word, "text/plain") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_TXT;
|
||||
}
|
||||
else if (strcasecmp(type_word, "text/html") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_HTM;
|
||||
}
|
||||
else if (strcasecmp(type_word, "application/octet-stream") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_BIN;
|
||||
}
|
||||
else if (strcasecmp(type_word, "image/jpeg") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_JPG;
|
||||
}
|
||||
else if (strcasecmp(type_word, "application/x-rtsp-tunnelled") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_RTSP_TUNNELLED;
|
||||
}
|
||||
else if (strcasecmp(type_word, "multipart/x-mixed-replace") == 0)
|
||||
{
|
||||
char * boundary = NULL;
|
||||
|
||||
w_ctx_type = CTT_MULTIPART;
|
||||
|
||||
boundary = strstr(pHdrV->value_string, "boundary=");
|
||||
if (boundary)
|
||||
{
|
||||
int offset = 0;
|
||||
while (*(boundary+9+offset) == '-')
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
|
||||
strcpy(p_msg->boundary, boundary+9+offset);
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(type_word, "video/x-flv") == 0)
|
||||
{
|
||||
w_ctx_type = CTT_FLV;
|
||||
}
|
||||
else
|
||||
{
|
||||
w_ctx_type = CTT_NULL;
|
||||
}
|
||||
|
||||
p_msg->ctt_type = w_ctx_type;
|
||||
flag++;
|
||||
}
|
||||
|
||||
pHdrV = (HDRV *)pps_lookup_next(&(p_msg->hdr_ctx), pHdrV);
|
||||
}
|
||||
pps_lookup_end(&(p_msg->hdr_ctx));
|
||||
|
||||
if (p_msg->ctt_type && p_msg->ctt_len)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HT_API int http_msg_parse(char * msg_buf, int msg_buf_len, HTTPMSG * msg)
|
||||
{
|
||||
BOOL bHaveNextLine;
|
||||
int line_len = 0;
|
||||
char * p_buf = msg_buf;
|
||||
|
||||
msg->msg_type = (uint32) -1;
|
||||
|
||||
if (GetSipLine(p_buf, msg_buf_len, &line_len, &bHaveNextLine) == FALSE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (line_len > 0)
|
||||
{
|
||||
http_headl_parse(p_buf, line_len-2, msg);
|
||||
}
|
||||
|
||||
if (msg->msg_type == (uint32) -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_buf += line_len;
|
||||
msg->hdr_len = http_line_parse(p_buf, msg_buf_len-line_len, ':', &(msg->hdr_ctx));
|
||||
if (msg->hdr_len <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_buf += msg->hdr_len;
|
||||
|
||||
if (http_ctt_parse(msg) == 1 && msg->ctt_len > 0)
|
||||
{
|
||||
int slen;
|
||||
HDRV * pHdrV;
|
||||
|
||||
pHdrV = hdrv_buf_get_idle();
|
||||
if (pHdrV == NULL)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(pHdrV->header, "");
|
||||
pHdrV->value_string = p_buf;
|
||||
|
||||
pps_ctx_ul_add(&(msg->ctt_ctx), pHdrV);
|
||||
|
||||
slen = (int)strlen(p_buf);
|
||||
if (slen != msg->ctt_len)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, text xml strlen[%d] != ctx len[%d]!!!\r\n", __FUNCTION__, slen, msg->ctt_len);
|
||||
}
|
||||
}
|
||||
|
||||
return (line_len + msg->hdr_len + msg->ctt_len);
|
||||
}
|
||||
|
||||
HT_API int http_msg_parse_part1(char * p_buf, int buf_len, HTTPMSG * msg)
|
||||
{
|
||||
BOOL bHaveNextLine;
|
||||
int line_len = 0;
|
||||
|
||||
msg->msg_type = (uint32) -1;
|
||||
|
||||
if (GetSipLine(p_buf, buf_len, &line_len, &bHaveNextLine) == FALSE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (line_len > 0)
|
||||
{
|
||||
http_headl_parse(p_buf, line_len-2, msg);
|
||||
}
|
||||
|
||||
if (msg->msg_type == (uint32) -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_buf += line_len;
|
||||
msg->hdr_len = http_line_parse(p_buf, buf_len-line_len, ':', &(msg->hdr_ctx));
|
||||
if (msg->hdr_len <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
http_ctt_parse(msg);
|
||||
|
||||
return (line_len + msg->hdr_len);
|
||||
}
|
||||
|
||||
HT_API int http_msg_parse_part2(char * p_buf, int buf_len, HTTPMSG * msg)
|
||||
{
|
||||
int slen;
|
||||
HDRV * pHdrV;
|
||||
|
||||
pHdrV = hdrv_buf_get_idle();
|
||||
if (pHdrV == NULL)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(pHdrV->header, "");
|
||||
pHdrV->value_string = p_buf;
|
||||
|
||||
pps_ctx_ul_add(&(msg->ctt_ctx), pHdrV);
|
||||
|
||||
slen = buf_len;
|
||||
|
||||
if (ctt_is_string(msg->ctt_type))
|
||||
{
|
||||
slen = (int)strlen(p_buf);
|
||||
|
||||
if (slen != msg->ctt_len)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, text xml strlen[%d] != ctx len[%d]!!!\r\n", __FUNCTION__, slen, msg->ctt_len);
|
||||
}
|
||||
}
|
||||
|
||||
return slen;
|
||||
}
|
||||
|
||||
HT_API HDRV * http_find_headline(HTTPMSG * msg, const char * head)
|
||||
{
|
||||
HDRV * line;
|
||||
|
||||
if (msg == NULL || head == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_start(&(msg->hdr_ctx));
|
||||
while (line != NULL)
|
||||
{
|
||||
if (strcasecmp(line->header, head) == 0)
|
||||
{
|
||||
pps_lookup_end(&(msg->hdr_ctx));
|
||||
return line;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line);
|
||||
}
|
||||
pps_lookup_end(&(msg->hdr_ctx));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HT_API HDRV * http_find_headline_next(HTTPMSG * msg, const char * head, HDRV * hrv)
|
||||
{
|
||||
HDRV * line;
|
||||
|
||||
if (msg == NULL || head == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_start(&(msg->hdr_ctx));
|
||||
while (line != NULL)
|
||||
{
|
||||
if (line == hrv)
|
||||
{
|
||||
line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line);
|
||||
break;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line);
|
||||
}
|
||||
|
||||
while (line != NULL)
|
||||
{
|
||||
if (strcasecmp(line->header, head) == 0)
|
||||
{
|
||||
pps_lookup_end(&(msg->hdr_ctx));
|
||||
return line;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line);
|
||||
}
|
||||
pps_lookup_end(&(msg->hdr_ctx));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HT_API char * http_get_headline(HTTPMSG * msg, const char * head)
|
||||
{
|
||||
HDRV * p_hdrv = http_find_headline(msg, head);
|
||||
if (p_hdrv == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p_hdrv->value_string;
|
||||
}
|
||||
|
||||
void http_add_tx_line(HTTPMSG * tx_msg, const char * msg_hdr, const char * msg_fmt,...)
|
||||
{
|
||||
va_list argptr;
|
||||
int slen;
|
||||
HDRV *pHdrV;
|
||||
|
||||
if (tx_msg == NULL || tx_msg->msg_buf == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pHdrV = hdrv_buf_get_idle();
|
||||
if (pHdrV == NULL)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
pHdrV->value_string = tx_msg->msg_buf + tx_msg->buf_offset;
|
||||
|
||||
strncpy(pHdrV->header, msg_hdr, 31);
|
||||
|
||||
va_start(argptr, msg_fmt);
|
||||
#if __LINUX_OS__
|
||||
slen = vsnprintf(pHdrV->value_string, 1600-tx_msg->buf_offset, msg_fmt, argptr);
|
||||
#else
|
||||
slen = vsprintf(pHdrV->value_string, msg_fmt, argptr);
|
||||
#endif
|
||||
va_end(argptr);
|
||||
|
||||
if (slen < 0)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
|
||||
hdrv_buf_free(pHdrV);
|
||||
return;
|
||||
}
|
||||
|
||||
pHdrV->value_string[slen] = '\0';
|
||||
tx_msg->buf_offset += slen + 1;
|
||||
|
||||
pps_ctx_ul_add(&(tx_msg->hdr_ctx), pHdrV);
|
||||
}
|
||||
|
||||
HT_API HDRV * http_find_ctt_headline(HTTPMSG * msg, const char * head)
|
||||
{
|
||||
HDRV * line;
|
||||
|
||||
if (msg == NULL || head == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_start(&(msg->ctt_ctx));
|
||||
while (line != NULL)
|
||||
{
|
||||
if (strcasecmp(line->header, head) == 0)
|
||||
{
|
||||
pps_lookup_end(&(msg->ctt_ctx));
|
||||
return line;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_next(&(msg->ctt_ctx), line);
|
||||
}
|
||||
pps_lookup_end(&(msg->ctt_ctx));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HT_API char * http_get_ctt(HTTPMSG * msg)
|
||||
{
|
||||
HDRV * line;
|
||||
|
||||
if (msg == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = (HDRV *)pps_lookup_start(&(msg->ctt_ctx));
|
||||
pps_lookup_end(&(msg->ctt_ctx));
|
||||
|
||||
if (line)
|
||||
{
|
||||
return line->value_string;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HT_API BOOL http_get_auth_digest_info(HTTPMSG * rx_msg, HD_AUTH_INFO * p_auth)
|
||||
{
|
||||
int len;
|
||||
int next_offset;
|
||||
char word_buf[128];
|
||||
char * p;
|
||||
|
||||
HDRV * res_line = http_find_headline(rx_msg, "Authorization");
|
||||
if (res_line == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GetLineWord(res_line->value_string, 0, (int)strlen(res_line->value_string),
|
||||
word_buf, sizeof(word_buf), &next_offset, WORD_TYPE_STRING);
|
||||
|
||||
if (strcasecmp(word_buf, "digest") != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
p = res_line->value_string+next_offset;
|
||||
len = (int)strlen(res_line->value_string)-next_offset;
|
||||
|
||||
if (!GetNameValuePair(p, len, "username", p_auth->auth_name, sizeof(p_auth->auth_name)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetNameValuePair(p, len, "realm", p_auth->auth_realm, sizeof(p_auth->auth_realm)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetNameValuePair(p, len, "nonce", p_auth->auth_nonce, sizeof(p_auth->auth_nonce)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetNameValuePair(p, len, "uri", p_auth->auth_uri, sizeof(p_auth->auth_uri)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetNameValuePair(p, len, "response", p_auth->auth_response, sizeof(p_auth->auth_response)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetNameValuePair(p, len, "algorithm", p_auth->auth_algorithm, sizeof(p_auth->auth_algorithm)))
|
||||
{
|
||||
p_auth->auth_algorithm[0] = '\0';
|
||||
}
|
||||
|
||||
if (GetNameValuePair(p, len, "qop", p_auth->auth_qop, sizeof(p_auth->auth_qop)))
|
||||
{
|
||||
char * stop_string;
|
||||
|
||||
if (!GetNameValuePair(p, len, "cnonce", p_auth->auth_cnonce, sizeof(p_auth->auth_cnonce)))
|
||||
{
|
||||
p_auth->auth_cnonce[0] = '\0';
|
||||
}
|
||||
|
||||
if (!GetNameValuePair(p, len, "nc", p_auth->auth_ncstr, sizeof(p_auth->auth_ncstr)))
|
||||
{
|
||||
p_auth->auth_ncstr[0] = '\0';
|
||||
}
|
||||
|
||||
p_auth->auth_nc = strtol(p_auth->auth_ncstr, &stop_string, 16);
|
||||
|
||||
if (strlen(stop_string) > 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p_auth->auth_qop[0] = '\0';
|
||||
p_auth->auth_cnonce[0] = '\0';
|
||||
p_auth->auth_ncstr[0] = '\0';
|
||||
p_auth->auth_nc = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
static PPSN_CTX * msg_buf_fl = NULL;
|
||||
static int http_msg_buf_init_count = 0;
|
||||
HT_API BOOL http_msg_buf_init(int num)
|
||||
{
|
||||
http_msg_buf_init_count++;
|
||||
if (msg_buf_fl)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
msg_buf_fl = pps_ctx_fl_init(num, sizeof(HTTPMSG), TRUE);
|
||||
if (msg_buf_fl == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HT_API void http_msg_buf_deinit()
|
||||
{
|
||||
http_msg_buf_init_count--;
|
||||
if (http_msg_buf_init_count == 0) {
|
||||
if (msg_buf_fl)
|
||||
{
|
||||
pps_fl_free(msg_buf_fl);
|
||||
msg_buf_fl = NULL;
|
||||
}
|
||||
}
|
||||
if (http_msg_buf_init_count < 0)http_msg_buf_init_count = 0;//Reset
|
||||
|
||||
}
|
||||
|
||||
HT_API HTTPMSG * http_get_msg_buf(int size)
|
||||
{
|
||||
HTTPMSG * tx_msg = (HTTPMSG *)pps_fl_pop(msg_buf_fl);
|
||||
if (tx_msg == NULL)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, pop null!!!\r\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(tx_msg, 0, sizeof(HTTPMSG));
|
||||
|
||||
if (size > (int) net_buf_get_size())
|
||||
{
|
||||
tx_msg->msg_buf = (char *)malloc(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_msg->msg_buf = net_buf_get_idle();
|
||||
}
|
||||
|
||||
if (tx_msg->msg_buf == NULL)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, net_buf_get_idle failed\r\n", __FUNCTION__);
|
||||
|
||||
http_free_msg_buf(tx_msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
http_msg_ctx_init(tx_msg);
|
||||
|
||||
return tx_msg;
|
||||
}
|
||||
|
||||
HT_API void http_msg_ctx_init(HTTPMSG * msg)
|
||||
{
|
||||
pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->hdr_ctx));
|
||||
pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->ctt_ctx));
|
||||
}
|
||||
|
||||
HT_API void http_free_msg_buf(HTTPMSG * msg)
|
||||
{
|
||||
pps_fl_push(msg_buf_fl, msg);
|
||||
}
|
||||
|
||||
HT_API uint32 http_idle_msg_buf_num()
|
||||
{
|
||||
return msg_buf_fl->node_num;
|
||||
}
|
||||
|
||||
HT_API void http_free_msg(HTTPMSG * msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
http_free_msg_content(msg);
|
||||
http_free_msg_buf(msg);
|
||||
}
|
||||
|
||||
HT_API void http_free_msg_content(HTTPMSG * msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
http_free_msg_ctx(msg, 0);
|
||||
http_free_msg_ctx(msg, 1);
|
||||
|
||||
net_buf_free(msg->msg_buf);
|
||||
}
|
||||
|
||||
HT_API void http_free_msg_ctx(HTTPMSG * msg, int type)
|
||||
{
|
||||
PPSN_CTX * p_free_ctx = NULL;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
p_free_ctx = &(msg->hdr_ctx);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
p_free_ctx = &(msg->ctt_ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_free_ctx == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hdrv_ctx_free(p_free_ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
70
MediaClient/http/http_parse.h
Normal file
70
MediaClient/http/http_parse.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef HTTP_PARSE_H
|
||||
#define HTTP_PARSE_H
|
||||
|
||||
#include "sys_inc.h"
|
||||
#include "http.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***********************************************************************/
|
||||
HT_API BOOL http_msg_buf_init(int num);
|
||||
HT_API void http_msg_buf_deinit();
|
||||
|
||||
/***********************************************************************/
|
||||
HT_API BOOL http_is_http_msg(char * msg_buf);
|
||||
HT_API int http_pkt_find_end(char * p_buf);
|
||||
HT_API void http_headl_parse(char * pline, int llen, HTTPMSG * p_msg);
|
||||
HT_API int http_line_parse(char * p_buf, int max_len, char sep_char, PPSN_CTX * p_ctx);
|
||||
HT_API BOOL http_get_headline_uri(HTTPMSG * rx_msg, char * p_uri, int size);
|
||||
HT_API int http_ctt_parse(HTTPMSG * p_msg);
|
||||
HT_API int http_msg_parse(char * msg_buf, int msg_buf_len, HTTPMSG * msg);
|
||||
HT_API int http_msg_parse_part1(char * p_buf, int buf_len, HTTPMSG * msg);
|
||||
HT_API int http_msg_parse_part2(char * p_buf, int buf_len, HTTPMSG * msg);
|
||||
HT_API HDRV * http_find_headline(HTTPMSG * msg, const char * head);
|
||||
HT_API HDRV * http_find_headline_next(HTTPMSG * msg, const char * head, HDRV * hrv);
|
||||
HT_API char * http_get_headline(HTTPMSG * msg, const char * head);
|
||||
HT_API HDRV * http_find_ctt_headline(HTTPMSG * msg, const char * head);
|
||||
HT_API char * http_get_ctt(HTTPMSG * msg);
|
||||
HT_API BOOL http_get_auth_digest_info(HTTPMSG * rx_msg, HD_AUTH_INFO * p_auth);
|
||||
|
||||
HT_API HTTPMSG * http_get_msg_buf(int size);
|
||||
HT_API void http_msg_ctx_init(HTTPMSG * msg);
|
||||
HT_API void http_free_msg_buf(HTTPMSG * msg);
|
||||
HT_API uint32 http_idle_msg_buf_num();
|
||||
|
||||
/***********************************************************************/
|
||||
HT_API void http_free_msg(HTTPMSG * msg);
|
||||
HT_API void http_free_msg_content(HTTPMSG * msg);
|
||||
HT_API void http_free_msg_ctx(HTTPMSG * msg, int type);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
304
MediaClient/http/http_test.cpp
Normal file
304
MediaClient/http/http_test.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
39
MediaClient/http/http_test.h
Normal file
39
MediaClient/http/http_test.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef HTTP_TEST_H
|
||||
#define HTTP_TEST_H
|
||||
|
||||
#include "sys_inc.h"
|
||||
#include "http.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
BOOL http_test(const char * url, const char * user, const char * pass, HTTPCTT * ctt, int timeout = 5*1000);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user