Modify Headers In Selenium test framework - c#

I'm trying to create an automated test framework using specflow and selenium and I need to pass basic auth, as well as x-forwarded-for header information to the browser for some of the tests. I see solutions for Browser mob proxy but it seems like that project is dead. I tried using Titanium Proxy but I'm having a heck of a time getting it to work. I'm mostly having trouble understanding what I need to do with certificates to get my webdriver to use the proxy and load the sites without fussing. Currently I can't get it to open http or https sites. When I run my test case I can see that the browser is correctly setting the proxy so I don't think that's the case. I left commented out code for things I tried to do to set a certificate but I'm not 100% sure what I'm actually doing there. Any help would be appreciated.
Alternatively if there is a better, easier way to add headers to a request I'm all ears.
public class ProxyService
{
private ProxyServer server;
public int port { get; }
public ProxyService(int port)
{
this.server = new ProxyServer();
//server.CertificateManager.CreateServerCertificate("rootCert.pfx");
//server.CertificateManager.LoadRootCertificate();
//server.CertificateManager.CertificateEngine = Titanium.Web.Proxy.Network.CertificateEngine.BouncyCastle;
//server.CertificateManager.TrustRootCertificate(true);
//server.CertificateManager.EnsureRootCertificate(true,true,false);
this.port = port;
}
public void AddHeader(string key, string value)
{
}
private async Task OnRequest(object sender, SessionEventArgs e) => await Task.Run(
() =>
{
e.HttpClient.Request.Headers.AddHeader("Authorization", "Basic xxxxxxxxxx");
});
public void Start()
{
var endpoint = new ExplicitProxyEndPoint(System.Net.IPAddress.Any, port, true);
server.AddEndPoint(endpoint);
server.Start();
server.BeforeRequest += OnRequest;
}
public void Stop()
{
server.Stop();
}
}

Related

Web Socket Cannot send message and disconnected from Game Lift

I developed a game lift back-end server using a websocket sharp. The local test function provided by GameLift worked fine, but Web socket communication is not possible with the game session of Fleet created by the GameLift server.
To be exact, the connection is initially shown on the client as successful, but it is said that the connection was immediately disconnected. And even if the connection is marked as successful, no messages reach the server.
I wonder if there is anything I need to communicate with the AWS game lift server using a web socket. Please help me.
Fleet type : spot instance
Not use TLS
EC2 Port was set as |2022|TCP|0.0.0.0/0
Client Code for Connection
public static void AddService(string hostName, int port, string serviceName, WebSocketClientSession socketSession, bool overTls = false)
{
Dictionary<string, WebSocket> serviceMap = _instance.mServiceMap;
string uri = overTls
? $"wss://{hostName}:{port}/{serviceName}"
: $"ws://{hostName}:{port}/{serviceName}";
Debug.Log(uri);
WebSocket webSocket = new WebSocket(uri);
if (overTls)
{
webSocket.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls;
}
webSocket.OnOpen += socketSession.OnOpen;
webSocket.OnClose += socketSession.OnClose;
webSocket.OnMessage += socketSession.OnMessage;
webSocket.OnError += socketSession.OnError;
serviceMap[serviceName] = webSocket;
}
public static async void ConnectAsync(string serviceName, Action<bool> onCompleted)
{
Dictionary<string, WebSocket> serviceMap = _instance.mServiceMap;
WebSocket webSocket = serviceMap[serviceName];
await Task.Run(webSocket.Connect);
if (webSocket.IsAlive)
{
// webSocket.EmitOnPing = true;
onCompleted?.Invoke(true);
return;
}
onCompleted?.Invoke(false);
}
Server Code for listening
public static void StartServer()
{
_instance.mServer.Start();
_instance.mHasStarted = true;
}
public static void StopServer()
{
_instance.mServer.Stop();
_instance.mHasStarted = false;
}
public static void AddService<T>(string serviceName) where T : WebSocketServerSession, new()
{
WebSocketServer server = _instance.mServer;
server.AddWebSocketService<T>($"/{serviceName}");
}
public static void RemoveService(string serviceName)
{
WebSocketServer server = _instance.mServer;
server.RemoveWebSocketService($"/{serviceName}");
}
At first, communication was attempted using TCP and UDP, but the same phenomenon occurred as a web socket.
Various searches and attempts were made for a week, but there was no harvest. There were so few questions about the game lift that there were no similar cases.
Even if it is not a game lift service, I would like to know if there are additional elements necessary for AWS connection.
It could be lots of different things. TLS mismatches, WebSocket parameter negotiation mismatches, authentication etc.
I'd suggest digging deeper into what is happening on the wire. Hopefully, it'll make things clearer, and lead you to a solution.
A Man-In-The-Middle proxy, like Burp, would be able to see into the HTTP connection, and the follow-up WebSocket negotiation. All you need to do is point your app at it via the proxy settings, and install the Burp CA certificate into your app platform (so it can intercept the TLS).
Otherwise, if that's not an option, you can always use Wireshark (though you won't be able to see inside the TLS).

0xC0000008: An invalid handle was specified in Hololens 2 using NetQM

I'm trying to send some data to a Python server through a ZMQ Socket. The Python server creates a socket using ZMQ as well.
```lang-python
print("Connecting with Unity Toolkit...")
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind('tcp://*:5555')
while True:
request = socket.recv_multipart()
print("Somethings received");
req = json.loads(request[1])
print("Received from Unity Toolkit: ", req)
```
I've tried to communicate with that server using a Python ZMQ client and it works, but when I try to do it with the .NET ZMQ library inside of an Unity 3D project, there is an exception that I don't know how to handle. The NETQMClient I was given (this is legacy code from an older project, but I'm allowed to change it) does something like this:
```lang-csharp
//this lines are executed using a Thread()
AsyncIO.ForceDotNet.Force();
requestSocket = new RequestSocket();
requestSocket.Connect("tcp://192.162.0.104:5555");
isAvailable = true;
while (!clientStopped){
//Debug.Log("Continuing");
}
requestSocket.Close();
NetMQConfig.Cleanup();
//end of the function running on a thread
//...
//later, when a button is pressed
try {
//endpoint is a one-character string that
//the server uses as a cue for something
requestSocket.SendMoreFrame(endpoint);
requestSocket.SendFrame(request); //this a class turned into a JSON using JsonUtility.ToJson
} catch (System.Exception) {
Debug.Log("Something went wrong");
throw;
}
```
Later the C# script waits for a response and I handle that response and use it. The thing is that I've tested it running the client and the server in the same computer and it works. HOWEVER, when I deploy the project into the real Hololens 2 (where the NETQM client runs), I get this error in Visual Studio.
I added the try catch block to see if there was some strange behaviour but there is no Exception in that point. Any hints on the right directions are appreciated.
EDIT: Whole Scripts used in this project for replicating the bug.
This class holds the data that will later be converted to JSON
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class Serialization {
public int numPanels;
public bool colorHarmony;
public float colorfulness;
[Serializable]
public Request(int numPanels, bool colorHarmony, float colorfulness) {
this.numPanels = numPanels;;
this.colorHarmony = colorHarmony;
this.colorfulness = colorfulness;
}
}
This is the script with the ZMQ logic
using System.Collections.Generic;
using System.Threading;
using NetMQ;
using NetMQ.Sockets;
using UnityEngine;
public class PythonNetworking {
private bool clientStopped;
private RequestSocket requestSocket;
private byte[] frame;
// for now only one request at a time is supported
public string requestResult;
private bool isAvailable;
public PythonNetworking() {
clientStopped = false;
var clientThread = new Thread(NetMQClient);
clientThread.Start();
}
public void StopClient() {
clientStopped = true;
}
// ReSharper disable once InconsistentNaming
private void NetMQClient() {
AsyncIO.ForceDotNet.Force();
requestSocket = new RequestSocket();
// Computer running the server which must receive the info
requestSocket.Connect("tcp://192.168.0.104:5555");
isAvailable = true;
while (!clientStopped)
{
//Debug.Log("Continuing");
}
requestSocket.Close();
NetMQConfig.Cleanup();
}
public void SetFrame(byte[] currFrame) {
frame = currFrame;
}
// Create queue of requests in case multiple have to be handled
private void SimpleRequest(string endpoint, string request) {
// wait until socket is available
while (!isAvailable) {
//Debug.Log("Socket unavailable");
}
isAvailable = false;
if (request == null) {
requestSocket.SendFrame(endpoint);
} else {
Debug.Log("Sending to Python server: " + request);
try
{
requestSocket.SendMoreFrame(endpoint);
Debug.Log("SendMoreFrame called");
requestSocket.SendFrame(request);
Debug.Log("SendFrame called");
}
catch (System.Exception)
{
Debug.Log("Something went wrong");
throw;
}
}
var msg = requestSocket.ReceiveFrameBytes();
Debug.Log("ReceiveFrameBytes returned a value");
isAvailable = true;
requestResult = System.Text.Encoding.UTF8.GetString(msg);
}
public void PerformRequest(string endpoint, string request) {
requestResult = null;
var requestThread = new Thread(() => SimpleRequest(endpoint, request));
requestThread.Start();
}
}
This is the script making the request when an event is triggered:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.UI;
using Newtonsoft.Json;
public class MyTool: MonoBehaviour {
private PythonNetworking pythonNetworking;
public struct PanelConstraints {
public string name;
public float height;
public float width;
}
public void Start() {
pythonNetworking = new PythonNetworking();
Debug.Log("Tool initialized!");
//called here for debugging purposes, this method is called when a button is pressed
SubmitConstraints();
}
//When a button is pressed
public void SubmitConstraints() {
Debug.Log("Submitting constraints...");
StartCoroutine(CreateRequest("P"));
}
private IEnumerator CreateRequest(string type) {
Serialization.Request request = new Serialization.Request(1, false, 1.0f);
var requestJson = JsonUtility.ToJson(request);
pythonNetworking.PerformRequest(type, requestJson);
yield return new WaitUntil(() => pythonNetworking.requestResult != null);
if (type == "P") {
panelData = JsonConvert.DeserializeObject<List<string>>(pythonNetworking.requestResult);
}
}
}
Finally, the Python server code is:
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind('tcp://*:5555')
while True:
request = socket.recv_multipart()
print("Somethings received");
req = json.loads(request[1])
#Data is processed
As per the setup, I'm using Unity 2019.4.26f1, I create a 3D scene, I add a GameObject to it, I attach the script MyTool.cs to it and I attach a button under the previous GameObject. On clicking the button, the SubmitContrainst() method is called (now called automatically in Start() for debugging purposes). This scene is deployed in the Hololens 2 using Visual Studio 2019 (although I've tried to run it in the Game Mode, communicating with a different computer to recreate the deployment environment, that is, with the client and the server in different devices and with different implementations of the library). When the application is about to start in the Hololens, the exception I introduced previously (see screenshot) is thrown. The Python server, running with Python version 3.10.4, doesn't receive anything. TCP communication seems to work, since when I run two Python scripts in different hosts performing client/server communication with ZMQ (using REQ and REP), it works, but I get the feeling this communication doesn't work on the Hololens 2. But this feels very strange because I've managed to communicate the Hololens 2 with another device (using another library, Windows.Networking.Socket).
Would you navigate to [Unity] -> [Player Settings] -> [Publishing Settings] to check the Capability of your project and make sure Internet Client or Internet Client Server is enabled according to the purpose. It can also be reviewed and modified in the manifest file of C# project.
The code around the thrown exception is more like Unity generated, you need to add break point to see if this issue is caused by a failed socket connection.
In addtion, you may also refer to the discussion on Web Socket Client Disconnecting Exception Being Thrown in UWP Builds - Unity Forum.

HttpListener returns bad request 400

I have the next problem. I have a windows service written in c# using HttpListener. The code of my server class:
public class SoaphttpServer
{
private HttpListener _listener;
private readonly IniFile _settings;
public bool Terminated { get; private set; }
public void Terminate()
{
Terminated = true;
Common.Cts.Cancel();
}
public SoaphttpServer()
{
_settings = Common.ReadSettings();
Terminated = false;
ServicePointManager.DefaultConnectionLimit = 500;
ServicePointManager.Expect100Continue = false;
ServicePointManager.MaxServicePoints = 500;
}
public void StartServer()
{
try
{
Common.Cts = new CancellationTokenSource();
_listener = new HttpListener();
_listener.Prefixes.Add("http://*:8012/");
_listener.Start();
while (!Terminated)
{
IAsyncResult result = _listener.BeginGetContext(ListenerCallback, _listener);
while (!result.AsyncWaitHandle.WaitOne(1000))
{
if (Terminated) break;
}
}
}
catch (Exception ex)
{
Log.Write("StartServer: " + ex.Message);
}
}
public static async void ListenerCallback(IAsyncResult result)
{
Log.Write("new connection");
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
SoapHttpClient client = new SoapHttpClient(context);
await client.SomeFuncAsync();
}
~SoaphttpServer()
{
if (_listener == null) return;
_listener.Stop();
_listener.Close();
}
}
In command line i executed next command:
netsh http add urlacl url="http://*:8012/" user="NETWORK SERVICE"
Everything works well from all places. I can accept connection from broweser, or from delphi programm using IdHTTP. But when i'm trying to connect from one programm (i have no code from this program), written in delphi to my service i'm getting in this programm: "HTTP/1.1 400 Bad Request". Previous version of this programm worked well with my service. I know that there were no changes in communication protocol in this programm. I found out using Wireshark that GET packet comes to my computer, but, as i think HttpListener forming this response (bad request) and sending back it without me. What can be the problem? Maybe i can ovverride some methods of HttpListener and look at incoming request from this prog and find out what is wrong where?
Upd. I have found out that HttpListener is sealed class. How can i find a trouble place?
Thanks everyone! I have found the solution.
It's all because by default HttpListener can't parse GET-requests with length more than 255 symbols.
To solve this problem you need steps:
Add to HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/services/HTTP/Parameters DWORD (32 bits) key and name it "UrlSegmentMaxLength" and set value = 0.
Next you need to restart http service:
net start http
net stop http
And that's all! Everything works well!

XSockets Client Connecting But Not Receiving Messages

I'm trying to set up a specific scenario but, obviously, I'm having problems. My server is a site that primarily hosts a WCF service but I want to add an XSockets host there as well. I have the standard code in the bootstrap code file as per the instructions in the readme.txt. Upon a client connection, I am starting a worker thread which is basically a heartbeat that the client will monitor. The relevant code from the controller is as follows:
public class HeartbeatController : XSocketController
{
public void AddMessage(string message)
{
this.SendToAll(message, "addMessage");
}
}
Within my worker thread I am calling this:
string message = String.Format("pump", Math.Round(cpuCounter.NextValue());
ClientPool connection = ClientPool.GetInstance("ws://mywebsite:4502/HeartbeatController", "*");
connection.Send(message, "addMessage");
Currently I'm testing this with a console client which looks like this:
class Program
{
static XSocketClient socketClient;
static void Main(string[] args)
{
Console.WriteLine("Starting client...");
string url = "ws://mywebsite:4502/HeartbeatController";
socketClient = new XSocketClient(url, "*");
socketClient.OnOpen += socketClient_OnOpen;
socketClient.Open();
while (true)
{
// let it sit and display the "pump" messages
string input = Console.ReadLine();
if (input.Equals("Q", StringComparison.Ordinal))
{
break;
}
}
}
static void socketClient_OnOpen(object sender, EventArgs e)
{
Console.WriteLine("socketClient Opened");
socketClient.Bind("addMessage", OnAddMessage);
}
private static void OnAddMessage(ITextArgs textArgs)
{
Console.WriteLine("AddMessage :: {0}", textArgs.data);
}
}
On the client, if I put a breakpoint in the socketClient_OnOpen method it gets hit so I think it is connecting. But the pump message never makes it to the client.
Two Questions:
Is there anything obvious that I'm missing?
(Unrelated) Since many enterprises really don't like punching holes in their firewalls, is there any way to use port 80 with this setup (so that the client connection would look like "ws://mywebsite/HeartbeatController")?
Thanks for any help!
So to see what your pump actually was sending in to the server I added a custom pipeline.
public class MyPipeline : XSocketPipeline
{
//Incomming textmessage
public override void OnMessage(IXSocketController controller, ITextArgs e)
{
Console.WriteLine("IN " + e.data);
//Let the message continue into the server
base.OnMessage(controller, e);
}
//Outgoing textmessage
public override ITextArgs OnSend(IXSocketProtocol protocol, ITextArgs e)
{
Console.WriteLine("OUT " + e.data);
return base.OnSend(protocol, e);
}
}
Since I then saw that you was sending in a string that actually did not have a property named "message". The actionmethod "AddMessage" expects you to pass in a property message of type string. So you can solve this in two ways, both of them are simple.
Just replace the string parameter in the AddMessage with ITextArgs
public void AddMessage(ITextArgs message)
or...
Pass in a object from your worker thread instead of a string like this
connection.Send(new {message}, "addMessage");
So all you need to do to get it to work is to change this row
connection.Send(message, "addMessage");
with this row
connection.Send(new {message}, "addMessage");
EDIT: Btw, 4.0 is on the way and the client will be very much improved as well as the serverside stuff.

Synchronizing collections and aborting tasks

I am writing a small multi-threaded network server. All classical stuff: it listens for incoming connections, accepts them and then serves them in different threads. Also, this server sometimes will have to restart, and to do so it must a) stop listening, b) kick out all connected clients, c) adjust some settings/wait, d) resume listening.
Well, I pretty much don't know a thing about developing multi-threaded programs, so I am looking for help. Here's what I came to (core stuff only):
class Server
{
class MyClient
{
Server server;
TcpClient client;
bool hasToFinish = false;
public MyClient(Server server, TcpClient client)
{
this.server = server;
this.client = client;
}
public void Go()
{
while (!hasToFinish)
{
// do all cool stuff
}
CleanUp();
}
private void CleanUp()
{
// finish all stuff
client.Close();
server.myClients.Remove(this);
}
public void Finish()
{
hasToFinish = true;
}
}
bool running = false;
TcpListener listener;
HashSet<MyClient> myClients = new HashSet<MyClient>();
public void Start()
{
if (running)
return;
myClients.Clear();
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
listener.Start();
listener.BeginAcceptTcpClient(AcceptClient, this);
running = true;
}
public void Stop()
{
if (!running)
return;
listener.Stop();
foreach (MyClient client in myClients)
{
client.Finish();
}
myClients.Clear();
running = false;
}
public void AcceptClient(IAsyncResult ar)
{
MyClient client = new MyClient(this, ((TcpListener)ar.AsyncState).EndAcceptTcpClient(ar));
myClients.Add(client);
client.Go();
}
}
It's absolutely unsatisfactory. There is no sychronizing (I just don't know where to put it!), and calling Server.Stop() doesn't make MyClient-s to stop immediately. How do I fix these problems?
The code looks quite clean, we can make it thread-safe with simple modifications.
There are three parts of the problem, the "client", the "server" and the client-server interaction.
Client first, the Go() method is invoked by one thread (let's call it A) and the Finish() method is invoke by another thread (B). When thread B modify hasToFinish field, thread A may not see the modification immediately because the variable may be cached in the CPU cache. We can fix it by making hasToFinish field "volatile", which force thread B to publish the variable change to thread A when update.
Now the server class. I recommend you to synchronise three methods on the "Server" instance like the example below. It makes sure Start and Stop are called sequentially and the variables they changes are published across threads.
The client-server interaction need to be addressed as well. In your code, Client remove its reference from the Server but the server clear all clients references when Finish() any way. It looks redundant to me. If we can remove the part of code in client, we have nothing to worry about. If you choose to keep the logic in the client rather in the server for what ever reason, create a public method call RemoveClient(Client client) in the Server class and synchronise it against the Server instance. Then let the client to invoke this method instead of manipulating the HashSet directly.
I hope this solve your problem.
public void Start()
{
lock(this)
{
if (running)
return;
myClients.Clear();
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
listener.Start();
listener.BeginAcceptTcpClient(AcceptClient, this);
running = true;
}
}
public void Stop()
{
lock(this)
{
if (!running)
return;
listener.Stop();
foreach (MyClient client in myClients)
{
client.Finish();
}
myClients.Clear();
running = false;
}
}
public void AcceptClient(IAsyncResult ar)
{
lock(this)
{
MyClient client = new MyClient(this, ((TcpListener)ar.AsyncState).EndAcceptTcpClient(ar));
myClients.Add(client);
client.Go();
}
}

Categories

Resources