예제 #1
0
    /// <summary>
    /// Analyse the frame header, calculate RTO.
    /// </summary>
    /// <param name="fh_message">The fh_message.</param>
    /// <param name="reload_connection">The reload_connection.</param>
    /// <returns></returns>
    private byte[] analyseFrameHeader(SimpleOverlayConnectionTableElement connectionTableEntry, byte[] fh_message) {
      if (ReloadGlobals.Framing) {
        /* Handle FrameHeader */
        FramedMessageType type = (FramedMessageType)fh_message[0];
        if (type == FramedMessageType.ack) {
          FramedMessageAck fh_ack = FMA_FromBytes(fh_message);

          m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_FH, String.Format("Rx FH ACK {0}, 0x{1:x}", fh_ack.ack_sequence, fh_ack.received));

          /* Calculate RTO */
          DateTime sent;
          if (connectionTableEntry.fh_sent.TryGetValue(fh_ack.ack_sequence, out sent)) {
            long rtt = DateTime.Now.Ticks - sent.Ticks;
            if (connectionTableEntry.srtt == 0.0) {
              connectionTableEntry.srtt = rtt;
              connectionTableEntry.rttvar = 0.5 * rtt;
              connectionTableEntry.rto = new TimeSpan(Convert.ToInt64(rtt + 4 * connectionTableEntry.rttvar));
            }
            else {
              double alpha = 0.125;
              double beta = 0.25;
              connectionTableEntry.srtt = (1.0 - alpha) * connectionTableEntry.srtt + alpha * rtt;
              connectionTableEntry.rttvar = (1.0 - beta) * connectionTableEntry.rttvar + beta * System.Math.Abs(connectionTableEntry.srtt - rtt);
              connectionTableEntry.rto = new TimeSpan(Convert.ToInt64(connectionTableEntry.srtt + 4 * connectionTableEntry.rttvar));
            }
            connectionTableEntry.fh_sent.Remove(fh_ack.ack_sequence);
            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_FH, String.Format("RTT {0}, SRTT {1}, RTTVAR {2}, RTO {3}", rtt, connectionTableEntry.srtt, connectionTableEntry.rttvar, connectionTableEntry.rto));
          }
        }
        else {
          if (type == FramedMessageType.data) {
            FramedMessageData fh_data = FMD_FromBytes(fh_message);
            byte[] fh_stripped_data = new byte[fh_message.Length - 8];
            Array.Copy(fh_message, 8, fh_stripped_data, 0, fh_message.Length - 8);

            UInt32 received = 0;
            UInt32 n = fh_data.sequence;
            /* Calculate FH received mask */
            foreach (UInt32 m in connectionTableEntry.fh_received) {
              if (m < n || m >= (n - 32)) {
                UInt32 bit = n - m - 1;
                if (bit < 32)
                  received |= ((UInt32)1 << (int)bit);
              }
            }
            while (connectionTableEntry.fh_received.Count >= 32)
              connectionTableEntry.fh_received.Dequeue();
            connectionTableEntry.fh_received.Enqueue(fh_data.sequence);

            /* Acknowledge it */
            FramedMessageAck fh_ack = new FramedMessageAck();
            fh_ack.type = FramedMessageType.ack;
            fh_ack.ack_sequence = fh_data.sequence;
            fh_ack.received = received;
            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_FH, String.Format("Tx FH ACK {0}, 0x{1:x}", fh_ack.ack_sequence, fh_ack.received));

            //in - offset out - bytesprocessed
            Send(new Node(connectionTableEntry.NodeID, null), ToBytes(fh_ack));

            return fh_stripped_data;
          }
        }
        return null;
      }
      else
        return fh_message;
    }
예제 #2
0
    public IEnumerator<ITask> Send(Node node, byte[] buffer) {
      Socket socket = null;
      SimpleOverlayConnectionTableElement socte = null;

#if false
            /* paranoia: check validity of buffer here again */
            if (   buffer[0] != 0xC2
                && buffer[1] != 0x45
                && buffer[2] != 0x4c
                && buffer[3] != 0x4f)
            {
                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "SimpleFLM: Wrong Tag in Send message!");
                yield break;
            }
#endif

#if CONNECTION_MANAGEMENT
      /* beginn connection management */
      lock (m_connection_table) {
        if (node.Id != null && m_connection_table.ContainsKey(node.Id.ToString())) {
          SimpleOverlayConnectionTableElement el = m_connection_table[node.Id.ToString()];

          if (el.NodeID == node.Id) {
            if (el.AssociatedSocket.Connected) {
              long offset = 0;
              socket = el.AssociatedSocket;
              try {
                ReloadMessage reloadMsg = new ReloadMessage(m_ReloadConfig).FromBytes(buffer, ref offset, ReloadMessage.ReadFlags.no_certcheck);
                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("SimpleFLM: >> {0} {1} ==> {2}, TransID={3:x16}", socket.RemoteEndPoint, reloadMsg.reload_message_body.RELOAD_MsgCode.ToString(), node.Id.ToString(), reloadMsg.TransactionID));
                socte = el;
              }
              catch (Exception ex) {
                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
                  String.Format("SimpleFLM Send: {0}", ex.Message));
              }
            }
            else {
              // no longer connected, remove entry
              m_connection_table.Remove(node.Id.ToString());
              m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("SimpleFLM: >> {0} removed, associated with {1}", el.AssociatedSocket, node.Id.ToString()));
            }
          }
        }
      }
      /* end connection management */
#endif

      if (socket == null) {
        if (node.IceCandidates != null) {
          /*                  if (node.Id != null)
                              {
                                  ReloadMessage reloadMsg = new ReloadMessage().FromBytes(buffer);
                                  m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TEST, String.Format("SimpleFLM: {0} ==> {1} TransID={2:x16}", reloadMsg.reload_message_body.RELOAD_MsgCode.ToString(), node.Id.ToString(), reloadMsg.TransactionID));
                              }
          */
          foreach (IceCandidate candidate in node.IceCandidates) {
            switch (candidate.addr_port.type) {
              case AddressType.IPv6_Address:
              case AddressType.IPv4_Address: {
                  if (socket == null) {
                    socket = new Socket(candidate.addr_port.ipaddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    var iarPort = new Port<IAsyncResult>();
                    socket.BeginConnect(new IPEndPoint(candidate.addr_port.ipaddr, candidate.addr_port.port), iarPort.Post, null);

                    yield return Arbiter.Receive(false, iarPort, iar => {
                      try {
                        socket.EndConnect(iar);
                      }
                      catch (Exception ex) {
                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "SimpleFLM: Send Connect: " + ex.Message);
                        HandleRemoteClosing(socket);
                        if (socket.Connected)
                          socket.Shutdown(SocketShutdown.Both);
                        socket.Close();
                        socket = null;
                        return;
                      }
                    });
                  }
                }
                break;
            }
            //just support one ice candidate only here
            break;
          }
        }
        else {
          long offset = 0;
          ReloadMessage reloadMsg = new ReloadMessage(m_ReloadConfig).FromBytes(buffer, ref offset, ReloadMessage.ReadFlags.no_certcheck);
          m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("SimpleFLM: {0} ==> {1} TransID={2:x16} (No ice candidates and no connection!)", reloadMsg.reload_message_body.RELOAD_MsgCode.ToString(), node.Id.ToString(), reloadMsg.TransactionID));
          m_ReloadConfig.Statistics.IncConnectionError();
        }
      }

      if (socket != null) {
        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET,
          String.Format("SimpleFLM: >> {0} Send {1} bytes",
          socket.RemoteEndPoint, buffer.Length));

        var iarPort2 = new Port<IAsyncResult>();

        socte = new SimpleOverlayConnectionTableElement();

        byte[] framed_buffer = addFrameHeader(socte, buffer);

        socket.BeginSend(framed_buffer, 0, framed_buffer.Length,
          SocketFlags.None, iarPort2.Post, null);

        m_ReloadConfig.Statistics.BytesTx = (UInt64)framed_buffer.Length;

        yield return Arbiter.Receive(false, iarPort2, iar => {
          try {
            socket.EndSend(iar);
          }
          catch (Exception ex) {
            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
              "SimpleFLM: SocketError : " + ex.Message);
            m_ReloadConfig.Statistics.IncConnectionError();
          }
        });

#if CONNECTION_MANAGEMENT

        if (socket.Connected) {
          /* beginn connection management */

          lock (m_connection_table) {
            if (node.Id != null && node.Id != m_ReloadConfig.LocalNodeID)
              if (m_connection_table.ContainsKey(node.Id.ToString())) {
                SimpleOverlayConnectionTableElement rcel = m_connection_table[node.Id.ToString()];
                rcel.LastActivity = DateTime.Now;
              }
              else {
                SimpleOverlayConnectionTableElement rcel = new SimpleOverlayConnectionTableElement();
                rcel.NodeID = node.Id;
                rcel.AssociatedSocket = socket;
                rcel.LastActivity = rcel.Start = DateTime.Now;
                rcel.Outbound = true;

                m_connection_table.Add(rcel.NodeID.ToString(), rcel);
                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("SimpleFLM: >> {0} Send: Associating node {1}", socket.RemoteEndPoint, rcel.NodeID.ToString()));
                Arbiter.Activate(m_ReloadConfig.DispatcherQueue, new IterativeTask<Socket, NodeId>(socket, node.Id, Receive));
              }
          }
          if (node.Id == null) {
            Arbiter.Activate(m_ReloadConfig.DispatcherQueue, new IterativeTask<Socket, NodeId>(socket, node.Id, Receive));
          }
        }
        else {
          m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "SimpleFLM: Socket not connected after send");
        }
        /* end connection management */
#else
                if(socket.Connected)
                    socket.Shutdown(SocketShutdown.Both);
                socket.Close();
#endif
      }
    }
예제 #3
0
    /// <summary>
    /// Add frame header to outgoing user message
    /// </summary>
    /// <param name="message">The message.</param>
    /// <param name="reload_connection">The reload_connection.</param>
    /// <returns></returns>
    private byte[] addFrameHeader(SimpleOverlayConnectionTableElement connectionTableEntry, byte[] message) {
      if (ReloadGlobals.Framing) {
        /* Add FH, manage connections */
        FramedMessageData fh_message_data = new FramedMessageData();
        fh_message_data.type = FramedMessageType.data;
        fh_message_data.sequence = connectionTableEntry.fh_sequence;

        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_FH, String.Format("Tx FH DATA {0}", connectionTableEntry.fh_sequence));

        connectionTableEntry.fh_sent.Add(connectionTableEntry.fh_sequence++, DateTime.Now);
        return ToBytes(fh_message_data, message);
      }
      else {
        return message;
      }
    }
예제 #4
0
    private IEnumerator<ITask> Receive(Socket socketClient, NodeId nodeid) {
      if (socketClient == null) {
        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("SimpleFLM: Receive: socket == null!!!"));
        yield break;
      }

      if (!socketClient.Connected) {
        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("SimpleFLM: << {0} receive, but client is not connected", socketClient.RemoteEndPoint));
        HandleRemoteClosing(socketClient);
        yield break;
      }

      while (socketClient != null && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Exit) {
        byte[] buffer = new byte[ReloadGlobals.MAX_PACKET_BUFFER_SIZE * ReloadGlobals.MAX_PACKETS_PER_RECEIVE_LOOP];

        var iarPort = new Port<IAsyncResult>();
        int bytesReceived = 0;

        try {
          m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("SimpleFLM: << {0} BeginReceive", socketClient == null ? "null" : socketClient.RemoteEndPoint.ToString()));
          socketClient.BeginReceive(
              buffer,
              0,
              buffer.Length,
              SocketFlags.None, iarPort.Post, null);
        }
        catch (Exception ex) {
          m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("SimpleFLM: << {0} BeginReceive", socketClient == null ? "null" : socketClient.RemoteEndPoint.ToString()) + ex.Message);
        }
        yield return Arbiter.Receive(false, iarPort, iar => {
          try {
            if (iar != null)
              bytesReceived = socketClient.EndReceive(iar);
          }
          catch (Exception ex) {
            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO,
              String.Format("SimpleFLM: << {0} Receive: {1} ",
              nodeid == null ? "" : nodeid.ToString(), ex.Message));
          }

          if (bytesReceived <= 0) {
            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, 
              String.Format("SimpleFLM: << {0} Receive: lost connection, closing socket",
              socketClient.RemoteEndPoint));
            HandleRemoteClosing(socketClient);
            socketClient.Close();
            socketClient = null;
            return;
          }

          m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET,
            String.Format("SimpleFLM: << {0} Read {1} bytes from {2}",
            socketClient.RemoteEndPoint, 
            bytesReceived, nodeid == null ? "" : nodeid.ToString()));

          m_ReloadConfig.Statistics.BytesRx = (UInt64)bytesReceived;

#if CONNECTION_MANAGEMENT
          /* beginn connection management */
          long bytesProcessed = 0;
          SimpleOverlayConnectionTableElement socte = null;

          if (ReloadGlobals.Framing) {
            foreach (KeyValuePair<string, SimpleOverlayConnectionTableElement> pair in m_connection_table) {
              if (socketClient == pair.Value.AssociatedSocket) {
                socte = pair.Value;
                break;
              }
            }

            if (socte == null)
              socte = new SimpleOverlayConnectionTableElement();
            Array.Resize(ref buffer, bytesReceived);
            buffer = analyseFrameHeader(socte, buffer);
            bytesReceived = buffer.Length;
          }

          ReloadMessage reloadMsg = null;

          if (buffer != null) {
            reloadMsg = new ReloadMessage(m_ReloadConfig).FromBytes(buffer,
              ref bytesProcessed, ReloadMessage.ReadFlags.full);
          }

          if (socketClient != null && reloadMsg != null) {
            if (nodeid == null)
              nodeid = reloadMsg.LastHopNodeId;

            if (nodeid != null)
              if (m_connection_table.ContainsKey(nodeid.ToString())) {
                SimpleOverlayConnectionTableElement rcel = m_connection_table[
                  nodeid.ToString()];
                rcel.LastActivity = DateTime.Now;
              }
              else {
                SimpleOverlayConnectionTableElement rcel = socte;
                if (rcel == null)
                  rcel = new SimpleOverlayConnectionTableElement();
                rcel.NodeID = reloadMsg.LastHopNodeId;
                rcel.AssociatedSocket = socketClient;
                /*
                 * tricky: if this is an answer, this must be issued by an 
                 * outgoing request before (probably the first 
                 * bootstrap contact, where we have no nodeid from)
                 */
                rcel.Outbound = !reloadMsg.IsRequest();
                rcel.LastActivity = rcel.Start = DateTime.Now;

                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET,
                  String.Format("SimpleFLM: << {0} Receive: Associating node {1}",
                  socketClient.RemoteEndPoint, rcel.NodeID.ToString()));
                lock (m_connection_table) {
                  if (nodeid != m_ReloadConfig.LocalNodeID) {
                    if (!m_connection_table.ContainsKey(rcel.NodeID.ToString()))
                      m_connection_table.Add(rcel.NodeID.ToString(), rcel);
                    else
                      m_connection_table[rcel.NodeID.ToString()] = rcel;
                  }
                }
              }
            /* end connection management */

            if (ReloadFLMEventHandler != null) {
              //there might by more then one packet inside
              m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET,
                String.Format("SimpleFLM: << {0} <== {1} {2}, TransID={3:x16}", socketClient.RemoteEndPoint, reloadMsg.reload_message_body.RELOAD_MsgCode.ToString(), nodeid.ToString(), reloadMsg.TransactionID));


              ReloadFLMEventHandler(this, new ReloadFLMEventArgs(
                ReloadFLMEventArgs.ReloadFLMEventTypes.RELOAD_EVENT_RECEIVE_OK,
                null, reloadMsg));

              if (bytesProcessed != bytesReceived) {
                long bytesProcessedTotal = 0;
                string lastMsgType = "";
                while (reloadMsg != null
                  && bytesProcessedTotal < bytesReceived) {
                  //in - offset out - bytesprocessed
                  bytesProcessed = bytesProcessedTotal;
                  //TKTODO add framing handling  here
                  reloadMsg = new ReloadMessage(m_ReloadConfig).FromBytes(
                    buffer, ref bytesProcessed, ReloadMessage.ReadFlags.full);
                  // Massive HACK!!! offset of TCP messages is set wrong TODO!!!
                  int offset = 0;
                  while (reloadMsg == null) {
                    offset++;
                    bytesProcessedTotal++;
                    bytesProcessed = bytesProcessedTotal;
                    reloadMsg = new ReloadMessage(m_ReloadConfig).FromBytes(
                      buffer, ref bytesProcessed, ReloadMessage.ReadFlags.full);
                    if (reloadMsg != null)
                      m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
                        String.Format("Last message type: {0}, offset: {1}",
                        lastMsgType, offset));
                  }
                  ReloadFLMEventHandler(this, new ReloadFLMEventArgs(
                    ReloadFLMEventArgs.ReloadFLMEventTypes.RELOAD_EVENT_RECEIVE_OK,
                    null, reloadMsg));
                  m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET,
                      String.Format("SimpleFLM: << {0} <== {1} {2}, TransID={3:x16}",
                      socketClient.RemoteEndPoint,
                      reloadMsg.reload_message_body.RELOAD_MsgCode.ToString(),
                      nodeid.ToString(),
                      reloadMsg.TransactionID));
                  bytesProcessedTotal += bytesProcessed;                  
                  lastMsgType = reloadMsg.reload_message_body.RELOAD_MsgCode.ToString();
                }
              }
            }
          }
          else {
            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
              String.Format("SimpleFLM: << {0} Receive: Dropping invalid packet,"+
              "bytes received: {1}", socketClient.RemoteEndPoint, bytesReceived));
          }
#endif
#if !CONNECTION_MANAGEMENT
                    m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("SimpleFLM: << {0} Receive: Closing socket", client.RemoteEndPoint));
                    if(client.Connected)
                        client.Shutdown(SocketShutdown.Both);
                    client.Close();
#endif
        });
      }
    }