mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	refine hls on_hls_notify, read a little of ts.
This commit is contained in:
		
							parent
							
								
									1f93fb3399
								
							
						
					
					
						commit
						5c00ce8a96
					
				
					 3 changed files with 122 additions and 76 deletions
				
			
		| 
						 | 
					@ -53,6 +53,9 @@ using namespace std;
 | 
				
			||||||
#define SRS_CONSTS_HTTP_PUT HTTP_PUT
 | 
					#define SRS_CONSTS_HTTP_PUT HTTP_PUT
 | 
				
			||||||
#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE
 | 
					#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// for ead all of http body, read each time.
 | 
				
			||||||
 | 
					#define SRS_HTTP_READ_CACHE_BYTES 4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SRS_HTTP_DEFAULT_PAGE "index.html"
 | 
					#define SRS_HTTP_DEFAULT_PAGE "index.html"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int srs_go_http_response_json(ISrsHttpResponseWriter* w, string data)
 | 
					int srs_go_http_response_json(ISrsHttpResponseWriter* w, string data)
 | 
				
			||||||
| 
						 | 
					@ -889,7 +892,8 @@ SrsHttpResponseReader::SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* i
 | 
				
			||||||
    skt = io;
 | 
					    skt = io;
 | 
				
			||||||
    owner = msg;
 | 
					    owner = msg;
 | 
				
			||||||
    is_eof = false;
 | 
					    is_eof = false;
 | 
				
			||||||
    nb_read = 0;
 | 
					    nb_total_read = 0;
 | 
				
			||||||
 | 
					    nb_left_chunk = 0;
 | 
				
			||||||
    buffer = NULL;
 | 
					    buffer = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -901,6 +905,8 @@ int SrsHttpResponseReader::initialize(SrsFastBuffer* body)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = ERROR_SUCCESS;
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    nb_left_chunk = 0;
 | 
				
			||||||
 | 
					    nb_total_read = 0;
 | 
				
			||||||
    buffer = body;
 | 
					    buffer = body;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
| 
						 | 
					@ -911,7 +917,7 @@ bool SrsHttpResponseReader::eof()
 | 
				
			||||||
    return is_eof;
 | 
					    return is_eof;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int SrsHttpResponseReader::read(std::string& data)
 | 
					int SrsHttpResponseReader::read(char* data, int nb_data, int* nb_read)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = ERROR_SUCCESS;
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -923,95 +929,115 @@ int SrsHttpResponseReader::read(std::string& data)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // chunked encoding.
 | 
					    // chunked encoding.
 | 
				
			||||||
    if (owner->is_chunked()) {
 | 
					    if (owner->is_chunked()) {
 | 
				
			||||||
        return read_chunked(data);
 | 
					        return read_chunked(data, nb_data, nb_read);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // read by specified content-length
 | 
					    // read by specified content-length
 | 
				
			||||||
    int max = (int)owner->content_length() - (int)nb_read;
 | 
					    int max = (int)owner->content_length() - (int)nb_total_read;
 | 
				
			||||||
    if (max <= 0) {
 | 
					    if (max <= 0) {
 | 
				
			||||||
        is_eof = true;
 | 
					        is_eof = true;
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return read_specified(max, data);
 | 
					    
 | 
				
			||||||
 | 
					    // change the max to read.
 | 
				
			||||||
 | 
					    nb_data = srs_min(nb_data, max);
 | 
				
			||||||
 | 
					    return read_specified(data, nb_data, nb_read);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int SrsHttpResponseReader::read_chunked(std::string& data)
 | 
					int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = ERROR_SUCCESS;
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    // when no bytes left in chunk,
 | 
				
			||||||
    // parse the chunk length first.
 | 
					    // parse the chunk length first.
 | 
				
			||||||
    char* at = NULL;
 | 
					    if (nb_left_chunk <= 0) {
 | 
				
			||||||
    int length = 0;
 | 
					        char* at = NULL;
 | 
				
			||||||
    while (!at) {
 | 
					        int length = 0;
 | 
				
			||||||
        // find the CRLF of chunk header end.
 | 
					        while (!at) {
 | 
				
			||||||
        char* start = buffer->bytes();
 | 
					            // find the CRLF of chunk header end.
 | 
				
			||||||
        char* end = start + buffer->size();
 | 
					            char* start = buffer->bytes();
 | 
				
			||||||
        for (char* p = start; p < end - 1; p++) {
 | 
					            char* end = start + buffer->size();
 | 
				
			||||||
            if (p[0] == SRS_HTTP_CR && p[1] == SRS_HTTP_LF) {
 | 
					            for (char* p = start; p < end - 1; p++) {
 | 
				
			||||||
                // invalid chunk, ignore.
 | 
					                if (p[0] == SRS_HTTP_CR && p[1] == SRS_HTTP_LF) {
 | 
				
			||||||
                if (p == start) {
 | 
					                    // invalid chunk, ignore.
 | 
				
			||||||
                    ret = ERROR_HTTP_INVALID_CHUNK_HEADER;
 | 
					                    if (p == start) {
 | 
				
			||||||
                    srs_error("chunk header start with CRLF. ret=%d", ret);
 | 
					                        ret = ERROR_HTTP_INVALID_CHUNK_HEADER;
 | 
				
			||||||
                    return ret;
 | 
					                        srs_error("chunk header start with CRLF. ret=%d", ret);
 | 
				
			||||||
 | 
					                        return ret;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    length = (int)(p - start + 2);
 | 
				
			||||||
 | 
					                    at = buffer->read_slice(length);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                length = (int)(p - start + 2);
 | 
					            }
 | 
				
			||||||
                at = buffer->read_slice(length);
 | 
					            
 | 
				
			||||||
 | 
					            // got at, ok.
 | 
				
			||||||
 | 
					            if (at) {
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					            
 | 
				
			||||||
        
 | 
					            // when empty, only grow 1bytes, but the buffer will cache more.
 | 
				
			||||||
        // got at, ok.
 | 
					            if ((ret = buffer->grow(skt, buffer->size() + 1)) != ERROR_SUCCESS) {
 | 
				
			||||||
        if (at) {
 | 
					                if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
            break;
 | 
					                    srs_error("read body from server failed. ret=%d", ret);
 | 
				
			||||||
        }
 | 
					                }
 | 
				
			||||||
        
 | 
					                return ret;
 | 
				
			||||||
        // when empty, only grow 1bytes, but the buffer will cache more.
 | 
					 | 
				
			||||||
        if ((ret = buffer->grow(skt, buffer->size() + 1)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
            if (!srs_is_client_gracefully_close(ret)) {
 | 
					 | 
				
			||||||
                srs_error("read body from server failed. ret=%d", ret);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_assert(length >= 3);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // it's ok to set the pos and pos+1 to NULL.
 | 
				
			||||||
 | 
					        at[length - 1] = 0;
 | 
				
			||||||
 | 
					        at[length - 2] = 0;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // size is the bytes size, excludes the chunk header and end CRLF.
 | 
				
			||||||
 | 
					        int ilength = (int)::strtol(at, NULL, 16);
 | 
				
			||||||
 | 
					        if (ilength < 0) {
 | 
				
			||||||
 | 
					            ret = ERROR_HTTP_INVALID_CHUNK_HEADER;
 | 
				
			||||||
 | 
					            srs_error("chunk header negative, length=%d. ret=%d", ilength, ret);
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // all bytes in chunk is left now.
 | 
				
			||||||
 | 
					        nb_left_chunk = ilength;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    srs_assert(length >= 3);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // it's ok to set the pos and pos+1 to NULL.
 | 
					    // left bytes in chunk, read some.
 | 
				
			||||||
    at[length - 1] = 0;
 | 
					    srs_assert(nb_left_chunk);
 | 
				
			||||||
    at[length - 2] = 0;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // size is the bytes size, excludes the chunk header and end CRLF.
 | 
					    int nb_bytes = srs_min(nb_left_chunk, nb_data);
 | 
				
			||||||
    int ilength = (int)::strtol(at, NULL, 16);
 | 
					    ret = read_specified(data, nb_bytes, &nb_bytes);
 | 
				
			||||||
    if (ilength < 0) {
 | 
					    
 | 
				
			||||||
        ret = ERROR_HTTP_INVALID_CHUNK_HEADER;
 | 
					    // the nb_bytes used for output already read size of bytes.
 | 
				
			||||||
        srs_error("chunk header negative, length=%d. ret=%d", ilength, ret);
 | 
					    if (nb_read) {
 | 
				
			||||||
 | 
					        *nb_read = nb_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    nb_left_chunk -= nb_bytes;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // error or still left bytes in chunk, ignore and read in future.
 | 
				
			||||||
 | 
					    if (nb_left_chunk > 0 || (ret != ERROR_SUCCESS)) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    srs_info("http: read %d bytes of chunk", nb_bytes);
 | 
				
			||||||
    // when empty, only grow 1bytes, but the buffer will cache more.
 | 
					 | 
				
			||||||
    if ((ret = buffer->grow(skt, ilength + 2)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
        if (!srs_is_client_gracefully_close(ret)) {
 | 
					 | 
				
			||||||
            srs_error("read body from server failed. ret=%d", ret);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return ret;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    srs_info("http: read %d chunk", ilength);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // read payload when length specifies some payload.
 | 
					    // read payload when length specifies some payload.
 | 
				
			||||||
    if (ilength <= 0) {
 | 
					    if (nb_left_chunk <= 0) {
 | 
				
			||||||
        is_eof = true;
 | 
					        is_eof = true;
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        srs_assert(ilength);
 | 
					 | 
				
			||||||
        data.append(buffer->read_slice(ilength), ilength);
 | 
					 | 
				
			||||||
        nb_read += ilength;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // the CRLF of chunk payload end.
 | 
					    // the CRLF of chunk payload end.
 | 
				
			||||||
 | 
					    if ((ret = buffer->grow(skt, 2)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("read EOF of chunk from server failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    buffer->read_slice(2);
 | 
					    buffer->read_slice(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int SrsHttpResponseReader::read_specified(int max, std::string& data)
 | 
					int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = ERROR_SUCCESS;
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -1025,14 +1051,21 @@ int SrsHttpResponseReader::read_specified(int max, std::string& data)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int nb_bytes = srs_min(max, buffer->size());
 | 
					    int nb_bytes = srs_min(nb_data, buffer->size());
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    // read data to buffer.
 | 
				
			||||||
    srs_assert(nb_bytes);
 | 
					    srs_assert(nb_bytes);
 | 
				
			||||||
    data.append(buffer->read_slice(nb_bytes), nb_bytes);
 | 
					    char* p = buffer->read_slice(nb_bytes);
 | 
				
			||||||
    nb_read += nb_bytes;
 | 
					    memcpy(data, p, nb_bytes);
 | 
				
			||||||
 | 
					    if (nb_read) {
 | 
				
			||||||
 | 
					        *nb_read = nb_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // increase the total read to determine whether EOF.
 | 
				
			||||||
 | 
					    nb_total_read += nb_bytes;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // when read completed, eof.
 | 
					    // when read completed, eof.
 | 
				
			||||||
    if (nb_read >= (int)owner->content_length()) {
 | 
					    if (nb_total_read >= (int)owner->content_length()) {
 | 
				
			||||||
        is_eof = true;
 | 
					        is_eof = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -1223,11 +1256,19 @@ int SrsHttpMessage::body_read_all(string& body)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = ERROR_SUCCESS;
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    // cache to read.
 | 
				
			||||||
 | 
					    char* buf = new char[SRS_HTTP_READ_CACHE_BYTES];
 | 
				
			||||||
 | 
					    SrsAutoFree(char, buf);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // whatever, read util EOF.
 | 
					    // whatever, read util EOF.
 | 
				
			||||||
    while (!_body->eof()) {
 | 
					    while (!_body->eof()) {
 | 
				
			||||||
        if ((ret = _body->read(body)) != ERROR_SUCCESS) {
 | 
					        int nb_read = 0;
 | 
				
			||||||
 | 
					        if ((ret = _body->read(buf, SRS_HTTP_READ_CACHE_BYTES, &nb_read)) != ERROR_SUCCESS) {
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert (nb_read > 0);
 | 
				
			||||||
 | 
					        body.append(buf, nb_read);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,10 +196,13 @@ public:
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    virtual bool eof() = 0;
 | 
					    virtual bool eof() = 0;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    * read from the response body.
 | 
					     * read from the response body.
 | 
				
			||||||
    * @remark when eof(), return error.
 | 
					     * @param data, the buffer to read data buffer to.
 | 
				
			||||||
    */
 | 
					     * @param nb_data, the max size of data buffer.
 | 
				
			||||||
    virtual int read(std::string& data) = 0;
 | 
					     * @param nb_read, the actual read size of bytes. NULL to ignore.
 | 
				
			||||||
 | 
					     * @remark when eof(), return error.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual int read(char* data, int nb_data, int* nb_read) = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Objects implementing the Handler interface can be
 | 
					// Objects implementing the Handler interface can be
 | 
				
			||||||
| 
						 | 
					@ -431,7 +434,10 @@ private:
 | 
				
			||||||
    SrsHttpMessage* owner;
 | 
					    SrsHttpMessage* owner;
 | 
				
			||||||
    SrsFastBuffer* buffer;
 | 
					    SrsFastBuffer* buffer;
 | 
				
			||||||
    bool is_eof;
 | 
					    bool is_eof;
 | 
				
			||||||
    int64_t nb_read;
 | 
					    // the left bytes in chunk.
 | 
				
			||||||
 | 
					    int nb_left_chunk;
 | 
				
			||||||
 | 
					    // already read total bytes.
 | 
				
			||||||
 | 
					    int64_t nb_total_read;
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* io);
 | 
					    SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* io);
 | 
				
			||||||
    virtual ~SrsHttpResponseReader();
 | 
					    virtual ~SrsHttpResponseReader();
 | 
				
			||||||
| 
						 | 
					@ -443,10 +449,10 @@ public:
 | 
				
			||||||
// interface ISrsHttpResponseReader
 | 
					// interface ISrsHttpResponseReader
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    virtual bool eof();
 | 
					    virtual bool eof();
 | 
				
			||||||
    virtual int read(std::string& data);
 | 
					    virtual int read(char* data, int nb_data, int* nb_read);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    virtual int read_chunked(std::string& data);
 | 
					    virtual int read_chunked(char* data, int nb_data, int* nb_read);
 | 
				
			||||||
    virtual int read_specified(int max, std::string& data);
 | 
					    virtual int read_specified(char* data, int nb_data, int* nb_read);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// for http header.
 | 
					// for http header.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -363,17 +363,16 @@ int SrsHttpHooks::on_hls_notify(std::string url, SrsRequest* req, std::string ts
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    SrsAutoFree(SrsHttpMessage, msg);
 | 
					    SrsAutoFree(SrsHttpMessage, msg);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    int nb_read = 0;
 | 
				
			||||||
    ISrsHttpResponseReader* br = msg->body_reader();
 | 
					    ISrsHttpResponseReader* br = msg->body_reader();
 | 
				
			||||||
    while (!br->eof()) {
 | 
					    if (!br->eof()) {
 | 
				
			||||||
        std::string data;
 | 
					        char buf[64]; // only read a little of bytes of ts.
 | 
				
			||||||
        // for notify, only read some data.
 | 
					        ret = br->read(buf, 64, &nb_read);
 | 
				
			||||||
        ret = br->read(data);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int spenttime = (int)(srs_update_system_time_ms() - starttime);
 | 
					    int spenttime = (int)(srs_update_system_time_ms() - starttime);
 | 
				
			||||||
    srs_trace("http hook on_hls_notify success. client_id=%d, url=%s, code=%d, spent=%dms, ret=%d",
 | 
					    srs_trace("http hook on_hls_notify success. client_id=%d, url=%s, code=%d, spent=%dms, read=%dB, ret=%d",
 | 
				
			||||||
        client_id, url.c_str(), msg->status_code(), spenttime, ret);
 | 
					        client_id, url.c_str(), msg->status_code(), spenttime, nb_read, ret);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ignore any error for on_hls_notify.
 | 
					    // ignore any error for on_hls_notify.
 | 
				
			||||||
    ret = ERROR_SUCCESS;
 | 
					    ret = ERROR_SUCCESS;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue