What hinders NetStream.onPeerConnect from being triggered? - apache-flex

I'm using Adobe Stratus (now renamed to Cirrus) to build a p2p application. Inside the application, I used NetStream.onPeerConnect callback function and expected it to be triggered every time when a peer is connected. However, it always failed with my friend A while strangely friend B managed to have the function called without any problem.
I was wondering what could be the cause to this issue?
Here are how the code pieces look like.
First of all, create a NetConnection.
netConnection = new NetConnection();
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);
netConnection.connect(SERVER_ADDRESS+DEVELOPER_KEY);
Secondly, create NetStream upon NetConnection successfully connected.
private function netConnectionHandler(event:NetStatusEvent):void{
switch (event.info.code){
case "NetConnection.Connect.Success":
sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);
sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
var sendObj:Object = new Object();
sendObj.onPeerConnect = function(subscriber:NetStream) : Boolean {
trace("[onPeerConnect] far id: " + subscriber.farID);
return true;
}
sendStream.client = sendObj;
sendStream.publish("file");
......
Thirdly, here's how I build the connection between two peers
receivedStream = new NetStream(netConnection, farId);
receivedStream.client = this;
receivedStream.addEventListener(NetStatusEvent.NET_STATUS, incomingStreamHandler);
receivedStream.play("file");
Please help enlighten me. Thanks!

It turns out my friend A is behind a symmetric NAT. I'm thinking to setup a TURN server for us to build a successful connection.

Related

"Unable to determine a valid ordering for dependent operations" on production server

I have been working on a WCF web service, which is used by a mobile app that would send some data to it and save to DB.
One of the test case is that we try to append 2 (or more) records in the app, and the service is called to do a batch insert / update action.
Everything goes fine when I test using localhost, but when we test it using production server, only
the first record is saved, while the other record triggers the error message
Unable to determine a valid ordering for dependent operations...store-generated values.
I have no idea what is the cause and how to solve it. I have done some research and I am quite sure that the related model/DB table has NO circular dependency or self dependency.
Below is a snippet of the web service:
public void submit(List<SubmissionParameter> param){
using (var context = ObjectContextManager.AuditEnabledInstance){
foreach (var item in param){
ReadingSubmission readingSubmission = context.ReadingSubmissions.Where(p => p.ReadingSubmissionUniqueIdentifier == item.Readingsubmissionuniqueidentifier).SingleOrDefault();
if (readingSubmission == null){
readingSubmission = new ReadingSubmission();
context.ReadingSubmissions.AddObject(readingSubmission);
}
readingSubmission.ReadingSubmissionUniqueIdentifier = item.Readingsubmissionuniqueidentifier;
readingSubmission.SystemID = item.Systemid;
readingSubmission.UserID = item.Userid;
foreach (var record in item.Readings){
SystemReading systemReading = context.SystemReadings.Where(p => p.SystemReadingUniqueIdentifier == record.Systemreadinguniqueidentifier).SingleOrDefault();
if (systemReading == null){
systemReading = new SystemReading();
readingSubmission.SystemReadings.Add(systemReading);
}
systemReading.SystemReadingUniqueIdentifier = record.Systemreadinguniqueidentifier;
systemReading.MeasurementID = record.Measurementid;
}
context.SaveChanges();
}
}
}
ReadingSubmission and SystemReading is a 1 to many relation
SubmissionParameter is just a transmission object as the mobile client will send the JSON object to this web service.
I use Telerik Fiddler to post the JSON into this web service for testing, so I am quite sure the problem is not at the mobile client side.
Any help is appreciated! Thanks!
Finally I solve the problem though I am not quite sure why it works.
I move the context.SaveChanges() out of the foreach loop then it all works again for
both localhost and production
Hope it can help someone to save some time

asp.net app calling service says its not initialized?

So this code runs in an asp.net app on Linux. The code calls one of my services. (WCF doesn't work on mono currently, that is why I'm using asmx). This code works AS INTENDED when running from Windows (while debugging). As soon as I deploy to Linux, it stops working. I'm definitely baffled. I've tested the service thoroughly and the service is fine.
Here is the code producing an error: (NewVisitor is a void function taking 3 strings in)
//This does not work.
try
{
var client = new Service1SoapClient();
var results = client.NewVisitor(Request.UserHostAddress, Request.UrlReferrer == null ? String.Empty : Request.UrlReferrer.ToString(), Request.UserAgent);
Logger.Debug("Result of client: " + results);
}
Here is the error generated: Object reference not set to an instance of an object
Here is the code that works perfectly:
//This works (from the service)
[WebMethod(CacheDuration = _cacheTime, Description = "Returns a List of Dates", MessageName = "GetDates")]
public List<MySqlDateTime> GetDates()
{
return db.GetDates();
}
//Here is the code for the method above
var client = new Service1Soap12Client();
var dbDates = client.GetDates();
I'd love to figure out why it is saying that the object is not set.
Methods tried:
new soap client.
new soap client with binding and endpoint address specified
Used channel factory to create and open the channel.
If more info is needed I can give more. I'm out of ideas.
It looks like a bug in mono. You should file a bug with a reproducible test case so it can be fixed (and possibly find a workaround you can use).
Unfortunately, I don't have Linux to test it but I'd suggest you put the client variable in an using() statement:
using(var client = new Service1SoapClient())
{
var results = client.NewVisitor(Request.UserHostAddress, Request.UrlReferrer == null ?
String.Empty : Request.UrlReferrer.ToString(), Request.UserAgent);
Logger.Debug("Result of client: " + results);
}
I hope it helps.
RC.

How often should I open/close my Booksleeve connection?

I'm using the Booksleeve library in a C#/ASP.NET 4 application. Currently the RedisConnection object is a static object across my MonoLink class. Should I be keeping this connection open, or should I be open/closing it after each query/transaction (as I'm doing now)? Just slightly confused. Here's how I'm using it, as of now:
public static MonoLink CreateMonolink(string URL)
{
redis.Open();
var transaction = redis.CreateTransaction();
string Key = null;
try
{
var IncrementTask = transaction.Strings.Increment(0, "nextmonolink");
if (!IncrementTask.Wait(5000))
{
transaction.Discard();
throw new System.TimeoutException("Monolink index increment timed out.");
}
// Increment complete
Key = string.Format("monolink:{0}", IncrementTask.Result);
var AddLinkTask = transaction.Strings.Set(0, Key, URL);
if (!AddLinkTask.Wait(5000))
{
transaction.Discard();
throw new System.TimeoutException("Add monolink creation timed out.");
}
// Run the transaction
var ExecTransaction = transaction.Execute();
if (!ExecTransaction.Wait(5000))
{
throw new System.TimeoutException("Add monolink transaction timed out.");
}
}
catch (Exception ex)
{
transaction.Discard();
throw ex;
}
finally
{
redis.Close(false);
}
// Link has been added to redis
MonoLink ml = new MonoLink();
ml.Key = Key;
ml.URL = URL;
return ml;
}
Thanks, in advance, for any responses/insight. Also, is there any sort of official documentation for this library? Thank you S.O. ^_^.
According to the author of Booksleeve,
The connection is thread safe and intended to be massively shared;
don't do a connection per operation.
Should I be keeping this connection open, or should I be open/closing
it after each query/transaction (as I'm doing now)?
There is probably a little overhead if you will open a new connection each time you want to make a query/transaction and although redis is designed for high level of concurrently connected clients, there might be performance problems if their number is around tens of thousands. As far as I know connection pooling should be done by the client libraries (because redis itself doesn't have this functionality), so you should check if booksleeve supports this stuff. Otherwise you should open the connection when your application starts and keep it open for it's lifetime (in case you don't need parallel clients connected to redis for some reason).
Also, is there any sort of official documentation for this library?
The only documentation I was able to find regarding how to use it was tests folder in it's source codes.
For reference (continuing #bzlm's answer), I created a Singleton that always provides the same Redis connection using BookSleeve (if it's closed, it's being created. Else, the existing connection is being served).
Look at this: https://stackoverflow.com/a/8777999/290343
You consume it like that:
RedisConnection connection = Redis.RedisConnectionGateway.Current.GetConnection();

netStream with groupSpecifier not sending handler, FLEX

I have a simple video/chat application built in FLEX. I've created a groupSpecifier, netGroup and a NetStream for the different functionalities.
NetGroup is mainly used for the messaging (Posting) and keeping track of the users who enter.
NetStream is (or would be used) to control some functions like "start video, stop video" for everyone under the same group.
The most important functions I will post on here. The first is setupGroup.
private function setupGroup():void{
var groupspec:GroupSpecifier = new GroupSpecifier("vid"+GROUP_ID+"_sid_"+SESSION_ID);
groupspec.serverChannelEnabled = true;
groupspec.postingEnabled = true;
groupspec.multicastEnabled = true;
groupspec.ipMulticastMemberUpdatesEnabled = true;
trace("Groupspec: "+groupspec.groupspecWithoutAuthorizations());
netGroup = new NetGroup(nc,groupspec.groupspecWithoutAuthorizations());
netGroup.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
netVideo = new NetStream(nc,groupspec.groupspecWithoutAuthorizations());
netVideo.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
user = "user"+Math.round(Math.random()*10000);
}
The second is sendMessage
private function sendMessage():void{
var message:Object = new Object();
message.sender = netGroup.convertPeerIDToGroupAddress(nc.nearID);
message.user = txtUser.text;
message.text = txtMessage.text;
netGroup.post(message);
receiveMessage(message);
txtMessage.text = "";
}
And then startVideo
private function startVideo():void{
netVideo.send("publishVideo");
ns.togglePause();
}
There is another function called "publishVideo" which I hope would be called for the rest of the members in the group, but this is not happening. Most of this code is straight from the example Tom has provided from http://www.flashrealtime.com. Any help / suggestions would be appreciated!
p.s. I am not using group object replication because of the latency.
Answer is prosaically simple.
You need to start video with:
netVideo.publish("channel");
NetStream.send() is for invoking callback method on receiver NetStream.client object.
http://www.flashrealtime.com/multicast-explained-flash-101-p2p/

Multiple instances of views in PureMVC: Am I doing this right?

What I'm doing NOW:
Often multiple instances of the view component would be used in multiple places in an application. Each time I do this, I register the same mediator with a different name.
When a notification is dispatched, I attach the name of the mediator to the body of the notification, like so:
var obj:Object = new Object();
obj.mediatorName = this.getMediatorName();
obj.someParameter = someParameter;
sendNotification ("someNotification", obj);
Then in the Command class, I parse the notification body and store the mediatorName in the proxy.
var mediatorName:String = notification.getBody().mediatorName;
var params:String = notification.getBody().someParameter;
getProxy().someMethod(params, mediatorName);
On the return notification, the mediatorName is returned with it.
var obj:Object = new Object();
obj.mediatorName = mediatorName;
obj.someReturnedValue= someReturnedValue;
sendNotification ("someReturnedNotification", obj);
In the multiple mediators that might be watching for "someReturnedNotification," in the handleNotification(), it does an if statement, to see
if obj.mediatorName == this.getMediatorName
returns true. If so, process the info, if not, don't.
My Question is:
Is this the right way of using Multiton PureMVC? My gut feeling is not. I am sure there's a better way of architecting the application so that I don't have to test for the mediator's name to see if the component should be updated with the returned info.
Would someone please help and give me some direction as to what is a better way?
Thanks.
I checked with Cliff (the puremvc.org guy) and he said it's fine.

Resources