1 Reply Latest reply on Dec 9, 2011 1:17 AM by Silviu Vergoti

    NetNegotiator not closing redundant connections

    acon cagua Level 1

      Hey,

      I believe I found a problem in NetNegotiator that causes not closing many connections to the server (we are using wowza) under certain circumstances. These forever hanging connections consequently make problems to the streaming servers. It took ages to isolate the issue and to fix it, so hopefully it could save you from a headache one day...

       

      The NetNegotiator tries to open rtmp connection at first. If it succeeds within one second, everything is OK. If it doesn't, then it tries to open rtmpt connection and then even other kinds of connections. When the first connection succeeds, the NetNegotiator calls shutDownUnsuccessfulConnections(), where it walks through individual connections and closes those not having "connected" flag set (and removes related event handlers). And this is the core of the problem! The NetNegotiator obviously shouldn't close not opened connections, but the opened ones (except for the first - the winner one, of course). The negotiator should wait with processing of "loser" connections until they either fail or succeed.

       

      To fix this issue, I did the following (OSMF 1.6.1):

      Added a new instance variable called "winner" of type NetConnection.

      Added code to onNetStatus that assigns "winner" to the first opened connection.

      Modified shutDownUnsuccessfulConnections() so that it does not close connections, but redirect their NetStatusEvent.NET_STATUS event to a new handler (onLoserNetStatus).

      Implemented a new onLoserNetStatus() handler that closes successful, but redundant connections.

       

      Enjoy (or correct me if I'm wrong, please),

      Jiri Volejnik

       


      NetNegotiator


      //added:
      private var winner:NetConnection;

       

      //modified:
      private function onNetStatus(event:NetStatusEvent):void
      {
          ...
          case NetConnectionCodes.CONNECT_SUCCESS:

              // added the following lines:
              var c: NetConnection = event.currentTarget as NetConnection;
              if (winner == null)
                  winner = c;
          ...
      }

       

      //modified:
      private function shutDownUnsuccessfulConnections():void
      {
          timeOutTimer.stop();
          connectionTimer.stop();

          var i:int = 0;
          while (i < netConnections.length)
          {
              var nc:NetConnection = netConnections[i];

              //if (!nc.connected) // replaced with the following line
              if (nc != winner)
              {
                  nc.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
                  nc.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onNetSecurityError);
                  nc.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);

                  // nc.close(); // these 2 lines replace with the following next 2 lines
                  // netConnections.splice(i, 1);
                  nc.addEventListener(NetStatusEvent.NET_STATUS, onLoserNetStatus);
                  i++;
              }
              else
              {
                  i++;
              }
          }
      }

      // added:
      private function onLoserNetStatus(event:NetStatusEvent):void
      {
          var nc: NetConnection = event.currentTarget as NetConnection;
          switch (event.info.code)
          {
              case NetConnectionCodes.CONNECT_SUCCESS:
                   nc.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
                  // NOTE: We cannot call nc.close() directly! See http://forums.adobe.com/thread/874302
                  setTimeout(
                      function f(nc:NetConnection):void {
                          nc.close();
                      },
                       0, nc);
              break;
          }
      }