After a bit of research I altered stock RTMPDump 2.4 to handle the MyFreeCams challenge/response system. More accurately, it's librtmp that is added to, since all rtmp/amf stuff really takes place there.
The patch comes with the following caveats:
- It only works on *public rooms*.
- You must have a socket connection to the chatserver *from the same IP* when you run RTMPDump. You can close it once you've latched onto the stream.
- It sometimes fails to create the stream for no apparent reason. This is due to the fact that the "real" Flash client sends the subscribe/play in an Invoke of UpdateSession() from the server, whereas RTMPDump sends it immediately. To change this would require altering the basic way librtmp and RTMPDump work.
- It assumes you've listened to the proper events and mapped camserv to videoserver as well as obtained a guest Session ID.
- Output files still have broken timestamps, but a quick run through FFMpeg to transcode to your favorite container and codec will fix this without loss of parts or sped-up video anywhere. Audio is usually well synchronized.
Here it is:
Code:
diff -rupN diffrtmp/Makefile librtmp/Makefile
--- diffrtmp/Makefile 2013-04-28 20:18:42.000000000 -0400
+++ librtmp/Makefile 2013-04-28 19:59:47.000000000 -0400
@@ -24,7 +24,7 @@ DEF_GNUTLS=-DUSE_GNUTLS
DEF_=-DNO_CRYPTO
REQ_GNUTLS=gnutls
REQ_OPENSSL=libssl,libcrypto
-LIBZ=-lz
+LIBZ=-lz -lm
LIBS_posix=
LIBS_darwin=
LIBS_mingw=-lws2_32 -lwinmm -lgdi32
diff -rupN diffrtmp/rtmp.c librtmp/rtmp.c
--- diffrtmp/rtmp.c 2013-04-28 20:18:42.000000000 -0400
+++ librtmp/rtmp.c 2013-04-28 20:01:46.000000000 -0400
@@ -28,6 +28,7 @@
#include <string.h>
#include <assert.h>
#include <time.h>
+#include <math.h>
#include "rtmp_sys.h"
#include "log.h"
@@ -2904,6 +2905,33 @@ static const AVal av_NetStream_Publish_S
static const AVal av_NetConnection_Connect_Rejected =
AVC("NetConnection.Connect.Rejected");
+/* MyFreeCams challenge/response */
+static int HandleMfcChallenge(RTMP *r,int txn,int key) {
+ RTMPPacket packet;
+ char pbuf[1024],*pend=pbuf+sizeof(pbuf);
+ char auth[256],*enc;
+ AVal av;
+
+ RTMP_Log(RTMP_LOGINFO,"Responding to MFC challenge");
+ snprintf(auth,sizeof(auth),"%d",(int)floor(sqrt((double)key)*4));
+ av.av_val=strdup(auth);
+ av.av_len=strlen(auth);
+ packet.m_nChannel=0x03;
+ packet.m_headerType=RTMP_PACKET_SIZE_MEDIUM;
+ packet.m_packetType=RTMP_PACKET_TYPE_INVOKE;
+ packet.m_nTimeStamp=0;
+ packet.m_nInfoField2=0;
+ packet.m_hasAbsTimestamp=0;
+ packet.m_body=pbuf+RTMP_MAX_HEADER_SIZE;
+ enc=packet.m_body;
+ enc=AMF_EncodeString(enc,pend,&av__result);
+ enc=AMF_EncodeNumber(enc,pend,(double) txn);
+ *enc++=0;
+ enc=AMF_EncodeString(enc,pend,&av);
+ packet.m_nBodySize=enc-packet.m_body;
+ return RTMP_SendPacket(r,&packet,FALSE);
+}
+
/* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */
static int
HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
@@ -2912,6 +2940,10 @@ HandleInvoke(RTMP *r, const char *body,
AVal method;
double txn;
int ret = 0, nRes;
+ AMFObject mfcobj;
+ int challenge;
+ AVal av;
+
if (body[0] != 0x02) /* make sure it is a string method name we start with */
{
RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet",
@@ -2931,6 +2963,16 @@ HandleInvoke(RTMP *r, const char *body,
txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1));
RTMP_Log(RTMP_LOGDEBUG, "%s, server invoking <%s>", __FUNCTION__, method.av_val);
+ av.av_val=strdup("key");
+ av.av_len=3;
+ if (!strcmp(method.av_val,"loginResult")) {
+ RTMP_Log(RTMP_LOGINFO,"MFC server sent challenge");
+ AMFProp_GetObject(AMF_GetProp(&obj,NULL,3),&mfcobj);
+ challenge=(int)AMFProp_GetNumber(AMF_GetProp(&mfcobj,&av,-1));
+ HandleMfcChallenge(r,txn,challenge);
+ return 1;
+ }
+
if (AVMATCH(&method, &av__result))
{
AVal methodInvoked = {0};
Put the above in a patchfile, say, mfc.patch, in the librtmp-directory (important! not in the rtmpdump directory) and run patch -p1 < mfc.patch, go up one level and make.
You still need to call RTMPDump with the appropriate parameters, as following:
Code:
rtmpdump -r rtmp://video434.myfreecams.com/NxServer -C S:42805804 -C S:'' -C S:102668880 -C S:DOWNLOAD -C S:2668880 -y mfc_102668880 -v -o CrumpetsNdTea_42805804.flv
I realize that this may not be terribly useful to *most* people, it's very rough around the edges, work in progress and so on. I also have a Flash-authored viewer that works flawlessly because it can emulate the "real" MFC client much more closely, but it's also fairly useless as a headless, unmonitored tool.
Why am I posting this? I'm not adverse to creating a more user-friendly tool but I have a job and like to not do much of anything in my spare time, so I'm hoping to be approached by some industrious people who have some knowledge of MFC and are willing to help out.
E.