⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpack.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * tcpack.{cc,hh} -- provides TCP like acknowledgement service * Benjie Chen * * Copyright (c) 2001 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/confparse.hh>#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <click/elemfilter.hh>#include <click/router.hh>#include <click/error.hh>#include "tcpbuffer.hh"#include "tcpack.hh"CLICK_DECLSTCPAck::TCPAck()  : Element(2, 3), _timer(this){}TCPAck::~TCPAck(){}intTCPAck::configure(Vector<String> &conf, ErrorHandler *errh){  _ackdelay_ms = 20;  return cp_va_parse(conf, this, errh,                      cpOptional, 		     cpUnsigned, "ack delay (ms)", &_ackdelay_ms, cpEnd);}intTCPAck::initialize(ErrorHandler *errh){  CastElementFilter filter("TCPBuffer");  Vector<Element*> tcpbuffers;    if (router()->downstream_elements(this, 0, &filter, tcpbuffers) < 0)    return errh->error("flow-based router context failure");  if (tcpbuffers.size() < 1)     return errh->error      ("%d downstream elements found, expecting at least 1", tcpbuffers.size());  for(int i=0; i<tcpbuffers.size(); i++) {    _tcpbuffer = reinterpret_cast<TCPBuffer*>(tcpbuffers[i]->cast("TCPBuffer"));    if (_tcpbuffer)      break;  }  if (!_tcpbuffer)    return errh->error("no TCPBuffer element found!");  _synack = false;  _needack = false;  _timer.initialize(this);  _timer.schedule_after_ms(_ackdelay_ms);  return 0;}voidTCPAck::push(int port, Packet *p){  bool forward;  if (port == 0)    forward = iput(p);  else    forward = oput(p);  if (forward)    output(port).push(p);  else    p->kill();}Packet *TCPAck::pull(int port){  bool forward;  Packet *p = input(port).pull();  if (p) {    if (port == 0)      forward = iput(p);    else      forward = oput(p);    if (forward)       return p;    else {      p->kill();      return 0;    }  }  return 0;}boolTCPAck::iput(Packet *p){  const click_tcp *tcph = p->tcp_header();  if (!_synack && (tcph->th_flags&(TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {    // synack on input, meaning next ackn is the seqn in packet    _ack_nxt = ntohl(tcph->th_seq)+1;    _synack = true;  }  if (!_synack)    return false;  if (tcph->th_flags & (TH_SYN|TH_FIN|TH_RST))    return true;  // determine what the next ack should be  if (TCPBuffer::seqno(p) == _ack_nxt) {    // if the packet is what we expected, increment the expected    // sequence number, and search for the next expected sequence    // number from the tcp buffer.    _ack_nxt += TCPBuffer::seqlen(p);    bool v = _tcpbuffer->next_missing_seq_no(_ack_nxt, _ack_nxt);    // passed seq, buffer cannot be empty    assert(v);  } else {    click_chatter("seqno < ack_nxt: out of order or retransmitted packet");  }  _needack = true;  if (!_timer.scheduled())     _timer.schedule_after_ms(_ackdelay_ms);  return true;}boolTCPAck::oput(Packet *p){  const click_tcp *tcph = p->tcp_header();  if (tcph->th_flags&(TH_SYN|TH_ACK) == (TH_SYN|TH_ACK)) {    // synack on output, meaning next ackn is the ackn in packet    _ack_nxt = ntohl(tcph->th_ack);    _synack = true;  }  if (!_synack)    return false;  _needack = false;  // XXX BUGGY, BUGGY CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  click_tcp *tcph_new = p->uniqueify()->tcp_header();  tcph_new->th_ack = htonl(_ack_nxt);  return true;}voidTCPAck::run_timer(){  if (_needack) {    send_ack();    _needack = false;  }}voidTCPAck::send_ack(){  struct click_ip *ip;  struct click_tcp *tcp;  WritablePacket *q = Packet::make(sizeof(*ip) + sizeof(*tcp));  if (q == 0) {    click_chatter("TCPAck: cannot make packet");    return;  }   memset(q->data(), '\0', q->length());  ip = (struct click_ip *) q->data();  tcp = (struct click_tcp *) (ip + 1);    ip->ip_v = 4;  ip->ip_hl = 5;  ip->ip_tos = 0x10;  ip->ip_len = htons(q->length());  ip->ip_id = htons(0); // what is this used for exactly?  ip->ip_off = htons(IP_DF);  ip->ip_ttl = 255;  ip->ip_p = IP_PROTO_TCP;  ip->ip_sum = 0;  tcp->th_ack = htonl(_ack_nxt);  tcp->th_off = 5;  tcp->th_flags = TH_ACK;  tcp->th_win = htons(32120); // when and where should this be set?  tcp->th_sum = htons(0);  tcp->th_urp = htons(0);  q->set_ip_header(ip, ip->ip_hl << 2);  output(2).push(q);}CLICK_ENDDECLSEXPORT_ELEMENT(TCPAck)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -