SSDP Search in Windows Phone 8 - c#

I'm new at SSDP/UPNP/Sockets and all that jazz. I'm playing around with it a bit and I just want to see what a generic SSDP search on my network will bring up.
Using this SSDP Sniffer app, I get a lot of results so I'm attempting to recreate this.
I'm using the following code, which I've found various versions of, but all the tweaking I do doesn't appear to bring back any results. I pretty much at a loss here and would appreciate any guidance.
thanks!
private const string SSDP_IP = "239.255.255.250";
private const string SSDP_PORT = "1900";
private const string SSDP_QUERY = "M-SEARCH * HTTP/1.1\r\n" +
"Host: " + SSDP_IP + ":" + SSDP_PORT + "\r\n" +
"Man: ssdp:discover\r\n" +
"ST: ssdp:all\r\n";
DataGramSocket socket;
async public void SsdpQueryAsync()
{
var remoteIP = new Windows.Networking.HostName(SSDP_IP);
var reqBuff = Encoding.UTF8.GetBytes(SSDP_QUERY);
socket = new DatagramSocket();
socket.MessageReceived += (sender, args) =>
{
// This is invoked for each device that responds to the query...
Task.Run(() =>
{
// do something useful
});
};
await socket.BindEndpointAsync(null, "");
socket.JoinMulticastGroup(remoteIP);
using (var stream = await socket.GetOutputStreamAsync(remoteIP, SSDP_PORT))
{
await stream.WriteAsync(reqBuff.AsBuffer());
}
await Task.Delay(5000);
}

I'm not familiar with C# or dotnet APIs, but I can see some details wrong with the M-SEARCH message:
MAN header must be enclosed in double quotes, so MAN: "ssdp:discover"\r\n
MX header is missing (required for multicast)
USER-AGENT header is missing
missing an empty line in the end
Header names are supposedly case insensitive, but I'd use upper case just in case...
See the Device Architecture reference pdf for more details

Related

Task hang infinitely when calling .Wait() in kafka-net

I'm currently trying to post messages from a for-loop on a kafka server running on my local machine using the kafka-net library in c# (https://github.com/Jroland/kafka-net), following the example given on the linked repo, my code is the following.
string kafkaServer = "http://" + ip + ":" + port;
Uri uri = new Uri(kafkaServer);
var options = new KafkaOptions(uri);
var router = new BrokerRouter(options);
var client = new Producer(router);
...
foreach(string sumup in LS){
payloadJson["fullPathDataFolder"] = remoteFolder;
payloadJson["globalName"] = GloablName;
payloadJson["name"] = name;
payloadJson["text"] = sumUp + "\n";
payloadJson["type"] = type;
string payload = payloadJson.ToString();
KafkaNet.Protocol.Message msg = new KafkaNet.Protocol.Message(payload);
client.SendMessageAsync(topic, new List<KafkaNet.Protocol.Message> { msg }).Wait();
}
This code run through the first iteration and i'm able to retrieve the first string from a second machine linked to the same server with a consumer.
Then the code here above remain stuck at the intruction:
client.SendMessageAsync(topic, new List<KafkaNet.Protocol.Message> { msg }).Wait();
If now I remove the .Wait() this code run quite fast but it randomly ignore some of the string i send
What am I missing ?
P.S.
I'v tried also to use Confluent.kafka and i got similar problems
P.P.S.
It's important that this program run sequentially.

c# Using static variables in different projects

I have a solution with two projects which act as Server and Client respectively. The Client is a simple console application which sends data to the server. The server is a WPF application which receives the data and displays it in a datagrid. The MVVM approach is used here.
In the Server UI there are three textboxes in which the user can type in:
IP Address: ("127.0.0.1")
Port: (some port)
Delimeter: (some char like '#' for example)
The challenge for me in this one is that, whatever delimeter the user provides, it should be used in the client project, to be put in between the data which is to be sent. For example the client sends:
Name + Delimeter + Surname + Delimeter + Age
What i have tried:
I added a Utils class with static fields for IPAddress, port and delimeter like this:
public class Utils
{
public static string IP_ADDRESS = " ";
public static int PORT = 0;
public static char DELIMETER = '\0';
}
I then tried to change these values in my ViewModel where the respective properties which are bound to the UI are by assigning them:
private void storeData()
{
Utils.IP_ADDRESS = IP;
Utils.PORT = Port;
Utils.DELIMETER = Delimeter;
}
In the client program:
static void Main(string[] args)
{
Client client = new Client(Utils.IP_ADDRESS, Utils.PORT);
while (true)
{
client.SendData("some Name" + Utils.DELIMETER + "some Surname" + Utils.DELIMETER + some Age + Utils.DELIMETER + "something else");
Thread.Sleep(3000);
}
}
The problem here is that whenever i start a new Client instance the values from the util class are still the default ones (null).
Any help is appreciated.
Let's break down your problem:
The server can change ip or ports at will and the clients will somehow guess the new port and connect.
The server changes the delimiter at will and the clients adapt to the new delimiter.
Problem 1 is impossible. Information cannot magically get transferred to clients before the client connects to the server, and the client needs ip and ports to connect to the server. Whatever technique you use to transfer the ip and port to the client is a better communication channel than your client/server, so you don't need a client/server.
Problem 2 has been solved by WCF already. Use WCF and SOAP or REST (which is just HTML).
Here is a sample of what the code would look like for the clients to determine the delimiter before sending the main request:
class Server
{
private TcpListener _listener = new TcpListener(12312);
public void Start()
{
_listener.Start();
while (true)
{
var client = _listener.AcceptTcpClient();
var stream = client.GetStream();
var request = getRequest(stream);
if (request == "GetDelimiter")
{
SendResponse(Utils.DELIMITER, stream);
}
else
{
ProcessNameSurnameAge(request);
}
}
}
}
class Client
{
private TcpClient _client = new TcpClient();
public void DoTheThing()
{
_client.Connect("127.0.0.1", 12312);
var stream = _client.GetStream();
SendRequest("GetDelimiter", stream);
var delimiter = GetResponse(stream);
var newRequest = "some Name" + delimiter + "some Surname" + delimiter + "some Age" + delimiter + "something else";
SendRequest(newRequest);
}
}
Note that I skip over the encoding details of sending data over TCP because it seems like you've already got a handle on that.
I was able to solve this in a rather simple manner. Steps i used to solve are as follow:
In the server:
Created a text file in my solution.
When the server starts in my view model, i saved the properties ip, port and delimeter in a string array.
Next i used the IO File class to write the content of the array in the text file.
In the client:
First i read from the file.
Next i created the client instance and passed the ip and port as parameters to it's constructor.
Thank you D Stanley and Damian Galletini for your suggestions. Also thank you everybody else who tried to help.

Pushing to bitbucket with libgit2sharp

I'm trying to use libgit2sharp to push to my repo on bitbucket. I'm trying to do this:
repo.Network.Push(repo.Branches[branchName], pushOptions);
Everything seems fine, no exceptions are thrown and I get no errors in the callback, but when I check on bitbucket none of my commits are there. Other methods seem to work fine (ie I can create a new branch on bitbucket and then use libgit2sharp to fetch and see that I now have that branch locally). Is there anything that I might be missing here?
edit:
Tried to just make a small sample program to see if I can get this working no go. I don't know if my code will help but here it is:
class Program
{
static void Main(string[] args)
{
PushOptions options = new PushOptions();
Credentials creds = new Credentials();
creds.Username = "username";
creds.Password = "password";
options.Credentials = creds;
options.OnPackBuilderProgress = Program.packBuilderProgressHandler;
options.OnPushTransferProgress = Program.pushTransferProgressHandler;
options.OnPushStatusError = Program.pushStatusErrorHandler;
Repository repo = new Repository("E:/Ohad/Work/libgitTest");
repo.Network.Push(repo.Branches["origin/master"], options);
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
public static bool packBuilderProgressHandler(PackBuilderStage stage, int current, int total)
{
Console.Out.WriteLine("packBuilder => " + current + " / " + total);
return true;
}
public static bool pushTransferProgressHandler(int current, int total, long bytes)
{
Console.Out.WriteLine("pushTransfer => " + current + " / " + total + " , " + bytes);
return true;
}
public static void pushStatusErrorHandler(PushStatusError error)
{
Console.Out.WriteLine("error => " + error.Message);
}
}
Just make a new repo on bitbucket and add the above code (changing the stuff thats hard coded) and it should be reproducible. I just made a random change, added and commited it and then used the program to try to push to bitbucket. The output that I am getting from the above is:
pushTransfer => 0 / 0 , 12
pushTransfer => 0 / 0 , 32
Press enter to close...
The 0/0 looks suspicious to me but I don't know what I'm doing wrong =/. Thanks for any help!!
edit 2:
I just added this:
repo.Branches.Update(repo.Head, delegate(BranchUpdater updater)
{
updater.Remote = "origin";
updater.UpstreamBranch= repo.Head.CanonicalName;
})
to before when I push and it fixed the issue. Not sure exactly why but I'll take it =).
I think that you're willing to push your local master branch rather than the remote tracking one.
repo.Network.Push(repo.Branches["master"], options);
Update:
*The branch 'master' ("refs/heads/master") that you are trying to push does not track an upstream branch. *
Provided you have no "origin" remote, the following should work.
Remote remote = localRepo.Network.Remotes.Add("origin", url);
repo.Branches.Update(repo.Head, -> (A)
b => b.Remote = remote.Name, -> (B)
b => b.UpstreamBranch = repo.Head.CanonicalName); -> (C)
The code above should be read as "The branch pointed at by the HEAD (A) on this local repository will be, by default, configured to track a branch bearing the same name (C) in the distant repository identified by this remote (B)."

C# Tcp is losing packets?

I wrote a C# chat software that uses a new (at least for me) system that I called request system. I don't know if that has been created before, but for now I think of it as my creation :P
Anyhow, this system works like this:
soc receives a signal
checks the signal
if the data it just received is the number 2, the client software knows that the server is about to send a chat message. if the number is 3, so the client knows that the server is about to send the member list, and so on.
The problem is this: when I do step-by-step in VS2012 it works fine, the chat is working properly. When I use it on debug mode or just run it on my desktop, there seems to be missing data, and it shouldn't be because the code is working just fine...
Example of code for the sending&receiving message on client:
public void RecieveSystem()
{
while (true)
{
byte[] req = new byte[1];
soc.Receive(req);
int requestID = int.Parse(Encoding.UTF8.GetString(req));
if (requestID == 3)
{
byte[] textSize = new byte[5];
soc.Receive(textSize);
byte[] text = new byte[int.Parse(Encoding.UTF8.GetString(textSize))];
soc.Receive(text);
Dispatcher.Invoke(() => { ChatBox.Text += Encoding.UTF8.GetString(text) + "\r\n"; });
}
}
}
public void OutSystem(string inputText)
{
byte[] req = Encoding.UTF8.GetBytes("3");
soc.Send(req);
byte[] textSize = Encoding.UTF8.GetBytes(Encoding.UTF8.GetByteCount(inputText).ToString());
soc.Send(textSize);
byte[] text = Encoding.UTF8.GetBytes(inputText);
soc.Send(text);
Thread.CurrentThread.Abort();
}
and on the server:
public void UpdateChat(string text)
{
byte[] req = Encoding.UTF8.GetBytes("3");
foreach (User user in onlineUsers)
user.UserSocket.Send(req);
byte[] textSize = Encoding.UTF8.GetBytes(Encoding.UTF8.GetByteCount(text).ToString());
foreach (User user in onlineUsers)
user.UserSocket.Send(textSize);
byte[] data = Encoding.UTF8.GetBytes(text);
foreach (User user in onlineUsers)
user.UserSocket.Send(data);
}
public void RequestSystem(Socket soc)
{
~~~
}
else if (request == 3)
{
byte[] dataSize = new byte[5];
soc.Receive(dataSize);
byte[] data = new byte[int.Parse(Encoding.UTF8.GetString(dataSize))];
soc.Receive(data);
UpdateChat(Encoding.UTF8.GetString(data));
}
}
catch
{
if (!soc.Connected)
{
Dispatcher.Invoke(() => { OnlineMembers.Items.Remove(decodedName + " - " + soc.RemoteEndPoint); Status.Text += soc.RemoteEndPoint + " Has disconnected"; });
onlineUsers.Remove(user);
Thread.CurrentThread.Abort();
}
}
}
}
What could be the problem?
You're assuming that you'll have one packet for each Send call. That's not stream-oriented - that's packet-oriented. You're sending multiple pieces of data which I suspect are coalesced into a single packet, and then you'll get them all in a single Receive call. (Even if there are multiple packets involved, a single Receive call could still receive all the data.)
If you're using TCP/IP, you should be thinking in a more stream-oriented fashion. I'd also encourage you to change the design of your protocol, which is odd to say the least. It's fine to use a length prefix before each message, but why would you want to encode it as text when you've got a perfectly good binary connection between the two computers?
I suggest you look at BinaryReader and BinaryWriter: use TcpClient and TcpListener rather than Socket (or at least use NetworkStream), and use the reader/writer pair to make it easier to read and write pieces of data (either payloads or primitives such as the length of messages). (BinaryWriter.Write(string) even performs the length-prefixing for you, which makes things a lot easier.)

WebSockets in firefox

For implementing my websocket server in C# I'm using Alchemy framework. I'm stuck with this issue. In the method OnReceive when I try to deserialize json object, I get a FormatException:
"Incorrect format of the input string." (maybe it's different in english, but I'm getting a localized exception message and that's my translation :P). What is odd about this is that when I print out the context.DataFrame I get: 111872281.1341000479.1335108793.1335108793.1335108793.1; __ad which is a substring of the cookies sent by the browser: __gutp=entrystamp%3D1288455757%7Csid%3D65a51a83cbf86945d0fd994e15eb94f9%7Cstamp%3D1288456520%7Contime%3D155; __utma=111872281.1341000479.1335108793.1335108793.1335108793.1; __adtaily_ui=cupIiq90q9.
JS code:
// I'm really not doing anything more than this
var ws = new WebSocket("ws://localhost:8080");
C# code:
static void Main(string[] args) {
int port = 8080;
WebSocketServer wsServer = new WebSocketServer(port, IPAddress.Any) {
OnReceive = OnReceive,
OnSend = OnSend,
OnConnect = OnConnect,
OnConnected = OnConnected,
OnDisconnect = OnDisconnect,
TimeOut = new TimeSpan(0, 5, 0)
};
wsServer.Start();
Console.WriteLine("Server started listening on port: " + port + "...");
string command = string.Empty;
while (command != "exit") {
command = Console.ReadLine();
}
Console.WriteLine("Server stopped listening on port: " + port + "...");
wsServer.Stop();
Console.WriteLine("Server exits...");
}
public static void OnReceive(UserContext context) {
string json = "";
dynamic obj;
try {
json = context.DataFrame.ToString();
Console.WriteLine(json);
obj = JsonConvert.DeserializeObject(json);
} catch (Exception e) {
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return;
}
}
On the C# side I'm using Newtonsoft.Json, though it's not a problem with this library...
EDIT:
One more thing - I browsed through the code in here: https://github.com/Olivine-Labs/Alchemy-Websockets-Example and found nothing - I mean, I'm doing everything the same way authors did in this tutorial...
EDIT:
I was testing the above code in Firefox v 17.0.1, and it didn't work, so I tested it under google chrome, and it works. So let me rephrase the question - what changes can be made in js, so that firefox would not send aforementioned string?
I ran into the same issue - simply replacing
var ws = new WebSocket("ws://localhost:8080");
with
var ws = new WebSocket("ws://127.0.0.1:8080");
fixed the issue for me.
In C# console app I connect the client to the server using :
var aClient = new WebSocketClient(#"ws://127.0.0.1:81/beef");
Your code above is connecting using
var ws = new WebSocket("ws://localhost:8080");
There could be one of two issues -
First is to see if WebSocketClient works instead.
To make sure your url is of the format ws://ur:port/context. This threw me off for a while.

Categories

Resources