<commit_before># Copyright 2015
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Implements reliable transport for our PILO messages

"""

from pox.core import core
import pox.lib.packet as pkt

from pox.lib.recoco import Timer
from pox.lib.addresses import IPAddr, IPAddr6, EthAddr
from twisted.internet.protocol import DatagramProtocol
from lib.util import get_hw_addr, get_ip_address
import socket, struct

log = core.getLogger()

class PiloTransport():
  def __init__ (self):
    log.debug('Creating PiloTransport object')

  def send_pilo_broadcast(self, packet):
    log.debug('Sending PILO broadcast')
    log.debug(packet)
    packed = packet.pack()

    sock = socket.socket(socket.AF_INET, # Internet
                         socket.SOCK_DGRAM) # UDP
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.sendto(packed, (self.udp_ip, self.udp_port))


class PiloSender(PiloTransport):
  def __init__ (self, udp_ip, udp_port, retransmission_timeout, src_address):
    self.in_transit = []
    self.seq_no = 0
    self.udp_ip = udp_ip
    self.udp_port = udp_port
    self.retransmission_timeout = retransmission_timeout
    self.src_address = EthAddr(src_address)
    self.receivers = []

  def send(self, packet, seq_no=None, callback=None):
    log.debug('Sending this pilo packet:')
    log.debug(packet)
    log.debug('seq_no passed in:')
    log.debug(seq_no)

    first_msg = True

    # Check if we've sent a packet to this sender
    for receiver in self.receivers:
      if pkt.packet_utils.same_mac(receiver['address'], packet.dst_address):
        this_receiver = receiver
        first_msg = False

    if first_msg:
      this_receiver = {
        'address': packet.dst_address,
        'seq_no': 0
        }
      self.receivers.append(this_receiver)

    if seq_no is None:
      packet.seq = this_receiver['seq_no']
      this_receiver['seq_no'] += len(packet.pack())

    self.send_pilo_broadcast(packet)
    self.in_transit.append(packet)
    core.callDelayed(self.retransmission_timeout, self.check_acked, packet, callback=callback)

  def check_acked(self, pilo_packet, callback=None):
    log.debug('checking if acked:')
    log.debug(pilo_packet)

    log.debug('in self.in_transit:')
    for p in self.in_transit:
      log.debug(p)
      log.debug('packet len:' + str(len(p.pack())))

    if pilo_packet in self.in_transit:
      log.debug('is still in transit')
      self.send_pilo_broadcast(pilo_packet)
      core.callDelayed(self.retransmission_timeout, self.check_acked, pilo_packet, callback=callback)

    else:
      log.debug('is not still in transit')
      log.debug('callback:')
      log.debug(callback)
      # TODO: This should really be evented, but it's easiest to do it this way for now
      if callback:
        callback(pilo_packet)

  def handle_ack(self, ack_packet):
    # TODO: Retransmit packet if we've received an out of order ack

    if not ack_packet.ACK:
      # if for some reason we get a packet here that isn't an ack, return
      return

    log.debug('Handling ack:')
    log.debug(ack_packet)

    log.debug('In transit:')
    # TODO: Potentially add some checksum check
    for packet in self.in_transit:
      log.debug(packet)
      if (ack_packet.seq == packet.seq and
          ack_packet.ack == packet.seq + len(packet.pack())):

        self.in_transit.remove(packet)

  def terminate_connection(self, address):
    for receiver in self.receivers:
      if pkt.packet_utils.same_mac(receiver['address'], address):
        self.receivers.remove(receiver)
        for packet in self.in_transit:
          if pkt.packet_utils.same_mac(receiver['address'], address):
            self.in_transit.remove(packet)

  def handle_fin(self, packet, callback):
    if not packet.FIN:
      # if for some reason we get a packet here that isn't a fin, return
      return

    def fin_callback(packet):
      # We've received a ACK from our FINACK and we can remove from our list of receivers
      # We also want to clear any in_transit packets
      # packet is the FINACK that we sent<commit_msg>Bugfix: Checking ack src address as well as seq numbers.<commit_after># Copyright 2015
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Implements reliable transport for our PILO messages

"""

from pox.core import core
import pox.lib.packet as pkt

from pox.lib.recoco import Timer
from pox.lib.addresses import IPAddr, IPAddr6, EthAddr
from twisted.internet.protocol import DatagramProtocol
from lib.util import get_hw_addr, get_ip_address
import socket, struct

log = core.getLogger()

class PiloTransport():
  def __init__ (self):
    log.debug('Creating PiloTransport object')

  def send_pilo_broadcast(self, packet):
    log.debug('Sending PILO broadcast')
    log.debug(packet)
    packed = packet.pack()

    sock = socket.socket(socket.AF_INET, # Internet
                         socket.SOCK_DGRAM) # UDP
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.sendto(packed, (self.udp_ip, self.udp_port))


class PiloSender(PiloTransport):
  def __init__ (self, udp_ip, udp_port, retransmission_timeout, src_address):
    self.in_transit = []
    self.seq_no = 0
    self.udp_ip = udp_ip
    self.udp_port = udp_port
    self.retransmission_timeout = retransmission_timeout
    self.src_address = EthAddr(src_address)
    self.receivers = []

  def send(self, packet, seq_no=None, callback=None):
    log.debug('Sending this pilo packet:')
    log.debug(packet)
    log.debug('seq_no passed in:')
    log.debug(seq_no)

    first_msg = True

    # Check if we've sent a packet to this sender
    for receiver in self.receivers:
      if pkt.packet_utils.same_mac(receiver['address'], packet.dst_address):
        this_receiver = receiver
        first_msg = False

    if first_msg:
      this_receiver = {
        'address': packet.dst_address,
        'seq_no': 0
        }
      self.receivers.append(this_receiver)

    if seq_no is None:
      packet.seq = this_receiver['seq_no']
      this_receiver['seq_no'] += len(packet.pack())

    self.send_pilo_broadcast(packet)
    self.in_transit.append(packet)
    core.callDelayed(self.retransmission_timeout, self.check_acked, packet, callback=callback)

  def check_acked(self, pilo_packet, callback=None):
    log.debug('checking if acked:')
    log.debug(pilo_packet)

    log.debug('in self.in_transit:')
    for p in self.in_transit:
      log.debug(p)
      log.debug('packet len:' + str(len(p.pack())))

    if pilo_packet in self.in_transit:
      log.debug('is still in transit')
      self.send_pilo_broadcast(pilo_packet)
      core.callDelayed(self.retransmission_timeout, self.check_acked, pilo_packet, callback=callback)

    else:
      log.debug('is not still in transit')
      log.debug('callback:')
      log.debug(callback)
      # TODO: This should really be evented, but it's easiest to do it this way for now
      if callback:
        callback(pilo_packet)

  def handle_ack(self, ack_packet):
    # TODO: Retransmit packet if we've received an out of order ack

    if not ack_packet.ACK:
      # if for some reason we get a packet here that isn't an ack, return
      return

    log.debug('Handling ack:')
    log.debug(ack_packet)

    log.debug('In transit:')
    # TODO: Potentially add some checksum check
    for packet in self.in_transit:
      log.debug(packet)
      if (pkt.packet_utils.same_mac(ack_packet.src_address, packet.dst_address) and
          ack_packet.seq == packet.seq and
          ack_packet.ack == packet.seq + len(packet.pack())):

        self.in_transit.remove(packet)

  def terminate_connection(self, address):
    for receiver in self.receivers:
      if pkt.packet_utils.same_mac(receiver['address'], address):
        self.receivers.remove(receiver)
        for packet in self.in_transit:
          if pkt.packet_utils.same_mac(receiver['address'], address):
            self.in_transit.remove(packet)

  def handle_fin(self, packet, callback):
    if not packet.FIN:
      # if for some reason we get a packet here that isn't a fin, return
      return

    def fin_callback(packet):
      # We've received a ACK from our FINACK and we can remove from our list of receivers
      # We also want to clear any in_transit packets
      # packet is the FINACK that we sent
{'fraction_non_alphanumeric': 0.09366598558984837, 'fraction_numerical': 0.0025809226798580494, 'mean_word_length': 3.3255813953488373, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1045202', 'n_tokens_mistral': 2989, 'n_tokens_neox': 2901, 'n_words': 841}