From: hyc Date: Mon, 2 Nov 2009 02:51:17 +0000 (+0000) Subject: SOCKS4 support from Monsieur Video X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82581d5734fb0f654aa0b0e8f1e02f29157cf4ed;p=rtmpdump SOCKS4 support from Monsieur Video git-svn-id: svn://svn.mplayerhq.hu/rtmpdump@19 400ebc74-4327-4243-bc38-086b20814532 --- diff --git a/rtmp.cpp b/rtmp.cpp index aaa39a8..14a5954 100644 --- a/rtmp.cpp +++ b/rtmp.cpp @@ -129,6 +129,7 @@ void CRTMP::SetupStream( int protocol, const char *hostname, unsigned int port, + const char *sockshost, const char *playpath, const char *tcUrl, const char *swfUrl, @@ -182,6 +183,20 @@ void CRTMP::SetupStream( Link.SWFSize = 0; } + if(sockshost) + { + const char *socksport = strchr(sockshost, ':'); + + Link.sockshost = strndup(sockshost, + socksport ? socksport - sockshost : strlen(sockshost)); + Link.socksport = socksport ? atoi(socksport + 1) : 1080; + Log(LOGDEBUG, "Connecting via SOCKS proxy: %s:%d", Link.sockshost, Link.socksport); + } else { + Link.sockshost = NULL; + Link.socksport = 0; + } + + Link.tcUrl = tcUrl; Link.swfUrl = swfUrl; Link.pageUrl = pageUrl; @@ -202,6 +217,24 @@ void CRTMP::SetupStream( Link.port = 1935; } +static bool add_addr_info(sockaddr_in* service, const char *hostname, int port) +{ + service->sin_addr.s_addr = inet_addr(hostname); + if (service->sin_addr.s_addr == INADDR_NONE) + { + struct hostent *host = gethostbyname(hostname); + if (host == NULL || host->h_addr == NULL) + { + Log(LOGERROR, "Problem accessing the DNS. (addr: %s)", hostname); + return false; + } + service->sin_addr = *(struct in_addr*)host->h_addr; + } + + service->sin_port = htons(port); + return true; +} + bool CRTMP::Connect() { if (!Link.hostname) return false; @@ -215,19 +248,16 @@ bool CRTMP::Connect() { sockaddr_in service; memset(&service, 0, sizeof(sockaddr_in)); service.sin_family = AF_INET; - service.sin_addr.s_addr = inet_addr(Link.hostname); - if (service.sin_addr.s_addr == INADDR_NONE) + + if (Link.socksport) { - struct hostent *host = gethostbyname(Link.hostname); - if (host == NULL || host->h_addr == NULL) - { - Log(LOGERROR, "Problem accessing the DNS. (addr: %s)", Link.hostname); - return false; - } - service.sin_addr = *(struct in_addr*)host->h_addr; + // Connect via SOCKS + if(!add_addr_info(&service, Link.sockshost, Link.socksport)) return false; + } else { + // Connect directly + if(!add_addr_info(&service, Link.hostname, Link.port)) return false; } - service.sin_port = htons(Link.port); m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_socket != -1) { @@ -240,6 +270,16 @@ bool CRTMP::Connect() { return false; } + if(Link.socksport) { + Log(LOGDEBUG, "%s ... SOCKS negotiation", __FUNCTION__); + if (!SocksNegotiate()) + { + Log(LOGERROR, "%s, SOCKS negotiation failed.", __FUNCTION__); + Close(); + return false; + } + } + Log(LOGDEBUG, "%s, ... connected, handshaking", __FUNCTION__); if (!HandShake()) { @@ -274,6 +314,35 @@ bool CRTMP::Connect() { return true; } +bool CRTMP::SocksNegotiate() { + char packet[255]; + sockaddr_in service; + memset(&service, 0, sizeof(sockaddr_in)); + + add_addr_info(&service, Link.hostname, Link.port); + unsigned long addr = htonl(service.sin_addr.s_addr); + + int len = snprintf(packet, sizeof packet, "%c%c%c%c%c%c%c%c%c", + 4, 1, // SOCKS 4, connect + (Link.port >> 8) & 0xFF, + (Link.port) & 0xFF, + (char) (addr >> 24) & 0xFF, (char) (addr >> 16) & 0xFF, + (char) (addr >> 8) & 0xFF, (char) addr & 0xFF, + 0); // NULL terminate + + WriteN(packet, len); + + if(ReadN(packet, 8) != 8) + return false; + + if(packet[0] == 0 && packet[1] == 90) { + return true; + } else { + Log(LOGERROR, "%s, SOCKS returned error code %d", packet[1]); + return false; + } +} + bool CRTMP::ConnectStream(double seekTime) { if (seekTime >= -2.0) Link.seekTime = seekTime; diff --git a/rtmp.h b/rtmp.h index 155a998..7a34f14 100644 --- a/rtmp.h +++ b/rtmp.h @@ -99,7 +99,10 @@ typedef struct //char SWFHashHMAC[32]; char SWFVerificationResponse[42]; - #endif + #endif + + const char *sockshost; + unsigned short socksport; } LNK; class CRTMP @@ -116,6 +119,7 @@ class CRTMP int protocol, const char *hostname, unsigned int port, + const char *sockshost, const char *playpath, const char *tcUrl, const char *swfUrl, @@ -164,6 +168,7 @@ class CRTMP protected: bool HandShake(bool FP9HandShake=true); bool RTMPConnect(); + bool SocksNegotiate(); bool SendConnectPacket(); bool SendServerBW(); diff --git a/rtmpdump.cpp b/rtmpdump.cpp index bca1db4..369d49b 100644 --- a/rtmpdump.cpp +++ b/rtmpdump.cpp @@ -874,6 +874,7 @@ int main(int argc, char **argv) char *swfHash = 0; uint32_t swfSize = 0; char *flashVer = 0; + char *sockshost = 0; char *flvFile = 0; @@ -900,6 +901,7 @@ int main(int argc, char **argv) {"help", 0, NULL, 'h'}, {"host", 1, NULL, 'n'}, {"port", 1, NULL, 'c'}, + {"socks", 1, NULL, 'S'}, {"protocol",1, NULL, 'l'}, {"playpath",1, NULL, 'y'}, {"rtmp", 1, NULL, 'r'}, @@ -926,7 +928,7 @@ int main(int argc, char **argv) {0,0,0,0} }; - while((opt = getopt_long(argc, argv, "hVveqzr:s:t:p:a:f:o:u:n:c:l:y:m:k:d:A:B:w:x:", longopts, NULL)) != -1) { + while((opt = getopt_long(argc, argv, "hVveqzr:s:t:p:a:f:o:u:n:c:l:y:m:k:d:A:B:w:x:S:", longopts, NULL)) != -1) { switch(opt) { case 'h': LogPrintf("\nThis program dumps the media content streamed over rtmp.\n\n"); @@ -934,6 +936,7 @@ int main(int argc, char **argv) LogPrintf("--rtmp|-r url URL (e.g. rtmp//hotname[:port]/path)\n"); LogPrintf("--host|-n hostname Overrides the hostname in the rtmp url\n"); LogPrintf("--port|-c port Overrides the port in the rtmp url\n"); + LogPrintf("--socks|-S host:port Use the specified SOCKS proxy\n"); LogPrintf("--protocol|-l Overrides the protocol in the rtmp url (0 - RTMP, 3 - RTMPE)\n"); LogPrintf("--playpath|-y Overrides the playpath parsed from rtmp url\n"); LogPrintf("--swfUrl|-s url URL to player swf file\n"); @@ -1095,6 +1098,9 @@ int main(int argc, char **argv) case 'z': debuglevel = LOGALL; break; + case 'S': + sockshost = optarg; + break; default: LogPrintf("unknown option: %c\n", opt); break; @@ -1177,7 +1183,7 @@ int main(int argc, char **argv) memset(buffer, 0, bufferSize); CRTMP *rtmp = new CRTMP(); - rtmp->SetupStream(protocol, hostname, port, playpath, tcUrl, swfUrl, + rtmp->SetupStream(protocol, hostname, port, sockshost, playpath, tcUrl, swfUrl, pageUrl, app, auth, swfHash, swfSize, flashVer, subscribepath, dSeek, bLiveStream, timeout);