88using System . Security . Principal ;
99using Newtonsoft . Json . Linq ;
1010
11+
12+ using System . Collections . Generic ;
13+ using System . Net . Http ;
14+ using System . Threading . Tasks ;
15+ using Newtonsoft . Json ;
16+
1117namespace BrowserStack
1218{
1319 public enum LocalState { Idle , Connecting , Connected , Error , Disconnected } ;
@@ -16,7 +22,11 @@ public class BrowserStackTunnel : IDisposable
1622 {
1723 static readonly string uname = Util . GetUName ( ) ;
1824 static readonly string binaryName = GetBinaryName ( ) ;
19- static readonly string downloadURL = "https://www.browserstack.com/local-testing/downloads/binaries/" + binaryName ;
25+
26+ static readonly string userAgent = "" ;
27+ static readonly string sourceUrl = null ;
28+ private bool isFallbackEnabled = false ;
29+ private Exception downloadFailureException = null ;
2030
2131 static readonly string homepath = ! IsWindows ( ) ?
2232 Environment . GetFolderPath ( Environment . SpecialFolder . Personal ) :
@@ -41,7 +51,7 @@ static bool IsDarwin(string osName)
4151 {
4252 return osName . Contains ( "darwin" ) ;
4353 }
44-
54+
4555
4656 static bool IsWindows ( )
4757 {
@@ -102,8 +112,9 @@ public virtual void addBinaryArguments(string binaryArguments)
102112 this . binaryArguments = binaryArguments ;
103113 }
104114
105- public BrowserStackTunnel ( )
115+ public BrowserStackTunnel ( string userAgent )
106116 {
117+ userAgent = userAgent ;
107118 localState = LocalState . Idle ;
108119 output = new StringBuilder ( ) ;
109120 }
@@ -121,7 +132,7 @@ public virtual void fallbackPaths()
121132 public void modifyBinaryPermission ( )
122133 {
123134 if ( ! IsWindows ( ) )
124- {
135+ {
125136 try
126137 {
127138 using ( Process proc = Process . Start ( "/bin/bash" , $ "-c \" chmod 0755 { this . binaryAbsolute } \" ") )
@@ -143,16 +154,59 @@ public void modifyBinaryPermission()
143154 }
144155 }
145156
146- public void downloadBinary ( )
157+ private string fetchSourceUrl ( string accessKey )
158+ {
159+ var url = "https://local.browserstack.com/binary/api/v1/endpoint" ;
160+
161+ using ( var client = new HttpClient ( ) )
162+ {
163+ var data = new Dictionary < string , object >
164+ {
165+ { "auth_token" , accessKey }
166+ } ;
167+ client . DefaultRequestHeaders . Add ( "Content-Type" , "application/json" ) ;
168+ client . DefaultRequestHeaders . Add ( "user-agent" , userAgent ) ;
169+
170+ if ( isFallbackEnabled )
171+ {
172+ data [ "error_message" ] = downloadFailureException . Message ;
173+ client . DefaultRequestHeaders . Add ( "X-Local-Fallback-Cloudflare" , "true" ) ;
174+ }
175+
176+ string jsonData = JsonConvert . SerializeObject ( data ) ;
177+ var content = new StringContent ( jsonData , Encoding . UTF8 , "application/json" ) ;
178+
179+ HttpResponseMessage response = await client . PostAsync ( url , content ) ;
180+
181+ response . EnsureSuccessStatusCode ( ) ;
182+
183+ string responseString = await response . Content . ReadAsStringAsync ( ) ;
184+
185+ dynamic jsonResponse = JsonConvert . DeserializeObject ( responseString ) ;
186+
187+ Console . WriteLine ( "Response JSON:" ) ;
188+ Console . WriteLine ( jsonResponse ) ;
189+
190+ if ( jsonResponse . error != null )
191+ {
192+ throw new Exception ( jsonResponse . error ) ;
193+ }
194+ return jsonResponse . data . endpoint ;
195+ }
196+ }
197+
198+ public void downloadBinary ( string accessKey )
147199 {
148200 string binaryDirectory = Path . Combine ( this . binaryAbsolute , ".." ) ;
149201 //string binaryAbsolute = Path.Combine(binaryDirectory, binaryName);
150202
203+ string sourceDownloadUrl = fetchSourceUrl ( accessKey ) ;
204+
151205 Directory . CreateDirectory ( binaryDirectory ) ;
152206
153207 using ( var client = new WebClient ( ) )
154208 {
155- client . DownloadFile ( downloadURL , this . binaryAbsolute ) ;
209+ client . DownloadFile ( sourceDownloadUrl + "/" + binaryName , this . binaryAbsolute ) ;
156210 }
157211
158212 if ( ! File . Exists ( binaryAbsolute ) )
@@ -163,7 +217,7 @@ public void downloadBinary()
163217 modifyBinaryPermission ( ) ;
164218 }
165219
166- public virtual void Run ( string accessKey , string folder , string logFilePath , string processType )
220+ public virtual void Run ( string accessKey , string folder , string logFilePath , string processType , bool fallbackEnabled , Exception failureException )
167221 {
168222 string arguments = "-d " + processType + " " ;
169223 if ( folder != null && folder . Trim ( ) . Length != 0 )
@@ -176,7 +230,9 @@ public virtual void Run(string accessKey, string folder, string logFilePath, str
176230 }
177231 if ( ! File . Exists ( binaryAbsolute ) )
178232 {
179- downloadBinary ( ) ;
233+ isFallbackEnabled = fallbackEnabled ;
234+ downloadFailureException = failureException ;
235+ downloadBinary ( accessKey ) ;
180236 }
181237
182238 if ( process != null )
0 commit comments