1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

for bug #251, refine the mic algorithm. 2.0.63

This commit is contained in:
winlin 2014-12-06 22:50:51 +08:00
parent d53fd7f570
commit 330819fb74
5 changed files with 140 additions and 151 deletions

View file

@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version // current release version
#define VERSION_MAJOR 2 #define VERSION_MAJOR 2
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 61 #define VERSION_REVISION 63
// server info. // server info.
#define RTMP_SIG_SRS_KEY "SRS" #define RTMP_SIG_SRS_KEY "SRS"
#define RTMP_SIG_SRS_ROLE "origin/edge server" #define RTMP_SIG_SRS_ROLE "origin/edge server"

View file

@ -97,13 +97,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// the default config of mw. // the default config of mw.
#define SRS_PERF_MW_SLEEP 350 #define SRS_PERF_MW_SLEEP 350
/** /**
* how many msgs can be send entirely.
* for play clients to get msgs then totally send out.
* for the mw sleep set to 1800, the msgs is about 133.
* @remark, recomment to 128.
*/
#define SRS_PERF_MW_MSGS 128
/**
* use iovs cache in each msg, * use iovs cache in each msg,
* for the shared ptr message, we calc once and used for every copy. * for the shared ptr message, we calc once and used for every copy.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251 * @see https://github.com/winlinvip/simple-rtmp-server/issues/251
@ -111,6 +104,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* @remark when reload change the chunk size, previous clients error. * @remark when reload change the chunk size, previous clients error.
*/ */
#undef SRS_PERF_MW_MSG_IOVS_CACHE #undef SRS_PERF_MW_MSG_IOVS_CACHE
/**
* how many msgs can be send entirely.
* for play clients to get msgs then totally send out.
* for the mw sleep set to 1800, the msgs is about 133.
* @remark, recomment to 128.
* @remark, when mic enabled, use larger iovs cache, to 512.
*/
#ifndef SRS_PERF_MW_MSG_IOVS_CACHE
#define SRS_PERF_MW_MSGS 128
#else
#define SRS_PERF_MW_MSGS 512
#endif
/** /**
* whether set the socket send buffer size. * whether set the socket send buffer size.

View file

@ -135,6 +135,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_OpenSslGetPeerPublicKey 2038 #define ERROR_OpenSslGetPeerPublicKey 2038
#define ERROR_OpenSslComputeSharedKey 2039 #define ERROR_OpenSslComputeSharedKey 2039
#define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED 2040 #define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED 2040
#define ERROR_RTMP_MIC_CACHE_OVERFLOW 2041
// //
// system control message, // system control message,
// not an error, but special control logic. // not an error, but special control logic.

View file

@ -422,7 +422,7 @@ int SrsSharedPtrMessage::__SrsSharedPtr::mic_evaluate(
if (mh->payload_length % chunk_size) { if (mh->payload_length % chunk_size) {
nb_chunks++; nb_chunks++;
} }
nb_iovs = 1/*cid*/ + 1/*size*/ + 1 /*type*/+ 1/*chunk*/; nb_iovs = 1/*cid*/ + 1/*size*//*type*/+ 1/*chunk*/;
// left chunks, always cid+chunk. // left chunks, always cid+chunk.
if (nb_chunks > 0) { if (nb_chunks > 0) {
nb_iovs += (nb_chunks - 1) * 2; nb_iovs += (nb_chunks - 1) * 2;
@ -448,19 +448,16 @@ int SrsSharedPtrMessage::__SrsSharedPtr::mic_evaluate(
iov[0].iov_len = 1; iov[0].iov_len = 1;
// size(payload length), 3B // size(payload length), 3B
// type(message type), 1B
iov[1].iov_base = mic_c0 + 4; iov[1].iov_base = mic_c0 + 4;
iov[1].iov_len = 3; iov[1].iov_len = 4;
// type(message type)
iov[2].iov_base = mic_c0 + 7;
iov[2].iov_len = 1;
// chunk // chunk
iov[3].iov_base = p; iov[2].iov_base = p;
iov[3].iov_len = payload_size; iov[2].iov_len = payload_size;
// move to next iovs. // move to next iovs.
iov += 4; iov += 3;
} else { } else {
// c3 // c3
iov[0].iov_base = &mic_c3; iov[0].iov_base = &mic_c3;
@ -488,8 +485,6 @@ SrsSharedPtrMessage::SrsSharedPtrMessage()
#ifdef SRS_PERF_MW_MSG_IOVS_CACHE #ifdef SRS_PERF_MW_MSG_IOVS_CACHE
mic_etime_present = false; mic_etime_present = false;
iovs = NULL;
nb_iovs = 0;
#endif #endif
} }
@ -502,10 +497,6 @@ SrsSharedPtrMessage::~SrsSharedPtrMessage()
ptr->shared_count--; ptr->shared_count--;
} }
} }
#ifdef SRS_PERF_MW_MSG_IOVS_CACHE
srs_freep(iovs);
#endif
} }
int SrsSharedPtrMessage::create(SrsCommonMessage* msg) int SrsSharedPtrMessage::create(SrsCommonMessage* msg)
@ -598,9 +589,26 @@ int SrsSharedPtrMessage::mic_evaluate(int chunk_size)
} }
} }
return ret;
}
int SrsSharedPtrMessage::mic_iovs_dump(iovec* iovs, int max_nb_iovs)
{
// calc the private iovs // calc the private iovs
char* pp = NULL; char* pp = NULL;
// calc number of iovs.
int nb_iovs = 1/*time*/ + 1/*sid*/;
// insert etime before all chunks.
if (mic_etime_present) {
nb_iovs += ptr->nb_chunks;
}
// not enough, return nagetive to try another loop.
if (max_nb_iovs < nb_iovs + ptr->nb_iovs) {
return -1;
}
// timestamp for c0/c3 // timestamp for c0/c3
u_int32_t timestamp = (u_int32_t)header.timestamp; u_int32_t timestamp = (u_int32_t)header.timestamp;
mic_etime_present = timestamp >= RTMP_EXTENDED_TIMESTAMP; mic_etime_present = timestamp >= RTMP_EXTENDED_TIMESTAMP;
@ -654,72 +662,57 @@ int SrsSharedPtrMessage::mic_evaluate(int chunk_size)
*p++ = pp[0]; *p++ = pp[0];
} }
// calc number of iovs. // dumps all ovs
nb_iovs = 1/*time*/ + 1/*sid*/; iovec* shared = ptr->iovs;
// insert etime before all chunks. iovec* iov = iovs;
if (mic_etime_present) {
nb_iovs += ptr->nb_chunks;
}
// create iovs
srs_freep(iovs);
iovs = new iovec[nb_iovs];
// time, 3B
iovs[0].iov_base = mic_c0_time;
iovs[0].iov_len = 3;
// sid, 4B
iovs[1].iov_base = mic_c0_sid;
iovs[1].iov_len = 4;
// etime, 4B for each chunks.
for (int i = 2; i < nb_iovs; i++) {
iovs[i].iov_base = mic_etime;
iovs[i].iov_len = 4;
}
return ret;
}
int SrsSharedPtrMessage::mic_iovs_count()
{
return nb_iovs + ptr->nb_iovs;
}
int SrsSharedPtrMessage::mic_iovs_dump(iovec* _iovs, int _nb_iovs)
{
int shared_index = 0;
int private_index = 0;
int index = 0;
// dumps all.
srs_assert(nb_iovs + ptr->nb_iovs <= _nb_iovs);
// dump the c0 chunk // dump the c0 chunk
_iovs[index++] = ptr->iovs[shared_index++]; // cid // cid
_iovs[index++] = iovs[private_index++]; // time iov->iov_len = shared->iov_len;
_iovs[index++] = ptr->iovs[shared_index++]; // size iov->iov_base = shared->iov_base;
_iovs[index++] = ptr->iovs[shared_index++]; // type iov++; shared++;
_iovs[index++] = iovs[private_index++]; // sid // time, 3B
iov->iov_base = mic_c0_time;
iov->iov_len = 3;
iov++;
// size, type
iov->iov_len = shared->iov_len;
iov->iov_base = shared->iov_base;
iov++; shared++;
// sid, 4B
iov->iov_base = mic_c0_sid;
iov->iov_len = 4;
iov++;
// etime, 4B
if (mic_etime_present) { if (mic_etime_present) {
_iovs[index++] = iovs[private_index++]; // etime // etime
iov->iov_base = mic_etime;
iov->iov_len = 4;
iov++;
} }
_iovs[index++] = ptr->iovs[shared_index++]; // chunk // chunk
iov->iov_len = shared->iov_len;
iov->iov_base = shared->iov_base;
iov++; shared++;
// dump left c3 chunks // dump left c3 chunks
for (int i = 1; i < ptr->nb_chunks; i++) { for (int i = 1; i < ptr->nb_chunks; i++) {
_iovs[index++] = ptr->iovs[shared_index++]; // cid // cid
iov->iov_len = shared->iov_len;
iov->iov_base = shared->iov_base;
iov++; shared++;
if (mic_etime_present) { if (mic_etime_present) {
_iovs[index++] = iovs[private_index++]; // etime // etime
iov->iov_base = mic_etime;
iov->iov_len = 4;
iov++;
} }
_iovs[index++] = ptr->iovs[shared_index++]; // chunk // chunk
iov->iov_len = shared->iov_len;
iov->iov_base = shared->iov_base;
iov++; shared++;
} }
srs_assert(index == private_index + shared_index);
srs_assert(index == nb_iovs + ptr->nb_iovs);
srs_assert(index <= _nb_iovs);
return nb_iovs + ptr->nb_iovs; return nb_iovs + ptr->nb_iovs;
} }
#endif #endif
@ -955,7 +948,6 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs)
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
#ifndef SRS_PERF_MW_MSG_IOVS_CACHE #ifndef SRS_PERF_MW_MSG_IOVS_CACHE
// TODO: FIXME: use cache system instead.
int iov_index = 0; int iov_index = 0;
iovec* iov = out_iovs + iov_index; iovec* iov = out_iovs + iov_index;
@ -1042,10 +1034,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs)
// when c0c3 cache dry, // when c0c3 cache dry,
// sendout all messages and reset the cache, then send again. // sendout all messages and reset the cache, then send again.
if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { if ((ret = do_iovs_send(out_iovs, iov_index)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send msgs with writev failed. ret=%d", ret);
}
return ret; return ret;
} }
@ -1059,76 +1048,73 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs)
} }
} }
} }
#else
// send all iovs for all msgs.
int total_iovs = 0;
for (int i = 0; i < nb_msgs; i++) {
SrsSharedPtrMessage* msg = msgs[i];
if ((ret = msg->mic_evaluate(out_chunk_size)) != ERROR_SUCCESS) {
srs_error("mic evaluate failed, chunk=%d. ret=%d", out_chunk_size, ret);
return ret;
}
total_iovs += msg->mic_iovs_count();
}
srs_verbose("mic nb_iovs=%d, max=%d", total_iovs, nb_out_iovs);
// realloc the iovs if exceed,
// for we donot know how many messges maybe to send entirely,
// we just alloc the iovs, it's ok.
if (total_iovs > nb_out_iovs) {
srs_warn("resize iovs %d => %d, msgs=%d, max_msgs=%d",
nb_out_iovs, total_iovs, nb_msgs, SRS_PERF_MW_MSGS);
nb_out_iovs = total_iovs;
int realloc_size = sizeof(iovec) * nb_out_iovs;
out_iovs = (iovec*)realloc(out_iovs, realloc_size);
}
// dumps iovs
int iov_index = 0;
for (int i = 0; i < nb_msgs; i++) {
SrsSharedPtrMessage* msg = msgs[i];
iov_index += msg->mic_iovs_dump(
out_iovs + iov_index, nb_out_iovs - iov_index
);
}
#endif
// maybe the iovs already sendout when c0c3 cache dry, // maybe the iovs already sendout when c0c3 cache dry,
// so just ignore when no iovs to send. // so just ignore when no iovs to send.
if (iov_index <= 0) { if (iov_index <= 0) {
return ret; return ret;
} }
#if 0
// calc the bytes of iovs, for debug.
int nb_bytes = 0;
for (int i = 0; i < iov_index; i++) {
iovec* iov = out_iovs + i;
nb_bytes += iov->iov_len;
}
#ifndef SRS_PERF_MW_MSG_IOVS_CACHE
srs_info("mw %d msgs %dB in %d iovs, max_msgs=%d, nb_out_iovs=%d",
nb_msgs, nb_bytes, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs);
#else
srs_info("mic nb_iovs=%d, max=%d, msgs=%d %dB",
total_iovs, nb_out_iovs, nb_msgs, nb_bytes);
#endif
#else
#ifndef SRS_PERF_MW_MSG_IOVS_CACHE
srs_info("mw %d msgs in %d iovs, max_msgs=%d, nb_out_iovs=%d", srs_info("mw %d msgs in %d iovs, max_msgs=%d, nb_out_iovs=%d",
nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs);
#else
srs_info("mic nb_iovs=%d, max=%d, msgs=%d", return do_iovs_send(out_iovs, iov_index);
total_iovs, nb_out_iovs, nb_msgs); #else
#endif // send all iovs for all msgs.
int msg_sent = 0;
while (msg_sent < nb_msgs) {
int iov_index = 0;
for (int i = msg_sent; i < nb_msgs; i++) {
SrsSharedPtrMessage* msg = msgs[i];
// evaluate
if ((ret = msg->mic_evaluate(out_chunk_size)) != ERROR_SUCCESS) {
return ret;
}
// dump msg to iovec.
int ok_iovs = msg->mic_iovs_dump(
out_iovs + iov_index, nb_out_iovs - iov_index
);
// protocol iovs cache exceed.
if (ok_iovs <= 0) {
break;
}
// ok, dump next.
msg_sent++;
iov_index += ok_iovs;
}
srs_info("mic nb_iovs=%d, msgs=%d, msg_sent=%d, iovs_sent=%d",
nb_out_iovs, nb_msgs, msg_sent, iov_index);
// cache not enough.
if (iov_index <= 0) {
ret = ERROR_RTMP_MIC_CACHE_OVERFLOW;
srs_warn("mic iovs overflow, nb_iovs=%d, msgs=%d, msg_sent=%d, iovs_sent=%d, ret=%d",
nb_out_iovs, nb_msgs, msg_sent, iov_index, ret);
return ret;
}
// send out these iovs.
if ((ret = do_iovs_send(out_iovs, iov_index)) != ERROR_SUCCESS) {
return ret;
}
}
return ret;
#endif #endif
}
int SrsProtocol::do_iovs_send(iovec* iovs, int size)
{
int ret = ERROR_SUCCESS;
// the limits of writev iovs. // the limits of writev iovs.
static int limits = sysconf(_SC_IOV_MAX); static int limits = sysconf(_SC_IOV_MAX);
// send in a time. // send in a time.
if (iov_index < limits) { if (size < limits) {
if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) { if ((ret = skt->writev(iovs, size, NULL)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) { if (!srs_is_client_gracefully_close(ret)) {
srs_error("send with writev failed. ret=%d", ret); srs_error("send with writev failed. ret=%d", ret);
} }
@ -1139,9 +1125,9 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs)
// send in multiple times. // send in multiple times.
int cur_iov = 0; int cur_iov = 0;
while (cur_iov < iov_index) { while (cur_iov < size) {
int cur_count = srs_min(limits, iov_index - cur_iov); int cur_count = srs_min(limits, size - cur_iov);
if ((ret = skt->writev(out_iovs + cur_iov, cur_count, NULL)) != ERROR_SUCCESS) { if ((ret = skt->writev(iovs + cur_iov, cur_count, NULL)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) { if (!srs_is_client_gracefully_close(ret)) {
srs_error("send with writev failed. ret=%d", ret); srs_error("send with writev failed. ret=%d", ret);
} }

View file

@ -286,9 +286,6 @@ private:
char mic_etime[4]; char mic_etime[4];
// whether etime present. // whether etime present.
bool mic_etime_present; bool mic_etime_present;
// the calced private iovs for this msg
iovec* iovs;
int nb_iovs;
#endif #endif
public: public:
SrsSharedPtrMessage(); SrsSharedPtrMessage();
@ -329,14 +326,10 @@ public:
*/ */
virtual int mic_evaluate(int chunk_size); virtual int mic_evaluate(int chunk_size);
/** /**
* count the total iovs needed.
*/
virtual int mic_iovs_count();
/**
* dump all iovs, the _nb_iovs must equals to mic_iovs_count(). * dump all iovs, the _nb_iovs must equals to mic_iovs_count().
* @return the dumped count. * @return the dumped count. -1 if not enough iovs.
*/ */
virtual int mic_iovs_dump(iovec* _iovs, int _nb_iovs); virtual int mic_iovs_dump(iovec* iovs, int max_nb_iovs);
#endif #endif
}; };
@ -594,6 +587,10 @@ private:
*/ */
virtual int do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs); virtual int do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs);
/** /**
* send iovs. send multiple times if exceed limits.
*/
virtual int do_iovs_send(iovec* iovs, int size);
/**
* underlayer api for send and free packet. * underlayer api for send and free packet.
*/ */
virtual int do_send_and_free_packet(SrsPacket* packet, int stream_id); virtual int do_send_and_free_packet(SrsPacket* packet, int stream_id);