/// <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; }
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 } }
/// <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; } }
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 }); } }