]> granicus.if.org Git - rtmpdump/commitdiff
SOCKS4 support from Monsieur Video
authorhyc <hyc@400ebc74-4327-4243-bc38-086b20814532>
Mon, 2 Nov 2009 02:51:17 +0000 (02:51 +0000)
committerhyc <hyc@400ebc74-4327-4243-bc38-086b20814532>
Mon, 2 Nov 2009 02:51:17 +0000 (02:51 +0000)
git-svn-id: svn://svn.mplayerhq.hu/rtmpdump@19 400ebc74-4327-4243-bc38-086b20814532

rtmp.cpp
rtmp.h
rtmpdump.cpp

index aaa39a8f969877b32c26bc0367283fc2773a278d..14a5954020da621ed2529de7c7349b253de1b85b 100644 (file)
--- 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 155a998b9c666fe3e52dd4579283eac26b2908d5..7a34f14e987cf954bf45b4661fcd5625cdf196a1 100644 (file)
--- 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();
index bca1db4e3925fbeff15fb2589308e221b8da2d3d..369d49b6a84539c4c53161739a0c1d14c1d71003 100644 (file)
@@ -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);