Extracting SID using Session PID & JID - erlang

I am trying to find a way for extracting SID of a bosh session (ejabberd) using PID and JID so that I can use it in ejabberd_sm:unset_presence, I have searched everywhere but can't find a way to do it.
Basically, I have built a chat system using Ejabberd and Strophe and what I am trying to achieve is when user press offline button on one page all the sessions associated with that JID needs to go offline, I have extraced the PID by using ejabberd_sm:get_session_pid but can't find a way to extrct SID. I have also tried SID ! Disconnect but that disconnects the user completely which I don't want.
If anybody has done this kind of work please help me, other ideas for implementing such thing are also welcome.
Thanks

I did some digging on this and here's the deal. The value you get back from ejabberd_sm:get_session_pid is the ejabberd_c2s process for that user's session. But ejabberd_c2s is entirely unaware of BOSH. What you really need is the user's BOSH session ID which is maintained by the module ejabberd_http_bind.
As best I can tell there's no "nice" way to get this information out of ejabberd_c2s. I ended up doing something like this:
St = sys:get_status(Pid),
State = lists:nth(3, lists:nth(5, element(4, St))),
SocketState = element(2, State),
BindPid = element(2, element(3, SocketState)),
Now, all that gives you at the end of the day is a PID for the ejabberd_http_bind process. You can repeat the whole sordid business again, but here I suggest cheating a little:
MS = ets:fun2ms(fun(#http_bind{pid=BP, id=Id}) when BP == BindPid -> Id end),
mnesia:dirty_select(http_bind, MS).
As you can see, this is horrendously ugly. The nicer way to do it would be to modify ejabberd_c2s to accept a new type of sync_event that would return the socket information, and likewise modify ejabberd_http_bind to accept a similar sort of event to return the SID. And of course, both of these would be wrapped in public functions that internally make the relevant gen_fsm calls.
All that said, I'm not sure what good the BOSH SID is really going to do you. And in particular, I'm not sure what the difference between "go offline" and "disconnect" is in this scenario. But anyway, that's how you get the information.

Related

Parse and Swift: How use advance targeting push to specific devices without users?

I currently creating an app where the users can add a posting without logging into the app or using any credentials.
Other users of the app can open the app and directly comment on the posts(the comments are an array of the post object).
I read the parse docs and I believe that this will use advance targeting. I saw PFInstallation.currentInstallation() for advanced targeting but I believe that is based on the users class and I am not using the Parse.com users class
What I would like to do is to send a push notification to the original poster when a comment is added to their post... So, I was wondering how I would go completing that?
Thanks!
It couldn't be easier,
Installation has a "user" column. Just make a query that matches the "user" of interest. So, your code will look something like this....
if ( .. comment made, need to send a push .. )
{
console.log(">>> 'comment' was added....");
var query = new Parse.Query(Parse.Installation);
query.equalTo('user', .. whoWroteThePost .. );
alert = "Wow! You have a new comment on a post you wrote!!!";
Parse.Push.send(
{
where:query,
data:{ alert: alert, badge: "Increment" }
});
return;
}
Note that you said ...
"What I would like to do is to send a push notification to the original poster when a comment is added to their post... "
In that sentence you speak of the "original poster". So, that's going to be a variable like originalPoster. So this line of code
query.equalTo('user', .. whoWroteThePost .. );
will be
query.equalTo('user', originalPoster );
Note that this is extremely common, and you can find endless examples on the web! Here's just one: example
Note that:
Parse's term "advanced targeting" is very confusing.
To phrase the same thought another way,
Parse's 'channels' are just silly, ignore them.
That is to say, simply ignore the "channels" nonsense, and just search on users. It's easier and less confusing than the channels business, which is just an extra field you have to fill-out al the time.
It's just one of those weird things about Parse.
I've never used the "non-advanced targeting" - it's stupid and pointless. And the "advanced" targeting is trivial to use: assuming you can write cloud code at all you can do "advanced" targeting. If you can write a query in cloud code, you can do "advanced" targeting.
Essentially,
query.equalTo('user', .. whoWroteThePost .. );
Note that, of course, you may have to first look up who wrote the post, and then from there you can make the query for the Push.
Note, in this process it makes:
no difference at all if the user is anonymous.
You can and should go ahead and send pushes, in the same way.
Advanced targeting is not done against users. It's just that is the easiest way to show an example.
You need to store the installation against the objects you want to push to. So in this case store the installation against the post. Then when the comment comes in you can send a notification to the installation connected to the post it relates to.
I think you are looking something called anonymous users. There is almost impossible to send notification without user's data. But, Parse.com provides something called anonymous users so that app users are not necessary to sign up in order to fully function something user related operations.
Then, you will need to store some information in order to find the target.
Parse.com Anonymous Users

Reference vs pid?

I'm not entirely sure the differences between the PID and Reference and when to use which.
If I were to spawn a new process with spawn/1 pid. I can kill it with the PID no? Why would I need a reference?
Likewise I see monitor/1 receiving a message with a ref and pid number.
Thanks!
Pid is process identifier. You can get one when you create new process with spawn, or you can get Pid of yourself with self(). It allows you to interact with given process. Especially send messages to it by Pid ! Message. And some other stuff, like killing it explicitly (should not do) or obtaining some process information with erlang:process_info.
And you can create relations between process with erlang:link(Pid) and erlang:monitor(process, Pid) (that's between Pid process, and process execution this function). In short, it gives you "notifications" when another process dies.
Reference is just almost unique value (of different type). One might say, that it gives you some reference to here and now, which you could recognize later. For example, if we are sending a message to another process, and we expect a response, we would like to make sure, that the message we will receive is associated to our request, and not just any message from someone else. The easiest way to do it is to tag the message with a unique value, and wait until a response with exactly the same tag.
Tag = make_ref(),
Pid ! {Tag, Message},
receive
{Tag, Response} ->
....
In this code, with use of pattern matching, we make sure that (we wait in receive until) Response is exactly for the Message we sent. No matter other messages from other processes. This is the most common use of reference you can encounter.
And now back to monitor. When calling Ref = monitor(process, Pid) we make this special connection with Pid process. Ref that is returned is just some unique reference, that we could use to demonitor this process. That is all.
One might ask, if we are able to create monitor with Pid, why do we need Ref for demonitoring? Couldn't we just use Pid again. In theory we could, but monitors are implemented in such a way, that multiple monitors could be established between two same processes. So when demonitoring, we have to remove only one of such connections. It is done in this way to make monitoring more transparent. If you have library of function that's creating and removing one monitor, you would not like to interfere with other libraries and functions and monitors they might be using.
According this page:
References are erlang objects with exactly two properties:
They can be created by a program (using make_ref/0), and,
They can be compared for equality.
You should use it ever you need to bind an unique identifier to some "object". Any time you could generate new one using erlang:make_ref/0. Documentation says:
make_ref() -> reference()
Returns an almost unique reference.
The returned reference will re-occur after approximately 2^82 calls;
therefore it is unique enough for practical purposes.
When you call erlang:monitor/2 function, it returns you reference to give you availability to cancel monitor (erlang:demonitor/1 function). This reference only identifies certain call of erlang:monitor/1. If you need operate with process (kill it, for example), you still have to use process pid.
Likewise I see monitor/1 receiving a message with a ref and pid number.
Yep, monitor sends messages like {'DOWN', Ref, process, Pid, Reason}. What to use (pid or ref) is only depends on your application logic, but (IMO) in most usual cases, there is no matter what to use.

C# Client to PHP server authentication

My XNA game needs to connect to my website with a WebRequest to a PHP page that checks the database for the user and checks to see if the password is correct.
I already have a login script that will return a message such as "success" or "fail" obviously this is temporary and needs to be improved for secrity reasons, it could easily be faked.
C# Login Request
//Create the POST data
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "username=" + user + "&pass=" + pass;
byte[] data = encoding.GetBytes(postData);
//Make a request
WebRequest request = WebRequest.Create("http://example.com/login.php");
request.Method = "POST"; //We are posting the info
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
//Open a stream, write into, then send it
Stream stream = request.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
//Get response
WebResponse response = request.GetResponse();
stream = response.GetResponseStream();
//Make a new stream, We will read from this
StreamReader sr = new StreamReader(stream);
string responseString = sr.ReadToEnd();
//TODO: If the responseString says the client if authenticated, procede, if not, display error to user (Invalid password, etc)
And the PHP script just finds user and compares submitted password (All of this is integrated with a Joomla site database, so users have a site and game account).
Now, how can my PHP script send back a reliable way of authentication, and provide some sort of token/id, so when I want to submit for example, a high score later, it knows that it is coming from this user, and isn't being faked?
To be blunt, there's no real way to ensure the data you are receiving in your PHP script is actually coming from your client. The best you can do is make it harder. Do be careful how much time you spend on this, it's a deep well, and those that want to cheat will.
Session Hijacking is only really concerning 3rd parties who are trying to access or manipulate your information. For games, this 3rd party doesn't care about your high score, they want credit cards and passwords. (Passwords are an other story, but you pretty much need SSL)
From your description, you are primarily concerned with cheating, and essentially all cheating is 1st party. The player wants to cheat. The only sure way to prevent (most) cheating is to run the game on your own systems and give the client as little control as possible (eg. EVE Online, Diablo 3, anything Blizzard). This is usually quite difficult to achieve, so I'll propose some alternatives.
To understand your enemy, there are a plethora of memory editing tools out there. Everything from injection functions to changing your money from 100 to 999999 can be done. Changing numeric values (like score) would take me ~15 minutes, and I am not very good at it.
Sanity checking. In your PHP, make sure the submitted score actually makes sense. Assume everything you get from the client is manipulated.
Punkbuster. Paying companies like Punkbuster or getting your game on Steam where you can (might be able to) use VAC. These tools don't publicize how they work, and VAC even has a delayed ban system so that you don't know what triggers it, but in broad strokes, they monitor for memory changes and/or scan for known hacks.
Honesty. Pssh, yeah right (j/k). Lol, but really: You trust your friends right? Consider scoreboards without griefers.
Maybe implementing something like season-based scoreboards? Every X days, the scoreboard resets. This reduces the incentive to cheat.
And that's pretty much it. You can try to obfuscate your memory values and it might stop people like me, but if somebody wants it bad enough and knows enough, they'll be able to break it and release a tool.
I will say this though: Make something worth hacking first! If people have gone through the effort to cheat, that's a great sign, and you should feel happy.
You're referring to a Session Token. Session tokens are a great way to authenticate actions for a given period of time after sign in. Your php can associate a session token with a username, which gets cleaned by a server process after a given amount of time, at which point the user must again log in.

method timeout instead of waiting

It would appear that the savechanges method on breeze waits indefinitely when calling to or waiting for the server. Is there a way of getting it to time out? I am calling save change with allowConcurrentSaves: false. This now causes users who somehow do not get a response from the server to simply hang in limbo indefinitely say for example with a dropped internet connection.
I do not want to re-call the method with allowConcurrentSaves to false fearing that I might duplicate the data.
Any ideas?
Thanks
Update 16 May 2014
You can set HTTP-level timeout and cancellation with the AJAX Adapter's requestInterceptor as of v.1.4.12. See the documentation, "Controlling AJAX calls".
I'd still be reluctant to use this feature on save as you have no chance of knowing what whether the server persisted the data or not. Of course if your client hangs or crashes you don't know anyway. It's up to you.
Original Answer
Actually, there is a ready-made solution from Q.js. It's called timeout and it's mentioned in the API reference with a simplified example of its implementation and use in the readme.md.
I know you asked about Save but your question is pertinent for promises in general. Here is a query example adapted from the queryTests.js in our DocCode Sample
var timeoutMs = 10000; // 10 second timeout
var em = newEm(); // creates a new EntityManager
var query = new EntityQuery().from("Customers").using(em);
Q.timeout(query.execute, timeoutMs)
.then(queryFinishedBeforeTimeout)
.fail(queryFailedOrTimedout);
function queryFailedOrTimedout(error) {
var expect = /timed out/i;
var emsg = error.message;
if (expect.test(emsg)) {
log("Query timed out w/ message '{0}' " + expectTimeoutMsg)
.format(emsg));
// do something
} else {
handleFail(error);
}
}
Note: I just added this test so you'd have to get if from github or wait for a Breeze release after 1.2.5.
Oops ... maybe not
I gave what I think is a great answer for query. It may not be the right answer for save.
The problem with save is that you do not know on the client if the save succeeded until the server responds. Things could go wrong anywhere along the way. The server might not have heard the request to save. The server may have failed during save. The server may have saved the data but the response never made it back to the client.
Changing the value of allowConcurrentSaves won't get you out of this bind. Neither will having a save timeout.
In fact, adding a timeout to the save is probably deceiving. It is even possible for the save response to arrive after your custom timeout ... in which case Breeze will have tried to update your EntityManager ... and you won't know if Breeze succeeded or failed!
What if we added a Breeze save timeout. What should it do? What if breeze said the save had timedout ... and Breeze ignored a belated response from the server? Then imagine that the save succeeded on the server - it just took "too long" for it to respond to the client. Now you've got a client whose state is unexpectedly out of sync with the server. This is not good.
So I think you want a different solution to this very real problem. It's a user experience problem really. You can indicate to the user that you think the save is still in progress and then set your own timer. If the save isn't done when your timer expires, you can query the server to see if the data have been saved or if there is a connection ... or something along these lines. I can't think of a better way right now honestly.
Note that I'm assuming you need to know that the server succeeded. If you avoid store-generated IDs and always assume saves succeed unless the server tells you otherwise ... well that's a completely different paradigm and programming model that we could talk about someday (see meteorjs).
The net of all of this: I'm pretty darned sure that a save timeout is NOT what you want.
Still useful on a query though :)
Great question, and I wish I had a good answer. But it is definitely worth looking into. Could you please add this as a feature request to the Breeze User Voice. We take these requests very seriously in determining our priorities for Breeze development.

Broadcasting to a subset of subscribers in Atmosphere

What I'm trying to do:
Be able to have users subscribed to a number of different 'chat rooms' and use reverse AJAX / comet to send messages from a chat room to everyone logged into that room. (a bit more complicated but this is a similar use case).
What I'm doing:
Using Grails with JMS and Atmosphere. When a message is sent, I'm using JMS to send the message object which is received by a Grails service which is then broadcasted to the atmosphere URL (i.e. atmosphere/messages).
Obviously JMS is a bit redundant there but I though I could use it to help me filter who should retrieve the message although that doesn't really look it'll work (given that the subscriber is basically a singleton service...).
Anyway, what I need to be able to do is only send out a message to the correct subset of people listening to atmosphere/messages. A RESTful-type URL will be perfect here (i.e. atmosphere/messages/* where * is the room ID) however I have no idea how to do that with Atmosphere.
Any ideas / suggestions on how I can achieve what I want? Nothing is concrete at all here so feel free to suggest almost anything. I've even been thinking (based on the response to another question), for example, if I could do something like send out messages to a Node.js server and have that handle the reverse AJAX / comet part.
If I understand your requirements correctly the following should work (jax-rs + scala code):
1) Everyone who wants to get messages from a chat room registers for it:
#GET
#Path(choose/a/path)
def register(#QueryParam("chatroomId") chatroomId: Broadcaster) {
// alternatively, the Suspend annotation can be used
new SuspendResponse.SuspendResponseBuilder[String]()
.resumeOnBroadcast(false).broadcaster(chatroomId).scope(SCOPE.REQUEST)
.period(suspendTimeout, TimeUnit.MINUTES)
.addListener(new AtmosphereEventsLogger()).build
}
2) To broadcast a message for all the registered users, call the following method:
#POST
#Broadcast
#Path(choose/a/path/{chatroomId})
def broadcast(#PathParam("chatroomId") id: String) {
// first find your broadcaster with the BroadcasterFactory
BroadcasterFactory.getDefault().lookupAll() // or maybe there is a find by id?
broadcaster = ...
broadcaster.broadcast(<your message>)
}
I also recommend reading the atmosphere whitepaper, have a look at the mailing list and at Jeanfrancois Arcand's blog.
Hope that helps.
There is a misunderstaning of the concept of comet. Its just another publish/subscribe implementation. If you have multiple chat-rooms, then you need to have multiple "topics", i.e. multiple channels the user can register to. E.g.:
broadcaster['/atmosphere/chatRoom1'].broadcast('Hello world!')
broadcaster['/atmosphere/chatRoom2'].broadcast('Hello world!')
So I would advance you to creaet multiple channels and do not filter manually the set of users, which should retrieve messages (which is definitely not the way it should be done). You do not need to create anything on the server side on this, since the user will just register for a specific channel and receive messages, which anyone is putting into it.
I would recommend you create an AtmosphereHandler for one URL like /atmosphere/chat-room and then use the AtmosphereResource and bind an BroadcastFilter with it, lets say name it ChatRoomBroadcastFilter.
Whenever a user subscribes to a new chat room, a message would be sent to the server (from the client) telling the server about the subscription. Once subscribed, maintain the list of users <> chat room bindings somewhere on the server.
Whenever a message is broadcasted, broadcast it with the chat room id with it. The in the ChatRoomBroadcastFilter (You probably need to make this a PerRequestBroacastFilter) propagate the message to the user only if the user subscribed to the chat room. I am not sure if this clears it out. If you need code example please mention in the comments. I'll put that but that needs some time so ain't putting it right now ;).

Resources