I'm having trouble with a proxy server which won't accept the authentication details my application is offering it. Here is what I'm doing:
private bool DoLoginTest(WebProxy wp = null)
{
if(MMremotingClient.LoginWCP(wp) == AdminNetworkFlags.CLIENTPOS)
{
FL.Log("Test licensing server connection REM finished");
FL.Log("Connection could be established successfully");
MMremotingClient.DoTask(BitConverter.GetBytes((int)AdminNetworkFlags.CLIENTEND), "Nothing");
MMremotingClient.DisableFLogging();
Invoke(txtDelegate, " finished\r\n");
return true;
}
else
{
FL.Log("Test server connection failed!");
FL.Log("NoTask");
Invoke(txtDelegate, " failed\r\n");
Invoke(MBDelegate, "Could not reach the licencing server. Please make sure that no firewall is blocking port 80, or that your computer is allowed to access the internet.");
return false;
}
}
In a series of tests, i try to connect to a server with the old remoting protocol (upgrade to WCF not possible atm). If the DoLoginTest Method fails, the user will see a little form where he can enter the proxy details which get injected into the HTTPClientChannel object. Then another try to connect to the Server is made.
public static AdminNetworkFlags LoginWCP(WebProxy wProx = null)
{
FileLogger.Log("MMLC: LoginWCP");
Register(wProx);
return Login();
}
private static void Register(WebProxy iwp = null)
{
FileLogger.Log("MMLC: Register");
try
{
IDictionary props = new Hashtable();
if(iwp == null)
{
props["useDefaultCredentials"] = true;
}
else
{
NetworkCredential nc = (NetworkCredential)iwp.Credentials;
if(nc != null)
{
props["domain"] = nc.Domain ?? null;
props["password"] = nc.Password;
props["username"] = nc.UserName;
props["useDefaultCredentials"] = false;
}
else
{
props["domain"] = null;
props["password"] = "1234";
props["username"] = "u.name";
props["useDefaultCredentials"] = false;
}
}
ServicePointManager.Expect100Continue = false;
HttpChan = new HttpClientChannel(props, new BinaryClientFormatterSinkProvider());
SetChannelProxy(HttpChan, iwp ?? WebRequest.GetSystemWebProxy());
FileLogger.Log("MMLC: RegChannel");
ChannelServices.RegisterChannel(HttpChan, true);
RemoteObject = (IRemObject)Activator.GetObject(typeof(IRemObject), "http://someAdress:80/IRemObject");
FileLogger.Log("MMLC: connected");
}
catch(Exception x)
{
Trace.WriteLine("Error connecting to remote server, reason: " + x.Message);
RemoteObject = null;
}
}
private static void SetChannelProxy(HttpClientChannel channel, IWebProxy proxy)
{
FieldInfo proxyObjectFieldInfo = typeof(HttpClientChannel).GetField("_proxyObject", BindingFlags.Instance | BindingFlags.NonPublic);
proxyObjectFieldInfo.SetValue(channel, proxy);
}
This is the Form asking the user for Proxy details. If the User ends it with hitting the "OK" button on it, the defined Proxy property is set. That property is then passed to the LoginWCP() function.
private void button1_Click(object sender, EventArgs e)
{
definedProxy = new WebProxy(txtAdress.Text, decimal.ToInt32(nudPort.Value));
Address = txtAdress.Text;
Port = decimal.ToInt32(nudPort.Value);
NetworkCredential nc = new NetworkCredential()
{
Domain = string.IsNullOrWhiteSpace(txtDomain.Text) ? null : txtDomain.Text,
UserName = txtName.Text,
Password = txtPassword.Text
};
definedProxy.Credentials = nc;
DialogResult = System.Windows.Forms.DialogResult.OK;
Close();
}
So far this worked fine, but now I have the first user with an proxy in an Active Directory Environment. As i am lacking an AD, i cannot test the application in it. So I am asking you, is there anything wrong with my application? Do i need to check the user ipnut for something? is the Expect100Continue = falsedoing something bad?
So, this thing happened again, but this time it could be solved. First I have to name the culprit giving me a hard time. ZScaler. This software suite build around blocking and sniffing into connections from the outside and inside seems to only allow connections to adresses, and not direct IPs. Up to this point my application directly connected to an IP, instead of an real adress. Some Changes later, my server is now browsable by an address, and the application is let through by the proxy of the ZScaler.
Related
Using PKCS11Interop on Safenet HSMs, I got this error
"Method C_OpenSession returned 2147484548"
the error, in my documentation, is CKR_SMS_ERROR: "General error from secure messaging system - probably caused by HSM failure or network failure".
This confirm the problem it happens when the connectivity is lacking.
The problem is when this happens, the service isn't able to resume the communication when the connectivity is back, until I restart manually the service managing the HSM access.
When the service starts, I call this:
private Pkcs11 _pkcs11 = null;
private Slot _slot = null;
private Session _session = null;
public async void InitPkcs11()
{
try
{
_pkcs11 = new Pkcs11(pathCryptoki, Inter_Settings.AppType);
_slot = Inter_Helpers.GetUsableSlot(_pkcs11, nSlot);
_session = _slot.OpenSession(SessionType.ReadOnly);
_session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
}
catch (Exception e)
{
...
}
}
When I have to use the HSM, I call something like:
using (var LocalSession = _slot.OpenSession(SessionType.ReadOnly))
{
...
}
And, when I fail the communication due to a connectivity lack, I call a function to reset the connection and try to change the slot:
private bool switching = false;
public async void SwitchSlot()
{
try
{
if (!switching)
{
switching = true;
if (nSlot == 0)
{
nSlot = 2;
}
else
{
nSlot = 0;
}
_session.Logout();
_slot.CloseAllSessions();
_pkcs11.Dispose();
InitPkcs11();
switching = false;
}
}
catch (Exception e)
{
...
}
}
But, this last snippet doens't work as expected: it tries to change the slot, but it fails always to communicate with the HSM (after a network down). If I restart the service manually (when the connectivity is back), it works like charms. So, I'm sure I'm doing something wrong in the SwitchSlot function, when I try to close the _session and open a new one.
Do you see any errors/misunderstoonding here?
I have a C++ Windows service exposing a .Net Remoting interface for a local client to use and everything works great until the IP address changes.
Since I have to support .Net 2.0, switching to WCF isn't an option.
Any ideas on what I can do?
Here's how I set up the channel:
Hashtable^ dict = gcnew Hashtable();
dict["port"] = 9085;
dict["authenticationMode"] = "IdentifyCallers";
dict["impersonate"] = nullptr;
dict["secure"] = true;
dict["typeFilterLevel"] = "Full";
TcpServerChannel^ tcpChannel;
try
{
tcpChannel = gcnew TcpServerChannel( dict, nullptr);
}
catch (Exception^ e)
{
}
try
{
ChannelServices::RegisterChannel(tcpChannel, true);
}
catch (RemotingException^ RemoteException)
{
return FALSE;
}
catch (Exception^ e) { }
MyServiceProxy^ proxy = gcnew MyServiceProxy(m_pService);
RemotingServices::Marshal(proxy,"ServiceProxy");
Here's how I'm connecting to that service via C#
IDictionary dict = new Hashtable();
dict["port"] = 9085;
dict["name"] = "127.0.0.1";
dict["secure"] = true;
dict["tokenImpersonationLevel"] = "Impersonation";
dict["typeFilterLevel"] = "Full";
dict["connectionTimeout"] = 10000; // 10 seconds timeout
workChannel = new TcpClientChannel(dict, null);
try
{
ChannelServices.RegisterChannel(workChannel, true);
}
catch (System.Exception /*e*/)
{
}
string objectPath = "tcp://127.0.0.1:9085/ServiceProxy";
obj = (IMyService)Activator.GetObject(typeof(IMyService), objectPath);
I mean when the computers IP address changes. So here's the flow.
Start the service which sets up the channel, then close the laptop lid, go home, open it back up again, get assigned a new IP address, now when I try to start the client and it can't connect the the service.
After a good bit of research, I ran across the 'bindTo' parameter...and all I needed to do was to add the parameter to the TCPServerChannel dictionary.
dict["bindTo"]= "127.0.0.1";
If this didn't work, I was going to try to using the IPCServerChannel, but thankfully this one line was all I needed.
And to think, this one line has caused so much grief.
Thank you Alexei for helping.
I have a project about going to a website. If the website cannot because of several reasons, such as not being connected to the Internet, wrong proxy ip, etc, the browser will show a page with text "You're not connected to a network". In this situation, I want to auto refresh the browser. How will the program detect that website can't be loaded?
Take a look at my below code:
public void exam()
{
var ie = new IE();
ie.GoTo("http://search.yahoo.com");
ie.WaitForComplete(5);
if (ie.ContainsText("You're not connected to a network"))
{
ie.Close();// or ie.Refresh()
}
}
It doesn't work.
Try testing to see if you can Ping the address first ... try using this
public bool CanConnect()
{
var ping = new Ping();
var reply = ping.Send("search.yahoo.com");
return reply.Status == IPStatus.Success;
}
or if you want to pass the address as a parameter:
public bool CanConnect(string addressToTest)
{
var ping = new Ping();
var reply = ping.Send(addressToTest);
return reply.Status == IPStatus.Success;
}
Basically I'm making a program to simulate a petrol station system.
My problem is that I'm trying to send a request through a WCF service such as this:
User Requests Pump to be activated ----> WCF SERVICE ----> Point of Sale
User starts pumping petrol<---- WCF SERVICE <---- Point of Sale Accepts
At the moment it works, but only sometimes.
This is how I try to get a response:
while(PumpserviceClient.getRequestedAcceptedStatusFromPos().Accepted == false)
{
PumpserviceClient.RequestPump(int.Parse(PumpID));
// needs to wait for pump to be activated
if (PumpserviceClient.getRequestedAcceptedStatusFromPos().Accepted == true /*&& PumpserviceClient.getRequestedAcceptedStatusFromPos().PumpNo == int.Parse(PumpID)*/)
{
MessageBox.Show(" The Pos has accepted your pump request");
// if its accepted you call
Customer.ActivatePump();
}
And these are the methods in the service:
bool Accepted= false;
bool Requested=false;
public void AcceptPump(int PumpNumber)
{
Accepted = true;
Requested = false;
int pumpnumber = PumpNumber;
PumpRequest.Accepted = Accepted;
PumpRequest.Requested = Requested;
}
public void RequestPump(int PumpNumber)
{
int pumpnumber = PumpNumber;
Requested = true;
Accepted = false;
PumpRequest.Accepted = Accepted;
PumpRequest.PumpNo = PumpNumber;
PumpRequest.Requested = Requested;
}
public void ResetRequest(int PumpNumber)
{
int pumpnumber = PumpNumber;
Requested = false;
Accepted = false;
PumpRequest.Accepted = Accepted;
PumpRequest.PumpNo = 0;
PumpRequest.Requested = Requested;
}
public Message getRequestedStatusFromPump()
{
return PumpRequest;
}
public Message getRequestedAcceptedStatusFromPos()
{
return PumpRequest;
}
}
and the point of sale system accepts the requests by:
if (Client.getRequestedStatusFromPump().Requested == true)
{
MessageBox.Show("Pump Number: "+Client.getRequestedStatusFromPump().PumpNo + " Is waiting to be accepted");
// need to press a button or something
Client.AcceptPump(Client.getRequestedStatusFromPump().PumpNo);
}
Code here http://www.pastebucket.com/8642
I read the code posted. You use the following attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
This means your code will not multi-thread. But there is no guarantee multiple sessions won't make requests and "interrupt" each other's workflow.
For example:
Client A calls request pump
Client B calls reset pump
Client A reads... client A wonders why pump was reset.
Your code is written expecting the object to be by session. I'd suggest using this context mode and seeing if you have better luck.
The other option is to add session information to your model. I can't imagine why this would be useful. It certainly won't be easy.
The only way i found around this problem, without changing service behaviors was to create a new list
public void CreatePumpList()
{
WaitingPumps = new List<WaitingPumps>();
for (int i = 0; i < PumpLimit+1 ; i++)
{
WaitingPumps.Add(new WaitingPumps());
}
}
Then just use the pump Number as the index in this list so they don't get confused with each other.
I have highload ASP .NET MVC2 website and WCF service that site uses. Early I created one proxy every time I need it and even didn't close it. Refer to my previous question (with my big thanks for SO user Richard Blewett) I found out that I should close this proxy. In other way it will succeed sessions limit.
Now, I'm creating proxy one time app starts and then just check it and recreate it if is needed. So, here is the code:
public static bool IsProxyValid(MyServ.MyService client) {
bool result = true;
if ((client == null) || (client.State != System.ServiceModel.CommunicationState.Opened) // || (client.InnerChannel.State != CommunicationState.Opened)
)
result = false;
return result;
}
public static AServ.AServClient GetClient(HttpContext http) {
if (!IsProxyValid((MyService)http.Application["client"]))
http.Application["client"] = new MyService();
return (MyService)http.Application["client"];
}
public static MyServ.MyService GetClient(HttpContextBase http)
{
if (!IsProxyValid((MyService)http.Application["client"]))
http.Application["client"] = new MyService();
return (MyService)http.Application["client"];
}
public ActionResult SelectDepartment(string departments)
{
try
{
MyService svc = CommonController.GetClient(this.HttpContext);
Department[] depsArray = svc.GetData(departments);
// .... I cut here ....
return View();
}
catch (Exception exc)
{
// log here
return ActionUnavailable();
}
}
So, what do you guys think about it? Should it work properly? Sometimes my app stucked. I think it is because client proxy state determines uncorrectly and app tries to use broken proxy.
POST EDIT
Also in TCP Monitor I see a lot of established connections from site to service. Why it creates a lot of connectiong insteads of using one global? Maybe some exception occured while invoking service method makes it faulted state?
Hope for your help guys!
I think you need to abort the channel if it gets faulted before creating a new one and
Make sure to close/ abort old client if you creating the new client, use something like this for that (this one is used with DI in singleton)
public class MyServiceClientInitializer : IMyServiceClientInitializer
{
[ThreadStatic]
private static MyServ.MyService _client;
public MyServ.MyService Client
{
get
{
if (_client == null
|| (_client.State != CommunicationState.Opened
&& _client.State != CommunicationState.Opening))
IntializeClient();
return _client;
}
}
private void IntializeClient()
{
if (_client != null)
{
if (_client.State == CommunicationState.Faulted)
{
_client.Abort();
}
else
{
_client.Close();
}
}
string url = //get url;
var binding = new WSHttpBinding();
var address = new EndpointAddress(url);
_client = new MyServ.MyService(binding, address);
}
}