|
|
|
@ -20,7 +20,7 @@
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* This is a Proxy Server that displays the connection parameters from a
|
|
|
|
|
/* This is a Proxy Server that displays the connection parameters from a
|
|
|
|
|
* client and then saves any data streamed to the client.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
@ -115,8 +115,7 @@ static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop");
|
|
|
|
|
static const char *cst[] = { "client", "server" };
|
|
|
|
|
|
|
|
|
|
// Returns 0 for OK/Failed/error, 1 for 'Stop or Complete'
|
|
|
|
|
int
|
|
|
|
|
ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *body)
|
|
|
|
|
int ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *body)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0, nRes;
|
|
|
|
|
int nBodySize = pack->m_nBodySize;
|
|
|
|
@ -151,7 +150,7 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
int i;
|
|
|
|
|
AMFProp_GetObject(AMF_GetProp(&obj, NULL, 2), &cobj);
|
|
|
|
|
RTMP_LogPrintf("Processing connect\n");
|
|
|
|
|
for (i=0; i<cobj.o_num; i++)
|
|
|
|
|
for (i = 0; i < cobj.o_num; i++)
|
|
|
|
|
{
|
|
|
|
|
pname = cobj.o_props[i].p_name;
|
|
|
|
|
pval.av_val = NULL;
|
|
|
|
@ -195,19 +194,19 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
if (pval.av_val[4] == ':')
|
|
|
|
|
{
|
|
|
|
|
server->rc.Link.protocol = RTMP_PROTOCOL_RTMP;
|
|
|
|
|
r1 = pval.av_val+7;
|
|
|
|
|
r1 = pval.av_val + 7;
|
|
|
|
|
}
|
|
|
|
|
else if ((pval.av_val[4] | 0x40) == 'e' && pval.av_val[5] == ':')
|
|
|
|
|
{
|
|
|
|
|
server->rc.Link.protocol = RTMP_PROTOCOL_RTMPE;
|
|
|
|
|
r1 = pval.av_val+8;
|
|
|
|
|
r1 = pval.av_val + 8;
|
|
|
|
|
}
|
|
|
|
|
r2 = strchr(r1, '/');
|
|
|
|
|
if (r2)
|
|
|
|
|
len = r2 - r1;
|
|
|
|
|
else
|
|
|
|
|
len = pval.av_len - (r1 - pval.av_val);
|
|
|
|
|
r2 = malloc(len+1);
|
|
|
|
|
r2 = malloc(len + 1);
|
|
|
|
|
memcpy(r2, r1, len);
|
|
|
|
|
r2[len] = '\0';
|
|
|
|
|
server->rc.Link.hostname.av_val = r2;
|
|
|
|
@ -285,7 +284,7 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
/* check for duplicates */
|
|
|
|
|
for (fl = server->f_head; fl; fl=fl->f_next)
|
|
|
|
|
for (fl = server->f_head; fl; fl = fl->f_next)
|
|
|
|
|
{
|
|
|
|
|
if (AVMATCH(&av, &fl->f_path))
|
|
|
|
|
count++;
|
|
|
|
@ -305,7 +304,7 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* strip leading slash components */
|
|
|
|
|
for (p=av.av_val+av.av_len-1; p>=av.av_val; p--)
|
|
|
|
|
for (p = av.av_val + av.av_len - 1; p >= av.av_val; p--)
|
|
|
|
|
if (*p == '/')
|
|
|
|
|
{
|
|
|
|
|
p++;
|
|
|
|
@ -323,14 +322,14 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
/* hope there aren't more than 255 dups */
|
|
|
|
|
if (count)
|
|
|
|
|
flen += 2;
|
|
|
|
|
file = malloc(flen+1);
|
|
|
|
|
file = malloc(flen + 1);
|
|
|
|
|
|
|
|
|
|
memcpy(file, av.av_val, av.av_len);
|
|
|
|
|
if (count)
|
|
|
|
|
sprintf(file+av.av_len, "%02x", count);
|
|
|
|
|
sprintf(file + av.av_len, "%02x", count);
|
|
|
|
|
else
|
|
|
|
|
file[av.av_len] = '\0';
|
|
|
|
|
for (p=file; *p; p++)
|
|
|
|
|
for (p = file; *p; p++)
|
|
|
|
|
if (*p == ':')
|
|
|
|
|
*p = '_';
|
|
|
|
|
RTMP_LogPrintf("Playpath: %.*s\nSaving as: %s\n",
|
|
|
|
@ -344,10 +343,10 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
{
|
|
|
|
|
fwrite(flvHeader, 1, sizeof(flvHeader), out);
|
|
|
|
|
av = server->rc.Link.playpath;
|
|
|
|
|
fl = malloc(sizeof(Flist)+av.av_len+1);
|
|
|
|
|
fl = malloc(sizeof(Flist) + av.av_len + 1);
|
|
|
|
|
fl->f_file = out;
|
|
|
|
|
fl->f_path.av_len = av.av_len;
|
|
|
|
|
fl->f_path.av_val = (char *)(fl+1);
|
|
|
|
|
fl->f_path.av_val = (char *)(fl + 1);
|
|
|
|
|
memcpy(fl->f_path.av_val, av.av_val, av.av_len);
|
|
|
|
|
fl->f_path.av_val[av.av_len] = '\0';
|
|
|
|
|
fl->f_next = NULL;
|
|
|
|
@ -386,7 +385,7 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (server->f_cur = server->f_head; server->f_cur &&
|
|
|
|
|
!server->f_cur->f_file; server->f_cur = server->f_cur->f_next) ;
|
|
|
|
|
!server->f_cur->f_file; server->f_cur = server->f_cur->f_next);
|
|
|
|
|
}
|
|
|
|
|
server->rc.m_bPlaying = TRUE;
|
|
|
|
|
}
|
|
|
|
@ -412,8 +411,7 @@ out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ServePacket(STREAMING_SERVER *server, int which, RTMPPacket *packet)
|
|
|
|
|
int ServePacket(STREAMING_SERVER *server, int which, RTMPPacket *packet)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
@ -424,7 +422,7 @@ ServePacket(STREAMING_SERVER *server, int which, RTMPPacket *packet)
|
|
|
|
|
{
|
|
|
|
|
case RTMP_PACKET_TYPE_CHUNK_SIZE:
|
|
|
|
|
// chunk size
|
|
|
|
|
// HandleChangeChunkSize(r, packet);
|
|
|
|
|
// HandleChangeChunkSize(r, packet);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RTMP_PACKET_TYPE_BYTES_READ_REPORT:
|
|
|
|
@ -433,12 +431,12 @@ ServePacket(STREAMING_SERVER *server, int which, RTMPPacket *packet)
|
|
|
|
|
|
|
|
|
|
case RTMP_PACKET_TYPE_CONTROL:
|
|
|
|
|
// ctrl
|
|
|
|
|
// HandleCtrl(r, packet);
|
|
|
|
|
// HandleCtrl(r, packet);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RTMP_PACKET_TYPE_SERVER_BW:
|
|
|
|
|
// server bw
|
|
|
|
|
// HandleServerBW(r, packet);
|
|
|
|
|
// HandleServerBW(r, packet);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RTMP_PACKET_TYPE_CLIENT_BW:
|
|
|
|
@ -497,8 +495,7 @@ ServePacket(STREAMING_SERVER *server, int which, RTMPPacket *packet)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
int WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
unsigned int *plen, // length of buffer if preallocated
|
|
|
|
|
uint32_t *nTimeStamp,
|
|
|
|
|
RTMPPacket *packet)
|
|
|
|
@ -552,7 +549,7 @@ WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
{
|
|
|
|
|
/* The extra 4 is for the case of an FLV stream without a last
|
|
|
|
|
* prevTagSize (we need extra 4 bytes to append it). */
|
|
|
|
|
*buf = (char *) realloc(*buf, size + 4);
|
|
|
|
|
*buf = (char *)realloc(*buf, size + 4);
|
|
|
|
|
if (*buf == 0)
|
|
|
|
|
{
|
|
|
|
|
RTMP_Log(RTMP_LOGERROR, "Couldn't reallocate memory!");
|
|
|
|
@ -560,7 +557,7 @@ WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
char *ptr = *buf, *pend = ptr + size+4;
|
|
|
|
|
char *ptr = *buf, *pend = ptr + size + 4;
|
|
|
|
|
|
|
|
|
|
/* audio (RTMP_PACKET_TYPE_AUDIO), video (RTMP_PACKET_TYPE_VIDEO)
|
|
|
|
|
* or metadata (RTMP_PACKET_TYPE_INFO) packets: construct 11 byte
|
|
|
|
@ -578,7 +575,7 @@ WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
*ptr++ = packet->m_packetType;
|
|
|
|
|
ptr = AMF_EncodeInt24(ptr, pend, nPacketLen);
|
|
|
|
|
ptr = AMF_EncodeInt24(ptr, pend, *nTimeStamp);
|
|
|
|
|
*ptr = (char) (((*nTimeStamp) & 0xFF000000) >> 24);
|
|
|
|
|
*ptr = (char)(((*nTimeStamp) & 0xFF000000) >> 24);
|
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
|
|
// stream id
|
|
|
|
@ -601,8 +598,8 @@ WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* set data type */
|
|
|
|
|
*dataType |= (((*(packetBody+pos) == RTMP_PACKET_TYPE_AUDIO) << 2)
|
|
|
|
|
| (*(packetBody+pos) == RTMP_PACKET_TYPE_VIDEO));
|
|
|
|
|
* dataType |= (((*(packetBody + pos) == RTMP_PACKET_TYPE_AUDIO) << 2)
|
|
|
|
|
| (*(packetBody + pos) == RTMP_PACKET_TYPE_VIDEO));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (pos + 11 + dataSize + 4 > nPacketLen)
|
|
|
|
@ -631,7 +628,7 @@ WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
RTMP_Log(RTMP_LOGDEBUG,
|
|
|
|
|
"FLV Packet: type %02X, dataSize: %lu, tagSize: %lu, timeStamp: %lu ms",
|
|
|
|
|
(unsigned char) packetBody[pos], dataSize, prevTagSize,
|
|
|
|
|
(unsigned char)packetBody[pos], dataSize, prevTagSize,
|
|
|
|
|
*nTimeStamp);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -669,8 +666,7 @@ WriteStream(char **buf, // target pointer, maybe preallocated
|
|
|
|
|
return ret; // no more media packets
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TFTYPE
|
|
|
|
|
controlServerThread(void *unused)
|
|
|
|
|
TFTYPE controlServerThread(void *unused)
|
|
|
|
|
{
|
|
|
|
|
char ich;
|
|
|
|
|
while (1)
|
|
|
|
@ -828,19 +824,19 @@ TFTYPE doServe(void *arg) // server sock and state (our listening sock)
|
|
|
|
|
/* UpdateBufferMS */
|
|
|
|
|
if (nType == 0x03)
|
|
|
|
|
{
|
|
|
|
|
char *ptr = ps.m_body+2;
|
|
|
|
|
char *ptr = ps.m_body + 2;
|
|
|
|
|
int id;
|
|
|
|
|
int len;
|
|
|
|
|
id = AMF_DecodeInt32(ptr);
|
|
|
|
|
/* Assume the interesting media is on a non-zero stream */
|
|
|
|
|
if (id)
|
|
|
|
|
{
|
|
|
|
|
len = AMF_DecodeInt32(ptr+4);
|
|
|
|
|
len = AMF_DecodeInt32(ptr + 4);
|
|
|
|
|
#if 1
|
|
|
|
|
/* request a big buffer */
|
|
|
|
|
if (len < BUFFERTIME)
|
|
|
|
|
{
|
|
|
|
|
AMF_EncodeInt32(ptr+4, ptr+8, BUFFERTIME);
|
|
|
|
|
AMF_EncodeInt32(ptr + 4, ptr + 8, BUFFERTIME);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
RTMP_Log(RTMP_LOGDEBUG, "%s, client: BufferTime change in stream %d to %d", __FUNCTION__,
|
|
|
|
@ -970,8 +966,7 @@ quit:
|
|
|
|
|
TFRET();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TFTYPE
|
|
|
|
|
serverThread(void *arg)
|
|
|
|
|
TFTYPE serverThread(void *arg)
|
|
|
|
|
{
|
|
|
|
|
STREAMING_SERVER *server = arg;
|
|
|
|
|
server->state = STREAMING_ACCEPTING;
|
|
|
|
@ -1029,7 +1024,7 @@ startStreaming(const char *address, int port)
|
|
|
|
|
|
|
|
|
|
tmp = 1;
|
|
|
|
|
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
|
|
|
|
(char *) &tmp, sizeof(tmp) );
|
|
|
|
|
(char *)&tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
|
|
addr.sin_family = AF_INET;
|
|
|
|
|
addr.sin_addr.s_addr = inet_addr(address); //htonl(INADDR_ANY);
|
|
|
|
@ -1050,7 +1045,7 @@ startStreaming(const char *address, int port)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server = (STREAMING_SERVER *) calloc(1, sizeof(STREAMING_SERVER));
|
|
|
|
|
server = (STREAMING_SERVER *)calloc(1, sizeof(STREAMING_SERVER));
|
|
|
|
|
server->sockfd = sockfd;
|
|
|
|
|
|
|
|
|
|
ThreadCreate(serverThread, server);
|
|
|
|
|