StreamSocket connection from HoloLens does not work properly - unity3d

I'm working on a HoloLens app which works as a client in a client-server connection to a local server written in Java (you can assume the server is working properly).
HoloLens should open a StreamSocket and connect to the server, but for some reasons the code remains stuck in the process of connection.
The code is the following:
void Start ()
{
text = GameObject.Find("DEBUG_TEXT").GetComponent<Text>();
Invoke("Connect", 7f);
}
public void Connect()
{
#if !UNITY_EDITOR
Task.Run(async () => {
try
{
socket = new StreamSocket();
await socket.ConnectAsync(new HostName(ip), port); //STOP HERE
writer = new StreamWriter(socket.OutputStream.AsStreamForWrite());
reader = new StreamReader(socket.InputStream.AsStreamForRead());
await Send("Hi");
await Receive();
}
catch(Exception e)
{
text.text = e.Message;
}
});
#endif
}
Basically, the code stops at the ConnectionAsync and never goes on. On the server side, the server notifies me with "new client connected!", so i suppose HoloLens effectively connects, but something happens after.
Any idea of what could be wrong?

I ran into the same problem, and solved it with the method mentioned here.
In short, you should never do anything like Task.Wait() or Task.Result on the main thread.
In my situation, I used Task.Result and stuck right at the connect operation.
After removing it, the program works fine.
Here's the bad code:
private async Task<string> _SocketSend(string request)
{
using(StreamSocket streamSocket = new StreamSocket())
{
await streamSocket.ConnectAsync(new HostName(this.socketHost), this.port);
// other code
...
}
}
public string SocketSend(string request)
{
return _SocketSend(request).Result;
}

Related

Quickfix/N the callbacks ToApp ToAdming is not trigering in Initiator

I created simple quickfix application:
public static void Main()
{
SessionSettings settings = new SessionSettings("C:\\Users\\user\\Desktop\\Work\\QFLib\\config\\Config2.txt");
MyQuickFixApp myApp = new MyQuickFixApp();
IMessageStoreFactory storeFactory = new FileStoreFactory(settings);
ILogFactory logFactory = new FileLogFactory(settings);
var acceptor = new SocketInitiator(
myApp,
storeFactory,
settings,
logFactory);
bool sendlogon = true;
acceptor.Start();
while (true)
{
if(sendlogon)
myApp.SendLogonRequest(myApp.session.SessionID);
sendlogon = false;
Thread.Sleep(1000);
}
acceptor.Stop();
}
}
The problem server is not getting requests, and not sending response. The configs looks okay and generated message also looks good. I also sending generated message via TCP client and in that case on server I get parse error and no response.
The config file:Config file
The logs:logs
As Cristoph John answered I didn't need to send logon.
I just needed to add code to autologin:
public void ToAdmin(Message msg, SessionID sessionID)
{
Console.WriteLine("ToAdmin " + msg);
if (msg.GetType() == typeof(QuickFix.FIX44.Logon))
{
msg.SetField(new Password("Password"));
msg.SetField(new ResetSeqNumFlag(true));
}
}

How can I reconnect a Photon Bolt client after it disconnects?

I'm trying to make a Photon Bolt game that connects two devices. The problem is that the Client tends to get disconnected a lot, an it doesn't reconnect automatically. I've tried using methods like ReconnectAndRejoin, but it seems like it only works in PUN. Right now I'm using this custom solution, without success:
[BoltGlobalBehaviour(BoltNetworkModes.Client)]
public class InitialiseGameClient : Photon.Bolt.GlobalEventListener
{
private bool disconnected;
public void Update(){
if(disconnected){
Reconnect();
}
}
public override void Disconnected(BoltConnection connection)
{
disconnected = true;
}
public void Reconnect(){
BoltLauncher.StartClient();
PlayerPrefs.DeleteAll();
if (BoltNetwork.IsRunning && BoltNetwork.IsClient)
{
foreach (var session in BoltNetwork.SessionList)
{
UdpSession udpSession = session.Value as UdpSession;
if (udpSession.Source != UdpSessionSource.Photon)
continue;
PhotonSession photonSession = udpSession as PhotonSession;
string sessionDescription = String.Format("{0} / {1} ({2})",
photonSession.Source, photonSession.HostName, photonSession.Id);
RoomProtocolToken token = photonSession.GetProtocolToken() as RoomProtocolToken;
if (token != null)
{
sessionDescription += String.Format(" :: {0}", token.ArbitraryData);
}
else
{
object value_t = -1;
object value_m = -1;
if (photonSession.Properties.ContainsKey("t"))
{
value_t = photonSession.Properties["t"];
}
if (photonSession.Properties.ContainsKey("m"))
{
value_m = photonSession.Properties["m"];
}
sessionDescription += String.Format(" :: {0}/{1}", value_t, value_m);
}
ServerConnectToken connectToken = new ServerConnectToken
{
data = "ConnectTokenData"
};
Debug.Log((int)photonSession.Properties["t"]);
var propertyID = PlayerPrefs.GetInt("PropertyID", 2);;
if((int)photonSession.Properties["t"] == propertyID){
BoltMatchmaking.JoinSession(photonSession, connectToken);
disconnected = false;
}
}
}
}
}
With this method I'm trying to use the same code used to connect the the client for the first time in the reconnect function, and keep trying until the client manages to connect. However it seems that the code never executes, even if the disconnect function gets triggered (the reconnect doesn't). Is there any Bolt integrated function that helps with reconnecting? Thanks in advance.
You need to shutdown bolt, then try reconnecting. Even if you don't get the below exception, it's just an example and you should shutdown and do BoltLauncher.StartClient() etc.
BoltException: Bolt is already running, you must call BoltLauncher.Shutdown() before starting a new instance of Bolt.

How to get Fiddler or Charles to capture traffic from Unity 2018 IL2CPP apps

I have built apps with Unity 5 and with Unity 2017, and am able to use Fiddler or Charles to capture network traffic successfully. However, When I build a Unity 2018 app using IL2CPP (the other apps were built with .Net), the app works (successfully sending network traffic), but the app seems to somehow bypass the Fiddler (or Charles) proxy. That is, Fiddler and Charles are unable to show the network traffic from the Unity 2018 IL2CPP app, even though it can show traffic from Unity 5 and Unity 2017 apps.
Note that everything works with Unity 5 and Unity 2017, and, that the SSL settings, etc. have been setup previously. Also, I have used the Fiddler "WinConfig" to EnableLoopback for the Unity 2018 app.
My question is: What do I need to do to get a Unity 2018 IL2CPP app to show traffic in Fiddler or Charles?
Update:
Here is some sample code that shows that HttpClient requests don't go through the proxy, but other (Unity) webrequests do go through the proxy:
public class RequestTest : MonoBehaviour
{
public UnityEngine.UI.Text text;
void Update()
{
if (Input.GetKeyUp(KeyCode.P))
{
StartCoroutine(yieldPing());
}
if (Input.GetKeyUp(KeyCode.O))
{
asyncPing();
}
}
private IEnumerator yieldPing()
{
Debug.Log("This request shows up in Fiddler");
text.text = "UWR in Coroutine";
using (UnityWebRequest uwr = UnityWebRequest.Get("https://www.google.com/"))
{
yield return uwr.SendWebRequest();
}
}
private async void asyncPing()
{
await awaitPing();
}
private async System.Threading.Tasks.Task<bool> awaitPing()
{
Debug.Log("This request also shows up in Fiddler");
UnityWebRequest uwr = UnityWebRequest.Get("https://www.google.com/");
text.text = "UWR in async await";
uwr.SendWebRequest().completed += delegate
{
uwr.Dispose();
};
Debug.Log("This request does NOT show up in Fiddler???");
text.text += "\nHttpClient in async await";
using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient())
{
using (System.Net.Http.HttpRequestMessage httpRequest = new System.Net.Http.HttpRequestMessage())
{
httpRequest.RequestUri = new System.Uri("http://www.youtube.com/");
httpRequest.Method = System.Net.Http.HttpMethod.Get;
using (System.Net.Http.HttpResponseMessage httpResponse = await httpClient.SendAsync(httpRequest, System.Net.Http.HttpCompletionOption.ResponseHeadersRead))
{
var responseCode = (int)httpResponse.StatusCode;
// We will get a 304 if the content has not been modified
// If there is new, good content, then we will get a 200
return (responseCode == 200);
}
}
}
}
}
Here are the Unity Player Settings:
Unity has acknowledged that this is a problem:
https://fogbugz.unity3d.com/default.asp?1222589_u6qsndet3umnp50u
https://issuetracker.unity3d.com/issues/httpclient-ignores-windows-proxy
It appears that during the "IL2CPP" code generation process, the generated code changes the HttpClient to not use the local proxy.
The code below was copied from here, and seems to overcome the Unity IL2CPP bug:
// might be overly complicated, there is an option to wrap the existing proxy here...
class myWebProxy : System.Net.IWebProxy
{
private System.Net.IWebProxy wrappedProxy;
private System.Net.ICredentials creds;
private void init()
{
wrappedProxy = null;
creds = CredentialCache.DefaultCredentials;
}
public myWebProxy()
{
init();
}
public myWebProxy(System.Net.IWebProxy theWrappedProxy)
{
init();
wrappedProxy = theWrappedProxy;
}
public System.Net.ICredentials Credentials
{
get
{
if (wrappedProxy != null)
{
return wrappedProxy.Credentials;
}
else
{
return creds;
}
}
set
{
if (wrappedProxy != null)
{
wrappedProxy.Credentials = value;
}
else
{
creds = value;
}
}
}
public Uri GetProxy(Uri destination)
{
if (wrappedProxy != null /* todo or Uri == certain Uri */)
{
return wrappedProxy.GetProxy(destination);
}
else
{
// hardcoded proxy here..
return new Uri("http://seeplusplus:8080");
}
}
public bool IsBypassed(Uri host)
{
if (wrappedProxy != null)
{
return wrappedProxy.IsBypassed(host);
}
else
{
return false;
}
}
}
// in your code use your new proxy
HttpClientHandler aHandler = new HttpClientHandler();
// use your proxy!
aHandler.Proxy = new myWebProxy();
HttpClient client = new HttpClient(aHandler);

netty issue when writeAndFlush called from different InboundChannelHandlerAdapter.channelRead

I've got an issue, for which I am unable to post full code (sorry), due to security reasons. The gist of my issue is that I have a ServerBootstrap, created as follows:
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
final ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst("idleStateHandler", new IdleStateHandler(0, 0, 3000));
//Adds the MQTT encoder and decoder
ch.pipeline().addLast("decoder", new MyMessageDecoder());
ch.pipeline().addLast("encoder", new MyMessageEncoder());
ch.pipeline().addLast(createMyHandler());
}
}).option(ChannelOption.SO_BACKLOG, 128).option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
channelFuture = b.bind(listenAddress, listenPort);
With createMyHandlerMethod() that basically returns an extended implementation of ChannelInboundHandlerAdapter
I also have a "client" listener, that listens for incoming connection requests, and is loaded as follows:
final String host = getHost();
final int port = getPort();
nioEventLoopGroup = new NioEventLoopGroup();
bootStrap = new Bootstrap();
bootStrap.group(nioEventLoopGroup);
bootStrap.channel(NioSocketChannel.class);
bootStrap.option(ChannelOption.SO_KEEPALIVE, true);
bootStrap.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst("idleStateHandler", new IdleStateHandler(0, 0, getKeepAliveInterval()));
ch.pipeline().addAfter("idleStateHandler", "idleEventHandler", new MoquetteIdleTimeoutHandler());
ch.pipeline().addLast("decoder", new MyMessageDecoder());
ch.pipeline().addLast("encoder", new MyMessageEncoder());
ch.pipeline().addLast(MyClientHandler.this);
}
})
.option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.TCP_NODELAY, true);
// Start the client.
try {
channelFuture = bootStrap.connect(host, port).sync();
} catch (InterruptedException e) {
throw new MyException(“Exception”, e);
}
Where MyClientHandler is again a subclassed instance of ChannelInboundHandlerAdapter. Everything works fine, I get messages coming in from the "server" adapter, i process them, and send them back on the same context. And vice-versa for the "client" handler.
The problem happens when I have to (for some messages) proxy them from the server or client handler to other connection. Again, I am very sorry for not being able to post much code, but the gist of it is that I'm calling from:
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(someOtherMessage);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
Now here's the problem: the bolded (client) writeAndFlush - never actually writes the message bytes, it doesn't throw any errors. The ChannelFuture returns all false (success, cancelled, done). And if I sync on it, eventually it times out for other reasons (connection timeout set within my code).
I know I haven't posted all of my code, but I'm hoping that someone has some tips and/or pointers for how to isolate the problem of WHY it is not writing to the client context. I'm not a Netty expert by any stretch, and most of this code was written by someone else. They are both subclassing ChannelInboundHandlerAdapter
Feel free to ask any questions if you have any.
*****EDIT*********
I tried to proxy the request back to a DIFFERENT context/channel (ie, the client channel) using the following test code:
public void proxyPubRec(int messageId) throws MQTTException {
logger.log(logLevel, "proxying PUBREC to context: " + debugContext());
PubRecMessage pubRecMessage = new PubRecMessage();
pubRecMessage.setMessageID(messageId);
pubRecMessage.setRemainingLength(2);
logger.log(logLevel, "pipeline writable flag: " + ctx.pipeline().channel().isWritable());
MyMQTTEncoder encoder = new MyMQTTEncoder();
ByteBuf buff = null;
try {
buff = encoder.encode(pubRecMessage);
ctx.channel().writeAndFlush(buff);
} catch (Throwable t) {
logger.log(Level.SEVERE, "unable to encode PUBREC");
} finally {
if (buff != null) {
buff.release();
}
}
}
public class MyMQTTEncoder extends MQTTEncoder {
public ByteBuf encode(AbstractMessage msg) {
PooledByteBufAllocator allocator = new PooledByteBufAllocator();
ByteBuf buf = allocator.buffer();
try {
super.encode(ctx, msg, buf);
} catch (Throwable t) {
logger.log(Level.SEVERE, "unable to encode PUBREC, " + t.getMessage());
}
return buf;
}
}
But the above at line: ctx.channel().writeAndFlush(buff) is NOT writing to the other channel - any tips/tricks on debugging this sort of issue?
someOtherMessage has to be ByteBuf.
So, take this :
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(someOtherMessage);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
... and replace it with this :
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(ByteBuf);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
Actually, this turned out to be a threading issue. One of my threads was blocked/waiting while other threads were writing to the context and because of this, the writes were buffered and not sent, even with a flush. Problem solved!
Essentially, I put the first message code in an Runnable/Executor thread, which allowed it to run separately so that the second write/response was able to write to the context. There are still potentially some issues with this (in terms of message ordering), but this is not on topic for the original question. Thanks for all your help!

Raspberry pi 2 server does not respond

I have started a client server project with my raspberry pi 2 running windows 10 IoT which is very nice because you can run the same application on both the PC and the RPI2. With that in mind I only created one application that could act as both client and server which I then deploy on both devices and use one of them as server and the other as Client. The only problem is that server side never answers the clients connect call.
My code is as follows:
Server:
///servername is the port that I use
///hostadapter is an adapter helper obj that has a HostName property set to my Ip address.
public async void Start(string serverName, HostName hostAdapter)
{
//create the "server" object
serverListener = new StreamSocketListener();
serverListener.ConnectionReceived += ServerListener_ConnectionReceived;
try
{
await serverListener.BindEndpointAsync(hostAdapter, serverName);
Started = true;
}
catch (Exception ee)
{
Started = false;
myConsole.Print("error while starting server: " + ee.Message);
}
}
private async void ServerListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
myConsole.Print("connection recieved callback called");
DataReader reader = new DataReader(args.Socket.InputStream);
DataWriter ServerWriter = new DataWriter(args.Socket.OutputStream);
string ServerAnswer = "message recieved by server";
try
{
while (true)
{
// Read first 4 bytes (length of the subsequent string).
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
if (sizeFieldCount != sizeof(uint))
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Read the string.
uint stringLength = reader.ReadUInt32();
uint actualStringLength = await reader.LoadAsync(stringLength);
if (stringLength != actualStringLength)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
ServerWriter.WriteUInt32(ServerWriter.MeasureString(ServerAnswer));
ServerWriter.WriteString(ServerAnswer);
await ServerWriter.StoreAsync();
}
}
catch (Exception exception)
{
myConsole.Print(exception.Message);
}
}
Client:
public async void Connect(string serverIP, string serverPort)
{
try
{
ServerHost = new HostName(serverIP);
}
catch (Exception ee)
{
return;
}
try
{
//open socket
ClientSocket = new StreamSocket();
await ClientSocket.ConnectAsync(ServerHost, serverPort);
Connected = true;
}
catch (Exception ex)
{
ClientSocket.Dispose();
ClientSocket = null;
myConsole.Print(ex.Message);
Connected = false;
}
}
Any help is much appreciated. I have downlaoded wireshark to be able to monitor the networkdata and I have located the tcp [syn] package that the client sends, but I can´t see any tcp [syn ack] packages.
It turned out that I was missing one capability. The capabilities that you need to communicate over ethernet are
<Capabilities>
<Capability Name="internetClient" />
<Capability Name="privateNetworkClientServer" />
<Capability Name="internetClientServer" />
</Capabilities>
I hade only added privateNetworkClientServer and internetClient..